On Sun, 24 Apr 2005 [EMAIL PROTECTED] wrote:

> On Mon, 18 Apr 2005, Jeff Moyer wrote:
>
>> 
>>  Okay, I've reviewed all parts except for the actual logging functions. 
>>  I'm
>>  actually not convinced this is the right approach.  The overhead of 
>>  setting
>>  up and tearing down the signal mask is quite expensive.  I fear that
>>  environments with a great number of mounts will fall over when debugging 
>>  is
>>  turned on, and that is the very thing we are trying to save.  Perhaps it 
>>  is
>>  worth another look at a separate logging process.
>> 
>
> I agree.
>
> The buffering approach is not the best way to handle this.
>
> I had a look around and found that the BSD folks have a reentrant syslog. I 
> found several posts on lists discussing the use of non-reentrant functions, 
> including syslog, in signal handlers. The responses claimed that their 
> reentrant syslog would work.
>
> I grabed the source from OpenBSD and tweeked it a bit to get it working.
> I've used the kernel printf code from the existing patch and checked all the 
> other function calls in glibc. It looks like it may well be signal safe.
>
> I've also tried to rationalise the signal setup and take down a bit.
> I've also tried to address the things that you picked up previously.
>
> So have a look at the attached patch.
>
> Ian

Sorry, did it again.
The patch is contaminated with white space.
Try this one instead please.

diff -Nur autofs-4.1.4.orig/daemon/automount.c autofs-4.1.4/daemon/automount.c
--- autofs-4.1.4.orig/daemon/automount.c        2005-03-06 17:43:55.000000000 
+0800
+++ autofs-4.1.4/daemon/automount.c     2005-04-24 13:43:54.000000000 +0800
@@ -5,7 +5,7 @@
   *
   *   Copyright 1997 Transmeta Corporation - All Rights Reserved
   *   Copyright 1999-2000 Jeremy Fitzhardinge <[EMAIL PROTECTED]>
- *   Copyright 2001-2003 Ian Kent <[EMAIL PROTECTED]>
+ *   Copyright 2001-2005 Ian Kent <[EMAIL PROTECTED]>
   *
   *   This program is free software; you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
@@ -28,7 +28,6 @@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
-#include <syslog.h>
  #include <unistd.h>
  #include <sys/ioctl.h>
  #include <sys/types.h>
@@ -38,13 +37,32 @@
  #include <sys/poll.h>
  #include <linux/auto_fs4.h>

+#include "automount.h"
+
  #ifndef NDEBUG
-#define assert(x)      do { if (!(x)) { syslog(LOG_CRIT, __FILE__ ":%d: 
assertion failed: " #x, __LINE__); } } while(0)
+#define assert(x)                                                  \
+       do {                                                        \
+               if (!(x)) {                                         \
+                       crit(__FILE__ ":%d: assertion failed: " #x, \
+                               __LINE__);                          \
+               }                                                   \
+       } while(0)
  #else
  #define assert(x)     do { } while(0)
  #endif

-#include "automount.h"
+#ifndef NDEBUG
+#define assert_r(context, x)                                      \
+       do {                                                       \
+               if (!(x)) {                                        \
+                       crit_r(context,                            \
+                               __FILE__ ":%d: assertion failed: ",\
+                               __LINE__);                         \
+               }                                                  \
+       } while(0)
+#else
+#define assert_r(context, x)   do { } while(0)
+#endif

  const char *program;          /* Initialized with argv[0] */
  const char *version = VERSION_STRING; /* Program version */
@@ -57,7 +75,7 @@
  int kproto_sub_version = 0;   /* Kernel protocol version used */

  static int submount = 0;
-
+
  int do_verbose = 0;           /* Verbose feedback option */
  int do_debug = 0;             /* Enable full debug output */

@@ -66,6 +84,9 @@
  sigset_t sigchld_mask;

  struct autofs_point ap;
+ 
+/* re-entrant syslog default context data */
+#define AUTOFS_SYSLOG_CONTEXT {-1, 0, 0, LOG_PID, (const char *)0, LOG_DAEMON, 
0xff};

  volatile struct pending_mount *junk_mounts = NULL;

@@ -480,19 +501,25 @@

  static void nextstate(enum states next)
  {
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
+
        if (write(ap.state_pipe[1], &next, sizeof(next)) != sizeof(next))
-               error("nextstate: write failed %m");
+               error_r(slc, "nextstate: write failed %m");
  }

  /* Deal with all the signal-driven events in the state machine */
  static void sig_statemachine(int sig)
  {
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
        int save_errno = errno;
        enum states next = ap.state;

        switch (sig) {
        default:                /* all the "can't happen" signals */
-               error("process %d got unexpected signal %d!", getpid(), sig);
+               error_r(slc, "process %d got unexpected signal %d!",
+                       getpid(), sig);
                break;
                /* don't FALLTHROUGH */

@@ -503,33 +530,36 @@
                break;

        case SIGUSR1:
-               assert(ap.state == ST_READY);
+               assert_r(slc, ap.state == ST_READY);
                nextstate(next = ST_PRUNE);
                break;

        case SIGALRM:
-               assert(ap.state == ST_READY);
+               assert_r(slc, ap.state == ST_READY);
                nextstate(next = ST_EXPIRE);
                break;

        case SIGHUP:
-               assert(ap.state == ST_READY);
+               assert_r(slc, ap.state == ST_READY);
                nextstate(next = ST_READMAP);
                break;
        }

-       debug("sig %d switching from %d to %d", sig, ap.state, next);
+       debug_r(slc, "sig %d switching from %d to %d", sig, ap.state, next);

        errno = save_errno;
  }

  static int send_ready(unsigned int wait_queue_token)
  {
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
+
        if (wait_queue_token == 0)
                return 0;
-       debug("send_ready: token=%d\n", wait_queue_token);
+       debug_r(slc, "send_ready: token=%d\n", wait_queue_token);
        if (ioctl(ap.ioctlfd, AUTOFS_IOC_READY, wait_queue_token) < 0) {
-               error("AUTOFS_IOC_READY: %m");
+               error_r(slc, "AUTOFS_IOC_READY: %m");
                return 1;
        }
        return 0;
@@ -537,11 +567,14 @@

  static int send_fail(unsigned int wait_queue_token)
  {
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
+
        if (wait_queue_token == 0)
                return 0;
-       debug("send_fail: token=%d\n", wait_queue_token);
+       debug_r(slc, "send_fail: token=%d\n", wait_queue_token);
        if (ioctl(ap.ioctlfd, AUTOFS_IOC_FAIL, wait_queue_token) < 0) {
-               syslog(LOG_ERR, "AUTOFS_IOC_FAIL: %m");
+               error_r(slc, "AUTOFS_IOC_FAIL: %m");
                return 1;
        }
        return 0;
@@ -552,6 +585,8 @@
     result.  */
  static enum states handle_child(int hang)
  {
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
        pid_t pid;
        int status;
        enum states next = ST_INVAL;
@@ -559,13 +594,13 @@
        while ((pid = waitpid(-1, &status, hang ? 0 : WNOHANG)) > 0) {
                struct pending_mount volatile *mt, *volatile *mtp;

-               debug("handle_child: got pid %d, sig %d (%d), stat %d\n",
+               debug_r(slc, "handle_child: got pid %d, sig %d (%d), stat %d",
                        pid, WIFSIGNALED(status),
                        WTERMSIG(status), WEXITSTATUS(status));

                /* Check to see if expire process finished */
                if (pid == ap.exp_process) {
-                       int success, ret;
+                       int success;

                        if (!WIFEXITED(status))
                                continue;
@@ -594,29 +629,23 @@

                        case ST_SHUTDOWN_PENDING:
                                next = ST_SHUTDOWN;
-                               if (success) {
-                                       ret = ioctl(ap.ioctlfd,
-                                               AUTOFS_IOC_ASKUMOUNT, &status);
-                                       if (!ret) {
-                                               if (status)
-                                                       break;
-                                       } else
-                                               break;
-                               }
+                               if (success)
+                                       break;

                                /* Failed shutdown returns to ready */
-                               warn("can't shutdown: filesystem %s still busy",
-                                    ap.path);
+                               warn_r(slc,
+                                  "can't shutdown: filesystem %s still busy",
+                                  ap.path);
                                alarm(ap.exp_runfreq);
                                next = ST_READY;
                                break;

                        default:
-                               error("bad state %d", ap.state);
+                               error_r(slc, "bad state %d", ap.state);
                        }

                        if (next != ST_INVAL)
-                               debug("sigchld: exp "
+                               debug_r(slc, "sigchld: exp "
                                     "%d finished, switching from %d to %d",
                                     pid, ap.state, next);

@@ -632,7 +661,7 @@
                        if (!WIFEXITED(status) && !WIFSIGNALED(status))
                                break;

-                       debug("sig_child: found pending iop pid %d: "
+                       debug_r(slc, "sig_child: found pending iop pid %d: "
                             "signalled %d (sig %d), exit status %d",
                                pid, WIFSIGNALED(status),
                                WTERMSIG(status), WEXITSTATUS(status));
@@ -673,10 +702,9 @@

  static int st_ready(void)
  {
-       debug("st_ready(): state = %d\n", ap.state);
+       debug("st_ready(): state = %d", ap.state);

        ap.state = ST_READY;
-       sigprocmask(SIG_UNBLOCK, &lock_sigs, NULL);

        return 0;
  }
@@ -796,6 +824,7 @@
        default:
                debug("expire_proc: exp_proc=%d", f);
                ap.exp_process = f;
+               sigprocmask(SIG_SETMASK, &old, NULL);
                return EXP_STARTED;
        }
  }
@@ -804,10 +833,15 @@
  {
        int status;

+       assert(ap.state == ST_READY);
+       ap.state = ST_READMAP;
+
        status = ap.lookup->lookup_ghost(ap.path, ap.ghost, 0, 
ap.lookup->context);

        debug("st_readmap: status %d\n", status);

+       ap.state = ST_READY;
+
        /* If I don't exist in the map any more then exit */
        if (status == LKP_FAIL)
                return 0;
@@ -822,15 +856,11 @@
        info("prep_shutdown: state = %d\n", ap.state);

        assert(ap.state == ST_READY || ap.state == ST_EXPIRE);
+       ap.state = ST_SHUTDOWN_PENDING;

        /* Turn off timeouts */
        alarm(0);

-       /* Prevent any new mounts */
-       sigprocmask(SIG_SETMASK, &lock_sigs, NULL);
-
-       ap.state = ST_SHUTDOWN_PENDING;
-
        /* Where're the boss, tell everyone to finish up */
        if (getpid() == getpgrp())
                signal_children(SIGUSR2);
@@ -844,8 +874,9 @@
        case EXP_ERROR:
        case EXP_PARTIAL:
                /* It didn't work: return to ready */
+               ap.state = ST_READY;
                alarm(ap.exp_runfreq);
-               return st_ready();
+               return 0;

        case EXP_DONE:
                /* All expired: go straight to exit */
@@ -853,8 +884,6 @@
                return 1;

        case EXP_STARTED:
-               /* Wait until expiry process finishes */
-               sigprocmask(SIG_SETMASK, &ready_sigs, NULL);
                return 0;
        }
        return 1;
@@ -865,6 +894,7 @@
        debug("st_prune(): state = %d\n", ap.state);

        assert(ap.state == ST_READY);
+       ap.state = ST_PRUNE;

        /* We're the boss, pass on the prune event */
        if (getpid() == getpgrp()) 
@@ -878,11 +908,10 @@

        case EXP_ERROR:
        case EXP_PARTIAL:
+               ap.state = ST_READY;
                return 1;

        case EXP_STARTED:
-               ap.state = ST_PRUNE;
-               sigprocmask(SIG_SETMASK, &ready_sigs, NULL);
                return 0;
        }
        return 1;
@@ -893,6 +922,7 @@
        debug("st_expire(): state = %d\n", ap.state);

        assert(ap.state == ST_READY);
+       ap.state = ST_EXPIRE;

        switch (expire_proc(0)) {
        case EXP_DONE:
@@ -902,12 +932,11 @@

        case EXP_ERROR:
        case EXP_PARTIAL:
+               ap.state = ST_READY;
                alarm(ap.exp_runfreq);
                return 1;

        case EXP_STARTED:
-               ap.state = ST_EXPIRE;
-               sigprocmask(SIG_SETMASK, &ready_sigs, NULL);
                return 0;
        }
        return 1;
@@ -947,7 +976,7 @@
                if (poll(fds, 2, -1) == -1) {
                        if (errno == EINTR)
                                continue;
-                       syslog(LOG_ERR, "get_pkt: poll failed: %m");
+                       error("get_pkt: poll failed: %m");
                        return -1;
                }

@@ -958,8 +987,7 @@
                        if (fullread(ap.state_pipe[0], &next_state, 
sizeof(next_state)))
                                continue;

-                       sigprocmask(SIG_BLOCK, &lock_sigs, &old);
-
+                       sigprocmask(SIG_BLOCK, &ready_sigs, &old);
                        if (next_state != ap.state) {
                                debug("get_pkt: state %d, next %d",
                                        ap.state, next_state);
@@ -999,9 +1027,7 @@
                                              next_state);
                                }
                        }
-
-                       if (ret)
-                               sigprocmask(SIG_SETMASK, &old, NULL);
+                       sigprocmask(SIG_SETMASK, &old, NULL);

                        if (ap.state == ST_SHUTDOWN)
                                return -1;
@@ -1484,24 +1510,25 @@

  /* Deal with the signals recieved by direct mount supervisor */
  static void sig_supervisor(int sig)
-{
+{ 
+       static struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
+       static struct syslog_data *slc = &syslog_context;
        int save_errno = errno;

        switch (sig) {
        default:                /* all the signals not handled */
-               error("process %d got unexpected signal %d!", getpid(), sig);
+               error_r(slc, "process %d got unexpected signal %d!",
+                       getpid(), sig);
                return;
                /* don't FALLTHROUGH */

        case SIGTERM:
        case SIGUSR2:
-               /* Tell everyone to finish up */
-               signal_children(sig);
+               ap.state = ST_SHUTDOWN_PENDING;
                break;

        case SIGUSR1:
-               /* Pass on the prune event and ignore self signal */
-               signal_children(sig);
+               ap.state = ST_PRUNE;
                break;

        case SIGCHLD:
@@ -1509,12 +1536,8 @@
                break;

        case SIGHUP:
-               ap.lookup->lookup_ghost(ap.path, ap.ghost, 0, 
ap.lookup->context);
-
                /* Pass on the reread event and ignore self signal */
-               kill(0, SIGHUP);
-               discard_pending(SIGHUP);
-
+               ap.state = ST_READMAP;
                break;
        }
        errno = save_errno;
@@ -1522,7 +1545,9 @@

  int supervisor(char *path)
  {
+       sigset_t olds;
        unsigned int map = 0;
+       int ret;

        ap.path = alloca(strlen(path) + 1);
        strcpy(ap.path, path);
@@ -1536,8 +1561,46 @@
                cleanup_exit(ap.path, 1);
        }

+       ap.state = ST_READY;
        setup_signals(sig_supervisor, sig_supervisor);

+       sigprocmask(SIG_BLOCK, &ready_sigs, &olds);
+       while (ap.state != ST_SHUTDOWN) {
+               switch (ap.state) {
+               case ST_READMAP:
+                       ret = st_readmap();
+                       if (!ret)
+                               /* Warn but try to continue anyway */
+                               warn("failed to read map");
+                       signal_children(SIGHUP);
+                       ap.state = ST_READY;
+                       break;
+               case ST_SHUTDOWN_PENDING:
+                       ret = signal_children(SIGUSR2);
+                       if (!ret) {
+                               ap.state = ST_SHUTDOWN;
+                               sigprocmask(SIG_SETMASK, &olds, NULL);
+                               continue;
+                       }
+
+                       /* Failed shutdown returns to ready */
+                       warn("can't shutdown: filesystem %s still busy",
+                                    ap.path);
+                       ap.state = ST_READY;
+                       break;
+               case ST_PRUNE:
+                       /* Pass on the prune event and ignore self signal */
+                       signal_children(SIGUSR1);
+                       ap.state = ST_READY;
+                       break;
+               default:
+                       ap.state = ST_READY;
+                       break;
+               }
+               sigsuspend(&olds);
+       }
+       sigprocmask(SIG_UNBLOCK, &ready_sigs, NULL);
+
        while (waitpid(0, NULL, 0) > 0);

        return 0;
@@ -1644,8 +1707,32 @@
                kill(my_pid, SIGSTOP);

        while (ap.state != ST_SHUTDOWN) {
-               if (handle_packet() && errno != EINTR)
-                       break;
+               if (handle_packet()) {
+                       sigset_t olds;
+                       int ret, status = 0;
+
+                       sigprocmask(SIG_BLOCK, &lock_sigs, &olds);
+                       ret = ioctl(ap.ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status);
+                       /*
+                        * If the ioctl fails assume the kernel doesn't have
+                        * AUTOFS_IOC_ASKUMOUNT and just continue.
+                        */
+                       if (ret) {
+                               sigprocmask(SIG_SETMASK, &olds, NULL);
+                               break;
+                       }
+                       if (status) {
+                               sigprocmask(SIG_SETMASK, &olds, NULL);
+                               break;
+                       }
+
+                       /* Failed shutdown returns to ready */
+                       warn("can't shutdown: filesystem %s still busy",
+                                       ap.path);
+                       alarm(ap.exp_runfreq);
+                       ap.state = ST_READY;
+                       sigprocmask(SIG_SETMASK, &olds, NULL);
+               }
        }

        /* Mop up remaining kids */
diff -Nur autofs-4.1.4.orig/daemon/module.c autofs-4.1.4/daemon/module.c
--- autofs-4.1.4.orig/daemon/module.c   2004-01-30 00:01:22.000000000 +0800
+++ autofs-4.1.4/daemon/module.c        2005-04-23 19:45:36.000000000 +0800
@@ -14,7 +14,6 @@
   * ----------------------------------------------------------------------- */

  #include <stdio.h>
-#include <syslog.h>
  #include <dlfcn.h>
  #include <string.h>
  #include <stdlib.h>
diff -Nur autofs-4.1.4.orig/daemon/mount.c autofs-4.1.4/daemon/mount.c
--- autofs-4.1.4.orig/daemon/mount.c    2004-11-17 22:38:27.000000000 +0800
+++ autofs-4.1.4/daemon/mount.c 2005-04-23 19:45:48.000000000 +0800
@@ -19,7 +19,6 @@
   *
   * ----------------------------------------------------------------------- */

-#include <syslog.h>
  #include <stdlib.h>
  #include <string.h>
  #include "automount.h"
diff -Nur autofs-4.1.4.orig/daemon/spawn.c autofs-4.1.4/daemon/spawn.c
--- autofs-4.1.4.orig/daemon/spawn.c    2005-02-10 20:56:53.000000000 +0800
+++ autofs-4.1.4/daemon/spawn.c 2005-04-23 19:46:01.000000000 +0800
@@ -21,7 +21,6 @@
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
-#include <syslog.h>
  #include <sys/types.h>
  #include <unistd.h>
  #include <time.h>
diff -Nur autofs-4.1.4.orig/include/automount.h autofs-4.1.4/include/automount.h
--- autofs-4.1.4.orig/include/automount.h       2005-01-26 21:03:02.000000000 
+0800
+++ autofs-4.1.4/include/automount.h    2005-04-23 21:54:01.000000000 +0800
@@ -15,6 +15,9 @@
  #include <time.h>
  #include "config.h"

+/* OpenBSD re-entrant syslog */
+#include "syslog.h"
+
  /* We MUST have the paths to mount(8) and umount(8) */
  #ifndef HAVE_MOUNT
  #error Failed to locate mount(8)!
@@ -283,24 +286,78 @@
  int allow_owner_mount(const char *);

  /* log notification */
-extern int do_verbose;
-extern int do_debug;
-
-#define info(msg, args...)             \
-if (do_verbose || do_debug)            \
-       syslog(LOG_INFO, msg, ##args);
-
-#define warn(msg, args...)                     \
-if (do_verbose || do_debug)            \
-       syslog(LOG_WARNING, msg, ##args);
-
-#define error(msg, args...)    syslog(LOG_ERR, msg, ##args);
+extern int do_verbose;         /* Verbose feedback option */
+extern int do_debug;           /* Enable full debug output */

-#define crit(msg, args...)     syslog(LOG_CRIT, msg, ##args);
+/* Define non-reentrant logging macros */

-#define debug(msg, args...)            \
-if (do_debug)                          \
-       syslog(LOG_DEBUG, msg, ##args);
+#define debug(msg, args...)                            \
+do {                                                   \
+       if (do_debug)                                   \
+               syslog(LOG_DEBUG, msg, ##args);         \
+} while (0)
+
+#define info(msg, args...)                             \
+do {                                                   \
+       if (do_verbose || do_debug)                     \
+               syslog(LOG_INFO, msg, ##args);          \
+} while (0)
+
+#define notice(msg, args...)                           \
+do {                                                   \
+       if (do_verbose || do_debug)                     \
+               syslog(LOG_NOTICE, msg, ##args);        \
+} while (0)
+
+#define warn(msg, args...)                             \
+do {                                                   \
+       if (do_verbose || do_debug)                     \
+               syslog(LOG_WARNING, msg, ##args);       \
+} while (0)
+
+#define error(msg, args...)                            \
+do {                                                   \
+       syslog(LOG_ERR, msg, ##args);                   \
+} while (0)
+
+#define crit(msg, args...)                             \
+do {                                                   \
+       syslog(LOG_CRIT, msg, ##args);                  \
+} while (0)
+
+#define alert(msg, args...)                            \
+do {                                                   \
+       syslog(LOG_ALERT, msg, ##args);                 \
+} while (0)
+
+#define emerg(msg, args...)                            \
+do {                                                   \
+       syslog(LOG_EMERG, msg, ##args);                 \
+} while (0)
+
+/* Define reentrant logging macros for signal handlers */
+
+#define debug_r(context, msg, args...)                         \
+do {                                                           \
+       if (do_debug)                                           \
+               syslog_r(LOG_DEBUG, context, msg, ##args);      \
+} while (0)
+
+#define warn_r(context, msg, args...)                          \
+do {                                                           \
+       if (do_verbose || do_debug)                             \
+               syslog_r(LOG_WARNING, context, msg, ##args);    \
+} while (0)
+
+#define error_r(context, msg, args...)                 \
+do {                                                   \
+       syslog_r(LOG_ERR, context, msg, ##args);        \
+} while (0)
+
+#define crit_r(context, msg, args...)                  \
+do {                                                   \
+       syslog_r(LOG_CRIT, context, msg, ##args);       \
+} while (0)

  #endif

diff -Nur autofs-4.1.4.orig/include/syslog.h autofs-4.1.4/include/syslog.h
--- autofs-4.1.4.orig/include/syslog.h  1970-01-01 08:00:00.000000000 +0800
+++ autofs-4.1.4/include/syslog.h       2005-04-24 01:00:58.000000000 +0800
@@ -0,0 +1,201 @@
+/*     $OpenBSD: syslog.h,v 1.11 2003/08/24 01:27:07 avsm Exp $        */
+/*     $NetBSD: syslog.h,v 1.14 1996/04/03 20:46:44 christos Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)syslog.h    8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _SYS_SYSLOG_H_
+#define _SYS_SYSLOG_H_
+
+#include <features.h>
+#define __need___va_list
+#include <stdarg.h>
+
+#define        _PATH_LOG       "/dev/log"
+
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number).  Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code.  This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+#define        LOG_EMERG       0       /* system is unusable */
+#define        LOG_ALERT       1       /* action must be taken immediately */
+#define        LOG_CRIT        2       /* critical conditions */
+#define        LOG_ERR         3       /* error conditions */
+#define        LOG_WARNING     4       /* warning conditions */
+#define        LOG_NOTICE      5       /* normal but significant condition */
+#define        LOG_INFO        6       /* informational */
+#define        LOG_DEBUG       7       /* debug-level messages */
+
+#define        LOG_PRIMASK     0x07    /* mask to extract priority part 
(internal) */
+                               /* extract priority */
+#define        LOG_PRI(p)      ((p) & LOG_PRIMASK)
+#define        LOG_MAKEPRI(fac, pri)   (((fac) << 3) | (pri))
+
+#ifdef SYSLOG_NAMES
+#define        INTERNAL_NOPRI  0x10    /* the "no priority" priority */
+                               /* mark "facility" */
+#define        INTERNAL_MARK   LOG_MAKEPRI(LOG_NFACILITIES, 0)
+typedef struct _code {
+       char    *c_name;
+       int     c_val;
+} CODE;
+
+CODE prioritynames[] = {
+       { "alert",      LOG_ALERT },
+       { "crit",       LOG_CRIT },
+       { "debug",      LOG_DEBUG },
+       { "emerg",      LOG_EMERG },
+       { "err",        LOG_ERR },
+       { "error",      LOG_ERR },              /* DEPRECATED */
+       { "info",       LOG_INFO },
+       { "none",       INTERNAL_NOPRI },       /* INTERNAL */
+       { "notice",     LOG_NOTICE },
+       { "panic",      LOG_EMERG },            /* DEPRECATED */
+       { "warn",       LOG_WARNING },          /* DEPRECATED */
+       { "warning",    LOG_WARNING },
+       { NULL,         -1 },
+};
+#endif
+
+/* facility codes */
+#define        LOG_KERN        (0<<3)  /* kernel messages */
+#define        LOG_USER        (1<<3)  /* random user-level messages */
+#define        LOG_MAIL        (2<<3)  /* mail system */
+#define        LOG_DAEMON      (3<<3)  /* system daemons */
+#define        LOG_AUTH        (4<<3)  /* security/authorization messages */
+#define        LOG_SYSLOG      (5<<3)  /* messages generated internally by 
syslogd */
+#define        LOG_LPR         (6<<3)  /* line printer subsystem */
+#define        LOG_NEWS        (7<<3)  /* network news subsystem */
+#define        LOG_UUCP        (8<<3)  /* UUCP subsystem */
+#define        LOG_CRON        (9<<3)  /* clock daemon */
+#define        LOG_AUTHPRIV    (10<<3) /* security/authorization messages 
(private) */
+#define        LOG_FTP         (11<<3) /* ftp daemon */
+
+       /* other codes through 15 reserved for system use */
+#define        LOG_LOCAL0      (16<<3) /* reserved for local use */
+#define        LOG_LOCAL1      (17<<3) /* reserved for local use */
+#define        LOG_LOCAL2      (18<<3) /* reserved for local use */
+#define        LOG_LOCAL3      (19<<3) /* reserved for local use */
+#define        LOG_LOCAL4      (20<<3) /* reserved for local use */
+#define        LOG_LOCAL5      (21<<3) /* reserved for local use */
+#define        LOG_LOCAL6      (22<<3) /* reserved for local use */
+#define        LOG_LOCAL7      (23<<3) /* reserved for local use */
+
+#define        LOG_NFACILITIES 24      /* current number of facilities */
+#define        LOG_FACMASK     0x03f8  /* mask to extract facility part */
+                               /* facility of pri */
+#define        LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
+
+#ifdef SYSLOG_NAMES
+CODE facilitynames[] = {
+       { "auth",       LOG_AUTH },
+       { "authpriv",   LOG_AUTHPRIV },
+       { "cron",       LOG_CRON },
+       { "daemon",     LOG_DAEMON },
+       { "ftp",        LOG_FTP },
+       { "kern",       LOG_KERN },
+       { "lpr",        LOG_LPR },
+       { "mail",       LOG_MAIL },
+       { "mark",       INTERNAL_MARK },        /* INTERNAL */
+       { "news",       LOG_NEWS },
+       { "security",   LOG_AUTH },             /* DEPRECATED */
+       { "syslog",     LOG_SYSLOG },
+       { "user",       LOG_USER },
+       { "uucp",       LOG_UUCP },
+       { "local0",     LOG_LOCAL0 },
+       { "local1",     LOG_LOCAL1 },
+       { "local2",     LOG_LOCAL2 },
+       { "local3",     LOG_LOCAL3 },
+       { "local4",     LOG_LOCAL4 },
+       { "local5",     LOG_LOCAL5 },
+       { "local6",     LOG_LOCAL6 },
+       { "local7",     LOG_LOCAL7 },
+       { NULL,         -1 },
+};
+#endif
+
+/* Used by reentrant functions */
+
+struct syslog_data {
+       int     log_file;
+       int     connected;
+       int     opened;
+       int     log_stat;
+       const char      *log_tag;
+       int     log_fac;
+       int     log_mask;
+};
+
+#define SYSLOG_DATA_INIT {-1, 0, 0, 0, (const char *)0, LOG_USER, 0xff}
+
+/*
+ * arguments to setlogmask.
+ */
+#define        LOG_MASK(pri)   (1 << (pri))            /* mask for one 
priority */
+#define        LOG_UPTO(pri)   ((1 << ((pri)+1)) - 1)  /* all priorities 
through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define        LOG_PID         0x01    /* log the pid with each message */
+#define        LOG_CONS        0x02    /* log on the console if errors in 
sending */
+#define        LOG_ODELAY      0x04    /* delay open until first syslog() 
(default) */
+#define        LOG_NDELAY      0x08    /* don't delay open */
+#define        LOG_NOWAIT      0x10    /* don't wait for console forks: 
DEPRECATED */
+#define        LOG_PERROR      0x20    /* log to stderr as well */
+
+__BEGIN_DECLS
+void   closelog(void);
+void   openlog(const char *__ident, int __option, int __facility);
+int    setlogmask(int __mask);
+void   syslog(int __pri, const char *__fmt, ...)
+               __attribute__((__format__(__printf__, 2, 3)));
+void   vsyslog(int __pri, const char *, __gnuc_va_list __ap)
+               __attribute__((__format__(__printf__, 2, 0)));
+void   closelog_r(struct syslog_data *__data);
+void   openlog_r(const char *__ident, int __option, int __facility, struct 
syslog_data *__data);
+int    setlogmask_r(int __mask, struct syslog_data *__data);
+void   syslog_r(int __pri, struct syslog_data *__data, const char *__fmt, ...)
+               __attribute__((__format__(__printf__, 3, 4)));
+void   vsyslog_r(int __pri, struct syslog_data *__data, const char *__fmt, 
__gnuc_va_list __ap)
+               __attribute__((__format__(__printf__, 3, 0)));
+__END_DECLS
+
+#endif /* !_SYS_SYSLOG_H_ */
+
diff -Nur autofs-4.1.4.orig/lib/Makefile autofs-4.1.4/lib/Makefile
--- autofs-4.1.4.orig/lib/Makefile      2005-01-09 17:16:43.000000000 +0800
+++ autofs-4.1.4/lib/Makefile   2005-04-23 18:48:53.000000000 +0800
@@ -9,10 +9,12 @@
  RPCGEN = /usr/bin/rpcgen
  RANLIB = /usr/bin/ranlib

-SRCS = cache.c listmount.c cat_path.c rpc_subs.c mounts.c lock.c
+SRCS = cache.c listmount.c cat_path.c rpc_subs.c mounts.c lock.c \
+       syslog.c vsprintf.c
  RPCS = mount.h mount_clnt.c mount_xdr.c
  OBJS = cache.o mount_clnt.o mount_xdr.o listmount.o \
-       cat_path.o rpc_subs.o mounts.o lock.o
+       cat_path.o rpc_subs.o mounts.o lock.o \
+       syslog.o vsprintf.o

  LIB = autofs.a

diff -Nur autofs-4.1.4.orig/lib/cache.c autofs-4.1.4/lib/cache.c
--- autofs-4.1.4.orig/lib/cache.c       2005-02-06 14:00:53.000000000 +0800
+++ autofs-4.1.4/lib/cache.c    2005-04-23 19:46:48.000000000 +0800
@@ -21,7 +21,6 @@
  #include <string.h>
  #include <unistd.h>
  #include <ctype.h>
-#include <syslog.h>
  #include <stdio.h>
  #include <fcntl.h>
  #include <sys/param.h>
diff -Nur autofs-4.1.4.orig/lib/cat_path.c autofs-4.1.4/lib/cat_path.c
--- autofs-4.1.4.orig/lib/cat_path.c    2005-04-06 23:14:23.000000000 +0800
+++ autofs-4.1.4/lib/cat_path.c 2005-04-23 19:47:59.000000000 +0800
@@ -16,7 +16,6 @@
  #include <alloca.h>
  #include <string.h>
  #include <limits.h>
-#include <syslog.h>
  #include <ctype.h>

  /*
diff -Nur autofs-4.1.4.orig/lib/mounts.c autofs-4.1.4/lib/mounts.c
--- autofs-4.1.4.orig/lib/mounts.c      2005-01-17 23:09:28.000000000 +0800
+++ autofs-4.1.4/lib/mounts.c   2005-04-23 19:48:31.000000000 +0800
@@ -16,7 +16,6 @@
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
-#include <syslog.h>
  #include <mntent.h>
  #include <limits.h>
  #include <sys/types.h>
diff -Nur autofs-4.1.4.orig/lib/syslog.c autofs-4.1.4/lib/syslog.c
--- autofs-4.1.4.orig/lib/syslog.c      1970-01-01 08:00:00.000000000 +0800
+++ autofs-4.1.4/lib/syslog.c   2005-04-24 14:29:37.000000000 +0800
@@ -0,0 +1,383 @@
+#ident "$Id$"
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "syslog.h"
+
+#define        TBUF_LEN        2048
+#define        FMT_LEN         1024
+#define        INTERNALLOG     LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
+
+#define        DEC()                                   \
+       do {                                    \
+               if (prlen < 0)                  \
+                       prlen = 0;              \
+               if (prlen >= tbuf_left)         \
+                       prlen = tbuf_left - 1;  \
+               p += prlen;                     \
+               tbuf_left -= prlen;             \
+       } while (0)
+
+/* Use our internal printf routines */
+extern int snprintf_int(char * buf, size_t size, const char * fmt, ...)
+       __attribute__ ((format (printf, 3, 4)));
+extern int vsnprintf_int(char *buf, size_t size, const char *fmt, va_list args)
+       __attribute__ ((format (printf, 3, 0)));
+
+static struct syslog_data sdata = SYSLOG_DATA_INIT;
+static int LogType = SOCK_DGRAM;       /* type of socket connection */
+
+extern char    *__progname;            /* Program name, from crt0. */
+
+static void    disconnectlog_r(struct syslog_data *);  /* disconnect from 
syslogd */
+static void    connectlog_r(struct syslog_data *);     /* (re)connect to 
syslogd */
+
+/*
+ * syslog, vsyslog --
+ *     print message on log file; output is intended for syslogd(8).
+ */
+void
+syslog(int pri, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsyslog(pri, fmt, ap);
+       va_end(ap);
+}
+
+void
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+       vsyslog_r(pri, &sdata, fmt, ap);
+}
+
+void
+openlog(const char *ident, int logstat, int logfac)
+{
+       openlog_r(ident, logstat, logfac, &sdata);
+}
+
+void
+closelog(void)
+{
+       closelog_r(&sdata);
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask(int pmask)
+{
+       return setlogmask_r(pmask, &sdata);
+}
+
+/* Reentrant version of syslog, i.e. syslog_r() */
+
+void
+syslog_r(int pri, struct syslog_data *data, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsyslog_r(pri, data, fmt, ap);
+       va_end(ap);
+}
+
+void
+vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap)
+{
+       int cnt;
+       char ch, *p, *t;
+       time_t now;
+       int fd, saved_errno, error;
+       char *stdp = NULL, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
+       int tbuf_left, fmt_left, prlen;
+
+       /* Check for invalid bits. */
+       if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+               if (data == &sdata) {
+                       syslog(INTERNALLOG,
+                           "syslog: unknown facility/priority: %x", pri);
+               } else {
+                       syslog_r(INTERNALLOG, data,
+                           "syslog_r: unknown facility/priority: %x", pri);
+               }
+               pri &= LOG_PRIMASK|LOG_FACMASK;
+       }
+
+       /* Check priority against setlogmask values. */
+       if (!(LOG_MASK(LOG_PRI(pri)) & data->log_mask))
+               return;
+
+       saved_errno = errno;
+
+       /* Set default facility if none specified. */
+       if ((pri & LOG_FACMASK) == 0)
+               pri |= data->log_fac;
+
+       /* If we have been called through syslog(), no need for reentrancy. */
+       if (data == &sdata)
+               (void)time(&now);
+
+       p = tbuf;
+       tbuf_left = TBUF_LEN;
+
+       prlen = snprintf_int(p, tbuf_left, "<%d>", pri);
+       DEC();
+
+       /* 
+        * syslogd will expand time automagically for reentrant case, and
+        * for normal case, just do like before
+        */
+       if (data == &sdata) {
+               prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
+               DEC();
+       }
+
+       if (data->log_stat & LOG_PERROR)
+               stdp = p;
+       if (data->log_tag == NULL)
+               data->log_tag = __progname;
+       if (data->log_tag != NULL) {
+               prlen = snprintf_int(p, tbuf_left, "%s", data->log_tag);
+               DEC();
+       }
+       if (data->log_stat & LOG_PID) {
+               prlen = snprintf_int(p, tbuf_left, "[%ld]", (long)getpid());
+               DEC();
+       }
+       if (data->log_tag != NULL) {
+               if (tbuf_left > 1) {
+                       *p++ = ':';
+                       tbuf_left--;
+               }
+               if (tbuf_left > 1) {
+                       *p++ = ' ';
+                       tbuf_left--;
+               }
+       }
+
+       /* strerror() is not reentrant */
+
+       for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
+               if (ch == '%' && fmt[1] == 'm') {
+                       ++fmt;
+                       if (data == &sdata) {
+                               prlen = snprintf_int(t, fmt_left, "%s",
+                                   strerror(saved_errno)); 
+                       } else {
+                               prlen = snprintf_int(t, fmt_left, "Error %d",
+                                   saved_errno); 
+                       }
+                       if (prlen < 0)
+                               prlen = 0;
+                       if (prlen >= fmt_left)
+                               prlen = fmt_left - 1;
+                       t += prlen;
+                       fmt_left -= prlen;
+               } else if (ch == '%' && fmt[1] == '%' && fmt_left > 2) {
+                       *t++ = '%';
+                       *t++ = '%';
+                       fmt++;
+                       fmt_left -= 2;
+               } else {
+                       if (fmt_left > 1) {
+                               *t++ = ch;
+                               fmt_left--;
+                       }
+               }
+       }
+       *t = '\0';
+
+       prlen = vsnprintf_int(p, tbuf_left, fmt_cpy, ap);
+       DEC();
+       cnt = p - tbuf;
+
+       /* Output to stderr if requested. */
+       if (data->log_stat & LOG_PERROR) {
+               struct iovec iov[2];
+
+               iov[0].iov_base = stdp;
+               iov[0].iov_len = cnt - (stdp - tbuf);
+               iov[1].iov_base = "\n";
+               iov[1].iov_len = 1;
+               (void)writev(STDERR_FILENO, iov, 2);
+       }
+
+       /* Get connected, output the message to the local logger. */
+       if (!data->opened)
+               openlog_r(data->log_tag, data->log_stat, 0, data);
+       connectlog_r(data);
+
+       /* If we have a SOCK_STREAM connection, also send ASCII NUL as
+          a record terminator.  */
+       if (LogType == SOCK_STREAM)
+               cnt++;
+
+       /*
+        * If the send() failed, there are two likely scenarios:
+        *  1) syslogd was restarted
+        *  2) /dev/log is out of socket buffer space
+        * We attempt to reconnect to /dev/log to take care of
+        * case #1 and keep send()ing data to cover case #2
+        * to give syslogd a chance to empty its socket buffer.
+        */
+       if ((error = send(data->log_file, tbuf, cnt, 0)) < 0) {
+               if (errno != ENOBUFS) {
+                       disconnectlog_r(data);
+                       connectlog_r(data);
+               }
+               do {
+                       usleep(1);
+                       if ((error = send(data->log_file, tbuf, cnt, 0)) >= 0)
+                               break;
+               } while (errno == ENOBUFS);
+       }
+
+       /*
+        * Output the message to the console; try not to block
+        * as a blocking console should not stop other processes.
+        * Make sure the error reported is the one from the syslogd failure.
+        */
+       if (error == -1 && (data->log_stat & LOG_CONS) &&
+           (fd = open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) {
+               struct iovec iov[2];
+ 
+               p = strchr(tbuf, '>') + 1;
+               iov[0].iov_base = p;
+               iov[0].iov_len = cnt - (p - tbuf);
+               iov[1].iov_base = "\r\n";
+               iov[1].iov_len = 2;
+               (void)writev(fd, iov, 2);
+               (void)close(fd);
+       }
+
+       if (data != &sdata)
+               closelog_r(data);
+}
+
+static void
+disconnectlog_r(struct syslog_data *data)
+{
+       /*
+        * If the user closed the FD and opened another in the same slot,
+        * that's their problem.  They should close it before calling on
+        * system services.
+        */
+       if (data->log_file != -1) {
+               close(data->log_file);
+               data->log_file = -1;
+       }
+       data->connected = 0;            /* retry connect */
+}
+
+static void
+connectlog_r(struct syslog_data *data)
+{
+       struct sockaddr_un SyslogAddr;  /* AF_UNIX address of local logger */
+
+again:
+       if (data->log_file == -1) {
+               if ((data->log_file = socket(AF_UNIX, LogType, 0)) == -1)
+                       return;
+               (void)fcntl(data->log_file, F_SETFD, 1);
+       }
+       if (data->log_file != -1 && !data->connected) {
+               int old_errno;
+ 
+               memset(&SyslogAddr, '\0', sizeof(SyslogAddr));
+               SyslogAddr.sun_family = AF_UNIX;
+               strncpy(SyslogAddr.sun_path, _PATH_LOG,
+                   sizeof(SyslogAddr.sun_path));
+               old_errno = errno;
+               if (connect(data->log_file, (struct sockaddr *)&SyslogAddr,
+                   sizeof(SyslogAddr)) == -1) {
+                       int save_errno = errno;
+                       (void)close(data->log_file);
+                       data->log_file = -1;
+                       if (LogType == SOCK_DGRAM && save_errno == EPROTOTYPE) {
+                               /* retry with SOCK_STREAM */
+                               LogType = SOCK_STREAM;
+                               errno = old_errno;
+                               goto again;
+                       }
+               } else
+                       data->connected = 1;
+       }
+}
+
+void
+openlog_r(const char *ident, int logstat, int logfac, struct syslog_data *data)
+{
+       if (ident != NULL)
+               data->log_tag = ident;
+       data->log_stat = logstat;
+       if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+               data->log_fac = logfac;
+
+       if (data->log_stat & LOG_NDELAY)        /* open immediately */
+               connectlog_r(data);
+
+       data->opened = 1;       /* ident and facility has been set */
+}
+
+void
+closelog_r(struct syslog_data *data)
+{
+       (void)close(data->log_file);
+       data->log_file = -1;
+       data->connected = 0;
+       data->log_tag = NULL;
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask_r(int pmask, struct syslog_data *data)
+{
+       int omask;
+
+       omask = data->log_mask;
+       if (pmask != 0)
+               data->log_mask = pmask;
+       return (omask);
+}
diff -Nur autofs-4.1.4.orig/lib/vsprintf.c autofs-4.1.4/lib/vsprintf.c
--- autofs-4.1.4.orig/lib/vsprintf.c    1970-01-01 08:00:00.000000000 +0800
+++ autofs-4.1.4/lib/vsprintf.c 2005-04-24 11:23:36.000000000 +0800
@@ -0,0 +1,619 @@
+#ident "$Id$"
+/*
+ *  Stolen from the linux kernel.
+ *
+ *  License: GPL
+ */
+/*------------------ Original Copyright -----------------*/
+/*
+ *  linux/lib/vsprintf.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/* 
+ * Fri Jul 13 2001 Crutcher Dunnavant <[EMAIL PROTECTED]>
+ * - changed to provide snprintf and vsnprintf functions
+ * So Feb  1 16:51:32 CET 2004 Juergen Quade <[EMAIL PROTECTED]>
+ * - scnprintf and vscnprintf
+ */
+
+/* Also copied from: */
+
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ *
+ * * Fri Jun 25 1999, Ingo Oeser <[EMAIL PROTECTED]>
+ * -  Added strsep() which will replace strtok() soon (because strsep() is
+ *    reentrant and should be faster). Use only strsep() in new code, please.
+ *
+ * * Sat Feb 09 2002, Jason Thomas <[EMAIL PROTECTED]>,
+ *                    Matthew Hawkins <[EMAIL PROTECTED]>
+ * -  Kissed strtok() goodbye
+ */
+/*-------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#define BITS_PER_LONG  __WORDSIZE
+#define PAGE_SIZE      getpagesize()
+
+
+#if BITS_PER_LONG == 64
+
+# define do_div(n,base) ({                                     \
+       uint32_t __base = (base);                               \
+       uint32_t __rem;                                         \
+       __rem = ((uint64_t)(n)) % __base;                       \
+       (n) = ((uint64_t)(n)) / __base;                         \
+       __rem;                                                  \
+ })
+
+#elif BITS_PER_LONG == 32
+
+/* Not needed on 64bit architectures */
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+       uint64_t rem = *n;
+       uint64_t b = base;
+       uint64_t res, d = 1;
+       uint32_t high = rem >> 32;
+
+       /* Reduce the thing a bit first */
+       res = 0;
+       if (high >= base) {
+               high /= base;
+               res = (uint64_t) high << 32;
+               rem -= (uint64_t) (high*base) << 32;
+       }
+
+       while ((int64_t)b > 0 && b < rem) {
+               b = b+b;
+               d = d+d;
+       }
+
+       do {
+               if (rem >= b) {
+                       rem -= b;
+                       res += d;
+               }
+               b >>= 1;
+               d >>= 1;
+       } while (d);
+
+       *n = res;
+       return rem;
+}
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({                             \
+       uint32_t __base = (base);                       \
+       uint32_t __rem;                                 \
+       (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
+       if (((n) >> 32) == 0) {                         \
+               __rem = (uint32_t)(n) % __base;         \
+               (n) = (uint32_t)(n) / __base;           \
+       } else                                          \
+               __rem = __div64_32(&(n), __base);       \
+       __rem;                                          \
+ })
+
+# else
+
+# error do_div() does not yet support the C64
+
+#endif /* BITS_PER_LONG */
+
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+       const char *sc;
+
+       for (sc = s; count-- && *sc != '\0'; ++sc)
+               /* nothing */;
+       return sc - s;
+}
+
+/**
+ * simple_strtoul - convert a string to an unsigned long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+       unsigned long result = 0,value;
+
+       if (!base) {
+               base = 10;
+               if (*cp == '0') {
+                       base = 8;
+                       cp++;
+                       if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+                               cp++;
+                               base = 16;
+                       }
+               }
+       } else if (base == 16) {
+               if (cp[0] == '0' && toupper(cp[1]) == 'X')
+                       cp += 2;
+       }
+       while (isxdigit(*cp) &&
+              (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+               result = result*base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+       return result;
+}
+
+/**
+ * simple_strtol - convert a string to a signed long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+       if(*cp=='-')
+               return -simple_strtoul(cp+1,endp,base);
+       return simple_strtoul(cp,endp,base);
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int 
base)
+{
+       unsigned long long result = 0,value;
+
+       if (!base) {
+               base = 10;
+               if (*cp == '0') {
+                       base = 8;
+                       cp++;
+                       if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+                               cp++;
+                               base = 16;
+                       }
+               }
+       } else if (base == 16) {
+               if (cp[0] == '0' && toupper(cp[1]) == 'X')
+                       cp += 2;
+       }
+       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+           ? toupper(*cp) : *cp)-'A'+10) < base) {
+               result = result*base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+       return result;
+}
+
+/**
+ * simple_strtoll - convert a string to a signed long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long simple_strtoll(const char *cp,char **endp,unsigned int base)
+{
+       if(*cp=='-')
+               return -simple_strtoull(cp+1,endp,base);
+       return simple_strtoull(cp,endp,base);
+}
+
+static int skip_atoi(const char **s)
+{
+       int i=0;
+
+       while (isdigit(**s))
+               i = i*10 + *((*s)++) - '0';
+       return i;
+}
+
+#define ZEROPAD        1               /* pad with zero */
+#define SIGN   2               /* unsigned/signed long */
+#define PLUS   4               /* show plus */
+#define SPACE  8               /* space if plus */
+#define LEFT   16              /* left justified */
+#define SPECIAL        32              /* 0x */
+#define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * buf, char * end, unsigned long long num, int base, 
int size, int precision, int type)
+{
+       char c,sign,tmp[66];
+       const char *digits;
+       static const char small_digits[] = 
"0123456789abcdefghijklmnopqrstuvwxyz";
+       static const char large_digits[] = 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       int i;
+
+       digits = (type & LARGE) ? large_digits : small_digits;
+       if (type & LEFT)
+               type &= ~ZEROPAD;
+       if (base < 2 || base > 36)
+               return NULL;
+       c = (type & ZEROPAD) ? '0' : ' ';
+       sign = 0;
+       if (type & SIGN) {
+               if ((signed long long) num < 0) {
+                       sign = '-';
+                       num = - (signed long long) num;
+                       size--;
+               } else if (type & PLUS) {
+                       sign = '+';
+                       size--;
+               } else if (type & SPACE) {
+                       sign = ' ';
+                       size--;
+               }
+       }
+       if (type & SPECIAL) {
+               if (base == 16)
+                       size -= 2;
+               else if (base == 8)
+                       size--;
+       }
+       i = 0;
+       if (num == 0)
+               tmp[i++]='0';
+       else while (num != 0)
+               tmp[i++] = digits[do_div(num,base)];
+       if (i > precision)
+               precision = i;
+       size -= precision;
+       if (!(type&(ZEROPAD+LEFT))) {
+               while(size-->0) {
+                       if (buf <= end)
+                               *buf = ' ';
+                       ++buf;
+               }
+       }
+       if (sign) {
+               if (buf <= end)
+                       *buf = sign;
+               ++buf;
+       }
+       if (type & SPECIAL) {
+               if (base==8) {
+                       if (buf <= end)
+                               *buf = '0';
+                       ++buf;
+               } else if (base==16) {
+                       if (buf <= end)
+                               *buf = '0';
+                       ++buf;
+                       if (buf <= end)
+                               *buf = digits[33];
+                       ++buf;
+               }
+       }
+       if (!(type & LEFT)) {
+               while (size-- > 0) {
+                       if (buf <= end)
+                               *buf = c;
+                       ++buf;
+               }
+       }
+       while (i < precision--) {
+               if (buf <= end)
+                       *buf = '0';
+               ++buf;
+       }
+       while (i-- > 0) {
+               if (buf <= end)
+                       *buf = tmp[i];
+               ++buf;
+       }
+       while (size-- > 0) {
+               if (buf <= end)
+                       *buf = ' ';
+               ++buf;
+       }
+       return buf;
+}
+
+/**
+ * vsnprintf_int - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * The return value is the number of characters which would
+ * be generated for the given input, excluding the trailing
+ * '\0', as per ISO C99. If you want to have the exact
+ * number of characters written into @buf as return value
+ * (not including the trailing '\0'), use vscnprintf. If the
+ * return is greater than or equal to @size, the resulting
+ * string is truncated.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf instead.
+ */
+int vsnprintf_int(char *buf, size_t size, const char *fmt, va_list args)
+{
+       int len;
+       unsigned long long num;
+       int i, base;
+       char *str, *end, c;
+       const char *s;
+
+       int flags;              /* flags to number() */
+
+       int field_width;        /* width of output field */
+       int precision;          /* min. # of digits for integers; max
+                                  number of chars for from string */
+       int qualifier;          /* 'h', 'l', or 'L' for integer fields */
+                               /* 'z' support added 23/7/1999 S.H.    */
+                               /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+       /* Reject out-of-range values early */
+       if ((int) size < 0)
+               return 0;
+
+       str = buf;
+       end = buf + size - 1;
+
+       if (end < buf - 1) {
+               end = ((void *) -1);
+               size = end - buf + 1;
+       }
+
+       for (; *fmt ; ++fmt) {
+               if (*fmt != '%') {
+                       if (str <= end)
+                               *str = *fmt;
+                       ++str;
+                       continue;
+               }
+
+               /* process flags */
+               flags = 0;
+               repeat:
+                       ++fmt;          /* this also skips first '%' */
+                       switch (*fmt) {
+                               case '-': flags |= LEFT; goto repeat;
+                               case '+': flags |= PLUS; goto repeat;
+                               case ' ': flags |= SPACE; goto repeat;
+                               case '#': flags |= SPECIAL; goto repeat;
+                               case '0': flags |= ZEROPAD; goto repeat;
+                       }
+
+               /* get field width */
+               field_width = -1;
+               if (isdigit(*fmt))
+                       field_width = skip_atoi(&fmt);
+               else if (*fmt == '*') {
+                       ++fmt;
+                       /* it's the next argument */
+                       field_width = va_arg(args, int);
+                       if (field_width < 0) {
+                               field_width = -field_width;
+                               flags |= LEFT;
+                       }
+               }
+
+               /* get the precision */
+               precision = -1;
+               if (*fmt == '.') {
+                       ++fmt; 
+                       if (isdigit(*fmt))
+                               precision = skip_atoi(&fmt);
+                       else if (*fmt == '*') {
+                               ++fmt;
+                               /* it's the next argument */
+                               precision = va_arg(args, int);
+                       }
+                       if (precision < 0)
+                               precision = 0;
+               }
+
+               /* get the conversion qualifier */
+               qualifier = -1;
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+                   *fmt =='Z' || *fmt == 'z') {
+                       qualifier = *fmt;
+                       ++fmt;
+                       if (qualifier == 'l' && *fmt == 'l') {
+                               qualifier = 'L';
+                               ++fmt;
+                       }
+               }
+
+               /* default base */
+               base = 10;
+
+               switch (*fmt) {
+                       case 'c':
+                               if (!(flags & LEFT)) {
+                                       while (--field_width > 0) {
+                                               if (str <= end)
+                                                       *str = ' ';
+                                               ++str;
+                                       }
+                               }
+                               c = (unsigned char) va_arg(args, int);
+                               if (str <= end)
+                                       *str = c;
+                               ++str;
+                               while (--field_width > 0) {
+                                       if (str <= end)
+                                               *str = ' ';
+                                       ++str;
+                               }
+                               continue;
+
+                       case 's':
+                               s = va_arg(args, char *);
+                               if ((unsigned long)s < PAGE_SIZE)
+                                       s = "<NULL>";
+
+                               len = strnlen(s, precision);
+
+                               if (!(flags & LEFT)) {
+                                       while (len < field_width--) {
+                                               if (str <= end)
+                                                       *str = ' ';
+                                               ++str;
+                                       }
+                               }
+                               for (i = 0; i < len; ++i) {
+                                       if (str <= end)
+                                               *str = *s;
+                                       ++str; ++s;
+                               }
+                               while (len < field_width--) {
+                                       if (str <= end)
+                                               *str = ' ';
+                                       ++str;
+                               }
+                               continue;
+
+                       case 'p':
+                               if (field_width == -1) {
+                                       field_width = 2*sizeof(void *);
+                                       flags |= ZEROPAD;
+                               }
+                               str = number(str, end,
+                                               (unsigned long) va_arg(args, 
void *),
+                                               16, field_width, precision, 
flags);
+                               continue;
+
+
+                       case 'n':
+                               /* FIXME:
+                               * What does C99 say about the overflow case 
here? */
+                               if (qualifier == 'l') {
+                                       long * ip = va_arg(args, long *);
+                                       *ip = (str - buf);
+                               } else if (qualifier == 'Z' || qualifier == 
'z') {
+                                       size_t * ip = va_arg(args, size_t *);
+                                       *ip = (str - buf);
+                               } else {
+                                       int * ip = va_arg(args, int *);
+                                       *ip = (str - buf);
+                               }
+                               continue;
+
+                       case '%':
+                               if (str <= end)
+                                       *str = '%';
+                               ++str;
+                               continue;
+
+                               /* integer number formats - set up the flags 
and "break" */
+                       case 'o':
+                               base = 8;
+                               break;
+
+                       case 'X':
+                               flags |= LARGE;
+                       case 'x':
+                               base = 16;
+                               break;
+
+                       case 'd':
+                       case 'i':
+                               flags |= SIGN;
+                       case 'u':
+                               break;
+
+                       default:
+                               if (str <= end)
+                                       *str = '%';
+                               ++str;
+                               if (*fmt) {
+                                       if (str <= end)
+                                               *str = *fmt;
+                                       ++str;
+                               } else {
+                                       --fmt;
+                               }
+                               continue;
+               }
+               if (qualifier == 'L')
+                       num = va_arg(args, long long);
+               else if (qualifier == 'l') {
+                       num = va_arg(args, unsigned long);
+                       if (flags & SIGN)
+                               num = (signed long) num;
+               } else if (qualifier == 'Z' || qualifier == 'z') {
+                       num = va_arg(args, size_t);
+               } else if (qualifier == 'h') {
+                       num = (unsigned short) va_arg(args, int);
+                       if (flags & SIGN)
+                               num = (signed short) num;
+               } else {
+                       num = va_arg(args, unsigned int);
+                       if (flags & SIGN)
+                               num = (signed int) num;
+               }
+               str = number(str, end, num, base,
+                               field_width, precision, flags);
+       }
+       if (str <= end)
+               *str = '\0';
+       else if (size > 0)
+               /* don't write out a null byte if the buf size is zero */
+               *end = '\0';
+       /* the trailing null byte doesn't count towards the total
+       * ++str;
+       */
+       return str-buf;
+}
+
+/**
+ * snprintf_int - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @...: Arguments for the format string
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing null,
+ * as per ISO C99.  If the return is greater than or equal to
+ * @size, the resulting string is truncated.
+ */
+int snprintf_int(char * buf, size_t size, const char *fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i=vsnprintf_int(buf,size,fmt,args);
+       va_end(args);
+       return i;
+}
+

_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs

Reply via email to