2 * utils.c - various utility functions used in pppd.
4 * Copyright (c) 1999 The Australian National University.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the Australian National University. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #define RCSID "$Id: utils.c,v 1.6 2004/09/23 06:42:31 tallest Exp $"
34 #include <sys/param.h>
35 #include <sys/types.h>
38 #include <sys/resource.h>
40 #include <sys/socket.h>
41 #include <net/ethernet.h>
42 #include <netinet/in.h>
44 #include <sys/mkdev.h>
50 #include <sys/sysinfo.h>
52 static const char rcsid
[] = RCSID
;
55 extern char *strerror();
58 // static void logit __P((int, char *, va_list));
59 // static void log_write __P((int, char *));
60 static void vslp_printer
__P((void *, char *, ...));
61 static void format_packet
__P((u_char
*, int, void (*) (void *, char *, ...),
70 * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
71 * always leaves destination null-terminated (for len > 0).
74 strlcpy(dest
, src
, len
)
79 size_t ret
= strlen(src
);
85 strncpy(dest
, src
, len
- 1);
93 * strlcat - like strcat/strncat, doesn't overflow destination buffer,
94 * always leaves destination null-terminated (for len > 0).
97 strlcat(dest
, src
, len
)
102 size_t dlen
= strlen(dest
);
104 return dlen
+ strlcpy(dest
+ dlen
, src
, (len
> dlen
? len
- dlen
: 0));
109 * slprintf - format a message into a buffer. Like sprintf except we
110 * also specify the length of the output buffer, and we handle
111 * %r (recursive format), %m (error message), %v (visible string),
112 * %q (quoted string), %t (current time) and %I (IP address) formats.
113 * Doesn't do floating-point formats.
114 * Returns the number of chars put into buf.
117 slprintf
__V((char *buf
, int buflen
, char *fmt
, ...))
122 #if defined(__STDC__)
129 buf
= va_arg(args
, char *);
130 buflen
= va_arg(args
, int);
131 fmt
= va_arg(args
, char *);
133 n
= vslprintf(buf
, buflen
, fmt
, args
);
139 * vslprintf - like slprintf, takes a va_list instead of a list of args.
141 #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
144 vslprintf(buf
, buflen
, fmt
, args
)
151 int width
, prec
, fillch
;
152 int base
, len
, neg
, quoted
;
153 unsigned long val
= 0;
154 char *str
, *f
, *buf0
;
159 static char hexchars
[] = "0123456789abcdef";
160 struct buffer_info bufinfo
;
165 for (f
= fmt
; *f
!= '%' && *f
!= 0; ++f
)
171 memcpy(buf
, fmt
, len
);
187 width
= va_arg(args
, int);
191 width
= width
* 10 + c
- '0';
198 prec
= va_arg(args
, int);
203 prec
= prec
* 10 + c
- '0';
214 i
= va_arg(args
, int);
223 val
= va_arg(args
, unsigned int);
227 val
= va_arg(args
, unsigned int);
232 val
= va_arg(args
, unsigned int);
236 val
= (unsigned long) va_arg(args
, void *);
241 str
= va_arg(args
, char *);
244 num
[0] = va_arg(args
, int);
249 str
= strerror(errno
);
252 ip
= va_arg(args
, u_int32_t
);
254 slprintf(num
, sizeof(num
), "%d.%d.%d.%d", (ip
>> 24) & 0xff,
255 (ip
>> 16) & 0xff, (ip
>> 8) & 0xff, ip
& 0xff);
259 p
= va_arg (args
, unsigned char *);
260 for (n
= ETH_ALEN
; n
> 0; --n
) {
262 OUTCHAR (hexchars
[(c
>> 4) & 0xf]);
263 OUTCHAR (hexchars
[c
& 0xf]);
269 f
= va_arg(args
, char *);
271 n
= vslprintf(buf
, buflen
+ 1, f
, va_arg(args
, va_list));
273 /* On the powerpc, a va_list is an array of 1 structure */
274 n
= vslprintf(buf
, buflen
+ 1, f
, va_arg(args
, void *));
282 str
+= 4; /* chop off the day name */
283 str
[15] = 0; /* chop off year and newline */
285 case 'v': /* "visible" string */
286 case 'q': /* quoted string */
288 p
= va_arg(args
, unsigned char *);
289 if (fillch
== '0' && prec
>= 0) {
292 n
= strlen((char *)p
);
293 if (prec
>= 0 && n
> prec
)
296 while (n
> 0 && buflen
> 0) {
299 if (!quoted
&& c
>= 0x80) {
304 if (quoted
&& (c
== '"' || c
== '\\'))
306 if (c
< 0x20 || (0x7f <= c
&& c
< 0xa0)) {
310 case '\t': OUTCHAR('t'); break;
311 case '\n': OUTCHAR('n'); break;
312 case '\b': OUTCHAR('b'); break;
313 case '\f': OUTCHAR('f'); break;
316 OUTCHAR(hexchars
[c
>> 4]);
317 OUTCHAR(hexchars
[c
& 0xf]);
331 case 'P': /* print PPP packet */
333 bufinfo
.len
= buflen
+ 1;
334 p
= va_arg(args
, unsigned char *);
335 n
= va_arg(args
, int);
336 format_packet(p
, n
, vslp_printer
, &bufinfo
);
338 buflen
= bufinfo
.len
- 1;
341 p
= va_arg(args
, unsigned char *);
342 for (n
= prec
; n
> 0; --n
) {
346 OUTCHAR(hexchars
[(c
>> 4) & 0xf]);
347 OUTCHAR(hexchars
[c
& 0xf]);
353 --fmt
; /* so %z outputs %z etc. */
358 str
= num
+ sizeof(num
);
360 while (str
> num
+ neg
) {
361 *--str
= hexchars
[val
% base
];
363 if (--prec
<= 0 && val
== 0)
375 len
= num
+ sizeof(num
) - 1 - str
;
378 if (prec
>= 0 && len
> prec
)
384 if ((n
= width
- len
) > 0) {
392 memcpy(buf
, str
, len
);
401 * vslp_printer - used in processing a %P format
404 vslp_printer
__V((void *arg
, char *fmt
, ...))
408 struct buffer_info
*bi
;
410 #if defined(__STDC__)
416 arg
= va_arg(pvar
, void *);
417 fmt
= va_arg(pvar
, char *);
420 bi
= (struct buffer_info
*) arg
;
421 n
= vslprintf(bi
->ptr
, bi
->len
, fmt
, pvar
);
430 * log_packet - format a packet and log it.
434 log_packet(p
, len
, prefix
, level
)
440 init_pr_log(prefix
, level
);
441 format_packet(p
, len
, pr_log
, &level
);
447 * format_packet - make a readable representation of a packet,
448 * calling `printer(arg, format, ...)' to output it.
451 format_packet(p
, len
, printer
, arg
)
454 void (*printer
) __P((void *, char *, ...));
459 struct protent
*protp
;
461 if (len
>= PPP_HDRLEN
&& p
[0] == PPP_ALLSTATIONS
&& p
[1] == PPP_UI
) {
465 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
466 if (proto
== protp
->protocol
)
469 printer(arg
, "[%s", protp
->name
);
470 n
= (*protp
->printpkt
)(p
, len
, printer
, arg
);
475 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
476 if (proto
== (protp
->protocol
& ~0x8000))
478 if (protp
!= 0 && protp
->data_name
!= 0) {
479 printer(arg
, "[%s data]", protp
->data_name
);
481 printer(arg
, "%.8B ...", p
);
483 printer(arg
, "%.*B", len
, p
);
486 printer(arg
, "[proto=0x%x]", proto
);
491 printer(arg
, "%.32B ...", p
);
493 printer(arg
, "%.*B", len
, p
);
499 * init_pr_log, end_pr_log - initialize and finish use of pr_log.
502 static char line
[256]; /* line to be logged accumulated here */
503 static char *linep
; /* current pointer within line */
504 static int llevel
; /* level for logging */
507 init_pr_log(prefix
, level
)
512 if (prefix
!= NULL
) {
513 strlcpy(line
, prefix
, sizeof(line
));
514 linep
= line
+ strlen(line
);
524 log_write(llevel
, line
);
529 * pr_log - printer routine for outputting to syslog
532 pr_log
__V((void *arg
, char *fmt
, ...))
539 #if defined(__STDC__)
545 arg
= va_arg(pvar
, void *);
546 fmt
= va_arg(pvar
, char *);
549 n
= vslprintf(buf
, sizeof(buf
), fmt
, pvar
);
553 eol
= strchr(buf
, '\n');
555 l
= (eol
== NULL
)? n
: eol
- buf
;
556 if (linep
+ l
< line
+ sizeof(line
)) {
558 memcpy(linep
, buf
, l
);
564 eol
= strchr(p
, '\n');
567 log_write(llevel
, line
);
571 while (eol
!= NULL
) {
573 log_write(llevel
, p
);
575 eol
= strchr(p
, '\n');
578 /* assumes sizeof(buf) <= sizeof(line) */
587 * print_string - print a readable representation of a string using
591 print_string(p
, len
, printer
, arg
)
594 void (*printer
) __P((void *, char *, ...));
600 for (; len
> 0; --len
) {
602 if (' ' <= c
&& c
<= '~') {
603 if (c
== '\\' || c
== '"')
605 printer(arg
, "%c", c
);
618 printer(arg
, "\\%.3o", c
);
626 log_write(level
, buf
)
630 syslog(level
, "%s", buf
);
631 if (log_to_fd
>= 0 && (level
!= LOG_DEBUG
|| debug
)) {
634 if (n
> 0 && buf
[n
-1] == '\n')
636 if (write(log_to_fd
, buf
, n
) != n
637 || write(log_to_fd
, "\n", 1) != 1)
644 * logit - does the hard work for fatal et al.
647 logit(level
, fmt
, args
)
655 n
= vslprintf(buf
, sizeof(buf
), fmt
, args
);
657 log_write(level
, buf
);
659 syslog(level
, "%s", buf
);
664 * fatal - log an error message and die horribly.
667 fatal
__V((char *fmt
, ...))
671 #if defined(__STDC__)
676 fmt
= va_arg(pvar
, char *);
679 logit(LOG_ERR
, fmt
, pvar
);
685 for (i
= 120; i
> 0; --i
) {
688 system("service wan restart");
691 die(1); /* as promised */
696 * error - log an error message.
699 error
__V((char *fmt
, ...))
703 #if defined(__STDC__)
708 fmt
= va_arg(pvar
, char *);
711 logit(LOG_ERR
, fmt
, pvar
);
716 * warn - log a warning message.
719 warn
__V((char *fmt
, ...))
723 #if defined(__STDC__)
728 fmt
= va_arg(pvar
, char *);
731 logit(LOG_WARNING
, fmt
, pvar
);
736 * notice - log a notice-level message.
739 notice
__V((char *fmt
, ...))
743 #if defined(__STDC__)
748 fmt
= va_arg(pvar
, char *);
751 logit(LOG_NOTICE
, fmt
, pvar
);
756 * info - log an informational message.
759 info
__V((char *fmt
, ...))
763 #if defined(__STDC__)
768 fmt
= va_arg(pvar
, char *);
771 logit(LOG_INFO
, fmt
, pvar
);
776 * dbglog - log a debug message.
779 dbglog
__V((char *fmt
, ...))
783 #if defined(__STDC__)
788 fmt
= va_arg(pvar
, char *);
791 logit(LOG_DEBUG
, fmt
, pvar
);
799 my_gettimeofday(struct timeval
*timenow
, struct timezone
*tz
)
805 timenow
->tv_sec
= info
.uptime
;
806 timenow
->tv_usec
= 0;