]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/uuidd.c
Merge branch 'meson-more-build-options' of https://github.com/jwillikers/util-linux
[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;
317 int num; /* intentionally uninitialized */
318 int s = 0;
319 int fd_pidfile = -1;
320 int ret;
321 struct pollfd pfd[2];
322 sigset_t sigmask;
323 int sigfd;
324 enum {
325 POLLFD_SIGNAL = 0,
326 POLLFD_SOCKET
327 };
328
329 #ifdef HAVE_LIBSYSTEMD
330 if (!uuidd_cxt->no_sock) /* no_sock implies no_fork and no_pid */
331 #endif
332 {
333 struct ul_timer timer;
334 struct itimerval timeout;
335
336 memset(&timeout, 0, sizeof timeout);
337 timeout.it_value.tv_sec = 30;
338 if (setup_timer(&timer, &timeout, &timeout_handler))
339 err(EXIT_FAILURE, _("cannot set up timer"));
340 if (pidfile_path)
341 fd_pidfile = create_pidfile(uuidd_cxt, pidfile_path);
342 ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
343 sizeof(reply_buf), 0, NULL);
344 cancel_timer(&timer);
345 if (ret > 0) {
346 if (!uuidd_cxt->quiet)
347 warnx(_("uuidd daemon is already running at pid %s"),
348 reply_buf);
349 exit(EXIT_FAILURE);
350 }
351
352 s = create_socket(uuidd_cxt, socket_path,
353 (!uuidd_cxt->debug || !uuidd_cxt->no_fork));
354 if (listen(s, SOMAXCONN) < 0) {
355 if (!uuidd_cxt->quiet)
356 warn(_("couldn't listen on unix socket %s"), socket_path);
357 exit(EXIT_FAILURE);
358 }
359
360 if (!uuidd_cxt->debug && !uuidd_cxt->no_fork)
361 create_daemon();
362
363 if (pidfile_path) {
364 sprintf(reply_buf, "%8d\n", getpid());
365 if (ftruncate(fd_pidfile, 0))
366 err(EXIT_FAILURE, _("could not truncate file: %s"), pidfile_path);
367 write_all(fd_pidfile, reply_buf, strlen(reply_buf));
368 if (fd_pidfile > 1 && close_fd(fd_pidfile) != 0)
369 err(EXIT_FAILURE, _("write failed: %s"), pidfile_path);
370 }
371
372 }
373
374 #ifdef HAVE_LIBSYSTEMD
375 if (uuidd_cxt->no_sock) {
376 const int r = sd_listen_fds(0);
377
378 if (r < 0) {
379 errno = r * -1;
380 err(EXIT_FAILURE, _("sd_listen_fds() failed"));
381 } else if (r == 0)
382 errx(EXIT_FAILURE,
383 _("no file descriptors received, check systemctl status uuidd.socket"));
384 else if (1 < r)
385 errx(EXIT_FAILURE,
386 _("too many file descriptors received, check uuidd.socket"));
387 s = SD_LISTEN_FDS_START + 0;
388 }
389 #endif
390
391 sigemptyset(&sigmask);
392 sigaddset(&sigmask, SIGHUP);
393 sigaddset(&sigmask, SIGINT);
394 sigaddset(&sigmask, SIGTERM);
395 sigaddset(&sigmask, SIGALRM);
396 sigaddset(&sigmask, SIGPIPE);
397 /* Block signals so that they aren't handled according to their
398 * default dispositions */
399 sigprocmask(SIG_BLOCK, &sigmask, NULL);
400 if ((sigfd = signalfd(-1, &sigmask, 0)) < 0)
401 err(EXIT_FAILURE, _("cannot set signal handler"));
402
403 pfd[POLLFD_SIGNAL].fd = sigfd;
404 pfd[POLLFD_SOCKET].fd = s;
405 pfd[POLLFD_SIGNAL].events = pfd[POLLFD_SOCKET].events = POLLIN | POLLERR | POLLHUP;
406
407 while (1) {
408 ret = poll(pfd, ARRAY_SIZE(pfd),
409 uuidd_cxt->timeout ?
410 (int) uuidd_cxt->timeout * 1000 : -1);
411 if (ret < 0) {
412 if (errno == EAGAIN)
413 continue;
414 warn(_("poll failed"));
415 all_done(uuidd_cxt, EXIT_FAILURE);
416 }
417 if (ret == 0) { /* true when poll() times out */
418 if (uuidd_cxt->debug)
419 fprintf(stderr, _("timeout [%d sec]\n"), uuidd_cxt->timeout),
420 all_done(uuidd_cxt, EXIT_SUCCESS);
421 }
422 if (pfd[POLLFD_SIGNAL].revents != 0)
423 handle_signal(uuidd_cxt, sigfd);
424 if (pfd[POLLFD_SOCKET].revents == 0)
425 continue;
426 fromlen = sizeof(from_addr);
427 ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
428 if (ns < 0) {
429 if ((errno == EAGAIN) || (errno == EINTR))
430 continue;
431 else
432 err(EXIT_FAILURE, "accept");
433 }
434 len = read(ns, &op, 1);
435 if (len != 1) {
436 if (len < 0)
437 warn(_("read failed"));
438 else
439 warnx(_("error reading from client, len = %d"),
440 len);
441 goto shutdown_socket;
442 }
443 if ((op == UUIDD_OP_BULK_TIME_UUID) ||
444 (op == UUIDD_OP_BULK_RANDOM_UUID)) {
445 if (read_all(ns, (char *) &num, sizeof(num)) != 4)
446 goto shutdown_socket;
447 if (uuidd_cxt->debug)
448 fprintf(stderr, _("operation %d, incoming num = %d\n"),
449 op, num);
450 } else if (uuidd_cxt->debug)
451 fprintf(stderr, _("operation %d\n"), op);
452
453 switch (op) {
454 case UUIDD_OP_GETPID:
455 sprintf(reply_buf, "%d", getpid());
456 reply_len = strlen(reply_buf) + 1;
457 break;
458 case UUIDD_OP_GET_MAXOP:
459 sprintf(reply_buf, "%d", UUIDD_MAX_OP);
460 reply_len = strlen(reply_buf) + 1;
461 break;
462 case UUIDD_OP_TIME_UUID:
463 num = 1;
464 __uuid_generate_time(uu, &num);
465 if (uuidd_cxt->debug) {
466 uuid_unparse(uu, str);
467 fprintf(stderr, _("Generated time UUID: %s\n"), str);
468 }
469 memcpy(reply_buf, uu, sizeof(uu));
470 reply_len = sizeof(uu);
471 break;
472 case UUIDD_OP_RANDOM_UUID:
473 num = 1;
474 __uuid_generate_random(uu, &num);
475 if (uuidd_cxt->debug) {
476 uuid_unparse(uu, str);
477 fprintf(stderr, _("Generated random UUID: %s\n"), str);
478 }
479 memcpy(reply_buf, uu, sizeof(uu));
480 reply_len = sizeof(uu);
481 break;
482 case UUIDD_OP_BULK_TIME_UUID:
483 __uuid_generate_time(uu, &num);
484 if (uuidd_cxt->debug) {
485 uuid_unparse(uu, str);
486 fprintf(stderr, P_("Generated time UUID %s "
487 "and %d following\n",
488 "Generated time UUID %s "
489 "and %d following\n", num - 1),
490 str, num - 1);
491 }
492 memcpy(reply_buf, uu, sizeof(uu));
493 reply_len = sizeof(uu);
494 memcpy(reply_buf + reply_len, &num, sizeof(num));
495 reply_len += sizeof(num);
496 break;
497 case UUIDD_OP_BULK_RANDOM_UUID:
498 if (num < 0)
499 num = 1;
500 if (num > 1000)
501 num = 1000;
502 if (num * UUID_LEN > (int) (sizeof(reply_buf) - sizeof(num)))
503 num = (sizeof(reply_buf) - sizeof(num)) / UUID_LEN;
504 __uuid_generate_random((unsigned char *) reply_buf +
505 sizeof(num), &num);
506 if (uuidd_cxt->debug) {
507 fprintf(stderr, P_("Generated %d UUID:\n",
508 "Generated %d UUIDs:\n", num), num);
509 for (i = 0, cp = reply_buf + sizeof(num);
510 i < num;
511 i++, cp += UUID_LEN) {
512 uuid_unparse((unsigned char *)cp, str);
513 fprintf(stderr, "\t%s\n", str);
514 }
515 }
516 reply_len = (num * UUID_LEN) + sizeof(num);
517 memcpy(reply_buf, &num, sizeof(num));
518 break;
519 default:
520 if (uuidd_cxt->debug)
521 fprintf(stderr, _("Invalid operation %d\n"), op);
522 goto shutdown_socket;
523 }
524 write_all(ns, (char *) &reply_len, sizeof(reply_len));
525 write_all(ns, reply_buf, reply_len);
526 shutdown_socket:
527 close(ns);
528 }
529 }
530
531 static void __attribute__ ((__noreturn__)) unexpected_size(int size)
532 {
533 errx(EXIT_FAILURE, _("Unexpected reply length from server %d"), size);
534 }
535
536 int main(int argc, char **argv)
537 {
538 const char *socket_path = UUIDD_SOCKET_PATH;
539 const char *pidfile_path = NULL;
540 const char *err_context = NULL;
541 char buf[1024], *cp;
542 char str[UUID_STR_LEN];
543 uuid_t uu;
544 int i, c, ret;
545 int do_type = 0, do_kill = 0, num = 0;
546 int no_pid = 0;
547 int s_flag = 0;
548
549 struct uuidd_cxt_t uuidd_cxt = { .timeout = 0 };
550
551 static const struct option longopts[] = {
552 {"pid", required_argument, NULL, 'p'},
553 {"socket", required_argument, NULL, 's'},
554 {"timeout", required_argument, NULL, 'T'},
555 {"kill", no_argument, NULL, 'k'},
556 {"random", no_argument, NULL, 'r'},
557 {"time", no_argument, NULL, 't'},
558 {"uuids", required_argument, NULL, 'n'},
559 {"no-pid", no_argument, NULL, 'P'},
560 {"no-fork", no_argument, NULL, 'F'},
561 {"socket-activation", no_argument, NULL, 'S'},
562 {"debug", no_argument, NULL, 'd'},
563 {"quiet", no_argument, NULL, 'q'},
564 {"version", no_argument, NULL, 'V'},
565 {"help", no_argument, NULL, 'h'},
566 {NULL, 0, NULL, 0}
567 };
568 static const ul_excl_t excl[] = {
569 { 'P', 'p' },
570 { 'd', 'q' },
571 { 'r', 't' },
572 { 0 }
573 };
574 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
575
576 setlocale(LC_ALL, "");
577 bindtextdomain(PACKAGE, LOCALEDIR);
578 textdomain(PACKAGE);
579 close_stdout_atexit();
580
581 while ((c =
582 getopt_long(argc, argv, "p:s:T:krtn:PFSdqVh", longopts,
583 NULL)) != -1) {
584 err_exclusive_options(c, longopts, excl, excl_st);
585 switch (c) {
586 case 'd':
587 uuidd_cxt.debug = 1;
588 break;
589 case 'k':
590 do_kill++;
591 break;
592 case 'n':
593 num = strtou32_or_err(optarg,
594 _("failed to parse --uuids"));
595 break;
596 case 'p':
597 pidfile_path = optarg;
598 break;
599 case 'P':
600 no_pid = 1;
601 break;
602 case 'F':
603 uuidd_cxt.no_fork = 1;
604 break;
605 case 'S':
606 #ifdef HAVE_LIBSYSTEMD
607 uuidd_cxt.no_sock = 1;
608 uuidd_cxt.no_fork = 1;
609 no_pid = 1;
610 #else
611 errx(EXIT_FAILURE, _("uuidd has been built without "
612 "support for socket activation"));
613 #endif
614 break;
615 case 'q':
616 uuidd_cxt.quiet = 1;
617 break;
618 case 'r':
619 do_type = UUIDD_OP_RANDOM_UUID;
620 break;
621 case 's':
622 socket_path = optarg;
623 s_flag = 1;
624 break;
625 case 't':
626 do_type = UUIDD_OP_TIME_UUID;
627 break;
628 case 'T':
629 uuidd_cxt.timeout = strtou32_or_err(optarg,
630 _("failed to parse --timeout"));
631 break;
632
633 case 'V':
634 print_version(EXIT_SUCCESS);
635 case 'h':
636 usage();
637 default:
638 errtryhelp(EXIT_FAILURE);
639 }
640 }
641
642 if (strlen(socket_path) >= sizeof(((struct sockaddr_un *)0)->sun_path))
643 errx(EXIT_FAILURE, _("socket name too long: %s"), socket_path);
644
645 if (!no_pid && !pidfile_path)
646 pidfile_path = UUIDD_PIDFILE_PATH;
647
648 /* custom socket path and socket-activation make no sense */
649 if (s_flag && uuidd_cxt.no_sock && !uuidd_cxt.quiet)
650 warnx(_("Both --socket-activation and --socket specified. "
651 "Ignoring --socket."));
652
653 if (num && do_type) {
654 ret = call_daemon(socket_path, do_type + 2, buf,
655 sizeof(buf), &num, &err_context);
656 if (ret < 0)
657 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
658 err_context ? : _("unexpected error"));
659
660 if (do_type == UUIDD_OP_TIME_UUID) {
661 if (ret != sizeof(uu) + sizeof(num))
662 unexpected_size(ret);
663
664 uuid_unparse((unsigned char *) buf, str);
665
666 printf(P_("%s and %d subsequent UUID\n",
667 "%s and %d subsequent UUIDs\n", num - 1),
668 str, num - 1);
669 } else {
670 printf(_("List of UUIDs:\n"));
671 cp = buf + 4;
672 if (ret != (int) (sizeof(num) + num * sizeof(uu)))
673 unexpected_size(ret);
674 for (i = 0; i < num; i++, cp += UUID_LEN) {
675 uuid_unparse((unsigned char *) cp, str);
676 printf("\t%s\n", str);
677 }
678 }
679 return EXIT_SUCCESS;
680 }
681 if (do_type) {
682 ret = call_daemon(socket_path, do_type, (char *) &uu,
683 sizeof(uu), 0, &err_context);
684 if (ret < 0)
685 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
686 err_context ? : _("unexpected error"));
687 if (ret != sizeof(uu))
688 unexpected_size(ret);
689
690 uuid_unparse(uu, str);
691
692 printf("%s\n", str);
693 return EXIT_SUCCESS;
694 }
695
696 if (do_kill) {
697 ret = call_daemon(socket_path, UUIDD_OP_GETPID, buf, sizeof(buf), 0, NULL);
698 if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
699 ret = kill(do_kill, SIGTERM);
700 if (ret < 0) {
701 if (!uuidd_cxt.quiet)
702 warn(_("couldn't kill uuidd running "
703 "at pid %d"), do_kill);
704 return EXIT_FAILURE;
705 }
706 if (!uuidd_cxt.quiet)
707 printf(_("Killed uuidd running at pid %d.\n"),
708 do_kill);
709 }
710 return EXIT_SUCCESS;
711 }
712
713 server_loop(socket_path, pidfile_path, &uuidd_cxt);
714 return EXIT_SUCCESS;
715 }