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