* 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 *);
* 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;
#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;
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':
OUTCHAR(c);
}
continue;
+#ifndef UNIT_TEST
case 'P': /* print PPP packet */
bufinfo.ptr = buf;
bufinfo.len = buflen + 1;
buf = bufinfo.ptr;
buflen = bufinfo.len - 1;
continue;
+#endif
case 'B':
p = va_arg(args, unsigned char *);
for (n = prec; n > 0; --n) {
}
#endif /* unused */
+#ifndef UNIT_TEST
/*
* format_packet - make a readable representation of a packet,
* calling `printer(arg, format, ...)' to output it.
else
printer(arg, "%.*B", len, p);
}
+#endif /* UNIT_TEST */
/*
* init_pr_log, end_pr_log - initialize and finish use of pr_log.
* 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];
log_write(level, buf);
}
+#ifndef UNIT_TEST
static void
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;
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;
* warn - log a warning message.
*/
void
-warn(char *fmt, ...)
+warn(const char *fmt, ...)
{
va_list pvar;
* notice - log a notice-level message.
*/
void
-notice(char *fmt, ...)
+notice(const char *fmt, ...)
{
va_list pvar;
* info - log an informational message.
*/
void
-info(char *fmt, ...)
+info(const char *fmt, ...)
{
va_list pvar;
* dbglog - log a debug message.
*/
void
-dbglog(char *fmt, ...)
+dbglog(const char *fmt, ...)
{
va_list pvar;
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.
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;
}
}
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];
/*
#else /* LOCKLIB */
char lock_buffer[12];
- int fd, pid, n;
+ int fd, pid, n, siz;
#ifdef SVR4
struct stat sbuf;
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;
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) {
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;
return -1;
#else /* LOCKLIB */
- int fd;
+ int fd, n, siz;
char lock_buffer[12];
if (lock_file[0] == 0)
}
#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;