]> err.no Git - util-linux/commitdiff
uuidd: new command (UUID daemon from e2fsprogs)
authorKarel Zak <kzak@redhat.com>
Fri, 22 May 2009 07:08:43 +0000 (09:08 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 22 May 2009 08:06:16 +0000 (10:06 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
configure.ac
example.files/uuidd.rc [new file with mode: 0644]
misc-utils/.gitignore
misc-utils/Makefile.am
misc-utils/uuidd.8 [new file with mode: 0644]
misc-utils/uuidd.c [new file with mode: 0644]
shlibs/uuid/src/Makefile.am
shlibs/uuid/src/uuid.sym

index 0b3cf35901a66677bb35f43657f373c56afda3b7..e9a89199846f80a3a594faa1820d752c12397453 100644 (file)
@@ -137,6 +137,8 @@ AC_CHECK_FUNCS(
        getdtablesize \
        getrlimit \
        srandom \
+       setresgid \
+       setresuid \
        inotify_init \
        prctl \
        __secure_getenv \
diff --git a/example.files/uuidd.rc b/example.files/uuidd.rc
new file mode 100644 (file)
index 0000000..d35645a
--- /dev/null
@@ -0,0 +1,55 @@
+#! /bin/sh -e
+### BEGIN INIT INFO
+# Provides:          uuidd
+# Required-Start:    $time $local_fs
+# Required-Stop:     $time $local_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: uuidd daemon
+# Description:       Init script for the uuid generation daemon
+### END INIT INFO
+#
+# Author:      "Theodore Ts'o" <tytso@mit.edu>
+#
+set -e
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+DAEMON=/usr/sbin/uuidd
+PIDFILE=/var/run/uuidd/uuidd.pid
+
+test -x $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+case "$1" in
+    start)
+       log_daemon_msg "Starting uuid generator" "uuidd"
+       start_daemon -p $PIDFILE $DAEMON
+       log_end_msg $?
+    ;;
+  stop)
+       log_daemon_msg "Stopping uuidd generator" "uuidd"
+       killproc -p $PIDFILE $DAEMON
+       log_end_msg $?
+    ;;
+  status)
+       if pidofproc -p $PIDFILE $DAEMON >& /dev/null ; then
+           echo "$DAEMON is running";
+           exit 0;
+       else
+           echo "$DAEMON is NOT running";
+           if test -f /var/run/uuidd.pid; then exit 2; fi
+           exit 3;
+       fi
+       ;;
+  force-reload|restart)
+    $0 stop
+    $0 start
+    ;;
+  *)
+    echo "Usage: /etc/init.d/uuidd {start|stop|restart|force-reload}"
+    exit 1
+    ;;
+esac
+
+exit 0
index ddb4421321cbde120b1e8b7d69b932ac09b6a956..e58c9301590f8717f24d4e198a08c33bbdbded9c 100644 (file)
@@ -13,3 +13,4 @@ whereis
 kill
 write
 uuidgen
+uuidd
index 781e5d2e344a42974f8dd910b6b80f0e0e6a0832..087e4a1bb1910cd193ba14347ee68325176a3ca9 100644 (file)
@@ -3,6 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am
 EXTRA_DIST = README.flushb
 
 bin_PROGRAMS =
+usrsbinexec_PROGRAMS =
 
 usrbinexec_PROGRAMS = cal ddate logger look mcookie \
        namei script whereis scriptreplay
@@ -22,6 +23,11 @@ usrbinexec_PROGRAMS += uuidgen
 dist_man_MANS += uuidgen.1
 uuidgen_LDADD = $(ul_libuuid_la)
 uuidgen_CFLAGS = -I$(ul_libuuid_srcdir)
+
+usrsbinexec_PROGRAMS += uuidd
+dist_man_MANS += uuidd.8
+uuidd_LDADD = $(ul_libuuid_la)
+uuidd_CFLAGS = -I$(ul_libuuid_srcdir)
 endif
 
 if HAVE_TINFO
diff --git a/misc-utils/uuidd.8 b/misc-utils/uuidd.8
new file mode 100644 (file)
index 0000000..ae033ea
--- /dev/null
@@ -0,0 +1,96 @@
+.\" -*- nroff -*-
+.\" Copyright 2007 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH UUIDD 8 "May 2009" "Linux"
+.SH NAME
+uuidd \- UUID generation daemon
+.SH SYNOPSIS
+.B uuidd
+[
+.B \-d
+]
+[
+.B \-p
+.I pidfile
+]
+[
+.B \-s
+.I socketpath
+]
+[
+.B \-T
+.I timeout
+]
+
+.B uuidd
+[
+.B \-r
+|
+.B \-t
+]
+[
+.B \-n
+.I number
+]
+[
+.B \-s
+.I socketpath
+]
+
+.B uuidd \-k
+.SH DESCRIPTION
+The
+.B uuidd
+daemon is used by the UUID library to generate
+universally unique identifiers (UUIDs), especially time-based UUID's
+in a secure and guaranteed-unique fashion, even in the face of large
+numbers of threads trying to grab UUID's running on different CPU's.
+.SH OPTIONS
+.TP
+.B \-d
+Run
+.B uuidd
+in debugging mode.  This prevents uuidd from running as a daemon.
+.TP
+.B \-k
+If a currently uuidd daemon is running, kill it.
+.TP
+.BI \-n " number"
+When issuing a test request to a running uuidd, request a bulk response
+of
+.I number
+UUID's.
+.TP
+.BI \-p  " pidfile"
+Specify the pathname where the pid file should be written.  By default,
+the pid file is written to /var/lib/libuuid/uuidd.pid.
+.TP
+.BI \-s " socketpath"
+Specify the pathname used for the unix-domain socket used by uuidd.  By
+default, the pathname used is /var/lib/libuuid/request.  This is primarily
+for debugging purposes, since the pathname is hard-coded in the libuuid
+library.
+.TP
+.B \-r
+Test uuidd by trying to connect to a running uuidd daemon and
+request it to return a random-based UUID.
+.TP
+.B \-t
+Test uuidd by trying to connect to a running uuidd daemon and
+request it to return a time-based UUID.
+.TP
+.BI \-T " timeout"
+Specify a timeout for uuidd.  If specified, then uuidd will exit after
+.I timeout
+seconds of inactivity.
+.SH AUTHOR
+The
+.B uuidd
+daemon  was written by Theodore Ts'o <tytso@mit.edu>.
+.SH AVAILABILITY
+uuidd is part of the util-linux-ng package and is available from
+ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.
+.SH "SEE ALSO"
+.BR libuuid (3),
+.BR uuidgen (1)
diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c
new file mode 100644 (file)
index 0000000..5e59783
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * uuidd.c --- UUID-generation daemon
+ *
+ * Copyright (C) 2007  Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+#endif
+
+#include "uuid.h"
+#include "uuidd.h"
+
+#include "nls.h"
+
+#ifdef __GNUC__
+#define CODE_ATTR(x) __attribute__(x)
+#else
+#define CODE_ATTR(x)
+#endif
+
+static void usage(const char *progname)
+{
+       fprintf(stderr, _("Usage: %s [-d] [-p pidfile] [-s socketpath] "
+                         "[-T timeout]\n"), progname);
+       fprintf(stderr, _("       %s [-r|t] [-n num] [-s socketpath]\n"),
+               progname);
+       fprintf(stderr, _("       %s -k\n"), progname);
+       exit(1);
+}
+
+static void die(const char *msg)
+{
+       perror(msg);
+       exit(1);
+}
+
+static void create_daemon(void)
+{
+       pid_t pid;
+       uid_t euid;
+
+       pid = fork();
+       if (pid == -1) {
+               perror("fork");
+               exit(1);
+       } else if (pid != 0) {
+           exit(0);
+       }
+
+       close(0);
+       close(1);
+       close(2);
+       open("/dev/null", O_RDWR);
+       open("/dev/null", O_RDWR);
+       open("/dev/null", O_RDWR);
+
+       if (chdir("/")) {}      /* Silence warn_unused_result warning */
+       (void) setsid();
+       euid = geteuid();
+       if (setreuid(euid, euid) < 0)
+               die("setreuid");
+}
+
+static int read_all(int fd, char *buf, size_t count)
+{
+       ssize_t ret;
+       int c = 0;
+
+       memset(buf, 0, count);
+       while (count > 0) {
+               ret = read(fd, buf, count);
+               if (ret < 0) {
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+                       return -1;
+               }
+               count -= ret;
+               buf += ret;
+               c += ret;
+       }
+       return c;
+}
+
+static int write_all(int fd, char *buf, size_t count)
+{
+       ssize_t ret;
+       int c = 0;
+
+       while (count > 0) {
+               ret = write(fd, buf, count);
+               if (ret < 0) {
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+                       return -1;
+               }
+               count -= ret;
+               buf += ret;
+               c += ret;
+       }
+       return c;
+}
+
+static const char *cleanup_pidfile, *cleanup_socket;
+
+static void terminate_intr(int signo CODE_ATTR((unused)))
+{
+       (void) unlink(cleanup_pidfile);
+       if (cleanup_socket)
+               (void) unlink(cleanup_socket);
+       exit(0);
+}
+
+static int call_daemon(const char *socket_path, int op, char *buf,
+                      int buflen, int *num, const char **err_context)
+{
+       char op_buf[8];
+       int op_len;
+       int s;
+       ssize_t ret;
+       int32_t reply_len = 0;
+       struct sockaddr_un srv_addr;
+
+       if (((op == 4) || (op == 5)) && !num) {
+               if (err_context)
+                       *err_context = _("bad arguments");
+               errno = EINVAL;
+               return -1;
+       }
+
+       if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+               if (err_context)
+                       *err_context = _("socket");
+               return -1;
+       }
+
+       srv_addr.sun_family = AF_UNIX;
+       strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
+       srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';
+
+       if (connect(s, (const struct sockaddr *) &srv_addr,
+                   sizeof(struct sockaddr_un)) < 0) {
+               if (err_context)
+                       *err_context = _("connect");
+               close(s);
+               return -1;
+       }
+
+       if (op == 5) {
+               if ((*num)*16 > buflen-4)
+                       *num = (buflen-4) / 16;
+       }
+       op_buf[0] = op;
+       op_len = 1;
+       if ((op == 4) || (op == 5)) {
+               memcpy(op_buf+1, num, sizeof(int));
+               op_len += sizeof(int);
+       }
+
+       ret = write_all(s, op_buf, op_len);
+       if (ret < op_len) {
+               if (err_context)
+                       *err_context = _("write");
+               close(s);
+               return -1;
+       }
+
+       ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
+       if (ret < 0) {
+               if (err_context)
+                       *err_context = _("read count");
+               close(s);
+               return -1;
+       }
+       if (reply_len < 0 || reply_len > buflen) {
+               if (err_context)
+                       *err_context = _("bad response length");
+               close(s);
+               return -1;
+       }
+       ret = read_all(s, (char *) buf, reply_len);
+
+       if ((ret > 0) && (op == 4)) {
+               if (reply_len >= (int) (16+sizeof(int)))
+                       memcpy(buf+16, num, sizeof(int));
+               else
+                       *num = -1;
+       }
+       if ((ret > 0) && (op == 5)) {
+               if (*num >= (int) sizeof(int))
+                       memcpy(buf, num, sizeof(int));
+               else
+                       *num = -1;
+       }
+
+       close(s);
+
+       return ret;
+}
+
+static void server_loop(const char *socket_path, const char *pidfile_path,
+                       int debug, int timeout, int quiet)
+{
+       struct sockaddr_un      my_addr, from_addr;
+       struct flock            fl;
+       socklen_t               fromlen;
+       int32_t                 reply_len = 0;
+       uuid_t                  uu;
+       mode_t                  save_umask;
+       char                    reply_buf[1024], *cp;
+       char                    op, str[37];
+       int                     i, s, ns, len, num;
+       int                     fd_pidfile, ret;
+
+       fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
+       if (fd_pidfile < 0) {
+               if (!quiet)
+                       fprintf(stderr, "Failed to open/create %s: %s\n",
+                               pidfile_path, strerror(errno));
+               exit(1);
+       }
+       cleanup_pidfile = pidfile_path;
+       cleanup_socket = 0;
+       signal(SIGALRM, terminate_intr);
+       alarm(30);
+       fl.l_type = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+       fl.l_start = 0;
+       fl.l_len = 0;
+       fl.l_pid = 0;
+       while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
+               if ((errno == EAGAIN) || (errno == EINTR))
+                       continue;
+               if (!quiet)
+                       fprintf(stderr, "Failed to lock %s: %s\n",
+                               pidfile_path, strerror(errno));
+               exit(1);
+       }
+       ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
+       if (ret > 0) {
+               if (!quiet)
+                       printf(_("uuidd daemon already running at pid %s\n"),
+                              reply_buf);
+               exit(1);
+       }
+       alarm(0);
+
+       if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+               if (!quiet)
+                       fprintf(stderr, _("Couldn't create unix stream "
+                                         "socket: %s"), strerror(errno));
+               exit(1);
+       }
+
+       /*
+        * Create the address we will be binding to.
+        */
+       my_addr.sun_family = AF_UNIX;
+       strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
+       my_addr.sun_path[sizeof(my_addr.sun_path)-1] = '\0';
+       (void) unlink(socket_path);
+       save_umask = umask(0);
+       if (bind(s, (const struct sockaddr *) &my_addr,
+                sizeof(struct sockaddr_un)) < 0) {
+               if (!quiet)
+                       fprintf(stderr,
+                               _("Couldn't bind unix socket %s: %s\n"),
+                               socket_path, strerror(errno));
+               exit(1);
+       }
+       (void) umask(save_umask);
+
+       if (listen(s, 5) < 0) {
+               if (!quiet)
+                       fprintf(stderr, _("Couldn't listen on unix "
+                                         "socket %s: %s\n"), socket_path,
+                               strerror(errno));
+               exit(1);
+       }
+
+       cleanup_socket = socket_path;
+       if (!debug)
+               create_daemon();
+       signal(SIGHUP, terminate_intr);
+       signal(SIGINT, terminate_intr);
+       signal(SIGTERM, terminate_intr);
+       signal(SIGALRM, terminate_intr);
+       signal(SIGPIPE, SIG_IGN);
+
+       sprintf(reply_buf, "%8d\n", getpid());
+       if (ftruncate(fd_pidfile, 0)) {} /* Silence warn_unused_result */
+       write_all(fd_pidfile, reply_buf, strlen(reply_buf));
+       if (fd_pidfile > 1)
+               close(fd_pidfile); /* Unlock the pid file */
+
+       while (1) {
+               fromlen = sizeof(from_addr);
+               if (timeout > 0)
+                       alarm(timeout);
+               ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
+               alarm(0);
+               if (ns < 0) {
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+                       perror("accept");
+                       exit(1);
+               }
+               len = read(ns, &op, 1);
+               if (len != 1) {
+                       if (len < 0)
+                               perror("read");
+                       else
+                               printf(_("Error reading from client, "
+                                        "len = %d\n"), len);
+                       goto shutdown_socket;
+               }
+               if ((op == 4) || (op == 5)) {
+                       if (read_all(ns, (char *) &num, sizeof(num)) != 4)
+                               goto shutdown_socket;
+                       if (debug)
+                               printf(_("operation %d, incoming num = %d\n"),
+                                      op, num);
+               } else if (debug)
+                       printf("operation %d\n", op);
+
+               switch(op) {
+               case UUIDD_OP_GETPID:
+                       sprintf(reply_buf, "%d", getpid());
+                       reply_len = strlen(reply_buf)+1;
+                       break;
+               case UUIDD_OP_GET_MAXOP:
+                       sprintf(reply_buf, "%d", UUIDD_MAX_OP);
+                       reply_len = strlen(reply_buf)+1;
+                       break;
+               case UUIDD_OP_TIME_UUID:
+                       num = 1;
+                       uuid__generate_time(uu, &num);
+                       if (debug) {
+                               uuid_unparse(uu, str);
+                               printf(_("Generated time UUID: %s\n"), str);
+                       }
+                       memcpy(reply_buf, uu, sizeof(uu));
+                       reply_len = sizeof(uu);
+                       break;
+               case UUIDD_OP_RANDOM_UUID:
+                       num = 1;
+                       uuid__generate_random(uu, &num);
+                       if (debug) {
+                               uuid_unparse(uu, str);
+                               printf(_("Generated random UUID: %s\n"), str);
+                       }
+                       memcpy(reply_buf, uu, sizeof(uu));
+                       reply_len = sizeof(uu);
+                       break;
+               case UUIDD_OP_BULK_TIME_UUID:
+                       uuid__generate_time(uu, &num);
+                       if (debug) {
+                               uuid_unparse(uu, str);
+                               printf(_("Generated time UUID %s and %d "
+                                        "following\n"), str, num);
+                       }
+                       memcpy(reply_buf, uu, sizeof(uu));
+                       reply_len = sizeof(uu);
+                       memcpy(reply_buf+reply_len, &num, sizeof(num));
+                       reply_len += sizeof(num);
+                       break;
+               case UUIDD_OP_BULK_RANDOM_UUID:
+                       if (num < 0)
+                               num = 1;
+                       if (num > 1000)
+                               num = 1000;
+                       if (num*16 > (int) (sizeof(reply_buf)-sizeof(num)))
+                               num = (sizeof(reply_buf)-sizeof(num)) / 16;
+                       uuid__generate_random((unsigned char *) reply_buf +
+                                             sizeof(num), &num);
+                       if (debug) {
+                               printf(_("Generated %d UUID's:\n"), num);
+                               for (i=0, cp=reply_buf+sizeof(num);
+                                    i < num; i++, cp+=16) {
+                                       uuid_unparse((unsigned char *)cp, str);
+                                       printf("\t%s\n", str);
+                               }
+                       }
+                       reply_len = (num*16) + sizeof(num);
+                       memcpy(reply_buf, &num, sizeof(num));
+                       break;
+               default:
+                       if (debug)
+                               printf(_("Invalid operation %d\n"), op);
+                       goto shutdown_socket;
+               }
+               write_all(ns, (char *) &reply_len, sizeof(reply_len));
+               write_all(ns, reply_buf, reply_len);
+       shutdown_socket:
+               close(ns);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       const char      *socket_path = UUIDD_SOCKET_PATH;
+       const char      *pidfile_path = UUIDD_PIDFILE_PATH;
+       const char      *err_context;
+       char            buf[1024], *cp;
+       char            str[37], *tmp;
+       uuid_t          uu;
+       uid_t           uid;
+       gid_t           gid;
+       int             i, c, ret;
+       int             debug = 0, do_type = 0, do_kill = 0, num = 0;
+       int             timeout = 0, quiet = 0, drop_privs = 0;
+
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+
+       while ((c = getopt (argc, argv, "dkn:qp:s:tT:r")) != EOF) {
+               switch (c) {
+               case 'd':
+                       debug++;
+                       drop_privs = 1;
+                       break;
+               case 'k':
+                       do_kill++;
+                       drop_privs = 1;
+                       break;
+               case 'n':
+                       num = strtol(optarg, &tmp, 0);
+                       if ((num < 0) || *tmp) {
+                               fprintf(stderr, _("Bad number: %s\n"), optarg);
+                               exit(1);
+                       }
+               case 'p':
+                       pidfile_path = optarg;
+                       drop_privs = 1;
+                       break;
+               case 'q':
+                       quiet++;
+                       break;
+               case 's':
+                       socket_path = optarg;
+                       drop_privs = 1;
+                       break;
+               case 't':
+                       do_type = UUIDD_OP_TIME_UUID;
+                       drop_privs = 1;
+                       break;
+               case 'T':
+                       timeout = strtol(optarg, &tmp, 0);
+                       if ((timeout < 0) || *tmp) {
+                               fprintf(stderr, _("Bad number: %s\n"), optarg);
+                               exit(1);
+                       }
+                       break;
+               case 'r':
+                       do_type = UUIDD_OP_RANDOM_UUID;
+                       drop_privs = 1;
+                       break;
+               default:
+                       usage(argv[0]);
+               }
+       }
+       uid = getuid();
+       if (uid && drop_privs) {
+               gid = getgid();
+#ifdef HAVE_SETRESGID
+               if (setresgid(gid, gid, gid) < 0)
+                       die("setresgid");
+#else
+               if (setregid(gid, gid) < 0)
+                       die("setregid");
+#endif
+
+#ifdef HAVE_SETRESUID
+               if (setresuid(uid, uid, uid) < 0)
+                       die("setresuid");
+#else
+               if (setreuid(uid, uid) < 0)
+                       die("setreuid");
+#endif
+       }
+       if (num && do_type) {
+               ret = call_daemon(socket_path, do_type+2, buf,
+                                 sizeof(buf), &num, &err_context);
+               if (ret < 0) {
+                       printf(_("Error calling uuidd daemon (%s): %s\n"),
+                              err_context, strerror(errno));
+                       exit(1);
+               }
+               if (do_type == UUIDD_OP_TIME_UUID) {
+                       if (ret != sizeof(uu) + sizeof(num))
+                               goto unexpected_size;
+
+                       uuid_unparse((unsigned char *) buf, str);
+
+                       printf(_("%s and subsequent %d UUID's\n"), str, num);
+               } else {
+                       printf(_("List of UUID's:\n"));
+                       cp = buf + 4;
+                       if (ret != (int) (sizeof(num) + num*sizeof(uu)))
+                               goto unexpected_size;
+                       for (i=0; i < num; i++, cp+=16) {
+                               uuid_unparse((unsigned char *) cp, str);
+                               printf("\t%s\n", str);
+                       }
+               }
+               exit(0);
+       }
+       if (do_type) {
+               ret = call_daemon(socket_path, do_type, (char *) &uu,
+                                 sizeof(uu), 0, &err_context);
+               if (ret < 0) {
+                       printf(_("Error calling uuidd daemon (%s): %s\n"),
+                              err_context, strerror(errno));
+                       exit(1);
+               }
+               if (ret != sizeof(uu)) {
+               unexpected_size:
+                       printf(_("Unexpected reply length from server %d\n"),
+                              ret);
+                       exit(1);
+               }
+               uuid_unparse(uu, str);
+
+               printf("%s\n", str);
+               exit(0);
+       }
+
+       if (do_kill) {
+               ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
+               if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
+                       ret = kill(do_kill, SIGTERM);
+                       if (ret < 0) {
+                               if (!quiet)
+                                       fprintf(stderr,
+                                               _("Couldn't kill uuidd running "
+                                                 "at pid %d: %s\n"), do_kill,
+                                               strerror(errno));
+                               exit(1);
+                       }
+                       if (!quiet)
+                               printf(_("Killed uuidd running at pid %d\n"),
+                                      do_kill);
+               }
+               exit(0);
+       }
+
+       server_loop(socket_path, pidfile_path, debug, timeout, quiet);
+       return 0;
+}
index cfbb004d958cd12bd917d96fce90cf826f7982a2..cc2ee7df788d3025beed87e02b9fbc0b0782f30c 100644 (file)
@@ -13,7 +13,7 @@ uuidinc_HEADERS = uuid.h
 lib_LTLIBRARIES = libuuid.la
 libuuid_la_SOURCES = clear.c compare.c copy.c gen_uuid.c \
            isnull.c pack.c parse.c unpack.c unparse.c uuidd.h \
-           uuid.h uuidP.h uuid_time.c $(uuidinc_HEADERS)
+           uuidd.h uuidP.h uuid_time.c $(uuidinc_HEADERS)
 
 libuuid_la_DEPENDENCIES = $(libuuid_la_LIBADD) uuid.sym
 
index 591319aaa744938bffd0cdfdc15130e0da3aca2d..05d9f39338bfbbed6e0592bc7029f736c614bb41 100644 (file)
@@ -22,6 +22,12 @@ global:
        uuid_time;
        uuid_type;
        uuid_variant;
+
+       /* uuid__* this is not part of the official API, this is
+        * uuidd (uuid daemon) specific stuff. Hell.
+        */
+       uuid__generate_time;
+       uuid__generate_random;
 local:
        *;
 };