2 * keydctl.c - A simple program to control a running keyd instance
4 * Copyright 2011 Jonathan McDowell <noodles@earth.li>
12 #include <sys/types.h>
13 #include <sys/socket.h>
17 #include "onak-conf.h"
20 /* HACK: We need to stop onak-conf.o requiring this. */
23 static int keyd_fd = -1;
24 static int verbose = 0;
26 static int keyd_do_command(enum keyd_ops cmd, void *buf, size_t len)
35 if (write(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
38 "Couldn't write keyd command %d: %s (%d)\n",
39 cmd, strerror(errno), errno);
42 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
45 "Couldn't read keyd command %d reply: "
47 cmd, strerror(errno), errno);
50 } else if (tmp != KEYD_REPLY_OK) {
52 } else if (buf == NULL) {
54 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
57 "Couldn't read keyd command %d reply length: "
59 cmd, strerror(errno), errno);
62 } else if (tmp > len) {
63 /* TODO: Read what we can into buf and skip the rest */
66 return read(keyd_fd, buf, tmp);
70 static void keyd_connect(void)
72 struct sockaddr_un sock;
73 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
75 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
79 "Couldn't open socket: %s (%d)\n",
86 sock.sun_family = AF_UNIX;
87 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
90 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
93 "Couldn't connect to socket %s: %s (%d)\n",
101 keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply));
102 if (reply != keyd_version) {
104 fprintf(stderr, "Error! keyd protocol version "
105 "mismatch. (us = %d, it = %d)\n",
106 keyd_version, reply);
114 static void keyd_close(void)
116 uint32_t cmd = KEYD_CMD_CLOSE;
118 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd) && verbose >= 0) {
119 fprintf(stderr, "Couldn't send close cmd: %s (%d)\n",
124 if (shutdown(keyd_fd, SHUT_RDWR) < 0 && verbose >= 0) {
125 fprintf(stderr, "Error shutting down socket: %d\n",
128 if (close(keyd_fd) < 0 && verbose >= 0) {
129 fprintf(stderr, "Error closing down socket: %d\n",
138 static void keyd_status(void)
142 keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply));
143 printf("Using keyd protocol version %d.\n", reply);
148 static void usage(void)
150 puts("keydctl " ONAK_VERSION " - control an onak keyd instance.\n");
152 puts("\tonak [options] <command> <parameters>\n");
153 puts("\tCommands:\n");
154 puts("\tcheck - check if keyd is running");
155 puts("\tquit - request that keyd cleanly shuts down");
156 puts("\tstatus - display running keyd status");
160 int main(int argc, char *argv[])
163 char *configfile = NULL;
165 while ((optchar = getopt(argc, argv, "c:h")) != -1 ) {
168 configfile = strdup(optarg);
177 readconfig(configfile);
181 if ((argc - optind) < 1) {
183 } else if (!strcmp("check", argv[optind])) {
184 /* Just do the connect and close quietly */
188 } else if (!strcmp("status", argv[optind])) {
192 } else if (!strcmp("quit", argv[optind])) {
194 keyd_do_command(KEYD_CMD_QUIT, NULL, 0);