]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/utils.c
pppd.8: Document netmask option
[ppp.git] / pppd / utils.c
index 7228279ec000517a07bb15a6342141a77423203d..bf9923ce362224d8c2095648b37202587f51f777 100644 (file)
@@ -17,7 +17,7 @@
  * 3. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by Paul Mackerras
- *     <paulus@samba.org>".
+ *     <paulus@ozlabs.org>".
  *
  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/mkdev.h>
 #endif
 
-#include "pppd.h"
+#include "pppd-private.h"
 #include "fsm.h"
 #include "lcp.h"
+#include "pathnames.h"
 
 
 #if defined(SUNOS4)
 extern char *strerror();
 #endif
 
-static void logit(int, char *, va_list);
+static void logit(int, const char *, va_list);
 static void log_write(int, char *);
 static void vslp_printer(void *, char *, ...);
 static void format_packet(u_char *, int, printer_func, void *);
@@ -115,7 +120,7 @@ strlcat(char *dest, const char *src, size_t len)
  * Returns the number of chars put into buf.
  */
 int
-slprintf(char *buf, int buflen, char *fmt, ...)
+slprintf(char *buf, int buflen, const char *fmt, ...)
 {
     va_list args;
     int n;
@@ -132,13 +137,15 @@ slprintf(char *buf, int buflen, char *fmt, ...)
 #define OUTCHAR(c)     (buflen > 0? (--buflen, *buf++ = (c)): 0)
 
 int
-vslprintf(char *buf, int buflen, char *fmt, va_list args)
+vslprintf(char *buf, int buflen, const char *fmt, va_list args)
 {
     int c, i, n;
     int width, prec, fillch;
     int base, len, neg, quoted;
+    long lval = 0;
     unsigned long val = 0;
-    char *str, *f, *buf0;
+    char *str, *buf0;
+    const char *f;
     unsigned char *p;
     char num[32];
     time_t t;
@@ -202,11 +209,12 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args)
            c = *fmt++;
            switch (c) {
            case 'd':
-               val = va_arg(args, long);
-               if (val < 0) {
+               lval = va_arg(args, long);
+               if (lval < 0) {
                    neg = 1;
-                   val = -val;
-               }
+                   val = -lval;
+               } else
+                   val = lval;
                base = 10;
                break;
            case 'u':
@@ -323,6 +331,7 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args)
                    OUTCHAR(c);
            }
            continue;
+#ifndef UNIT_TEST
        case 'P':               /* print PPP packet */
            bufinfo.ptr = buf;
            bufinfo.len = buflen + 1;
@@ -332,6 +341,7 @@ vslprintf(char *buf, int buflen, char *fmt, va_list args)
            buf = bufinfo.ptr;
            buflen = bufinfo.len - 1;
            continue;
+#endif
        case 'B':
            p = va_arg(args, unsigned char *);
            for (n = prec; n > 0; --n) {
@@ -426,6 +436,7 @@ log_packet(u_char *p, int len, char *prefix, int level)
 }
 #endif /* unused */
 
+#ifndef UNIT_TEST
 /*
  * format_packet - make a readable representation of a packet,
  * calling `printer(arg, format, ...)' to output it.
@@ -471,6 +482,7 @@ format_packet(u_char *p, int len, printer_func printer, void *arg)
     else
        printer(arg, "%.*B", len, p);
 }
+#endif  /* UNIT_TEST */
 
 /*
  * init_pr_log, end_pr_log - initialize and finish use of pr_log.
@@ -589,7 +601,7 @@ print_string(char *p, int len, printer_func printer, void *arg)
  * logit - does the hard work for fatal et al.
  */
 static void
-logit(int level, char *fmt, va_list args)
+logit(int level, const char *fmt, va_list args)
 {
     char buf[1024];
 
@@ -597,6 +609,7 @@ logit(int level, char *fmt, va_list args)
     log_write(level, buf);
 }
 
+#ifndef UNIT_TEST
 static void
 log_write(int level, char *buf)
 {
@@ -611,12 +624,19 @@ log_write(int level, char *buf)
            log_to_fd = -1;
     }
 }
+#else
+static void
+log_write(int level, char *buf)
+{
+    printf("<%d>: %s\n", level, buf);
+}
+#endif
 
 /*
  * fatal - log an error message and die horribly.
  */
 void
-fatal(char *fmt, ...)
+fatal(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -625,14 +645,18 @@ fatal(char *fmt, ...)
     logit(LOG_ERR, fmt, pvar);
     va_end(pvar);
 
+#ifndef UNIT_TEST
     die(1);                    /* as promised */
+#else
+    exit(-1);
+#endif
 }
 
 /*
  * error - log an error message.
  */
 void
-error(char *fmt, ...)
+error(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -647,7 +671,7 @@ error(char *fmt, ...)
  * warn - log a warning message.
  */
 void
-warn(char *fmt, ...)
+warn(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -661,7 +685,7 @@ warn(char *fmt, ...)
  * notice - log a notice-level message.
  */
 void
-notice(char *fmt, ...)
+notice(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -675,7 +699,7 @@ notice(char *fmt, ...)
  * info - log an informational message.
  */
 void
-info(char *fmt, ...)
+info(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -689,7 +713,7 @@ info(char *fmt, ...)
  * dbglog - log a debug message.
  */
 void
-dbglog(char *fmt, ...)
+dbglog(const char *fmt, ...)
 {
     va_list pvar;
 
@@ -729,6 +753,8 @@ dump_packet(const char *tag, unsigned char *p, int len)
     dbglog("%s %P", tag, p, len);
 }
 
+
+#ifndef UNIT_TEST
 /*
  * complete_read - read a full `count' bytes from fd,
  * unless end-of-file or an error other than EINTR is encountered.
@@ -743,7 +769,7 @@ complete_read(int fd, void *buf, size_t count)
        for (done = 0; done < count; ) {
                nb = read(fd, ptr, count - done);
                if (nb < 0) {
-                       if (errno == EINTR && !got_sigterm)
+                       if (errno == EINTR && !ppp_signaled(SIGTERM))
                                continue;
                        return -1;
                }
@@ -754,20 +780,91 @@ complete_read(int fd, void *buf, size_t count)
        }
        return done;
 }
-
-/* Procedures for locking the serial device using a lock file. */
-#ifndef LOCK_DIR
-#ifdef __linux__
-#define LOCK_DIR       "/var/lock"
-#else
-#ifdef SVR4
-#define LOCK_DIR       "/var/spool/locks"
-#else
-#define LOCK_DIR       "/var/spool/lock"
-#endif
 #endif
-#endif /* LOCK_DIR */
 
+/*
+ * mkdir_check - helper for mkdir_recursive, creates a directory
+ * but do not error on EEXIST if and only if entry is a directory
+ * The caller must check for errno == ENOENT if appropriate.
+ */
+static int
+mkdir_check(const char *path)
+{
+    struct stat statbuf;
+
+    if (mkdir(path, 0755) >= 0)
+       return 0;
+
+    if (errno == EEXIST) {
+       if (stat(path, &statbuf) < 0)
+           /* got raced? */
+           return -1;
+
+       if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
+           return 0;
+
+       /* already exists but not a dir, treat as failure */
+       errno = EEXIST;
+       return -1;
+    }
+
+    return -1;
+}
+
+/*
+ * mkdir_parent - helper for mkdir_recursive, modifies the string in place
+ * Assumes mkdir(path) already failed, so it first creates the parent then
+ * full path again.
+ */
+static int
+mkdir_parent(char *path)
+{
+    char *slash;
+    int rc;
+
+    slash = strrchr(path, '/');
+    if (!slash)
+       return -1;
+
+    *slash = 0;
+    if (mkdir_check(path) < 0) {
+       if (errno != ENOENT) {
+           *slash = '/';
+           return -1;
+       }
+       if (mkdir_parent(path) < 0) {
+           *slash = '/';
+           return -1;
+       }
+    }
+    *slash = '/';
+
+    return mkdir_check(path);
+}
+
+/*
+ * mkdir_recursive - recursively create directory if it didn't exist
+ */
+int
+mkdir_recursive(const char *path)
+{
+    char *copy;
+    int rc;
+
+    // optimistically try on full path first to avoid allocation
+    if (mkdir_check(path) == 0)
+       return 0;
+
+    copy = strdup(path);
+    if (!copy)
+       return -1;
+
+    rc = mkdir_parent(copy);
+    free(copy);
+    return rc;
+}
+
+/* Procedures for locking the serial device using a lock file. */
 static char lock_file[MAXPATHLEN];
 
 /*
@@ -794,7 +891,7 @@ lock(char *dev)
 #else /* LOCKLIB */
 
     char lock_buffer[12];
-    int fd, pid, n;
+    int fd, pid, n, siz;
 
 #ifdef SVR4
     struct stat sbuf;
@@ -808,7 +905,7 @@ lock(char *dev)
        return -1;
     }
     slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
-            LOCK_DIR, major(sbuf.st_dev),
+            PPP_PATH_LOCKDIR, major(sbuf.st_dev),
             major(sbuf.st_rdev), minor(sbuf.st_rdev));
 #else
     char *p;
@@ -826,7 +923,7 @@ lock(char *dev)
        if ((p = strrchr(dev, '/')) != NULL)
            dev = p + 1;
 
-    slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
+    slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", PPP_PATH_LOCKDIR, dev);
 #endif
 
     while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
@@ -881,11 +978,16 @@ lock(char *dev)
 
     pid = getpid();
 #ifndef LOCK_BINARY
+    siz = 11;
     slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
-    write (fd, lock_buffer, 11);
+    n = write (fd, lock_buffer, siz);
 #else
-    write(fd, &pid, sizeof (pid));
+    siz = sizeof (pid);
+    n = write(fd, &pid, siz);
 #endif
+    if (n != siz) {
+       error("Could not write pid to lock file when locking");
+    }
     close(fd);
     return 0;
 
@@ -909,7 +1011,7 @@ relock(int pid)
     return -1;
 #else /* LOCKLIB */
 
-    int fd;
+    int fd, n, siz;
     char lock_buffer[12];
 
     if (lock_file[0] == 0)
@@ -922,11 +1024,16 @@ relock(int pid)
     }
 
 #ifndef LOCK_BINARY
+    siz = 11;
     slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
-    write (fd, lock_buffer, 11);
+    n = write (fd, lock_buffer, siz);
 #else
-    write(fd, &pid, sizeof(pid));
+    siz = sizeof(pid);
+    n = write(fd, &pid, siz);
 #endif /* LOCK_BINARY */
+    if (n != siz) {
+       error("Could not write pid to lock file when locking");
+    }
     close(fd);
     return 0;