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
12 #define _GNU_SOURCE /* for setres[ug]id() */
21 #include <sys/types.h>
23 #include <sys/socket.h>
31 extern int getopt(int argc, char * const argv[], const char *optstring);
35 #include "uuid/uuid.h"
36 #include "uuid/uuidd.h"
37 #include "nls-enable.h"
40 #define CODE_ATTR(x) __attribute__(x)
45 static void usage(const char *progname)
47 fprintf(stderr, _("Usage: %s [-d] [-p pidfile] [-s socketpath] "
48 "[-T timeout]\n"), progname);
49 fprintf(stderr, _(" %s [-r|t] [-n num] [-s socketpath]\n"),
51 fprintf(stderr, _(" %s -k\n"), progname);
55 static void die(const char *msg)
61 static void create_daemon(void)
70 } else if (pid != 0) {
77 open("/dev/null", O_RDWR);
78 open("/dev/null", O_RDWR);
79 open("/dev/null", O_RDWR);
84 if (setreuid(euid, euid) < 0)
88 static int read_all(int fd, char *buf, size_t count)
93 memset(buf, 0, count);
95 ret = read(fd, buf, count);
97 if ((errno == EAGAIN) || (errno == EINTR))
108 static const char *cleanup_pidfile, *cleanup_socket;
110 static void terminate_intr(int signo CODE_ATTR((unused)))
112 (void) unlink(cleanup_pidfile);
114 (void) unlink(cleanup_socket);
118 static int call_daemon(const char *socket_path, int op, char *buf,
119 int buflen, int *num, const char **err_context)
125 int32_t reply_len = 0;
126 struct sockaddr_un srv_addr;
128 if (((op == 4) || (op == 5)) && !num) {
130 *err_context = _("bad arguments");
135 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
137 *err_context = _("socket");
141 srv_addr.sun_family = AF_UNIX;
142 strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
143 srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';
145 if (connect(s, (const struct sockaddr *) &srv_addr,
146 sizeof(struct sockaddr_un)) < 0) {
148 *err_context = _("connect");
154 if ((*num)*16 > buflen-4)
155 *num = (buflen-4) / 16;
159 if ((op == 4) || (op == 5)) {
160 memcpy(op_buf+1, num, sizeof(int));
161 op_len += sizeof(int);
164 ret = write(s, op_buf, op_len);
167 *err_context = _("write");
172 ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
175 *err_context = _("read count");
179 if (reply_len < 0 || reply_len > buflen) {
181 *err_context = _("bad response length");
185 ret = read_all(s, (char *) buf, reply_len);
187 if ((ret > 0) && (op == 4)) {
188 if (reply_len >= (int) (16+sizeof(int)))
189 memcpy(buf+16, num, sizeof(int));
193 if ((ret > 0) && (op == 5)) {
194 if (*num >= (int) sizeof(int))
195 memcpy(buf, num, sizeof(int));
205 static void server_loop(const char *socket_path, const char *pidfile_path,
206 int debug, int timeout, int quiet)
208 struct sockaddr_un my_addr, from_addr;
211 int32_t reply_len = 0;
214 char reply_buf[1024], *cp;
216 int i, s, ns, len, num;
219 fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
220 if (fd_pidfile < 0) {
222 fprintf(stderr, "Failed to open/create %s: %s\n",
223 pidfile_path, strerror(errno));
226 cleanup_pidfile = pidfile_path;
228 signal(SIGALRM, terminate_intr);
231 fl.l_whence = SEEK_SET;
235 while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
236 if ((errno == EAGAIN) || (errno == EINTR))
239 fprintf(stderr, "Failed to lock %s: %s\n",
240 pidfile_path, strerror(errno));
243 ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
246 printf(_("uuidd daemon already running at pid %s\n"),
252 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
254 fprintf(stderr, _("Couldn't create unix stream "
255 "socket: %s"), strerror(errno));
260 * Create the address we will be binding to.
262 my_addr.sun_family = AF_UNIX;
263 strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
264 my_addr.sun_path[sizeof(my_addr.sun_path)-1] = '\0';
265 (void) unlink(socket_path);
266 save_umask = umask(0);
267 if (bind(s, (const struct sockaddr *) &my_addr,
268 sizeof(struct sockaddr_un)) < 0) {
271 _("Couldn't bind unix socket %s: %s\n"),
272 socket_path, strerror(errno));
275 (void) umask(save_umask);
277 if (listen(s, 5) < 0) {
279 fprintf(stderr, _("Couldn't listen on unix "
280 "socket %s: %s\n"), socket_path,
285 cleanup_socket = socket_path;
288 signal(SIGHUP, terminate_intr);
289 signal(SIGINT, terminate_intr);
290 signal(SIGTERM, terminate_intr);
291 signal(SIGALRM, terminate_intr);
292 signal(SIGPIPE, SIG_IGN);
294 sprintf(reply_buf, "%d\n", getpid());
295 ftruncate(fd_pidfile, 0);
296 write(fd_pidfile, reply_buf, strlen(reply_buf));
298 close(fd_pidfile); /* Unlock the pid file */
301 fromlen = sizeof(from_addr);
304 ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
307 if ((errno == EAGAIN) || (errno == EINTR))
312 len = read(ns, &op, 1);
317 printf(_("Error reading from client, "
319 goto shutdown_socket;
321 if ((op == 4) || (op == 5)) {
322 if (read_all(ns, (char *) &num, sizeof(num)) != 4)
323 goto shutdown_socket;
325 printf(_("operation %d, incoming num = %d\n"),
328 printf("operation %d\n", op);
331 case UUIDD_OP_GETPID:
332 sprintf(reply_buf, "%d", getpid());
333 reply_len = strlen(reply_buf)+1;
335 case UUIDD_OP_GET_MAXOP:
336 sprintf(reply_buf, "%d", UUIDD_MAX_OP);
337 reply_len = strlen(reply_buf)+1;
339 case UUIDD_OP_TIME_UUID:
341 uuid__generate_time(uu, &num);
343 uuid_unparse(uu, str);
344 printf(_("Generated time UUID: %s\n"), str);
346 memcpy(reply_buf, uu, sizeof(uu));
347 reply_len = sizeof(uu);
349 case UUIDD_OP_RANDOM_UUID:
351 uuid__generate_random(uu, &num);
353 uuid_unparse(uu, str);
354 printf(_("Generated random UUID: %s\n"), str);
356 memcpy(reply_buf, uu, sizeof(uu));
357 reply_len = sizeof(uu);
359 case UUIDD_OP_BULK_TIME_UUID:
360 uuid__generate_time(uu, &num);
362 uuid_unparse(uu, str);
363 printf(_("Generated time UUID %s and %d "
364 "following\n"), str, num);
366 memcpy(reply_buf, uu, sizeof(uu));
367 reply_len = sizeof(uu);
368 memcpy(reply_buf+reply_len, &num, sizeof(num));
369 reply_len += sizeof(num);
371 case UUIDD_OP_BULK_RANDOM_UUID:
376 if (num*16 > (int) (sizeof(reply_buf)-sizeof(num)))
377 num = (sizeof(reply_buf)-sizeof(num)) / 16;
378 uuid__generate_random((unsigned char *) reply_buf +
381 printf(_("Generated %d UUID's:\n"), num);
382 for (i=0, cp=reply_buf+sizeof(num);
383 i < num; i++, cp+=16) {
384 uuid_unparse((unsigned char *)cp, str);
385 printf("\t%s\n", str);
388 reply_len = (num*16) + sizeof(num);
389 memcpy(reply_buf, &num, sizeof(num));
393 printf(_("Invalid operation %d\n"), op);
394 goto shutdown_socket;
396 write(ns, &reply_len, sizeof(reply_len));
397 write(ns, reply_buf, reply_len);
403 int main(int argc, char **argv)
405 const char *socket_path = UUIDD_SOCKET_PATH;
406 const char *pidfile_path = UUIDD_PIDFILE_PATH;
407 const char *err_context;
414 int debug = 0, do_type = 0, do_kill = 0, num = 0;
415 int timeout = 0, quiet = 0, drop_privs = 0;
418 setlocale(LC_MESSAGES, "");
419 setlocale(LC_CTYPE, "");
420 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
421 textdomain(NLS_CAT_NAME);
424 while ((c = getopt (argc, argv, "dkn:qp:s:tT:r")) != EOF) {
435 num = strtol(optarg, &tmp, 0);
436 if ((num < 0) || *tmp) {
437 fprintf(stderr, _("Bad number: %s\n"), optarg);
441 pidfile_path = optarg;
448 socket_path = optarg;
452 do_type = UUIDD_OP_TIME_UUID;
456 timeout = strtol(optarg, &tmp, 0);
457 if ((timeout < 0) || *tmp) {
458 fprintf(stderr, _("Bad number: %s\n"), optarg);
463 do_type = UUIDD_OP_RANDOM_UUID;
471 if (uid && drop_privs) {
473 #ifdef HAVE_SETRESGID
474 if (setresgid(gid, gid, gid) < 0)
477 if (setregid(gid, gid) < 0)
481 #ifdef HAVE_SETRESUID
482 if (setresuid(uid, uid, uid) < 0)
485 if (setreuid(uid, uid) < 0)
489 if (num && do_type) {
490 ret = call_daemon(socket_path, do_type+2, buf,
491 sizeof(buf), &num, &err_context);
493 printf(_("Error calling uuidd daemon (%s): %s\n"),
494 err_context, strerror(errno));
497 if (do_type == UUIDD_OP_TIME_UUID) {
498 if (ret != sizeof(uu) + sizeof(num))
499 goto unexpected_size;
501 uuid_unparse((unsigned char *) buf, str);
503 printf(_("%s and subsequent %d UUID's\n"), str, num);
505 printf(_("List of UUID's:\n"));
507 if (ret != (int) (sizeof(num) + num*sizeof(uu)))
508 goto unexpected_size;
509 for (i=0; i < num; i++, cp+=16) {
510 uuid_unparse((unsigned char *) cp, str);
511 printf("\t%s\n", str);
517 ret = call_daemon(socket_path, do_type, (char *) &uu,
518 sizeof(uu), 0, &err_context);
520 printf(_("Error calling uuidd daemon (%s): %s\n"),
521 err_context, strerror(errno));
524 if (ret != sizeof(uu)) {
526 printf(_("Unexpected reply length from server %d\n"),
530 uuid_unparse(uu, str);
537 ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
538 if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
539 ret = kill(do_kill, SIGTERM);
543 _("Couldn't kill uuidd running "
544 "at pid %d: %s\n"), do_kill,
549 printf(_("Killed uuidd running at pid %d\n"),
555 server_loop(socket_path, pidfile_path, debug, timeout, quiet);