]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/uuidd.c
feb0a0a663d69b639e55b680f108c545dbffcf3b
[thirdparty/util-linux.git] / misc-utils / uuidd.c
1 /*
2 * uuidd.c --- UUID-generation daemon
3 *
4 * Copyright (C) 2007 Theodore Ts'o
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <inttypes.h>
15 #include <errno.h>
16 #include <err.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <fcntl.h>
22 #include <signal.h>
23 #include <string.h>
24 #include <getopt.h>
25 #include <sys/signalfd.h>
26 #include <poll.h>
27
28 #include "uuid.h"
29 #include "uuidd.h"
30 #include "all-io.h"
31 #include "c.h"
32 #include "closestream.h"
33 #include "strutils.h"
34 #include "optutils.h"
35 #include "monotonic.h"
36 #include "timer.h"
37
38 #ifdef HAVE_LIBSYSTEMD
39 # include <systemd/sd-daemon.h>
40 #endif
41
42 #include "nls.h"
43
44 #ifdef __GNUC__
45 #define CODE_ATTR(x) __attribute__(x)
46 #else
47 #define CODE_ATTR(x)
48 #endif
49
50 /* length of textual representation of UUID, including trailing \0 */
51 #define UUID_STR_LEN 37
52
53 /* length of binary representation of UUID */
54 #define UUID_LEN (sizeof(uuid_t))
55
56 /* server loop control structure */
57 struct uuidd_cxt_t {
58 const char *cleanup_pidfile;
59 const char *cleanup_socket;
60 uint32_t timeout;
61 unsigned int debug: 1,
62 quiet: 1,
63 no_fork: 1,
64 no_sock: 1;
65 };
66
67 static void __attribute__ ((__noreturn__)) usage(FILE * out)
68 {
69 fputs(USAGE_HEADER, out);
70 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
71 fputs(USAGE_SEPARATOR, out);
72 fputs(_("A daemon for generating UUIDs.\n"), out);
73 fputs(USAGE_OPTIONS, out);
74 fputs(_(" -p, --pid <path> path to pid file\n"), out);
75 fputs(_(" -s, --socket <path> path to socket\n"), out);
76 fputs(_(" -T, --timeout <sec> specify inactivity timeout\n"), out);
77 fputs(_(" -k, --kill kill running daemon\n"), out);
78 fputs(_(" -r, --random test random-based generation\n"), out);
79 fputs(_(" -t, --time test time-based generation\n"), out);
80 fputs(_(" -n, --uuids <num> request number of uuids\n"), out);
81 fputs(_(" -P, --no-pid do not create pid file\n"), out);
82 fputs(_(" -F, --no-fork do not daemonize using double-fork\n"), out);
83 fputs(_(" -S, --socket-activation do not create listening socket\n"), out);
84 fputs(_(" -d, --debug run in debugging mode\n"), out);
85 fputs(_(" -q, --quiet turn on quiet mode\n"), out);
86 fputs(USAGE_SEPARATOR, out);
87 fputs(USAGE_HELP, out);
88 fputs(USAGE_VERSION, out);
89 fprintf(out, USAGE_MAN_TAIL("uuidd(8)"));
90 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
91 }
92
93 static void create_daemon(void)
94 {
95 uid_t euid;
96
97 if (daemon(0, 0))
98 err(EXIT_FAILURE, "daemon");
99
100 euid = geteuid();
101 if (setreuid(euid, euid) < 0)
102 err(EXIT_FAILURE, "setreuid");
103 }
104
105 static int call_daemon(const char *socket_path, int op, char *buf,
106 size_t buflen, int *num, const char **err_context)
107 {
108 char op_buf[8];
109 int op_len;
110 int s;
111 ssize_t ret;
112 int32_t reply_len = 0;
113 struct sockaddr_un srv_addr;
114
115 if (((op == UUIDD_OP_BULK_TIME_UUID) ||
116 (op == UUIDD_OP_BULK_RANDOM_UUID)) && !num) {
117 if (err_context)
118 *err_context = _("bad arguments");
119 errno = EINVAL;
120 return -1;
121 }
122
123 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
124 if (err_context)
125 *err_context = _("socket");
126 return -1;
127 }
128
129 srv_addr.sun_family = AF_UNIX;
130 strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
131 srv_addr.sun_path[sizeof(srv_addr.sun_path) - 1] = '\0';
132
133 if (connect(s, (const struct sockaddr *) &srv_addr,
134 sizeof(struct sockaddr_un)) < 0) {
135 if (err_context)
136 *err_context = _("connect");
137 close(s);
138 return -1;
139 }
140
141 if (op == UUIDD_OP_BULK_RANDOM_UUID) {
142 if ((*num) * UUID_LEN > buflen - 4)
143 *num = (buflen - 4) / UUID_LEN;
144 }
145 op_buf[0] = op;
146 op_len = 1;
147 if ((op == UUIDD_OP_BULK_TIME_UUID) ||
148 (op == UUIDD_OP_BULK_RANDOM_UUID)) {
149 memcpy(op_buf + 1, num, sizeof(int));
150 op_len += sizeof(int);
151 }
152
153 ret = write_all(s, op_buf, op_len);
154 if (ret < 0) {
155 if (err_context)
156 *err_context = _("write");
157 close(s);
158 return -1;
159 }
160
161 ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
162 if (ret < 0) {
163 if (err_context)
164 *err_context = _("read count");
165 close(s);
166 return -1;
167 }
168 if (reply_len < 0 || (size_t) reply_len > buflen) {
169 if (err_context)
170 *err_context = _("bad response length");
171 close(s);
172 return -1;
173 }
174 ret = read_all(s, (char *) buf, reply_len);
175
176 if ((ret > 0) && (op == UUIDD_OP_BULK_TIME_UUID)) {
177 if (reply_len >= (int) (UUID_LEN + sizeof(int)))
178 memcpy(buf + UUID_LEN, num, sizeof(int));
179 else
180 *num = -1;
181 }
182 if ((ret > 0) && (op == UUIDD_OP_BULK_RANDOM_UUID)) {
183 if (reply_len >= (int) sizeof(int))
184 memcpy(buf, num, sizeof(int));
185 else
186 *num = -1;
187 }
188
189 close(s);
190
191 return ret;
192 }
193
194 /*
195 * Exclusively create and open a pid file with path @pidfile_path
196 *
197 * Return file descriptor of the created pid_file.
198 */
199 static int create_pidfile(struct uuidd_cxt_t *cxt, const char *pidfile_path)
200 {
201 int fd_pidfile;
202 struct flock fl;
203
204 fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
205 if (fd_pidfile < 0) {
206 if (!cxt->quiet)
207 warn(_("cannot open %s"), pidfile_path);
208 exit(EXIT_FAILURE);
209 }
210 cxt->cleanup_pidfile = pidfile_path;
211
212 fl.l_type = F_WRLCK;
213 fl.l_whence = SEEK_SET;
214 fl.l_start = 0;
215 fl.l_len = 0;
216 fl.l_pid = 0;
217 while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
218 if ((errno == EAGAIN) || (errno == EINTR))
219 continue;
220 if (!cxt->quiet)
221 warn(_("cannot lock %s"), pidfile_path);
222 exit(EXIT_FAILURE);
223 }
224
225 return fd_pidfile;
226 }
227
228 /*
229 * Create AF_UNIX, SOCK_STREAM socket and bind to @socket_path
230 *
231 * If @will_fork is true, then make sure the descriptor
232 * of the socket is >2, so that it won't be later closed
233 * during create_daemon().
234 *
235 * Return file descriptor corresponding to created socket.
236 */
237 static int create_socket(struct uuidd_cxt_t *uuidd_cxt,
238 const char *socket_path, int will_fork)
239 {
240 struct sockaddr_un my_addr;
241 mode_t save_umask;
242 int s;
243
244 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
245 if (!uuidd_cxt->quiet)
246 warn(_("couldn't create unix stream socket"));
247 exit(EXIT_FAILURE);
248 }
249
250 /*
251 * Make sure the socket isn't using fd numbers 0-2 to avoid it
252 * getting closed by create_daemon()
253 */
254 while (will_fork && s <= 2) {
255 s = dup(s);
256 if (s < 0)
257 err(EXIT_FAILURE, "dup");
258 }
259
260 /*
261 * Create the address we will be binding to.
262 */
263 my_addr.sun_family = AF_UNIX;
264 strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
265 my_addr.sun_path[sizeof(my_addr.sun_path) - 1] = '\0';
266 unlink(socket_path);
267 save_umask = umask(0);
268 if (bind(s, (const struct sockaddr *) &my_addr,
269 sizeof(struct sockaddr_un)) < 0) {
270 if (!uuidd_cxt->quiet)
271 warn(_("couldn't bind unix socket %s"), socket_path);
272 exit(EXIT_FAILURE);
273 }
274 umask(save_umask);
275 uuidd_cxt->cleanup_socket = socket_path;
276
277 return s;
278 }
279
280 static void __attribute__((__noreturn__)) all_done(const struct uuidd_cxt_t *uuidd_cxt, int ret)
281 {
282 if (uuidd_cxt->cleanup_pidfile)
283 unlink(uuidd_cxt->cleanup_pidfile);
284 if (uuidd_cxt->cleanup_socket)
285 unlink(uuidd_cxt->cleanup_socket);
286 exit(ret);
287 }
288
289 static void handle_signal(const struct uuidd_cxt_t *uuidd_cxt, int fd)
290 {
291 struct signalfd_siginfo info;
292 ssize_t bytes;
293
294 bytes = read(fd, &info, sizeof(info));
295 if (bytes != sizeof(info)) {
296 if (errno == EAGAIN)
297 return;
298 warn(_("receiving signal failed"));
299 info.ssi_signo = 0;
300 }
301 if (info.ssi_signo == SIGPIPE)
302 return; /* ignored */
303 all_done(uuidd_cxt, EXIT_SUCCESS);
304 }
305
306 static void timeout_handler(int sig __attribute__((__unused__)),
307 siginfo_t * info,
308 void *context __attribute__((__unused__)))
309 {
310 if (info->si_code == SI_TIMER)
311 errx(EXIT_FAILURE, _("timed out"));
312 }
313
314 static void server_loop(const char *socket_path, const char *pidfile_path,
315 struct uuidd_cxt_t *uuidd_cxt)
316 {
317 struct sockaddr_un from_addr;
318 socklen_t fromlen;
319 int32_t reply_len = 0;
320 uuid_t uu;
321 char reply_buf[1024], *cp;
322 char op, str[UUID_STR_LEN];
323 int i, ns, len, num;
324 int s = 0;
325 int fd_pidfile = -1;
326 int ret;
327 struct pollfd pfd[2];
328 sigset_t sigmask;
329 int sigfd;
330 enum {
331 POLLFD_SIGNAL = 0,
332 POLLFD_SOCKET
333 };
334
335 #ifdef HAVE_LIBSYSTEMD
336 if (!uuidd_cxt->no_sock) /* no_sock implies no_fork and no_pid */
337 #endif
338 {
339 static timer_t t_id;
340 struct itimerval timeout;
341
342 memset(&timeout, 0, sizeof timeout);
343 timeout.it_value.tv_sec = 30;
344 if (setup_timer(&t_id, &timeout, &timeout_handler))
345 err(EXIT_FAILURE, _("cannot set up timer"));
346 if (pidfile_path)
347 fd_pidfile = create_pidfile(uuidd_cxt, pidfile_path);
348 ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
349 sizeof(reply_buf), 0, NULL);
350 cancel_timer(&t_id);
351 if (ret > 0) {
352 if (!uuidd_cxt->quiet)
353 warnx(_("uuidd daemon is already running at pid %s"),
354 reply_buf);
355 exit(EXIT_FAILURE);
356 }
357
358 s = create_socket(uuidd_cxt, socket_path,
359 (!uuidd_cxt->debug || !uuidd_cxt->no_fork));
360 if (listen(s, SOMAXCONN) < 0) {
361 if (!uuidd_cxt->quiet)
362 warn(_("couldn't listen on unix socket %s"), socket_path);
363 exit(EXIT_FAILURE);
364 }
365
366 if (!uuidd_cxt->debug && !uuidd_cxt->no_fork)
367 create_daemon();
368
369 if (pidfile_path) {
370 sprintf(reply_buf, "%8d\n", getpid());
371 if (ftruncate(fd_pidfile, 0))
372 err(EXIT_FAILURE, _("could not truncate file: %s"), pidfile_path);
373 write_all(fd_pidfile, reply_buf, strlen(reply_buf));
374 if (fd_pidfile > 1)
375 if (close_fd(fd_pidfile) != 0) /* Unlock the pid file */
376 err(EXIT_FAILURE, _("write failed: %s"), pidfile_path);
377 }
378
379 }
380
381 #ifdef HAVE_LIBSYSTEMD
382 if (uuidd_cxt->no_sock) {
383 const int r = sd_listen_fds(0);
384
385 if (r < 0) {
386 errno = r * -1;
387 err(EXIT_FAILURE, _("sd_listen_fds() failed"));
388 } else if (r == 0)
389 errx(EXIT_FAILURE,
390 _("no file descriptors received, check systemctl status uuidd.socket"));
391 else if (1 < r)
392 errx(EXIT_FAILURE,
393 _("too many file descriptors received, check uuidd.socket"));
394 s = SD_LISTEN_FDS_START + 0;
395 }
396 #endif
397
398 sigemptyset(&sigmask);
399 sigaddset(&sigmask, SIGHUP);
400 sigaddset(&sigmask, SIGINT);
401 sigaddset(&sigmask, SIGTERM);
402 sigaddset(&sigmask, SIGALRM);
403 sigaddset(&sigmask, SIGPIPE);
404 /* Block signals so that they aren't handled according to their
405 * default dispositions */
406 sigprocmask(SIG_BLOCK, &sigmask, NULL);
407 if ((sigfd = signalfd(-1, &sigmask, 0)) < 0)
408 err(EXIT_FAILURE, _("cannot set signal handler"));
409
410 pfd[POLLFD_SIGNAL].fd = sigfd;
411 pfd[POLLFD_SOCKET].fd = s;
412 pfd[POLLFD_SIGNAL].events = pfd[POLLFD_SOCKET].events = POLLIN | POLLERR | POLLHUP;
413
414 while (1) {
415 ret = poll(pfd, ARRAY_SIZE(pfd),
416 uuidd_cxt->timeout ?
417 (int) uuidd_cxt->timeout * 1000 : -1);
418 if (ret < 0) {
419 if (errno == EAGAIN)
420 continue;
421 warn(_("poll failed"));
422 all_done(uuidd_cxt, EXIT_FAILURE);
423 }
424 if (ret == 0) { /* truen when poll() times out */
425 if (uuidd_cxt->debug)
426 fprintf(stderr, _("timeout [%d sec]\n"), uuidd_cxt->timeout),
427 all_done(uuidd_cxt, EXIT_SUCCESS);
428 }
429 if (pfd[POLLFD_SIGNAL].revents != 0)
430 handle_signal(uuidd_cxt, sigfd);
431 if (pfd[POLLFD_SOCKET].revents == 0)
432 continue;
433 fromlen = sizeof(from_addr);
434 ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
435 if (ns < 0) {
436 if ((errno == EAGAIN) || (errno == EINTR))
437 continue;
438 else
439 err(EXIT_FAILURE, "accept");
440 }
441 len = read(ns, &op, 1);
442 if (len != 1) {
443 if (len < 0)
444 warn(_("read failed"));
445 else
446 warnx(_("error reading from client, len = %d"),
447 len);
448 goto shutdown_socket;
449 }
450 if ((op == UUIDD_OP_BULK_TIME_UUID) ||
451 (op == UUIDD_OP_BULK_RANDOM_UUID)) {
452 if (read_all(ns, (char *) &num, sizeof(num)) != 4)
453 goto shutdown_socket;
454 if (uuidd_cxt->debug)
455 fprintf(stderr, _("operation %d, incoming num = %d\n"),
456 op, num);
457 } else if (uuidd_cxt->debug)
458 fprintf(stderr, _("operation %d\n"), op);
459
460 switch (op) {
461 case UUIDD_OP_GETPID:
462 sprintf(reply_buf, "%d", getpid());
463 reply_len = strlen(reply_buf) + 1;
464 break;
465 case UUIDD_OP_GET_MAXOP:
466 sprintf(reply_buf, "%d", UUIDD_MAX_OP);
467 reply_len = strlen(reply_buf) + 1;
468 break;
469 case UUIDD_OP_TIME_UUID:
470 num = 1;
471 __uuid_generate_time(uu, &num);
472 if (uuidd_cxt->debug) {
473 uuid_unparse(uu, str);
474 fprintf(stderr, _("Generated time UUID: %s\n"), str);
475 }
476 memcpy(reply_buf, uu, sizeof(uu));
477 reply_len = sizeof(uu);
478 break;
479 case UUIDD_OP_RANDOM_UUID:
480 num = 1;
481 __uuid_generate_random(uu, &num);
482 if (uuidd_cxt->debug) {
483 uuid_unparse(uu, str);
484 fprintf(stderr, _("Generated random UUID: %s\n"), str);
485 }
486 memcpy(reply_buf, uu, sizeof(uu));
487 reply_len = sizeof(uu);
488 break;
489 case UUIDD_OP_BULK_TIME_UUID:
490 __uuid_generate_time(uu, &num);
491 if (uuidd_cxt->debug) {
492 uuid_unparse(uu, str);
493 fprintf(stderr, P_("Generated time UUID %s "
494 "and %d following\n",
495 "Generated time UUID %s "
496 "and %d following\n", num - 1),
497 str, num - 1);
498 }
499 memcpy(reply_buf, uu, sizeof(uu));
500 reply_len = sizeof(uu);
501 memcpy(reply_buf + reply_len, &num, sizeof(num));
502 reply_len += sizeof(num);
503 break;
504 case UUIDD_OP_BULK_RANDOM_UUID:
505 if (num < 0)
506 num = 1;
507 if (num > 1000)
508 num = 1000;
509 if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
510 num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
511 __uuid_generate_random((unsigned char *) reply_buf +
512 sizeof(num), &num);
513 if (uuidd_cxt->debug) {
514 fprintf(stderr, P_("Generated %d UUID:\n",
515 "Generated %d UUIDs:\n", num), num);
516 for (i = 0, cp = reply_buf + sizeof(num);
517 i < num;
518 i++, cp += UUID_LEN) {
519 uuid_unparse((unsigned char *)cp, str);
520 fprintf(stderr, "\t%s\n", str);
521 }
522 }
523 reply_len = (num * UUID_LEN) + sizeof(num);
524 memcpy(reply_buf, &num, sizeof(num));
525 break;
526 default:
527 if (uuidd_cxt->debug)
528 fprintf(stderr, _("Invalid operation %d\n"), op);
529 goto shutdown_socket;
530 }
531 write_all(ns, (char *) &reply_len, sizeof(reply_len));
532 write_all(ns, reply_buf, reply_len);
533 shutdown_socket:
534 close(ns);
535 }
536 }
537
538 static void __attribute__ ((__noreturn__)) unexpected_size(int size)
539 {
540 errx(EXIT_FAILURE, _("Unexpected reply length from server %d"), size);
541 }
542
543 int main(int argc, char **argv)
544 {
545 const char *socket_path = UUIDD_SOCKET_PATH;
546 const char *pidfile_path = NULL;
547 const char *pidfile_path_param = NULL;
548 const char *err_context = NULL;
549 char buf[1024], *cp;
550 char str[UUID_STR_LEN];
551 uuid_t uu;
552 int i, c, ret;
553 int do_type = 0, do_kill = 0, num = 0;
554 int no_pid = 0;
555 int s_flag = 0;
556
557 struct uuidd_cxt_t uuidd_cxt = { .timeout = 0 };
558
559 static const struct option longopts[] = {
560 {"pid", required_argument, NULL, 'p'},
561 {"socket", required_argument, NULL, 's'},
562 {"timeout", required_argument, NULL, 'T'},
563 {"kill", no_argument, NULL, 'k'},
564 {"random", no_argument, NULL, 'r'},
565 {"time", no_argument, NULL, 't'},
566 {"uuids", required_argument, NULL, 'n'},
567 {"no-pid", no_argument, NULL, 'P'},
568 {"no-fork", no_argument, NULL, 'F'},
569 {"socket-activation", no_argument, NULL, 'S'},
570 {"debug", no_argument, NULL, 'd'},
571 {"quiet", no_argument, NULL, 'q'},
572 {"version", no_argument, NULL, 'V'},
573 {"help", no_argument, NULL, 'h'},
574 {NULL, 0, NULL, 0}
575 };
576 static const ul_excl_t excl[] = {
577 { 'P', 'p' },
578 { 'd', 'q' },
579 { 'r', 't' },
580 { 0 }
581 };
582 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
583
584 setlocale(LC_ALL, "");
585 bindtextdomain(PACKAGE, LOCALEDIR);
586 textdomain(PACKAGE);
587 atexit(close_stdout);
588
589 while ((c =
590 getopt_long(argc, argv, "p:s:T:krtn:PFSdqVh", longopts,
591 NULL)) != -1) {
592 err_exclusive_options(c, longopts, excl, excl_st);
593 switch (c) {
594 case 'd':
595 uuidd_cxt.debug = 1;
596 break;
597 case 'k':
598 do_kill++;
599 break;
600 case 'n':
601 num = strtou32_or_err(optarg,
602 _("failed to parse --uuids"));
603 break;
604 case 'p':
605 pidfile_path_param = optarg;
606 break;
607 case 'P':
608 no_pid = 1;
609 break;
610 case 'F':
611 uuidd_cxt.no_fork = 1;
612 break;
613 case 'S':
614 #ifdef HAVE_LIBSYSTEMD
615 uuidd_cxt.no_sock = 1;
616 uuidd_cxt.no_fork = 1;
617 no_pid = 1;
618 #else
619 errx(EXIT_FAILURE, _("uuidd has been built without "
620 "support for socket activation"));
621 #endif
622 break;
623 case 'q':
624 uuidd_cxt.quiet = 1;
625 break;
626 case 'r':
627 do_type = UUIDD_OP_RANDOM_UUID;
628 break;
629 case 's':
630 socket_path = optarg;
631 s_flag = 1;
632 break;
633 case 't':
634 do_type = UUIDD_OP_TIME_UUID;
635 break;
636 case 'T':
637 uuidd_cxt.timeout = strtou32_or_err(optarg,
638 _("failed to parse --timeout"));
639 break;
640 case 'V':
641 printf(UTIL_LINUX_VERSION);
642 return EXIT_SUCCESS;
643 case 'h':
644 usage(stdout);
645 default:
646 usage(stderr);
647 }
648 }
649
650 if (!no_pid && !pidfile_path_param)
651 pidfile_path = UUIDD_PIDFILE_PATH;
652 else if (pidfile_path_param)
653 pidfile_path = pidfile_path_param;
654
655 /* custom socket path and socket-activation make no sense */
656 if (s_flag && uuidd_cxt.no_sock && !uuidd_cxt.quiet)
657 warnx(_("Both --socket-activation and --socket specified. "
658 "Ignoring --socket."));
659
660 if (num && do_type) {
661 ret = call_daemon(socket_path, do_type + 2, buf,
662 sizeof(buf), &num, &err_context);
663 if (ret < 0)
664 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
665 err_context ? : _("unexpected error"));
666
667 if (do_type == UUIDD_OP_TIME_UUID) {
668 if (ret != sizeof(uu) + sizeof(num))
669 unexpected_size(ret);
670
671 uuid_unparse((unsigned char *) buf, str);
672
673 printf(P_("%s and %d subsequent UUID\n",
674 "%s and %d subsequent UUIDs\n", num - 1),
675 str, num - 1);
676 } else {
677 printf(_("List of UUIDs:\n"));
678 cp = buf + 4;
679 if (ret != (int) (sizeof(num) + num * sizeof(uu)))
680 unexpected_size(ret);
681 for (i = 0; i < num; i++, cp += UUID_LEN) {
682 uuid_unparse((unsigned char *) cp, str);
683 printf("\t%s\n", str);
684 }
685 }
686 return EXIT_SUCCESS;
687 }
688 if (do_type) {
689 ret = call_daemon(socket_path, do_type, (char *) &uu,
690 sizeof(uu), 0, &err_context);
691 if (ret < 0)
692 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
693 err_context ? : _("unexpected error"));
694 if (ret != sizeof(uu))
695 unexpected_size(ret);
696
697 uuid_unparse(uu, str);
698
699 printf("%s\n", str);
700 return EXIT_SUCCESS;
701 }
702
703 if (do_kill) {
704 ret = call_daemon(socket_path, UUIDD_OP_GETPID, buf, sizeof(buf), 0, NULL);
705 if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
706 ret = kill(do_kill, SIGTERM);
707 if (ret < 0) {
708 if (!uuidd_cxt.quiet)
709 warn(_("couldn't kill uuidd running "
710 "at pid %d"), do_kill);
711 return EXIT_FAILURE;
712 }
713 if (!uuidd_cxt.quiet)
714 printf(_("Killed uuidd running at pid %d.\n"),
715 do_kill);
716 }
717 return EXIT_SUCCESS;
718 }
719
720 server_loop(socket_path, pidfile_path, &uuidd_cxt);
721 return EXIT_SUCCESS;
722 }