X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Futils.c;h=e75bb9c8eecd21279a999c18f8c0bc4f132ef1e3;hb=4a54e34cf5629f9fed61f0b7d69ee3ba4d874bc6;hp=580363a950dec0ee7f77afb1681c60f2880217b3;hpb=cc593def97b4f6f271fad15805b61c4773c4e30a;p=ppp.git diff --git a/pppd/utils.c b/pppd/utils.c index 580363a..e75bb9c 100644 --- a/pppd/utils.c +++ b/pppd/utils.c @@ -1,24 +1,38 @@ /* * utils.c - various utility functions used in pppd. * - * Copyright (c) 1999 The Australian National University. - * All rights reserved. + * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the Australian National University. The name of the University - * may not be used to endorse or promote products derived from this - * software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * 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. The name(s) of the authors of this software must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 3. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Paul Mackerras + * ". + * + * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: utils.c,v 1.14 2001/05/23 03:39:14 paulus Exp $" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include #include #include #include @@ -29,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -47,17 +62,15 @@ #include "fsm.h" #include "lcp.h" -static const char rcsid[] = RCSID; #if defined(SUNOS4) extern char *strerror(); #endif -static void logit __P((int, char *, va_list)); -static void log_write __P((int, char *)); -static void vslp_printer __P((void *, char *, ...)); -static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), - void *)); +static void logit(int, 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 *); struct buffer_info { char *ptr; @@ -69,10 +82,7 @@ struct buffer_info { * always leaves destination null-terminated (for len > 0). */ size_t -strlcpy(dest, src, len) - char *dest; - const char *src; - size_t len; +strlcpy(char *dest, const char *src, size_t len) { size_t ret = strlen(src); @@ -92,10 +102,7 @@ strlcpy(dest, src, len) * always leaves destination null-terminated (for len > 0). */ size_t -strlcat(dest, src, len) - char *dest; - const char *src; - size_t len; +strlcat(char *dest, const char *src, size_t len) { size_t dlen = strlen(dest); @@ -106,28 +113,18 @@ strlcat(dest, src, len) /* * slprintf - format a message into a buffer. Like sprintf except we * also specify the length of the output buffer, and we handle - * %r (recursive format), %m (error message), %v (visible string), + * %m (error message), %v (visible string), * %q (quoted string), %t (current time) and %I (IP address) formats. * Doesn't do floating-point formats. * Returns the number of chars put into buf. */ int -slprintf __V((char *buf, int buflen, char *fmt, ...)) +slprintf(char *buf, int buflen, char *fmt, ...) { va_list args; int n; -#if defined(__STDC__) va_start(args, fmt); -#else - char *buf; - int buflen; - char *fmt; - va_start(args); - buf = va_arg(args, char *); - buflen = va_arg(args, int); - fmt = va_arg(args, char *); -#endif n = vslprintf(buf, buflen, fmt, args); va_end(args); return n; @@ -139,15 +136,12 @@ slprintf __V((char *buf, int buflen, char *fmt, ...)) #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) int -vslprintf(buf, buflen, fmt, args) - char *buf; - int buflen; - char *fmt; - va_list args; +vslprintf(char *buf, int buflen, 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; unsigned char *p; @@ -156,6 +150,7 @@ vslprintf(buf, buflen, fmt, args) u_int32_t ip; static char hexchars[] = "0123456789abcdef"; struct buffer_info bufinfo; + int termch; buf0 = buf; --buflen; @@ -208,6 +203,29 @@ vslprintf(buf, buflen, fmt, args) neg = 0; ++fmt; switch (c) { + case 'l': + c = *fmt++; + switch (c) { + case 'd': + lval = va_arg(args, long); + if (lval < 0) { + neg = 1; + val = -lval; + } else + val = lval; + base = 10; + break; + case 'u': + val = va_arg(args, unsigned long); + base = 10; + break; + default: + OUTCHAR('%'); + OUTCHAR('l'); + --fmt; /* so %lz outputs %lz etc. */ + continue; + } + break; case 'd': i = va_arg(args, int); if (i < 0) { @@ -253,17 +271,6 @@ vslprintf(buf, buflen, fmt, args) (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); str = num; break; - case 'r': - f = va_arg(args, char *); -#ifndef __powerpc__ - n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list)); -#else - /* On the powerpc, a va_list is an array of 1 structure */ - n = vslprintf(buf, buflen + 1, f, va_arg(args, void *)); -#endif - buf += n; - buflen -= n; - continue; case 't': time(&t); str = ctime(&t); @@ -274,15 +281,21 @@ vslprintf(buf, buflen, fmt, args) case 'q': /* quoted string */ quoted = c == 'q'; p = va_arg(args, unsigned char *); + if (p == NULL) + p = (unsigned char *)""; if (fillch == '0' && prec >= 0) { n = prec; + termch = -1; /* matches no unsigned char value */ } else { - n = strlen((char *)p); - if (prec >= 0 && n > prec) + n = buflen; + if (prec != -1 && n > prec) n = prec; + termch = 0; /* stop on null byte */ } while (n > 0 && buflen > 0) { c = *p++; + if (c == termch) + break; --n; if (!quoted && c >= 0x80) { OUTCHAR('M'); @@ -316,6 +329,7 @@ vslprintf(buf, buflen, fmt, args) OUTCHAR(c); } continue; +#ifndef UNIT_TEST case 'P': /* print PPP packet */ bufinfo.ptr = buf; bufinfo.len = buflen + 1; @@ -325,6 +339,7 @@ vslprintf(buf, buflen, fmt, args) buf = bufinfo.ptr; buflen = bufinfo.len - 1; continue; +#endif case 'B': p = va_arg(args, unsigned char *); for (n = prec; n > 0; --n) { @@ -362,9 +377,9 @@ vslprintf(buf, buflen, fmt, args) } len = num + sizeof(num) - 1 - str; } else { - len = strlen(str); - if (prec >= 0 && len > prec) - len = prec; + for (len = 0; len < buflen && (prec == -1 || len < prec); ++len) + if (str[len] == 0) + break; } if (width > 0) { if (width > buflen) @@ -389,21 +404,13 @@ vslprintf(buf, buflen, fmt, args) * vslp_printer - used in processing a %P format */ static void -vslp_printer __V((void *arg, char *fmt, ...)) +vslp_printer(void *arg, char *fmt, ...) { int n; va_list pvar; struct buffer_info *bi; -#if defined(__STDC__) va_start(pvar, fmt); -#else - void *arg; - char *fmt; - va_start(pvar); - arg = va_arg(pvar, void *); - fmt = va_arg(pvar, char *); -#endif bi = (struct buffer_info *) arg; n = vslprintf(bi->ptr, bi->len, fmt, pvar); @@ -419,11 +426,7 @@ vslp_printer __V((void *arg, char *fmt, ...)) */ void -log_packet(p, len, prefix, level) - u_char *p; - int len; - char *prefix; - int level; +log_packet(u_char *p, int len, char *prefix, int level) { init_pr_log(prefix, level); format_packet(p, len, pr_log, &level); @@ -431,16 +434,13 @@ log_packet(p, len, prefix, level) } #endif /* unused */ +#ifndef UNIT_TEST /* * format_packet - make a readable representation of a packet, * calling `printer(arg, format, ...)' to output it. */ static void -format_packet(p, len, printer, arg) - u_char *p; - int len; - void (*printer) __P((void *, char *, ...)); - void *arg; +format_packet(u_char *p, int len, printer_func printer, void *arg) { int i, n; u_short proto; @@ -480,6 +480,7 @@ format_packet(p, len, printer, arg) else printer(arg, "%.*B", len, p); } +#endif /* UNIT_TEST */ /* * init_pr_log, end_pr_log - initialize and finish use of pr_log. @@ -490,9 +491,7 @@ static char *linep; /* current pointer within line */ static int llevel; /* level for logging */ void -init_pr_log(prefix, level) - char *prefix; - int level; +init_pr_log(const char *prefix, int level) { linep = line; if (prefix != NULL) { @@ -503,7 +502,7 @@ init_pr_log(prefix, level) } void -end_pr_log() +end_pr_log(void) { if (linep != line) { *linep = 0; @@ -515,22 +514,14 @@ end_pr_log() * pr_log - printer routine for outputting to syslog */ void -pr_log __V((void *arg, char *fmt, ...)) +pr_log(void *arg, char *fmt, ...) { int l, n; va_list pvar; char *p, *eol; char buf[256]; -#if defined(__STDC__) va_start(pvar, fmt); -#else - void *arg; - char *fmt; - va_start(pvar); - arg = va_arg(pvar, void *); - fmt = va_arg(pvar, char *); -#endif n = vslprintf(buf, sizeof(buf), fmt, pvar); va_end(pvar); @@ -574,11 +565,7 @@ pr_log __V((void *arg, char *fmt, ...)) * printer. */ void -print_string(p, len, printer, arg) - char *p; - int len; - void (*printer) __P((void *, char *, ...)); - void *arg; +print_string(char *p, int len, printer_func printer, void *arg) { int c; @@ -601,7 +588,7 @@ print_string(p, len, printer, arg) printer(arg, "\\t"); break; default: - printer(arg, "\\%.3o", c); + printer(arg, "\\%.3o", (unsigned char) c); } } } @@ -612,22 +599,17 @@ print_string(p, len, printer, arg) * logit - does the hard work for fatal et al. */ static void -logit(level, fmt, args) - int level; - char *fmt; - va_list args; +logit(int level, char *fmt, va_list args) { - int n; char buf[1024]; - n = vslprintf(buf, sizeof(buf), fmt, args); + vslprintf(buf, sizeof(buf), fmt, args); log_write(level, buf); } +#ifndef UNIT_TEST static void -log_write(level, buf) - int level; - char *buf; +log_write(int level, char *buf) { syslog(level, "%s", buf); if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { @@ -640,64 +622,58 @@ log_write(level, 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 __V((char *fmt, ...)) +fatal(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif 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 __V((char *fmt, ...)) +error(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif logit(LOG_ERR, fmt, pvar); va_end(pvar); + ++error_count; } /* * warn - log a warning message. */ void -warn __V((char *fmt, ...)) +warn(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif logit(LOG_WARNING, fmt, pvar); va_end(pvar); @@ -707,17 +683,11 @@ warn __V((char *fmt, ...)) * notice - log a notice-level message. */ void -notice __V((char *fmt, ...)) +notice(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif logit(LOG_NOTICE, fmt, pvar); va_end(pvar); @@ -727,17 +697,11 @@ notice __V((char *fmt, ...)) * info - log an informational message. */ void -info __V((char *fmt, ...)) +info(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif logit(LOG_INFO, fmt, pvar); va_end(pvar); @@ -747,17 +711,11 @@ info __V((char *fmt, ...)) * dbglog - log a debug message. */ void -dbglog __V((char *fmt, ...)) +dbglog(char *fmt, ...) { va_list pvar; -#if defined(__STDC__) va_start(pvar, fmt); -#else - char *fmt; - va_start(pvar); - fmt = va_arg(pvar, char *); -#endif logit(LOG_DEBUG, fmt, pvar); va_end(pvar); @@ -790,12 +748,41 @@ dump_packet(const char *tag, unsigned char *p, int len) return; } - dbglog("%s %P", tag, p - PPP_HDRLEN, len + PPP_HDRLEN); + 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. + */ +ssize_t +complete_read(int fd, void *buf, size_t count) +{ + size_t done; + ssize_t nb; + char *ptr = buf; + + for (done = 0; done < count; ) { + nb = read(fd, ptr, count - done); + if (nb < 0) { + if (errno == EINTR && !got_sigterm) + continue; + return -1; + } + if (nb == 0) + break; + done += nb; + ptr += nb; + } + return done; +} +#endif + /* Procedures for locking the serial device using a lock file. */ #ifndef LOCK_DIR -#ifdef _linux_ +#ifdef __linux__ #define LOCK_DIR "/var/lock" #else #ifdef SVR4 @@ -812,15 +799,14 @@ static char lock_file[MAXPATHLEN]; * lock - create a lock file for the named device */ int -lock(dev) - char *dev; +lock(char *dev) { #ifdef LOCKLIB int result; result = mklock (dev, (void *) 0); if (result == 0) { - strlcpy(lock_file, sizeof(lock_file), dev); + strlcpy(lock_file, dev, sizeof(lock_file)); return 0; } @@ -833,7 +819,7 @@ lock(dev) #else /* LOCKLIB */ char lock_buffer[12]; - int fd, pid, n; + int fd, pid, n, siz; #ifdef SVR4 struct stat sbuf; @@ -851,9 +837,20 @@ lock(dev) major(sbuf.st_rdev), minor(sbuf.st_rdev)); #else char *p; + char lockdev[MAXPATHLEN]; + + if ((p = strstr(dev, "dev/")) != NULL) { + dev = p + 4; + strncpy(lockdev, dev, MAXPATHLEN-1); + lockdev[MAXPATHLEN-1] = 0; + while ((p = strrchr(lockdev, '/')) != NULL) { + *p = '_'; + } + dev = lockdev; + } else + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; - if ((p = strrchr(dev, '/')) != NULL) - dev = p + 1; slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); #endif @@ -909,11 +906,16 @@ lock(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; @@ -930,15 +932,14 @@ lock(dev) * between when the parent died and the child rewrote the lockfile). */ int -relock(pid) - int pid; +relock(int pid) { #ifdef LOCKLIB /* XXX is there a way to do this? */ return -1; #else /* LOCKLIB */ - int fd; + int fd, n, siz; char lock_buffer[12]; if (lock_file[0] == 0) @@ -951,11 +952,16 @@ relock(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; @@ -966,7 +972,7 @@ relock(pid) * unlock - remove our lockfile */ void -unlock() +unlock(void) { if (lock_file[0]) { #ifdef LOCKLIB