2 * keydctl.c - A simple program to control a running keyd instance
4 * Copyright 2011 Jonathan McDowell <noodles@earth.li>
13 #include <sys/types.h>
14 #include <sys/socket.h>
18 #include "onak-conf.h"
21 /* HACK: We need to stop onak-conf.o requiring this. */
24 static int keyd_fd = -1;
25 static int verbose = 0;
27 static int keyd_do_command(enum keyd_ops cmd, void *buf, size_t len)
36 if (write(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
39 "Couldn't write keyd command %d: %s (%d)\n",
40 cmd, strerror(errno), errno);
43 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
46 "Couldn't read keyd command %d reply: "
48 cmd, strerror(errno), errno);
51 } else if (tmp != KEYD_REPLY_OK) {
53 } else if (buf == NULL) {
55 } else if (read(keyd_fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
58 "Couldn't read keyd command %d reply length: "
60 cmd, strerror(errno), errno);
63 } else if (tmp > len) {
64 /* TODO: Read what we can into buf and skip the rest */
67 return read(keyd_fd, buf, tmp);
71 static void keyd_connect(void)
73 struct sockaddr_un sock;
74 uint32_t reply = KEYD_REPLY_UNKNOWN_CMD;
76 keyd_fd = socket(PF_UNIX, SOCK_STREAM, 0);
80 "Couldn't open socket: %s (%d)\n",
87 sock.sun_family = AF_UNIX;
88 snprintf(sock.sun_path, sizeof(sock.sun_path) - 1, "%s/%s",
91 if (connect(keyd_fd, (struct sockaddr *) &sock, sizeof(sock)) < 0) {
94 "Couldn't connect to socket %s: %s (%d)\n",
102 keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply));
103 if (reply != keyd_version) {
105 fprintf(stderr, "Error! keyd protocol version "
106 "mismatch. (us = %d, it = %d)\n",
107 keyd_version, reply);
115 static void keyd_close(void)
117 uint32_t cmd = KEYD_CMD_CLOSE;
119 if (write(keyd_fd, &cmd, sizeof(cmd)) != sizeof(cmd) && verbose >= 0) {
120 fprintf(stderr, "Couldn't send close cmd: %s (%d)\n",
125 if (shutdown(keyd_fd, SHUT_RDWR) < 0 && verbose >= 0) {
126 fprintf(stderr, "Error shutting down socket: %d\n",
129 if (close(keyd_fd) < 0 && verbose >= 0) {
130 fprintf(stderr, "Error closing down socket: %d\n",
139 static void keyd_status(void)
142 struct keyd_stats stats;
144 keyd_do_command(KEYD_CMD_VERSION, &reply, sizeof(reply));
145 printf("Using keyd protocol version %d.\n", reply);
147 keyd_do_command(KEYD_CMD_STATS, &stats, sizeof(stats));
148 printf("keyd running since %s", ctime(&stats.started));
149 printf("%d client connections received\n", stats.connects);
151 printf("Command statistics:\n");
152 printf(" Version: %d\n",
153 stats.command_stats[KEYD_CMD_VERSION]);
154 printf(" Get key: %d\n", stats.command_stats[KEYD_CMD_GET]);
155 printf(" Store key: %d\n",
156 stats.command_stats[KEYD_CMD_STORE]);
157 printf(" Delete key: %d\n",
158 stats.command_stats[KEYD_CMD_DELETE]);
159 printf(" Search key: %d\n",
160 stats.command_stats[KEYD_CMD_GETTEXT]);
161 printf(" Get full keyid: %d\n",
162 stats.command_stats[KEYD_CMD_GETFULLKEYID]);
163 printf(" Iterate all keys: %d\n",
164 stats.command_stats[KEYD_CMD_KEYITER]);
165 printf(" Close: %d\n",
166 stats.command_stats[KEYD_CMD_CLOSE]);
167 printf(" Quit: %d\n", stats.command_stats[KEYD_CMD_QUIT]);
168 printf(" Get statistics: %d\n",
169 stats.command_stats[KEYD_CMD_STATS]);
170 printf(" Unknown: %d\n",
171 stats.command_stats[KEYD_CMD_UNKNOWN]);
176 static void usage(void)
178 puts("keydctl " ONAK_VERSION " - control an onak keyd instance.\n");
180 puts("\tonak [options] <command> <parameters>\n");
181 puts("\tCommands:\n");
182 puts("\tcheck - check if keyd is running");
183 puts("\tquit - request that keyd cleanly shuts down");
184 puts("\tstatus - display running keyd status");
188 int main(int argc, char *argv[])
191 char *configfile = NULL;
193 while ((optchar = getopt(argc, argv, "c:h")) != -1 ) {
196 configfile = strdup(optarg);
205 readconfig(configfile);
209 if ((argc - optind) < 1) {
211 } else if (!strcmp("check", argv[optind])) {
212 /* Just do the connect and close quietly */
216 } else if (!strcmp("status", argv[optind])) {
220 } else if (!strcmp("quit", argv[optind])) {
222 keyd_do_command(KEYD_CMD_QUIT, NULL, 0);