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