2 * uuidd.c --- UUID-generation daemon
4 * Copyright (C) 2007 Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
19 #include <sys/types.h>
21 #include <sys/socket.h>
28 extern int getopt(int argc, char * const argv[], const char *optstring);
32 #include "uuid/uuid.h"
33 #include "uuid/uuidd.h"
34 #include "nls-enable.h"
37 #define CODE_ATTR(x) __attribute__(x)
42 static void usage(const char *progname)
44 fprintf(stderr, _("Usage: %s [-d] [-p pidfile] [-s socketpath] "
45 "[-T timeout]\n"), progname);
46 fprintf(stderr, _(" %s [-r|t] [-n num] [-s socketpath]\n"),
48 fprintf(stderr, _(" %s -k\n"), progname);
52 static void create_daemon(void)
61 } else if (pid != 0) {
68 open("/dev/null", O_RDWR);
69 open("/dev/null", O_RDWR);
70 open("/dev/null", O_RDWR);
75 (void) setreuid(euid, euid);
78 static int read_all(int fd, char *buf, size_t count)
83 memset(buf, 0, count);
85 ret = read(fd, buf, count);
87 if ((errno == EAGAIN) || (errno == EINTR))
98 static const char *cleanup_pidfile, *cleanup_socket;
100 static void terminate_intr(int signo CODE_ATTR((unused)))
102 (void) unlink(cleanup_pidfile);
104 (void) unlink(cleanup_socket);
108 static void server_loop(const char *socket_path, int debug,
109 int fd_pidfile, int timeout, int quiet)
111 struct sockaddr_un my_addr, from_addr;
112 unsigned char reply_buf[1024], *cp;
114 int32_t reply_len = 0;
118 int i, s, ns, len, num;
120 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
122 fprintf(stderr, _("Couldn't create unix stream "
123 "socket: %s"), strerror(errno));
128 * Create the address we will be binding to.
130 my_addr.sun_family = AF_UNIX;
131 strcpy(my_addr.sun_path, socket_path);
132 (void) unlink(socket_path);
133 save_umask = umask(0);
134 if (bind(s, (const struct sockaddr *) &my_addr,
135 sizeof(struct sockaddr_un)) < 0) {
138 _("Couldn't bind unix socket %s: %s\n"),
139 socket_path, strerror(errno));
142 (void) umask(save_umask);
144 if (listen(s, 5) < 0) {
146 fprintf(stderr, _("Couldn't listen on unix "
147 "socket %s: %s\n"), socket_path,
153 close(fd_pidfile); /* Unlock the pid file */
154 cleanup_socket = socket_path;
157 signal(SIGHUP, terminate_intr);
158 signal(SIGINT, terminate_intr);
159 signal(SIGTERM, terminate_intr);
160 signal(SIGALRM, terminate_intr);
161 signal(SIGPIPE, SIG_IGN);
164 fromlen = sizeof(from_addr);
167 ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
170 if ((errno == EAGAIN) || (errno == EINTR))
175 len = read(ns, &op, 1);
180 printf(_("Error reading from client, "
182 goto shutdown_socket;
184 if ((op == 4) || (op == 5)) {
185 if (read_all(ns, (char *) &num, sizeof(num)) != 4)
186 goto shutdown_socket;
188 printf(_("operation %d, incoming num = %d\n"),
191 printf("operation %d\n", op);
194 case UUIDD_OP_GETPID:
195 sprintf((char *) reply_buf, "%d", getpid());
196 reply_len = strlen((char *) reply_buf)+1;
198 case UUIDD_OP_GET_MAXOP:
199 sprintf((char *) reply_buf, "%d", UUIDD_MAX_OP);
200 reply_len = strlen((char *) reply_buf)+1;
202 case UUIDD_OP_TIME_UUID:
204 uuid__generate_time(uu, &num);
206 uuid_unparse(uu, str);
207 printf(_("Generated time UUID: %s\n"), str);
209 memcpy(reply_buf, uu, sizeof(uu));
210 reply_len = sizeof(uu);
212 case UUIDD_OP_RANDOM_UUID:
214 uuid__generate_random(uu, &num);
216 uuid_unparse(uu, str);
217 printf(_("Generated random UUID: %s\n"), str);
219 memcpy(reply_buf, uu, sizeof(uu));
220 reply_len = sizeof(uu);
222 case UUIDD_OP_BULK_TIME_UUID:
223 uuid__generate_time(uu, &num);
225 uuid_unparse(uu, str);
226 printf(_("Generated time UUID %s and %d "
227 "following\n"), str, num);
229 memcpy(reply_buf, uu, sizeof(uu));
230 reply_len = sizeof(uu);
231 memcpy(reply_buf+reply_len, &num, sizeof(num));
232 reply_len += sizeof(num);
234 case UUIDD_OP_BULK_RANDOM_UUID:
239 if (num*16 > (int) (sizeof(reply_buf)-sizeof(num)))
240 num = (sizeof(reply_buf)-sizeof(num)) / 16;
241 uuid__generate_random(reply_buf+sizeof(num), &num);
243 printf(_("Generated %d UUID's:\n"), num);
244 for (i=0, cp=reply_buf+sizeof(num);
245 i < num; i++, cp+=16) {
246 uuid_unparse(cp, str);
247 printf("\t%s\n", str);
250 reply_len = (num*16) + sizeof(num);
251 memcpy(reply_buf, &num, sizeof(num));
255 printf(_("Invalid operation %d\n"), op);
256 goto shutdown_socket;
258 write(ns, &reply_len, sizeof(reply_len));
259 write(ns, reply_buf, reply_len);
265 static int call_daemon(const char *socket_path, int op, char *buf,
266 int buflen, int *num, const char **err_context)
272 int32_t reply_len = 0;
273 struct sockaddr_un srv_addr;
275 if (((op == 4) || (op == 5)) && !num) {
277 *err_context = _("bad arguments");
282 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
284 *err_context = _("socket");
288 srv_addr.sun_family = AF_UNIX;
289 strcpy(srv_addr.sun_path, socket_path);
291 if (connect(s, (const struct sockaddr *) &srv_addr,
292 sizeof(struct sockaddr_un)) < 0) {
294 *err_context = _("connect");
300 if ((*num)*16 > buflen-4)
301 *num = (buflen-4) / 16;
305 if ((op == 4) || (op == 5)) {
306 memcpy(op_buf+1, num, sizeof(int));
307 op_len += sizeof(int);
310 ret = write(s, op_buf, op_len);
313 *err_context = _("write");
318 ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
321 *err_context = _("read count");
325 if (reply_len < 0 || reply_len > buflen) {
327 *err_context = _("bad response length");
331 ret = read_all(s, (char *) buf, reply_len);
333 if ((ret > 0) && (op == 4)) {
334 if (reply_len >= (int) (16+sizeof(int)))
335 memcpy(buf+16, num, sizeof(int));
339 if ((ret > 0) && (op == 5)) {
340 if (*num >= (int) sizeof(int))
341 memcpy(buf, num, sizeof(int));
351 static int create_pidfile(const char *socket_path, const char *pidfile_path,
357 fd = open(pidfile_path, O_CREAT | O_RDWR, 0664);
360 fprintf(stderr, "Failed to open/create %s: %s\n",
361 pidfile_path, strerror(errno));
364 cleanup_pidfile = pidfile_path;
366 signal(SIGALRM, terminate_intr);
368 if (lockf(fd, F_LOCK, 0) < 0) {
370 fprintf(stderr, "Failed to lock %s: %s\n",
371 pidfile_path, strerror(errno));
374 ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
377 printf(_("uuidd daemon already running at pid %s\n"),
383 sprintf(buf, "%d\n", getpid());
385 write(fd, buf, strlen(buf));
389 int main(int argc, char **argv)
391 const char *socket_path = UUIDD_SOCKET_PATH;
392 const char *pidfile_path = UUIDD_PIDFILE_PATH;
393 const char *err_context;
399 int i, c, ret, fd_pidfile = -1;
400 int debug = 0, do_type = 0, do_kill = 0, num = 0;
401 int timeout = 0, quiet = 0, drop_privs = 0;
404 setlocale(LC_MESSAGES, "");
405 setlocale(LC_CTYPE, "");
406 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
407 textdomain(NLS_CAT_NAME);
410 while ((c = getopt (argc, argv, "dkn:qp:s:tT:r")) != EOF) {
421 num = strtol(optarg, &tmp, 0);
422 if ((num < 0) || *tmp) {
423 fprintf(stderr, _("Bad number: %s\n"), optarg);
427 pidfile_path = optarg;
434 socket_path = optarg;
438 do_type = UUIDD_OP_TIME_UUID;
442 timeout = strtol(optarg, &tmp, 0);
443 if ((timeout < 0) || *tmp) {
444 fprintf(stderr, _("Bad number: %s\n"), optarg);
449 do_type = UUIDD_OP_RANDOM_UUID;
457 if (uid && drop_privs) {
459 #ifdef HAVE_SETRESUID
460 setresuid(uid, uid, uid);
464 #ifdef HAVE_SETRESGID
465 setresgid(gid, gid, gid);
470 if (num && do_type) {
471 ret = call_daemon(socket_path, do_type+2, buf,
472 sizeof(buf), &num, &err_context);
474 printf(_("Error calling uuidd daemon (%s): %s\n"),
475 err_context, strerror(errno));
478 if (do_type == UUIDD_OP_TIME_UUID) {
479 if (ret != sizeof(uu) + sizeof(num))
480 goto unexpected_size;
482 uuid_unparse((unsigned char *) buf, str);
484 printf(_("%s and subsequent %d UUID's\n"), str, num);
486 printf(_("List of UUID's:\n"));
488 if (ret != (int) (sizeof(num) + num*sizeof(uu)))
489 goto unexpected_size;
490 for (i=0; i < num; i++, cp+=16) {
491 uuid_unparse((unsigned char *) cp, str);
492 printf("\t%s\n", str);
498 ret = call_daemon(socket_path, do_type, (char *) &uu,
499 sizeof(uu), 0, &err_context);
501 printf(_("Error calling uuidd daemon (%s): %s\n"),
502 err_context, strerror(errno));
505 if (ret != sizeof(uu)) {
507 printf(_("Unexpected reply length from server %d\n"),
511 uuid_unparse(uu, str);
518 ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
519 if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
520 ret = kill(do_kill, SIGTERM);
524 _("Couldn't kill uuidd running "
525 "at pid %d: %s\n"), do_kill,
530 printf(_("Killed uuidd running at pid %d\n"),
536 fd_pidfile = create_pidfile(socket_path, pidfile_path, quiet);
538 server_loop(socket_path, debug, fd_pidfile, timeout, quiet);