]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/uuidd.c
371975d631f4b9c34452f6ab5fb4cc9b77a1cb3f
[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 textual representation of UUID, including trailing \0 */
45 #define UUID_STR_LEN 37
46
47 /* length of binary representation of UUID */
48 #define UUID_LEN (sizeof(uuid_t))
49
50 /* server loop control structure */
51 struct uuidd_cxt_t {
52 const char *cleanup_pidfile;
53 const char *cleanup_socket;
54 uint32_t timeout;
55 unsigned int debug: 1,
56 quiet: 1,
57 no_fork: 1,
58 no_sock: 1;
59 };
60
61 static void __attribute__ ((__noreturn__)) usage(FILE * out)
62 {
63 fputs(USAGE_HEADER, out);
64 fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
65 fputs(USAGE_SEPARATOR, out);
66 fputs(_("A daemon for generating UUIDs.\n"), out);
67 fputs(USAGE_OPTIONS, out);
68 fputs(_(" -p, --pid <path> path to pid file\n"), out);
69 fputs(_(" -s, --socket <path> path to socket\n"), out);
70 fputs(_(" -T, --timeout <sec> specify inactivity timeout\n"), out);
71 fputs(_(" -k, --kill kill running daemon\n"), out);
72 fputs(_(" -r, --random test random-based generation\n"), out);
73 fputs(_(" -t, --time test time-based generation\n"), out);
74 fputs(_(" -n, --uuids <num> request number of uuids\n"), out);
75 fputs(_(" -P, --no-pid do not create pid file\n"), out);
76 fputs(_(" -F, --no-fork do not daemonize using double-fork\n"), out);
77 fputs(_(" -S, --socket-activation do not create listening socket\n"), out);
78 fputs(_(" -d, --debug run in debugging mode\n"), out);
79 fputs(_(" -q, --quiet turn on quiet mode\n"), out);
80 fputs(USAGE_SEPARATOR, out);
81 fputs(USAGE_HELP, out);
82 fputs(USAGE_VERSION, out);
83 fprintf(out, USAGE_MAN_TAIL("uuidd(8)"));
84 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
85 }
86
87 static void create_daemon(void)
88 {
89 uid_t euid;
90
91 if (daemon(0, 0))
92 err(EXIT_FAILURE, "daemon");
93
94 euid = geteuid();
95 if (setreuid(euid, euid) < 0)
96 err(EXIT_FAILURE, "setreuid");
97 }
98
99 static int call_daemon(const char *socket_path, int op, char *buf,
100 size_t buflen, int *num, const char **err_context)
101 {
102 char op_buf[8];
103 int op_len;
104 int s;
105 ssize_t ret;
106 int32_t reply_len = 0;
107 struct sockaddr_un srv_addr;
108
109 if (((op == UUIDD_OP_BULK_TIME_UUID) ||
110 (op == UUIDD_OP_BULK_RANDOM_UUID)) && !num) {
111 if (err_context)
112 *err_context = _("bad arguments");
113 errno = EINVAL;
114 return -1;
115 }
116
117 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
118 if (err_context)
119 *err_context = _("socket");
120 return -1;
121 }
122
123 srv_addr.sun_family = AF_UNIX;
124 strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
125 srv_addr.sun_path[sizeof(srv_addr.sun_path) - 1] = '\0';
126
127 if (connect(s, (const struct sockaddr *) &srv_addr,
128 sizeof(struct sockaddr_un)) < 0) {
129 if (err_context)
130 *err_context = _("connect");
131 close(s);
132 return -1;
133 }
134
135 if (op == UUIDD_OP_BULK_RANDOM_UUID) {
136 if ((*num) * UUID_LEN > buflen - 4)
137 *num = (buflen - 4) / UUID_LEN;
138 }
139 op_buf[0] = op;
140 op_len = 1;
141 if ((op == UUIDD_OP_BULK_TIME_UUID) ||
142 (op == UUIDD_OP_BULK_RANDOM_UUID)) {
143 memcpy(op_buf + 1, num, sizeof(int));
144 op_len += sizeof(int);
145 }
146
147 ret = write_all(s, op_buf, op_len);
148 if (ret < 0) {
149 if (err_context)
150 *err_context = _("write");
151 close(s);
152 return -1;
153 }
154
155 ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
156 if (ret < 0) {
157 if (err_context)
158 *err_context = _("read count");
159 close(s);
160 return -1;
161 }
162 if (reply_len < 0 || (size_t) reply_len > buflen) {
163 if (err_context)
164 *err_context = _("bad response length");
165 close(s);
166 return -1;
167 }
168 ret = read_all(s, (char *) buf, reply_len);
169
170 if ((ret > 0) && (op == UUIDD_OP_BULK_TIME_UUID)) {
171 if (reply_len >= (int) (UUID_LEN + sizeof(int)))
172 memcpy(buf + UUID_LEN, num, sizeof(int));
173 else
174 *num = -1;
175 }
176 if ((ret > 0) && (op == UUIDD_OP_BULK_RANDOM_UUID)) {
177 if (reply_len >= (int) sizeof(int))
178 memcpy(buf, num, sizeof(int));
179 else
180 *num = -1;
181 }
182
183 close(s);
184
185 return ret;
186 }
187
188 /*
189 * Exclusively create and open a pid file with path @pidfile_path
190 *
191 * Return file descriptor of the created pid_file.
192 */
193 static int create_pidfile(struct uuidd_cxt_t *cxt, const char *pidfile_path)
194 {
195 int fd_pidfile;
196 struct flock fl;
197
198 fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
199 if (fd_pidfile < 0) {
200 if (!cxt->quiet)
201 warn(_("cannot open %s"), pidfile_path);
202 exit(EXIT_FAILURE);
203 }
204 cxt->cleanup_pidfile = pidfile_path;
205
206 fl.l_type = F_WRLCK;
207 fl.l_whence = SEEK_SET;
208 fl.l_start = 0;
209 fl.l_len = 0;
210 fl.l_pid = 0;
211 while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
212 if ((errno == EAGAIN) || (errno == EINTR))
213 continue;
214 if (!cxt->quiet)
215 warn(_("cannot lock %s"), pidfile_path);
216 exit(EXIT_FAILURE);
217 }
218
219 return fd_pidfile;
220 }
221
222 /*
223 * Create AF_UNIX, SOCK_STREAM socket and bind to @socket_path
224 *
225 * If @will_fork is true, then make sure the descriptor
226 * of the socket is >2, so that it won't be later closed
227 * during create_daemon().
228 *
229 * Return file descriptor corresponding to created socket.
230 */
231 static int create_socket(struct uuidd_cxt_t *uuidd_cxt,
232 const char *socket_path, int will_fork)
233 {
234 struct sockaddr_un my_addr;
235 mode_t save_umask;
236 int s;
237
238 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
239 if (!uuidd_cxt->quiet)
240 warn(_("couldn't create unix stream socket"));
241 exit(EXIT_FAILURE);
242 }
243
244 /*
245 * Make sure the socket isn't using fd numbers 0-2 to avoid it
246 * getting closed by create_daemon()
247 */
248 while (will_fork && s <= 2) {
249 s = dup(s);
250 if (s < 0)
251 err(EXIT_FAILURE, "dup");
252 }
253
254 /*
255 * Create the address we will be binding to.
256 */
257 my_addr.sun_family = AF_UNIX;
258 strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
259 my_addr.sun_path[sizeof(my_addr.sun_path) - 1] = '\0';
260 unlink(socket_path);
261 save_umask = umask(0);
262 if (bind(s, (const struct sockaddr *) &my_addr,
263 sizeof(struct sockaddr_un)) < 0) {
264 if (!uuidd_cxt->quiet)
265 warn(_("couldn't bind unix socket %s"), socket_path);
266 exit(EXIT_FAILURE);
267 }
268 umask(save_umask);
269 uuidd_cxt->cleanup_socket = socket_path;
270
271 return s;
272 }
273
274 static void __attribute__((__noreturn__)) all_done(const struct uuidd_cxt_t *uuidd_cxt, int ret)
275 {
276 if (uuidd_cxt->cleanup_pidfile)
277 unlink(uuidd_cxt->cleanup_pidfile);
278 if (uuidd_cxt->cleanup_socket)
279 unlink(uuidd_cxt->cleanup_socket);
280 exit(ret);
281 }
282
283 static void handle_signal(const struct uuidd_cxt_t *uuidd_cxt, int fd)
284 {
285 struct signalfd_siginfo info;
286 ssize_t bytes;
287
288 bytes = read(fd, &info, sizeof(info));
289 if (bytes != sizeof(info)) {
290 if (errno == EAGAIN)
291 return;
292 warn(_("receiving signal failed"));
293 info.ssi_signo = 0;
294 }
295 if (info.ssi_signo == SIGPIPE)
296 return; /* ignored */
297 all_done(uuidd_cxt, EXIT_SUCCESS);
298 }
299
300 static void timeout_handler(int sig __attribute__((__unused__)),
301 siginfo_t * info,
302 void *context __attribute__((__unused__)))
303 {
304 if (info->si_code == SI_TIMER)
305 errx(EXIT_FAILURE, _("timed out"));
306 }
307
308 static void server_loop(const char *socket_path, const char *pidfile_path,
309 struct uuidd_cxt_t *uuidd_cxt)
310 {
311 struct sockaddr_un from_addr;
312 socklen_t fromlen;
313 int32_t reply_len = 0;
314 uuid_t uu;
315 char reply_buf[1024], *cp;
316 char op, str[UUID_STR_LEN];
317 int i, ns, len, num;
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 static timer_t t_id;
334 struct itimerval timeout;
335
336 memset(&timeout, 0, sizeof timeout);
337 timeout.it_value.tv_sec = 30;
338 if (setup_timer(&t_id, &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(&t_id);
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 atexit(close_stdout);
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 case 'V':
633 printf(UTIL_LINUX_VERSION);
634 return EXIT_SUCCESS;
635 case 'h':
636 usage(stdout);
637 default:
638 errtryhelp(EXIT_FAILURE);
639 }
640 }
641
642 if (!no_pid && !pidfile_path)
643 pidfile_path = UUIDD_PIDFILE_PATH;
644
645 /* custom socket path and socket-activation make no sense */
646 if (s_flag && uuidd_cxt.no_sock && !uuidd_cxt.quiet)
647 warnx(_("Both --socket-activation and --socket specified. "
648 "Ignoring --socket."));
649
650 if (num && do_type) {
651 ret = call_daemon(socket_path, do_type + 2, buf,
652 sizeof(buf), &num, &err_context);
653 if (ret < 0)
654 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
655 err_context ? : _("unexpected error"));
656
657 if (do_type == UUIDD_OP_TIME_UUID) {
658 if (ret != sizeof(uu) + sizeof(num))
659 unexpected_size(ret);
660
661 uuid_unparse((unsigned char *) buf, str);
662
663 printf(P_("%s and %d subsequent UUID\n",
664 "%s and %d subsequent UUIDs\n", num - 1),
665 str, num - 1);
666 } else {
667 printf(_("List of UUIDs:\n"));
668 cp = buf + 4;
669 if (ret != (int) (sizeof(num) + num * sizeof(uu)))
670 unexpected_size(ret);
671 for (i = 0; i < num; i++, cp += UUID_LEN) {
672 uuid_unparse((unsigned char *) cp, str);
673 printf("\t%s\n", str);
674 }
675 }
676 return EXIT_SUCCESS;
677 }
678 if (do_type) {
679 ret = call_daemon(socket_path, do_type, (char *) &uu,
680 sizeof(uu), 0, &err_context);
681 if (ret < 0)
682 err(EXIT_FAILURE, _("error calling uuidd daemon (%s)"),
683 err_context ? : _("unexpected error"));
684 if (ret != sizeof(uu))
685 unexpected_size(ret);
686
687 uuid_unparse(uu, str);
688
689 printf("%s\n", str);
690 return EXIT_SUCCESS;
691 }
692
693 if (do_kill) {
694 ret = call_daemon(socket_path, UUIDD_OP_GETPID, buf, sizeof(buf), 0, NULL);
695 if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
696 ret = kill(do_kill, SIGTERM);
697 if (ret < 0) {
698 if (!uuidd_cxt.quiet)
699 warn(_("couldn't kill uuidd running "
700 "at pid %d"), do_kill);
701 return EXIT_FAILURE;
702 }
703 if (!uuidd_cxt.quiet)
704 printf(_("Killed uuidd running at pid %d.\n"),
705 do_kill);
706 }
707 return EXIT_SUCCESS;
708 }
709
710 server_loop(socket_path, pidfile_path, &uuidd_cxt);
711 return EXIT_SUCCESS;
712 }