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