summaryrefslogtreecommitdiffstats
path: root/liblog
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /liblog
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2
Initial checkin
Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'liblog')
-rw-r--r--liblog/Makefile.am23
-rw-r--r--liblog/configure.in44
-rw-r--r--liblog/courierlogger.sgml252
-rw-r--r--liblog/logger.c519
4 files changed, 838 insertions, 0 deletions
diff --git a/liblog/Makefile.am b/liblog/Makefile.am
new file mode 100644
index 0000000..dfec2c3
--- /dev/null
+++ b/liblog/Makefile.am
@@ -0,0 +1,23 @@
+#
+# Copyright 2004-2007 Double Precision, Inc. See COPYING for
+# distribution information.
+
+sbin_PROGRAMS=courierlogger
+
+BUILT_SOURCES=courierlogger.html courierlogger.1
+man_MANS=courierlogger.1
+
+EXTRA_DIST=$(BUILT_SOURCES)
+
+courierlogger_SOURCES=logger.c
+courierlogger_DEPENDENCIES=../liblock/liblock.la ../numlib/libnumlib.la
+courierlogger_LDADD=../liblock/liblock.la ../numlib/libnumlib.la
+courierlogger_LDFLAGS=-static
+
+if HAVE_SGML
+courierlogger.html: courierlogger.sgml ../docbook/sgml2html
+ ../docbook/sgml2html courierlogger.sgml courierlogger.html
+
+courierlogger.1: courierlogger.sgml ../docbook/sgml2html
+ ../docbook/sgml2man courierlogger.sgml courierlogger.1
+endif
diff --git a/liblog/configure.in b/liblog/configure.in
new file mode 100644
index 0000000..5cfcd20
--- /dev/null
+++ b/liblog/configure.in
@@ -0,0 +1,44 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl Copyright 2004 Double Precision, Inc. See COPYING for
+dnl distribution information.
+
+AC_INIT(courierlogger, 0.10, [courier-users@lists.sourceforge.net])
+
+>confdefs.h # Kill PACKAGE_ macros.
+LPATH="$PATH:/usr/local/bin"
+AC_CONFIG_SRCDIR(logger.c)
+AC_CONFIG_AUX_DIR(../..)
+AM_INIT_AUTOMAKE([foreign no-define])
+AM_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_LIBTOOL
+
+if test x$GCC = xyes
+then
+ CFLAGS="-Wall $CFLAGS"
+fi
+if test x$GXX = xyes
+then
+ CXXFLAGS="-Wall $CXXFLAGS"
+fi
+
+AC_C_CONST
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h string.h syslog.h)
+AC_TYPE_UID_T
+AC_SYS_LARGEFILE
+AC_CHECK_FUNCS(strchr)
+
+AC_ARG_WITH(syslog,
+ AC_HELP_STRING([--with-syslog=XXX],[syslog facility [[MAIL]]]),
+ logdest="LOG_$withval", logdest="LOG_MAIL")
+
+AC_DEFINE_UNQUOTED(LOG_DEST, [$logdest],
+ [ syslog facility ])
+AM_CONDITIONAL(HAVE_SGML, test -d ${srcdir}/../docbook)
+AC_OUTPUT(Makefile)
diff --git a/liblog/courierlogger.sgml b/liblog/courierlogger.sgml
new file mode 100644
index 0000000..47f7014
--- /dev/null
+++ b/liblog/courierlogger.sgml
@@ -0,0 +1,252 @@
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+
+ <!-- Copyright 2004-2007 Double Precision, Inc. See COPYING for -->
+ <!-- distribution information. -->
+
+<refentry id="courierlogger">
+
+ <refmeta>
+ <refentrytitle>courierlogger</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>Double Precision, Inc.</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>courierlogger</refname>
+ <refpurpose>Courier syslog wrapper</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>courierlogger</command>
+ <arg>-name=<replaceable>title</replaceable></arg>
+ <arg>-facility=<replaceable>subsystem</replaceable></arg>
+ <arg>-pid=<replaceable>filename</replaceable></arg>
+ <arg>-user=<replaceable>user</replaceable></arg>
+ <arg>-group=<replaceable>group</replaceable></arg>
+ <arg>-droproot</arg>
+ <group>
+ <arg><arg choice='opt'>-respawn</arg> <arg choice='opt'>-start</arg>
+ <replaceable>program</replaceable> <arg rep='repeat'>argument</arg></arg>
+ <arg>-stop</arg>
+ <arg>-restart</arg>
+ </group>
+ </cmdsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>
+<command>courierlogger</command>
+is a wrapper that captures
+another process's error messages, and forwards them
+to the system logging facility,
+<quote>syslog</quote>.</para>
+
+ <para>
+There are two ways to use courierlogger:
+<orderedlist>
+ <listitem>
+ <para>
+Use the shell to pipe another command's standard error, and/or its standard
+output, to
+<command>courierlogger</command>'s standard input.</para>
+ </listitem>
+ <listitem>
+ <para>
+Alternatively,
+<command>courierlogger</command>
+itself can start another process, and arrange to have its standard error
+captured.</para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+In either case, each read line of text is sent as a syslog message.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term>-name=<replaceable>title</replaceable></term>
+ <listitem>
+<para>
+Use <replaceable>title</replaceable> for sending messages to syslog.
+<replaceable>title</replaceable> should be the application's name.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-facility=<replaceable>subsystem</replaceable></term>
+ <listitem>
+ <para>
+Use <replaceable>subsystem</replaceable> for classifying messages.
+Your syslog facility uses <replaceable>subsystem</replaceable> to determine
+which log messages are recorded in which log files.
+The currently defined subsystems are:</para>
+
+ <itemizedlist>
+ <listitem><para><literal>auth</literal></para></listitem>
+ <listitem><para><literal>authpriv</literal></para></listitem>
+ <listitem><para><literal>console</literal></para></listitem>
+ <listitem><para><literal>cron</literal></para></listitem>
+ <listitem><para><literal>daemon</literal></para></listitem>
+ <listitem><para><literal>ftp</literal></para></listitem>
+ <listitem><para><literal>kern</literal></para></listitem>
+ <listitem><para><literal>lpr</literal></para></listitem>
+ <listitem><para><literal>mail</literal></para></listitem>
+ <listitem><para><literal>news</literal></para></listitem>
+ <listitem><para><literal>security</literal></para></listitem>
+ <listitem><para><literal>user</literal></para></listitem>
+ <listitem><para><literal>uucp</literal></para></listitem>
+ <listitem><para><literal>local0</literal></para></listitem>
+ <listitem><para><literal>local1</literal></para></listitem>
+ <listitem><para><literal>local2</literal></para></listitem>
+ <listitem><para><literal>local3</literal></para></listitem>
+ <listitem><para><literal>local4</literal></para></listitem>
+ <listitem><para><literal>local5</literal></para></listitem>
+ <listitem><para><literal>local6</literal></para></listitem>
+ <listitem><para><literal>local7</literal></para></listitem>
+ </itemizedlist>
+
+ <note>
+ <para>
+Not all of the above facility names are implemented on every system.
+Check your system's syslog documentation for information on which facility
+names are allowed, and which log files record the corresponding messages
+for each facility.</para>
+ </note>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-pid=<replaceable>filename</replaceable></term>
+ <listitem>
+<para>
+Save <command>courierlogger</command>'s
+process ID in <replaceable>filename</replaceable>.
+The <parameter>-pid</parameter> option is required when
+<parameter>-start</parameter>,
+<parameter>-stop</parameter>,
+<parameter>-restart</parameter> are given. If <parameter>-pid</parameter>
+is given without any of these, <parameter>-start</parameter> is assumed.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-start</term>
+ <listitem>
+ <para>
+Run as a daemon. The <option>pid</option> option is required.
+<command>courierlogger</command> will quietly terminate if another
+<command>courierlogger</command> process is already running.
+This is used to make sure that only one instance of
+<filename>program</filename> is running at the same time.
+Specify a different filename with <option>pid</option> to start a second
+copy of <filename>program</filename>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-respawn</term>
+ <listitem>
+<para>
+Restart <filename>program</filename> if it terminates.
+Normally
+<command>courierlogger</command> itself will terminate when
+<filename>program</filename> finishes running.
+Use <option>respawn</option> to restart it instead.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-restart</term>
+ <listitem>
+ <para>
+Send a <literal>SIGHUP</literal> signal to the courierlogger process
+(as determined by examining the contents of the file specified by
+<option>pid</option>), which will in turn send a <literal>SIGHUP</literal>
+to its child <filename>program</filename>.
+Does nothing if courierlogger is not running.</para>
+
+ <note>
+ <para>
+<filename>program</filename> must be originally started with the
+<option>respawn</option> option if sending it a <literal>SIGHUP</literal>
+causes it to terminate.</para>
+ </note>
+
+ <para>
+The same thing may be accomplished by sending <literal>SIGHUP</literal>
+to <command>courierlogger</command> itself.</para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-stop</term>
+ <listitem>
+<para>
+Send a <literal>SIGTERM</literal> signal to courierlogger, which in turn
+forwards it on to <filename>program</filename>.
+If <filename>program</filename> does not terminate in 8 seconds, kill it
+with <literal>SIGKILL</literal>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-user=<replaceable>user</replaceable>, -group=<replaceable>group</replaceable></term>
+ <listitem>
+ <para>
+If running as root, change credentials to the given user and/or group, which
+may be given as names or numeric ids.</para>
+<para>When running a child program, it is started
+<emphasis>before</emphasis> privileges are dropped
+(unless the <option>-droproot</option> option is also given).
+This gives a means of
+starting a child as root so it can bind to a privileged port, but still have
+courierlogger run as a non-root user. For the <option>-stop</option> and
+<option>-restart</option> options to work, you should configure the child
+program to drop its privileges to the same userid too.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-droproot</term>
+ <listitem>
+ <para>
+Drop root privileges before starting the child process.
+The <option>-user</option> and <option>-group</option> options specify
+the non-privileges userid and groupid.
+Without the <option>-droproot</option> option the child process remains
+a root process, and only the parent <command>courierlogger</command>
+process drops root privileges.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable>program</replaceable> [ argument ] ... </term>
+ <listitem>
+ <para>
+If a program is given <filename>program</filename>
+will be started as a child process of
+<command>courierlogger</command>, capturing its standard error.
+Otherwise, <command>courierlogger</command>
+reads message from standard input, and automatically terminates when
+standard input is closed.</para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+
+ <para>
+<ulink url="couriertcpd.html"><citerefentry><refentrytitle>couriertcpd</refentrytitle><manvolnum>1</manvolnum></citerefentry></ulink>, your syslog man page.</para>
+ </refsect1>
+</refentry>
diff --git a/liblog/logger.c b/liblog/logger.c
new file mode 100644
index 0000000..2fe40cc
--- /dev/null
+++ b/liblog/logger.c
@@ -0,0 +1,519 @@
+/*
+** Copyright 1998 - 2006 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYSLOG_H
+#include <syslog.h>
+#else
+#undef TESTMODE
+#define TESTMODE 1
+#endif
+#include "../liblock/config.h"
+#include "../liblock/liblock.h"
+#include "../numlib/numlib.h"
+
+
+static int do_logger(const char *name, int facility, FILE *f)
+{
+char buf[512];
+char *p;
+int c;
+
+#if TESTMODE
+
+#else
+ openlog(name, 0
+
+#ifdef LOG_NDELAY
+ | LOG_NDELAY
+#else
+ | LOG_NOWAIT
+#endif
+
+ , facility);
+#endif
+ if (chdir("/") < 0)
+ {
+ perror("chdir(\"/\")");
+ exit(1);
+ }
+
+ while (fgets(buf, sizeof(buf), f))
+ {
+ if ((p=strchr(buf, '\n')) != 0) *p=0;
+ else
+ while ((c=getchar()) != EOF && c != '\n')
+ ;
+
+#if TESTMODE
+ fprintf(stderr, "%s: %s\n", name, buf);
+#else
+ c=LOG_INFO;
+ if (strncmp(buf, "ERR:", 4) == 0)
+ {
+ c=LOG_ERR;
+ p=buf+4;
+ }
+ else if (strncmp(buf, "WARN:", 5) == 0)
+ {
+ c=LOG_WARNING;
+ p=buf+5;
+ }
+ else if (strncmp(buf, "ALERT:", 6) == 0)
+ {
+ c=LOG_ALERT;
+ p=buf+6;
+ }
+ else if (strncmp(buf, "CRIT:", 5) == 0)
+ {
+ c=LOG_CRIT;
+ p=buf+5;
+ }
+ else if (strncmp(buf, "DEBUG:", 6) == 0)
+ {
+ c=LOG_DEBUG;
+ p=buf+6;
+ }
+ else if (strncmp(buf, "INFO:", 5) == 0)
+ p=buf+5;
+ else p=buf;
+
+ while (*p == ' ')
+ ++p;
+
+ syslog(c, "%s", p);
+#endif
+ }
+ return (0);
+}
+
+static const char *namearg=0;
+static const char *pidarg=0;
+static char *lockfilename=0;
+
+struct lognames
+{
+ char *name;
+ int value;
+};
+
+static struct lognames facilitynames[] =
+{
+#ifdef LOG_AUTH
+ { "auth", LOG_AUTH },
+#endif
+#ifdef LOG_AUTHPRIV
+ { "authpriv", LOG_AUTHPRIV },
+#endif
+#ifdef LOG_CONSOLE
+ { "console", LOG_CONSOLE },
+#endif
+#ifdef LOG_CRON
+ { "cron", LOG_CRON },
+#endif
+#ifdef LOG_DAEMON
+ { "daemon", LOG_DAEMON },
+#endif
+#ifdef LOG_FTP
+ { "ftp", LOG_FTP },
+#endif
+#ifdef LOG_KERN
+ { "kern", LOG_KERN },
+#endif
+#ifdef LOG_LPR
+ { "lpr", LOG_LPR },
+#endif
+#ifdef LOG_MAIL
+ { "mail", LOG_MAIL },
+#endif
+#ifdef LOG_AUTHPRIV
+ { "news", LOG_NEWS },
+#endif
+#ifdef LOG_SECURITY
+ { "security", LOG_SECURITY },
+#endif
+#ifdef LOG_USER
+ { "user", LOG_USER },
+#endif
+#ifdef LOG_UUCP
+ { "uucp", LOG_UUCP },
+#endif
+#ifdef LOG_LOCAL0
+ { "local0", LOG_LOCAL0 },
+#endif
+#ifdef LOG_LOCAL1
+ { "local1", LOG_LOCAL1 },
+#endif
+#ifdef LOG_LOCAL2
+ { "local2", LOG_LOCAL2 },
+#endif
+#ifdef LOG_LOCAL3
+ { "local3", LOG_LOCAL3 },
+#endif
+#ifdef LOG_LOCAL4
+ { "local4", LOG_LOCAL4 },
+#endif
+#ifdef LOG_LOCAL5
+ { "local5", LOG_LOCAL5 },
+#endif
+#ifdef LOG_LOCAL6
+ { "local6", LOG_LOCAL6 },
+#endif
+#ifdef LOG_LOCAL7
+ { "local7", LOG_LOCAL7 },
+#endif
+ { 0, 0 }
+};
+
+static int hup_restart = 0;
+static int respawn = 0;
+static int child_pid = -1;
+
+static RETSIGTYPE sighup(int n)
+{
+ if (child_pid > 0)
+ {
+ /* The child may respond to HUP by dying. If so it will
+ close its stderr and do_logger will terminate; at that
+ point we need to restart it */
+ hup_restart = 1;
+ kill (child_pid, SIGHUP);
+ }
+ signal(SIGHUP, sighup);
+#if RETSIGTYPE != void
+ return (1);
+#endif
+}
+
+static RETSIGTYPE sigalrm(int n)
+{
+ if (child_pid > 0) kill(child_pid, SIGKILL);
+#if RETSIGTYPE != void
+ return (1);
+#endif
+}
+
+static RETSIGTYPE sigterm(int n)
+{
+ if (child_pid > 0)
+ {
+ hup_restart = 0;
+ respawn = 0;
+ kill(child_pid, SIGTERM);
+ signal(SIGALRM, sigalrm); /* kill after 8 secs */
+ alarm(8);
+ }
+ else exit(0);
+#if RETSIGTYPE != void
+ return (1);
+#endif
+}
+
+static void checkfd(int actual, int exp)
+{
+ if (actual == exp) return;
+ fprintf(stderr, "Bad fd, got %d, expected %d\n", actual, exp);
+ if (actual < 0) perror("error");
+ exit(1);
+}
+
+static int isid(const char *p)
+{
+ while (*p)
+ {
+ if (*p < '0' || *p > '9') return (0);
+ ++p;
+ }
+ return (1);
+}
+
+static void setuidgid(const char *userarg,
+ const char *grouparg)
+{
+ if (grouparg)
+ {
+ gid_t gid = 0;
+ struct group *gr;
+
+ if (isid(grouparg))
+ gid=atoi(grouparg);
+ else if ((gr=getgrnam(grouparg)) == 0)
+ {
+ fprintf(stderr, "Group not found: %s\n", grouparg);
+ exit(1);
+ }
+ else gid=gr->gr_gid;
+
+ libmail_changegroup(gid);
+ }
+
+ if (userarg)
+ {
+ uid_t uid;
+
+ if (isid(userarg))
+ {
+ uid=atoi(userarg);
+ libmail_changeuidgid(uid, getgid());
+ }
+ else
+ {
+ gid_t g=getgid(), *gp=0;
+
+ if (grouparg) gp= &g;
+ libmail_changeusername(userarg, gp);
+ }
+ }
+}
+
+
+static void startchild(char **argv, const char *userarg, const char *grouparg)
+{
+pid_t p;
+int pipefd[2];
+int tmp;
+
+ signal(SIGTERM, sigterm);
+ signal(SIGHUP, sighup);
+
+ /* Make sure the pipefds are at least 3 and 4. If we have an open
+ stderr then keep it around for debugging purposes. */
+ close(0);
+ checkfd(open("/dev/null", O_RDWR), 0);
+ close(1);
+ checkfd(dup(0), 1);
+ if ((tmp = dup(0)) > 2) close(tmp);
+
+ if (pipe(pipefd) < 0)
+ {
+ perror("pipe");
+ exit(1);
+ }
+ p = fork();
+ if (p < 0)
+ {
+ perror("fork");
+ exit(1);
+ }
+ if (p == 0)
+ {
+
+ close(pipefd[0]);
+ close(2);
+ checkfd(dup(pipefd[1]), 2);
+ close(pipefd[1]);
+ setuidgid(userarg, grouparg);
+ execvp(argv[0], argv);
+ perror("exec");
+ exit(1);
+ }
+
+ // We can close stderr now
+
+ close(2);
+ checkfd(dup(0), 2);
+
+
+ close(pipefd[1]);
+ close(0);
+ checkfd(dup(pipefd[0]), 0);
+ close(pipefd[0]);
+ child_pid = p;
+}
+/*
+ * Note that we now support several modes of operation:
+ *
+ * (1) standalone logger, just collect messages on stdin and feed to syslog
+ * courierlogger foo
+ * courierlogger -name=foo
+ *
+ * (2) run a child process, collect its stderr messages and feed to syslog
+ * courierlogger [-name=foo] foo arg1 arg2
+ *
+ * (3) start a detached daemon with a child process
+ * courierlogger [-name=foo] -pid=/var/run/foo.pid -start foo arg1 arg2
+ *
+ * (4) stop or restart a detached daemon
+ * courierlogger -pid=/var/run/foo.pid -stop (or receive a SIGTERM)
+ * courierlogger -pid=/var/run/foo.pid -restart (or receive a SIGHUP)
+ */
+
+int main(int argc, char **argv)
+{
+int facility = LOG_DEST;
+int daemon = 0;
+int lockfd = -1;
+const char *userarg = 0;
+const char *grouparg = 0;
+int droproot=0;
+
+ if (argc == 2 && argv[1][0] != '-')
+ {
+ /* backwards-compatibility mode */
+ close(1);
+ close(2);
+ checkfd(open("/dev/null", O_WRONLY), 1);
+ checkfd(open("/dev/null", O_WRONLY), 2);
+ do_logger(argv[1], facility, stdin);
+ exit(0);
+ }
+
+ if (argc <= 1)
+ {
+ fprintf(stderr,
+
+ "Usage: courierlogger [-name=name] [-pid=pidfile] [-facility=type]\n"
+ " [-start|-stop|-restart] [cmd [args...]]\n"
+ );
+ exit(1);
+ }
+
+ argv++, argc--;
+ while (argc > 0 && argv[0][0]=='-')
+ {
+ if (strncmp(argv[0],"-pid=",5) == 0 && argv[0][5])
+ {
+ pidarg=&argv[0][5];
+ lockfilename=malloc(strlen(pidarg)+sizeof(".lock"));
+ if (!lockfilename)
+ {
+ perror("malloc");
+ exit(1);
+ }
+ strcat(strcpy(lockfilename, pidarg), ".lock");
+ }
+ else
+ if (strncmp(argv[0],"-name=",6) == 0 && argv[0][6])
+ namearg=&argv[0][6];
+ else if (strncmp(argv[0],"-user=",6) == 0)
+ userarg=argv[0]+6;
+ else if (strncmp(argv[0],"-group=",7) == 0)
+ grouparg=argv[0]+7;
+ else if (strcmp(argv[0], "-droproot") == 0)
+ droproot=1;
+ else
+ if (strncmp(argv[0],"-facility=",10) == 0)
+ {
+ struct lognames *p = facilitynames;
+
+ while (p->name && strcmp(p->name, &argv[0][10]))
+ p++;
+ if (p->name == 0)
+ {
+ fprintf(stderr, "Unknown facility name '%s'\n",
+ &argv[0][10]);
+ exit(1);
+ }
+ facility = p->value;
+ }
+ else
+ if (strcmp(argv[0],"-start") == 0)
+ daemon = 1;
+ else
+ if (strcmp(argv[0],"-stop") == 0)
+ daemon = 2;
+ else
+ if (strcmp(argv[0],"-restart") == 0)
+ daemon = 3;
+ else
+ if (strcmp(argv[0],"-respawn") == 0)
+ respawn = 1;
+ else
+ {
+ fprintf(stderr, "Unknown option '%s'\n", argv[0]);
+ exit(1);
+ }
+ argv++, argc--;
+ }
+
+ if (daemon && !pidarg)
+ {
+ fprintf(stderr, "-pid argument required\n");
+ exit(1);
+ }
+
+ if (!daemon && pidarg)
+ daemon = 1; /* -start implied */
+
+ if (!namearg && daemon != 2 && daemon != 3)
+ {
+ /* choose a default name based on the program we're running */
+ if (argc <= 0 || !argv[0] || !argv[0][0])
+ {
+ fprintf(stderr, "-name option required for standalone logger\n");
+ exit(1);
+ }
+ namearg = strrchr(argv[0],'/');
+ namearg = namearg ? namearg+1 : argv[0];
+ }
+
+ switch (daemon)
+ {
+ case 1: /* start */
+ if (argc <= 0 || !argv[0] || !argv[0][0])
+ {
+ fprintf(stderr, "-start must be followed by a command to execute\n");
+ exit(1);
+ }
+ lockfd=ll_daemon_start(lockfilename);
+ if (lockfd < 0)
+ {
+ perror("ll_daemon_start");
+ exit(1);
+ }
+ startchild(argv, droproot ? userarg:NULL,
+ droproot ? grouparg:NULL);
+ ll_daemon_started(pidarg, lockfd);
+ break;
+ case 2: /* stop */
+ exit(ll_daemon_stop(lockfilename, pidarg));
+ case 3: /* restart */
+ exit(ll_daemon_restart(lockfilename, pidarg));
+ default: /* run in foreground, with or without a child process */
+
+ if (argc > 0)
+ startchild(argv, droproot ? userarg:NULL,
+ droproot ? grouparg:NULL);
+ }
+
+ setuidgid(userarg, grouparg);
+
+ while (1)
+ {
+ int waitstat;
+ pid_t p2;
+ FILE *f = fdopen(0, "r");
+
+ do_logger(namearg, facility, f);
+ fclose(f);
+ if (child_pid < 0) break;
+ while ((p2=wait(&waitstat)) != child_pid &&
+ (p2 != -1 || errno != ECHILD))
+ ;
+ if (hup_restart)
+ hup_restart = 0;
+ else if (respawn)
+ sleep (5);
+ else
+ break;
+ startchild(argv, NULL, NULL);
+ }
+ exit(0);
+}