1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * utils.c - various utility functions used in pppd. 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * Copyright (c) 2000-2001 by Sun Microsystems, Inc. 5*0Sstevel@tonic-gate * All rights reserved. 6*0Sstevel@tonic-gate * 7*0Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its 8*0Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright 9*0Sstevel@tonic-gate * notice appears in all copies. 10*0Sstevel@tonic-gate * 11*0Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF 12*0Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13*0Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 14*0Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR 15*0Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 16*0Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES 17*0Sstevel@tonic-gate * 18*0Sstevel@tonic-gate * Copyright (c) 1999 The Australian National University. 19*0Sstevel@tonic-gate * All rights reserved. 20*0Sstevel@tonic-gate * 21*0Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 22*0Sstevel@tonic-gate * provided that the above copyright notice and this paragraph are 23*0Sstevel@tonic-gate * duplicated in all such forms and that any documentation, 24*0Sstevel@tonic-gate * advertising materials, and other materials related to such 25*0Sstevel@tonic-gate * distribution and use acknowledge that the software was developed 26*0Sstevel@tonic-gate * by the Australian National University. The name of the University 27*0Sstevel@tonic-gate * may not be used to endorse or promote products derived from this 28*0Sstevel@tonic-gate * software without specific prior written permission. 29*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 30*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 31*0Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*0Sstevel@tonic-gate #define RCSID "$Id: utils.c,v 1.10 2000/03/27 01:36:48 paulus Exp $" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #ifdef __linux__ 38*0Sstevel@tonic-gate #define _GNU_SOURCE 39*0Sstevel@tonic-gate #endif 40*0Sstevel@tonic-gate #include <stdio.h> 41*0Sstevel@tonic-gate #include <ctype.h> 42*0Sstevel@tonic-gate #include <stdlib.h> 43*0Sstevel@tonic-gate #include <string.h> 44*0Sstevel@tonic-gate #include <unistd.h> 45*0Sstevel@tonic-gate #include <signal.h> 46*0Sstevel@tonic-gate #include <errno.h> 47*0Sstevel@tonic-gate #include <fcntl.h> 48*0Sstevel@tonic-gate #include <syslog.h> 49*0Sstevel@tonic-gate #include <netdb.h> 50*0Sstevel@tonic-gate #include <utmp.h> 51*0Sstevel@tonic-gate #include <pwd.h> 52*0Sstevel@tonic-gate #include <sys/param.h> 53*0Sstevel@tonic-gate #include <sys/types.h> 54*0Sstevel@tonic-gate #include <sys/wait.h> 55*0Sstevel@tonic-gate #include <sys/time.h> 56*0Sstevel@tonic-gate #include <sys/resource.h> 57*0Sstevel@tonic-gate #include <sys/stat.h> 58*0Sstevel@tonic-gate #include <sys/socket.h> 59*0Sstevel@tonic-gate #include <netinet/in.h> 60*0Sstevel@tonic-gate #ifdef SVR4 61*0Sstevel@tonic-gate #include <sys/mkdev.h> 62*0Sstevel@tonic-gate #endif 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate #include "pppd.h" 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate #if !defined(lint) && !defined(_lint) 67*0Sstevel@tonic-gate static const char rcsid[] = RCSID; 68*0Sstevel@tonic-gate #endif 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate #if defined(SUNOS4) 71*0Sstevel@tonic-gate extern char *strerror(); 72*0Sstevel@tonic-gate #endif 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* Don't log to stdout until we're sure it's ok to do so. */ 75*0Sstevel@tonic-gate bool early_log = 1; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate static void pr_log __P((void *, const char *, ...)); 78*0Sstevel@tonic-gate static void logit __P((int, const char *, va_list)); 79*0Sstevel@tonic-gate static void vslp_printer __P((void *, const char *, ...)); 80*0Sstevel@tonic-gate static void format_packet __P((u_char *, int, 81*0Sstevel@tonic-gate void (*) (void *, const char *, ...), void *)); 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate struct buffer_info { 84*0Sstevel@tonic-gate char *ptr; 85*0Sstevel@tonic-gate int len; 86*0Sstevel@tonic-gate }; 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate /* 89*0Sstevel@tonic-gate * strllen - like strlen, but doesn't run past end of input. 90*0Sstevel@tonic-gate */ 91*0Sstevel@tonic-gate size_t 92*0Sstevel@tonic-gate strllen(str, len) 93*0Sstevel@tonic-gate const char *str; 94*0Sstevel@tonic-gate size_t len; 95*0Sstevel@tonic-gate { 96*0Sstevel@tonic-gate size_t ret; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate for (ret = 0; ret < len; ret++) 99*0Sstevel@tonic-gate if (*str++ == '\0') 100*0Sstevel@tonic-gate break; 101*0Sstevel@tonic-gate return (ret); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, 106*0Sstevel@tonic-gate * always leaves destination null-terminated (for len > 0). 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate size_t 109*0Sstevel@tonic-gate strlcpy(dest, src, len) 110*0Sstevel@tonic-gate char *dest; 111*0Sstevel@tonic-gate const char *src; 112*0Sstevel@tonic-gate size_t len; 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate size_t ret = strlen(src); 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate if (len != 0) { 117*0Sstevel@tonic-gate if (ret < len) 118*0Sstevel@tonic-gate (void) strcpy(dest, src); 119*0Sstevel@tonic-gate else { 120*0Sstevel@tonic-gate (void) strncpy(dest, src, len - 1); 121*0Sstevel@tonic-gate dest[len-1] = 0; 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate return (ret); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * strlcat - like strcat/strncat, doesn't overflow destination buffer, 129*0Sstevel@tonic-gate * always leaves destination null-terminated (for len > 0). 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate size_t 132*0Sstevel@tonic-gate strlcat(dest, src, len) 133*0Sstevel@tonic-gate char *dest; 134*0Sstevel@tonic-gate const char *src; 135*0Sstevel@tonic-gate size_t len; 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate size_t dlen = strlen(dest); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate return (dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0))); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate /* 144*0Sstevel@tonic-gate * slprintf - format a message into a buffer. Like sprintf except we 145*0Sstevel@tonic-gate * also specify the length of the output buffer, and we handle %m 146*0Sstevel@tonic-gate * (error message), %v (visible string), %q (quoted string), %t 147*0Sstevel@tonic-gate * (current time), %I (IP address), %P (PPP packet), and %B (sequence 148*0Sstevel@tonic-gate * of bytes) formats. Doesn't do floating-point formats. Returns the 149*0Sstevel@tonic-gate * number of chars put into buf. 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate int 152*0Sstevel@tonic-gate slprintf __V((char *buf, int buflen, const char *fmt, ...)) 153*0Sstevel@tonic-gate { 154*0Sstevel@tonic-gate va_list args; 155*0Sstevel@tonic-gate int n; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate #if defined(__STDC__) 158*0Sstevel@tonic-gate va_start(args, fmt); 159*0Sstevel@tonic-gate #else 160*0Sstevel@tonic-gate char *buf; 161*0Sstevel@tonic-gate int buflen; 162*0Sstevel@tonic-gate const char *fmt; 163*0Sstevel@tonic-gate va_start(args); 164*0Sstevel@tonic-gate buf = va_arg(args, char *); 165*0Sstevel@tonic-gate buflen = va_arg(args, int); 166*0Sstevel@tonic-gate fmt = va_arg(args, const char *); 167*0Sstevel@tonic-gate #endif 168*0Sstevel@tonic-gate n = vslprintf(buf, buflen, fmt, args); 169*0Sstevel@tonic-gate va_end(args); 170*0Sstevel@tonic-gate return (n); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * Print to file or, if argument is NULL, to syslog at debug level. 175*0Sstevel@tonic-gate */ 176*0Sstevel@tonic-gate int 177*0Sstevel@tonic-gate flprintf __V((FILE *strptr, const char *fmt, ...)) 178*0Sstevel@tonic-gate { 179*0Sstevel@tonic-gate va_list args; 180*0Sstevel@tonic-gate int n; 181*0Sstevel@tonic-gate char buf[1024], *bp, *nlp, *ebp; 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate #if defined(__STDC__) 184*0Sstevel@tonic-gate va_start(args, fmt); 185*0Sstevel@tonic-gate #else 186*0Sstevel@tonic-gate FILE *strptr; 187*0Sstevel@tonic-gate const char *fmt; 188*0Sstevel@tonic-gate va_start(args); 189*0Sstevel@tonic-gate strptr = va_arg(args, FILE *); 190*0Sstevel@tonic-gate fmt = va_arg(args, const char *); 191*0Sstevel@tonic-gate #endif 192*0Sstevel@tonic-gate n = vslprintf(buf, sizeof (buf), fmt, args); 193*0Sstevel@tonic-gate va_end(args); 194*0Sstevel@tonic-gate if (strptr == NULL) { 195*0Sstevel@tonic-gate bp = buf; 196*0Sstevel@tonic-gate ebp = buf + n; 197*0Sstevel@tonic-gate while (bp < ebp) { 198*0Sstevel@tonic-gate if ((nlp = strchr(bp, '\n')) == NULL) 199*0Sstevel@tonic-gate nlp = ebp; 200*0Sstevel@tonic-gate if (nlp > bp) { 201*0Sstevel@tonic-gate *nlp = '\0'; 202*0Sstevel@tonic-gate syslog(LOG_DEBUG, "%s", bp); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate bp = nlp + 1; 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate } else { 207*0Sstevel@tonic-gate n = fwrite(buf, 1, n, strptr); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate return (n); 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* 213*0Sstevel@tonic-gate * vslprintf - like slprintf, takes a va_list instead of a list of args. 214*0Sstevel@tonic-gate */ 215*0Sstevel@tonic-gate #define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate int 218*0Sstevel@tonic-gate vslprintf(buf, buflen, fmt, args) 219*0Sstevel@tonic-gate char *buf; 220*0Sstevel@tonic-gate int buflen; 221*0Sstevel@tonic-gate const char *fmt; 222*0Sstevel@tonic-gate va_list args; 223*0Sstevel@tonic-gate { 224*0Sstevel@tonic-gate int c, n, longs; 225*0Sstevel@tonic-gate int width, prec, fillch; 226*0Sstevel@tonic-gate int base, len, neg, quoted; 227*0Sstevel@tonic-gate #ifdef SOL2 228*0Sstevel@tonic-gate uint64_t val; 229*0Sstevel@tonic-gate int64_t sval; 230*0Sstevel@tonic-gate #else 231*0Sstevel@tonic-gate unsigned long val; 232*0Sstevel@tonic-gate long sval; 233*0Sstevel@tonic-gate #endif 234*0Sstevel@tonic-gate char *buf0, *mstr; 235*0Sstevel@tonic-gate const char *f, *str; 236*0Sstevel@tonic-gate unsigned char *p; 237*0Sstevel@tonic-gate char num[32]; /* 2^64 is 20 chars decimal, 22 octal */ 238*0Sstevel@tonic-gate time_t t; 239*0Sstevel@tonic-gate u_int32_t ip; 240*0Sstevel@tonic-gate static const char hexchars[] = "0123456789abcdef"; 241*0Sstevel@tonic-gate struct buffer_info bufinfo; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate buf0 = buf; 244*0Sstevel@tonic-gate --buflen; 245*0Sstevel@tonic-gate while (buflen > 0) { 246*0Sstevel@tonic-gate for (f = fmt; *f != '%' && *f != 0; ++f) 247*0Sstevel@tonic-gate ; 248*0Sstevel@tonic-gate if (f > fmt) { 249*0Sstevel@tonic-gate len = f - fmt; 250*0Sstevel@tonic-gate if (len > buflen) 251*0Sstevel@tonic-gate len = buflen; 252*0Sstevel@tonic-gate (void) memcpy(buf, fmt, len); 253*0Sstevel@tonic-gate buf += len; 254*0Sstevel@tonic-gate buflen -= len; 255*0Sstevel@tonic-gate fmt = f; 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate if (*fmt == 0) 258*0Sstevel@tonic-gate break; 259*0Sstevel@tonic-gate c = *++fmt; 260*0Sstevel@tonic-gate width = 0; 261*0Sstevel@tonic-gate prec = -1; 262*0Sstevel@tonic-gate fillch = ' '; 263*0Sstevel@tonic-gate if (c == '0') { 264*0Sstevel@tonic-gate fillch = '0'; 265*0Sstevel@tonic-gate c = *++fmt; 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate if (c == '*') { 268*0Sstevel@tonic-gate width = va_arg(args, int); 269*0Sstevel@tonic-gate c = *++fmt; 270*0Sstevel@tonic-gate } else { 271*0Sstevel@tonic-gate while (isdigit(c)) { 272*0Sstevel@tonic-gate width = width * 10 + c - '0'; 273*0Sstevel@tonic-gate c = *++fmt; 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate if (c == '.') { 277*0Sstevel@tonic-gate c = *++fmt; 278*0Sstevel@tonic-gate if (c == '*') { 279*0Sstevel@tonic-gate prec = va_arg(args, int); 280*0Sstevel@tonic-gate c = *++fmt; 281*0Sstevel@tonic-gate } else { 282*0Sstevel@tonic-gate prec = 0; 283*0Sstevel@tonic-gate while (isdigit(c)) { 284*0Sstevel@tonic-gate prec = prec * 10 + c - '0'; 285*0Sstevel@tonic-gate c = *++fmt; 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate longs = 0; 290*0Sstevel@tonic-gate if (c == 'l') { 291*0Sstevel@tonic-gate longs++; 292*0Sstevel@tonic-gate c = *++fmt; 293*0Sstevel@tonic-gate if (c == 'l') { 294*0Sstevel@tonic-gate longs++; 295*0Sstevel@tonic-gate c = *++fmt; 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate str = 0; 299*0Sstevel@tonic-gate base = 0; 300*0Sstevel@tonic-gate neg = 0; 301*0Sstevel@tonic-gate val = 0; 302*0Sstevel@tonic-gate ++fmt; 303*0Sstevel@tonic-gate switch (c) { 304*0Sstevel@tonic-gate case 'u': 305*0Sstevel@tonic-gate #ifdef SOL2 306*0Sstevel@tonic-gate if (longs >= 2) 307*0Sstevel@tonic-gate val = va_arg(args, uint64_t); 308*0Sstevel@tonic-gate else 309*0Sstevel@tonic-gate #endif 310*0Sstevel@tonic-gate if (longs > 0) 311*0Sstevel@tonic-gate val = va_arg(args, unsigned long); 312*0Sstevel@tonic-gate else 313*0Sstevel@tonic-gate val = va_arg(args, unsigned int); 314*0Sstevel@tonic-gate base = 10; 315*0Sstevel@tonic-gate break; 316*0Sstevel@tonic-gate case 'd': 317*0Sstevel@tonic-gate #ifdef SOL2 318*0Sstevel@tonic-gate if (longs >= 2) 319*0Sstevel@tonic-gate sval = va_arg(args, int64_t); 320*0Sstevel@tonic-gate else 321*0Sstevel@tonic-gate #endif 322*0Sstevel@tonic-gate if (longs > 0) 323*0Sstevel@tonic-gate sval = va_arg(args, long); 324*0Sstevel@tonic-gate else 325*0Sstevel@tonic-gate sval = va_arg(args, int); 326*0Sstevel@tonic-gate if (sval < 0) { 327*0Sstevel@tonic-gate neg = 1; 328*0Sstevel@tonic-gate val = -sval; 329*0Sstevel@tonic-gate } else 330*0Sstevel@tonic-gate val = sval; 331*0Sstevel@tonic-gate base = 10; 332*0Sstevel@tonic-gate break; 333*0Sstevel@tonic-gate case 'o': 334*0Sstevel@tonic-gate #ifdef SOL2 335*0Sstevel@tonic-gate if (longs >= 2) 336*0Sstevel@tonic-gate val = va_arg(args, uint64_t); 337*0Sstevel@tonic-gate else 338*0Sstevel@tonic-gate #endif 339*0Sstevel@tonic-gate if (longs > 0) 340*0Sstevel@tonic-gate val = va_arg(args, unsigned long); 341*0Sstevel@tonic-gate else 342*0Sstevel@tonic-gate val = va_arg(args, unsigned int); 343*0Sstevel@tonic-gate base = 8; 344*0Sstevel@tonic-gate break; 345*0Sstevel@tonic-gate case 'x': 346*0Sstevel@tonic-gate case 'X': 347*0Sstevel@tonic-gate #ifdef SOL2 348*0Sstevel@tonic-gate if (longs >= 2) 349*0Sstevel@tonic-gate val = va_arg(args, uint64_t); 350*0Sstevel@tonic-gate else 351*0Sstevel@tonic-gate #endif 352*0Sstevel@tonic-gate if (longs > 0) 353*0Sstevel@tonic-gate val = va_arg(args, unsigned long); 354*0Sstevel@tonic-gate else 355*0Sstevel@tonic-gate val = va_arg(args, unsigned int); 356*0Sstevel@tonic-gate base = 16; 357*0Sstevel@tonic-gate break; 358*0Sstevel@tonic-gate case 'p': 359*0Sstevel@tonic-gate val = (unsigned long) va_arg(args, void *); 360*0Sstevel@tonic-gate base = 16; 361*0Sstevel@tonic-gate neg = 2; 362*0Sstevel@tonic-gate break; 363*0Sstevel@tonic-gate case 's': 364*0Sstevel@tonic-gate str = va_arg(args, const char *); 365*0Sstevel@tonic-gate break; 366*0Sstevel@tonic-gate case 'c': 367*0Sstevel@tonic-gate num[0] = va_arg(args, int); 368*0Sstevel@tonic-gate num[1] = 0; 369*0Sstevel@tonic-gate str = num; 370*0Sstevel@tonic-gate break; 371*0Sstevel@tonic-gate case 'm': 372*0Sstevel@tonic-gate str = strerror(errno); 373*0Sstevel@tonic-gate break; 374*0Sstevel@tonic-gate case 'I': 375*0Sstevel@tonic-gate ip = va_arg(args, u_int32_t); 376*0Sstevel@tonic-gate ip = ntohl(ip); 377*0Sstevel@tonic-gate (void) slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, 378*0Sstevel@tonic-gate (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 379*0Sstevel@tonic-gate str = num; 380*0Sstevel@tonic-gate break; 381*0Sstevel@tonic-gate case 't': 382*0Sstevel@tonic-gate (void) time(&t); 383*0Sstevel@tonic-gate mstr = ctime(&t); 384*0Sstevel@tonic-gate mstr += 4; /* chop off the day name */ 385*0Sstevel@tonic-gate mstr[15] = 0; /* chop off year and newline */ 386*0Sstevel@tonic-gate str = (const char *)mstr; 387*0Sstevel@tonic-gate break; 388*0Sstevel@tonic-gate case 'v': /* "visible" string */ 389*0Sstevel@tonic-gate case 'q': /* quoted string */ 390*0Sstevel@tonic-gate quoted = c == 'q'; 391*0Sstevel@tonic-gate p = va_arg(args, unsigned char *); 392*0Sstevel@tonic-gate if (fillch == '0' && prec >= 0) { 393*0Sstevel@tonic-gate n = prec; 394*0Sstevel@tonic-gate } else { 395*0Sstevel@tonic-gate n = strlen((char *)p); 396*0Sstevel@tonic-gate if (prec >= 0 && n > prec) 397*0Sstevel@tonic-gate n = prec; 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate while (n > 0 && buflen > 0) { 400*0Sstevel@tonic-gate c = *p++; 401*0Sstevel@tonic-gate --n; 402*0Sstevel@tonic-gate if (!quoted && c >= 0x80) { 403*0Sstevel@tonic-gate (void) OUTCHAR('M'); 404*0Sstevel@tonic-gate (void) OUTCHAR('-'); 405*0Sstevel@tonic-gate c -= 0x80; 406*0Sstevel@tonic-gate } 407*0Sstevel@tonic-gate if (quoted && (c == '"' || c == '\\')) 408*0Sstevel@tonic-gate (void) OUTCHAR('\\'); 409*0Sstevel@tonic-gate if (c < 0x20 || (0x7f <= c && c < 0xa0)) { 410*0Sstevel@tonic-gate if (quoted) { 411*0Sstevel@tonic-gate (void) OUTCHAR('\\'); 412*0Sstevel@tonic-gate switch (c) { 413*0Sstevel@tonic-gate case '\t': (void) OUTCHAR('t'); break; 414*0Sstevel@tonic-gate case '\n': (void) OUTCHAR('n'); break; 415*0Sstevel@tonic-gate case '\b': (void) OUTCHAR('b'); break; 416*0Sstevel@tonic-gate case '\f': (void) OUTCHAR('f'); break; 417*0Sstevel@tonic-gate default: 418*0Sstevel@tonic-gate (void) OUTCHAR('x'); 419*0Sstevel@tonic-gate (void) OUTCHAR(hexchars[c >> 4]); 420*0Sstevel@tonic-gate (void) OUTCHAR(hexchars[c & 0xf]); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate } else { 423*0Sstevel@tonic-gate if (c == '\t') 424*0Sstevel@tonic-gate (void) OUTCHAR(c); 425*0Sstevel@tonic-gate else { 426*0Sstevel@tonic-gate (void) OUTCHAR('^'); 427*0Sstevel@tonic-gate (void) OUTCHAR(c ^ 0x40); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate } else 431*0Sstevel@tonic-gate (void) OUTCHAR(c); 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate continue; 434*0Sstevel@tonic-gate case 'P': /* print PPP packet */ 435*0Sstevel@tonic-gate bufinfo.ptr = buf; 436*0Sstevel@tonic-gate bufinfo.len = buflen + 1; 437*0Sstevel@tonic-gate p = va_arg(args, unsigned char *); 438*0Sstevel@tonic-gate n = va_arg(args, int); 439*0Sstevel@tonic-gate format_packet(p, n, vslp_printer, &bufinfo); 440*0Sstevel@tonic-gate buf = bufinfo.ptr; 441*0Sstevel@tonic-gate buflen = bufinfo.len - 1; 442*0Sstevel@tonic-gate continue; 443*0Sstevel@tonic-gate case 'B': 444*0Sstevel@tonic-gate p = va_arg(args, unsigned char *); 445*0Sstevel@tonic-gate if ((n = prec) > width && width > 0) 446*0Sstevel@tonic-gate n = width; 447*0Sstevel@tonic-gate /* For safety's sake */ 448*0Sstevel@tonic-gate if (n > 2000) 449*0Sstevel@tonic-gate n = 2000; 450*0Sstevel@tonic-gate while (--n >= 0) { 451*0Sstevel@tonic-gate c = *p++; 452*0Sstevel@tonic-gate if (fillch == ' ') 453*0Sstevel@tonic-gate (void) OUTCHAR(' '); 454*0Sstevel@tonic-gate (void) OUTCHAR(hexchars[(c >> 4) & 0xf]); 455*0Sstevel@tonic-gate (void) OUTCHAR(hexchars[c & 0xf]); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate if (prec > width && width > 0) { 458*0Sstevel@tonic-gate (void) OUTCHAR('.'); 459*0Sstevel@tonic-gate (void) OUTCHAR('.'); 460*0Sstevel@tonic-gate (void) OUTCHAR('.'); 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate continue; 463*0Sstevel@tonic-gate default: 464*0Sstevel@tonic-gate *buf++ = '%'; 465*0Sstevel@tonic-gate if (c != '%') 466*0Sstevel@tonic-gate --fmt; /* so %z outputs %z etc. */ 467*0Sstevel@tonic-gate --buflen; 468*0Sstevel@tonic-gate continue; 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate if (base != 0) { 471*0Sstevel@tonic-gate mstr = num + sizeof(num); 472*0Sstevel@tonic-gate *--mstr = 0; 473*0Sstevel@tonic-gate while (mstr > num + neg) { 474*0Sstevel@tonic-gate *--mstr = hexchars[val % base]; 475*0Sstevel@tonic-gate val = val / base; 476*0Sstevel@tonic-gate if (--prec <= 0 && val == 0) 477*0Sstevel@tonic-gate break; 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate switch (neg) { 480*0Sstevel@tonic-gate case 1: 481*0Sstevel@tonic-gate *--mstr = '-'; 482*0Sstevel@tonic-gate break; 483*0Sstevel@tonic-gate case 2: 484*0Sstevel@tonic-gate *--mstr = 'x'; 485*0Sstevel@tonic-gate *--mstr = '0'; 486*0Sstevel@tonic-gate break; 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate len = num + sizeof(num) - 1 - mstr; 489*0Sstevel@tonic-gate str = (const char *)mstr; 490*0Sstevel@tonic-gate } else { 491*0Sstevel@tonic-gate len = strlen(str); 492*0Sstevel@tonic-gate if (prec >= 0 && len > prec) 493*0Sstevel@tonic-gate len = prec; 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate if (width > 0) { 496*0Sstevel@tonic-gate if (width > buflen) 497*0Sstevel@tonic-gate width = buflen; 498*0Sstevel@tonic-gate if ((n = width - len) > 0) { 499*0Sstevel@tonic-gate buflen -= n; 500*0Sstevel@tonic-gate for (; n > 0; --n) 501*0Sstevel@tonic-gate *buf++ = fillch; 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate if (len > buflen) 505*0Sstevel@tonic-gate len = buflen; 506*0Sstevel@tonic-gate (void) memcpy(buf, str, len); 507*0Sstevel@tonic-gate buf += len; 508*0Sstevel@tonic-gate buflen -= len; 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate *buf = 0; 511*0Sstevel@tonic-gate return (buf - buf0); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate /* 515*0Sstevel@tonic-gate * vslp_printer - used in processing a %P format 516*0Sstevel@tonic-gate */ 517*0Sstevel@tonic-gate static void 518*0Sstevel@tonic-gate vslp_printer __V((void *arg, const char *fmt, ...)) 519*0Sstevel@tonic-gate { 520*0Sstevel@tonic-gate int n; 521*0Sstevel@tonic-gate va_list pvar; 522*0Sstevel@tonic-gate struct buffer_info *bi; 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate #if defined(__STDC__) 525*0Sstevel@tonic-gate va_start(pvar, fmt); 526*0Sstevel@tonic-gate #else 527*0Sstevel@tonic-gate void *arg; 528*0Sstevel@tonic-gate const char *fmt; 529*0Sstevel@tonic-gate va_start(pvar); 530*0Sstevel@tonic-gate arg = va_arg(pvar, void *); 531*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 532*0Sstevel@tonic-gate #endif 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate bi = (struct buffer_info *) arg; 535*0Sstevel@tonic-gate n = vslprintf(bi->ptr, bi->len, fmt, pvar); 536*0Sstevel@tonic-gate va_end(pvar); 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate bi->ptr += n; 539*0Sstevel@tonic-gate bi->len -= n; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * log_packet - format a packet and log it. 544*0Sstevel@tonic-gate */ 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate static char line[256]; /* line to be logged accumulated here */ 547*0Sstevel@tonic-gate static char *linep; 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate void 550*0Sstevel@tonic-gate log_packet(p, len, prefix, level) 551*0Sstevel@tonic-gate u_char *p; 552*0Sstevel@tonic-gate int len; 553*0Sstevel@tonic-gate const char *prefix; 554*0Sstevel@tonic-gate int level; 555*0Sstevel@tonic-gate { 556*0Sstevel@tonic-gate (void) strlcpy(line, prefix, sizeof(line)); 557*0Sstevel@tonic-gate linep = line + strlen(line); 558*0Sstevel@tonic-gate format_packet(p, len, pr_log, (void *)level); 559*0Sstevel@tonic-gate if (linep != line) 560*0Sstevel@tonic-gate syslog(level, "%s", line); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * format_packet - make a readable representation of a packet, 565*0Sstevel@tonic-gate * calling `printer(arg, format, ...)' to output it. 566*0Sstevel@tonic-gate */ 567*0Sstevel@tonic-gate static void 568*0Sstevel@tonic-gate format_packet(p, len, printer, arg) 569*0Sstevel@tonic-gate u_char *p; 570*0Sstevel@tonic-gate int len; 571*0Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)); 572*0Sstevel@tonic-gate void *arg; 573*0Sstevel@tonic-gate { 574*0Sstevel@tonic-gate int i, n; 575*0Sstevel@tonic-gate u_short proto; 576*0Sstevel@tonic-gate struct protent *protp; 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { 579*0Sstevel@tonic-gate p += 2; 580*0Sstevel@tonic-gate GETSHORT(proto, p); 581*0Sstevel@tonic-gate len -= PPP_HDRLEN; 582*0Sstevel@tonic-gate for (i = 0; (protp = protocols[i]) != NULL; ++i) 583*0Sstevel@tonic-gate if (proto == protp->protocol) 584*0Sstevel@tonic-gate break; 585*0Sstevel@tonic-gate if (protp != NULL) { 586*0Sstevel@tonic-gate printer(arg, "[%s", protp->name); 587*0Sstevel@tonic-gate n = (*protp->printpkt)(p, len, printer, arg); 588*0Sstevel@tonic-gate printer(arg, "]"); 589*0Sstevel@tonic-gate p += n; 590*0Sstevel@tonic-gate len -= n; 591*0Sstevel@tonic-gate } else { 592*0Sstevel@tonic-gate for (i = 0; (protp = protocols[i]) != NULL; ++i) 593*0Sstevel@tonic-gate if (proto == (protp->protocol & ~0x8000)) 594*0Sstevel@tonic-gate break; 595*0Sstevel@tonic-gate if (protp != NULL && protp->data_name != NULL) { 596*0Sstevel@tonic-gate printer(arg, "[%s data] %8.*B", protp->data_name, len, p); 597*0Sstevel@tonic-gate len = 0; 598*0Sstevel@tonic-gate } else 599*0Sstevel@tonic-gate printer(arg, "[proto=0x%x]", proto); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate printer(arg, "%32.*B", len, p); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate static void 607*0Sstevel@tonic-gate pr_log __V((void *arg, const char *fmt, ...)) 608*0Sstevel@tonic-gate { 609*0Sstevel@tonic-gate int n; 610*0Sstevel@tonic-gate va_list pvar; 611*0Sstevel@tonic-gate char buf[256]; 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate #if defined(__STDC__) 614*0Sstevel@tonic-gate va_start(pvar, fmt); 615*0Sstevel@tonic-gate #else 616*0Sstevel@tonic-gate void *arg; 617*0Sstevel@tonic-gate const char *fmt; 618*0Sstevel@tonic-gate va_start(pvar); 619*0Sstevel@tonic-gate arg = va_arg(pvar, void *); 620*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 621*0Sstevel@tonic-gate #endif 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate n = vslprintf(buf, sizeof(buf), fmt, pvar); 624*0Sstevel@tonic-gate va_end(pvar); 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate if (linep + n + 1 > line + sizeof(line)) { 627*0Sstevel@tonic-gate syslog((int)arg, "%s", line); 628*0Sstevel@tonic-gate linep = line; 629*0Sstevel@tonic-gate } 630*0Sstevel@tonic-gate (void) strlcpy(linep, buf, line + sizeof(line) - linep); 631*0Sstevel@tonic-gate linep += n; 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate /* 635*0Sstevel@tonic-gate * print_string - print a readable representation of a string using 636*0Sstevel@tonic-gate * printer. 637*0Sstevel@tonic-gate */ 638*0Sstevel@tonic-gate void 639*0Sstevel@tonic-gate print_string(p, len, printer, arg) 640*0Sstevel@tonic-gate char *p; 641*0Sstevel@tonic-gate int len; 642*0Sstevel@tonic-gate void (*printer) __P((void *, const char *, ...)); 643*0Sstevel@tonic-gate void *arg; 644*0Sstevel@tonic-gate { 645*0Sstevel@tonic-gate int c; 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate printer(arg, "\""); 648*0Sstevel@tonic-gate for (; len > 0; --len) { 649*0Sstevel@tonic-gate c = *p++; 650*0Sstevel@tonic-gate if (isprint(c)) { 651*0Sstevel@tonic-gate if (c == '\\' || c == '"') 652*0Sstevel@tonic-gate printer(arg, "\\"); 653*0Sstevel@tonic-gate printer(arg, "%c", c); 654*0Sstevel@tonic-gate } else { 655*0Sstevel@tonic-gate switch (c) { 656*0Sstevel@tonic-gate case '\n': 657*0Sstevel@tonic-gate printer(arg, "\\n"); 658*0Sstevel@tonic-gate break; 659*0Sstevel@tonic-gate case '\r': 660*0Sstevel@tonic-gate printer(arg, "\\r"); 661*0Sstevel@tonic-gate break; 662*0Sstevel@tonic-gate case '\t': 663*0Sstevel@tonic-gate printer(arg, "\\t"); 664*0Sstevel@tonic-gate break; 665*0Sstevel@tonic-gate default: 666*0Sstevel@tonic-gate printer(arg, "\\%.3o", c); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate } 669*0Sstevel@tonic-gate } 670*0Sstevel@tonic-gate printer(arg, "\""); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* 674*0Sstevel@tonic-gate * logit - does the hard work for fatal et al. 675*0Sstevel@tonic-gate */ 676*0Sstevel@tonic-gate static void 677*0Sstevel@tonic-gate logit(level, fmt, args) 678*0Sstevel@tonic-gate int level; 679*0Sstevel@tonic-gate const char *fmt; 680*0Sstevel@tonic-gate va_list args; 681*0Sstevel@tonic-gate { 682*0Sstevel@tonic-gate int n; 683*0Sstevel@tonic-gate char buf[1024]; 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate n = vslprintf(buf, sizeof(buf), fmt, args); 686*0Sstevel@tonic-gate syslog(level, "%s", buf); 687*0Sstevel@tonic-gate if (log_to_fd >= 0 && (level != LOG_DEBUG || debug) && 688*0Sstevel@tonic-gate (!early_log || log_to_specific_fd)) { 689*0Sstevel@tonic-gate if (buf[n-1] != '\n') 690*0Sstevel@tonic-gate buf[n++] = '\n'; 691*0Sstevel@tonic-gate if (write(log_to_fd, buf, n) != n) 692*0Sstevel@tonic-gate log_to_fd = -1; 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate } 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate /* 697*0Sstevel@tonic-gate * fatal - log an error message and die horribly. 698*0Sstevel@tonic-gate */ 699*0Sstevel@tonic-gate void 700*0Sstevel@tonic-gate fatal __V((const char *fmt, ...)) 701*0Sstevel@tonic-gate { 702*0Sstevel@tonic-gate va_list pvar; 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate #if defined(__STDC__) 705*0Sstevel@tonic-gate va_start(pvar, fmt); 706*0Sstevel@tonic-gate #else 707*0Sstevel@tonic-gate const char *fmt; 708*0Sstevel@tonic-gate va_start(pvar); 709*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 710*0Sstevel@tonic-gate #endif 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate logit(LOG_ERR, fmt, pvar); 713*0Sstevel@tonic-gate va_end(pvar); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate die(1); /* as promised */ 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate /* 719*0Sstevel@tonic-gate * error - log an error message. 720*0Sstevel@tonic-gate */ 721*0Sstevel@tonic-gate void 722*0Sstevel@tonic-gate error __V((const char *fmt, ...)) 723*0Sstevel@tonic-gate { 724*0Sstevel@tonic-gate va_list pvar; 725*0Sstevel@tonic-gate 726*0Sstevel@tonic-gate #if defined(__STDC__) 727*0Sstevel@tonic-gate va_start(pvar, fmt); 728*0Sstevel@tonic-gate #else 729*0Sstevel@tonic-gate const char *fmt; 730*0Sstevel@tonic-gate va_start(pvar); 731*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 732*0Sstevel@tonic-gate #endif 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate logit(LOG_ERR, fmt, pvar); 735*0Sstevel@tonic-gate va_end(pvar); 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate /* 739*0Sstevel@tonic-gate * warn - log a warning message. 740*0Sstevel@tonic-gate */ 741*0Sstevel@tonic-gate void 742*0Sstevel@tonic-gate warn __V((const char *fmt, ...)) 743*0Sstevel@tonic-gate { 744*0Sstevel@tonic-gate va_list pvar; 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate #if defined(__STDC__) 747*0Sstevel@tonic-gate va_start(pvar, fmt); 748*0Sstevel@tonic-gate #else 749*0Sstevel@tonic-gate const char *fmt; 750*0Sstevel@tonic-gate va_start(pvar); 751*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 752*0Sstevel@tonic-gate #endif 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate logit(LOG_WARNING, fmt, pvar); 755*0Sstevel@tonic-gate va_end(pvar); 756*0Sstevel@tonic-gate } 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate /* 759*0Sstevel@tonic-gate * notice - log a notice-level message. 760*0Sstevel@tonic-gate */ 761*0Sstevel@tonic-gate void 762*0Sstevel@tonic-gate notice __V((const char *fmt, ...)) 763*0Sstevel@tonic-gate { 764*0Sstevel@tonic-gate va_list pvar; 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate #if defined(__STDC__) 767*0Sstevel@tonic-gate va_start(pvar, fmt); 768*0Sstevel@tonic-gate #else 769*0Sstevel@tonic-gate const char *fmt; 770*0Sstevel@tonic-gate va_start(pvar); 771*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 772*0Sstevel@tonic-gate #endif 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate logit(LOG_NOTICE, fmt, pvar); 775*0Sstevel@tonic-gate va_end(pvar); 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate /* 779*0Sstevel@tonic-gate * info - log an informational message. 780*0Sstevel@tonic-gate */ 781*0Sstevel@tonic-gate void 782*0Sstevel@tonic-gate info __V((const char *fmt, ...)) 783*0Sstevel@tonic-gate { 784*0Sstevel@tonic-gate va_list pvar; 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate #if defined(__STDC__) 787*0Sstevel@tonic-gate va_start(pvar, fmt); 788*0Sstevel@tonic-gate #else 789*0Sstevel@tonic-gate const char *fmt; 790*0Sstevel@tonic-gate va_start(pvar); 791*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 792*0Sstevel@tonic-gate #endif 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate logit(LOG_INFO, fmt, pvar); 795*0Sstevel@tonic-gate va_end(pvar); 796*0Sstevel@tonic-gate } 797*0Sstevel@tonic-gate 798*0Sstevel@tonic-gate /* 799*0Sstevel@tonic-gate * dbglog - log a debug message. 800*0Sstevel@tonic-gate */ 801*0Sstevel@tonic-gate void 802*0Sstevel@tonic-gate dbglog __V((const char *fmt, ...)) 803*0Sstevel@tonic-gate { 804*0Sstevel@tonic-gate va_list pvar; 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate #if defined(__STDC__) 807*0Sstevel@tonic-gate va_start(pvar, fmt); 808*0Sstevel@tonic-gate #else 809*0Sstevel@tonic-gate const char *fmt; 810*0Sstevel@tonic-gate va_start(pvar); 811*0Sstevel@tonic-gate fmt = va_arg(pvar, const char *); 812*0Sstevel@tonic-gate #endif 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate logit(LOG_DEBUG, fmt, pvar); 815*0Sstevel@tonic-gate va_end(pvar); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate /* 819*0Sstevel@tonic-gate * Code names for regular PPP messages. Used by LCP and most NCPs, 820*0Sstevel@tonic-gate * not used by authentication protocols. 821*0Sstevel@tonic-gate */ 822*0Sstevel@tonic-gate const char * 823*0Sstevel@tonic-gate code_name(int code, int shortflag) 824*0Sstevel@tonic-gate { 825*0Sstevel@tonic-gate static const char *codelist[] = { 826*0Sstevel@tonic-gate "Vendor-Extension", "Configure-Request", "Configure-Ack", 827*0Sstevel@tonic-gate "Configure-Nak", "Configure-Reject", "Terminate-Request", 828*0Sstevel@tonic-gate "Terminate-Ack", "Code-Reject", "Protocol-Reject", 829*0Sstevel@tonic-gate "Echo-Request", "Echo-Reply", "Discard-Request", 830*0Sstevel@tonic-gate "Identification", "Time-Remaining", 831*0Sstevel@tonic-gate "Reset-Request", "Reset-Ack" 832*0Sstevel@tonic-gate }; 833*0Sstevel@tonic-gate static const char *shortcode[] = { 834*0Sstevel@tonic-gate "VendExt", "ConfReq", "ConfAck", 835*0Sstevel@tonic-gate "ConfNak", "ConfRej", "TermReq", 836*0Sstevel@tonic-gate "TermAck", "CodeRej", "ProtRej", 837*0Sstevel@tonic-gate "EchoReq", "EchoRep", "DiscReq", 838*0Sstevel@tonic-gate "Ident", "TimeRem", 839*0Sstevel@tonic-gate "ResetReq", "ResetAck" 840*0Sstevel@tonic-gate }; 841*0Sstevel@tonic-gate static char msgbuf[64]; 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate if (code < 0 || code >= sizeof (codelist) / sizeof (*codelist)) { 844*0Sstevel@tonic-gate if (shortflag) 845*0Sstevel@tonic-gate (void) slprintf(msgbuf, sizeof (msgbuf), "Code#%d", code); 846*0Sstevel@tonic-gate else 847*0Sstevel@tonic-gate (void) slprintf(msgbuf, sizeof (msgbuf), "unknown code %d", code); 848*0Sstevel@tonic-gate return ((const char *)msgbuf); 849*0Sstevel@tonic-gate } 850*0Sstevel@tonic-gate return (shortflag ? shortcode[code] : codelist[code]); 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate /* Procedures for locking the serial device using a lock file. */ 854*0Sstevel@tonic-gate #ifndef LOCK_DIR 855*0Sstevel@tonic-gate #ifdef _linux_ 856*0Sstevel@tonic-gate #define LOCK_DIR "/var/lock" 857*0Sstevel@tonic-gate #else 858*0Sstevel@tonic-gate #ifdef SVR4 859*0Sstevel@tonic-gate #define LOCK_DIR "/var/spool/locks" 860*0Sstevel@tonic-gate #else 861*0Sstevel@tonic-gate #define LOCK_DIR "/var/spool/lock" 862*0Sstevel@tonic-gate #endif 863*0Sstevel@tonic-gate #endif 864*0Sstevel@tonic-gate #endif /* LOCK_DIR */ 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate static char lock_file[MAXPATHLEN]; 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate /* 869*0Sstevel@tonic-gate * lock - create a lock file for the named device 870*0Sstevel@tonic-gate */ 871*0Sstevel@tonic-gate int 872*0Sstevel@tonic-gate lock(dev) 873*0Sstevel@tonic-gate char *dev; 874*0Sstevel@tonic-gate { 875*0Sstevel@tonic-gate #ifdef LOCKLIB 876*0Sstevel@tonic-gate int result; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate result = mklock (dev, (void *) 0); 879*0Sstevel@tonic-gate if (result == 0) { 880*0Sstevel@tonic-gate (void) strlcpy(lock_file, sizeof(lock_file), dev); 881*0Sstevel@tonic-gate return (0); 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate if (result > 0) 885*0Sstevel@tonic-gate notice("Device %s is locked by pid %d", dev, result); 886*0Sstevel@tonic-gate else 887*0Sstevel@tonic-gate error("Can't create lock file %s", lock_file); 888*0Sstevel@tonic-gate return (-1); 889*0Sstevel@tonic-gate 890*0Sstevel@tonic-gate #else /* LOCKLIB */ 891*0Sstevel@tonic-gate 892*0Sstevel@tonic-gate char lock_buffer[12]; 893*0Sstevel@tonic-gate int fd, pid, n; 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate #ifdef SVR4 896*0Sstevel@tonic-gate struct stat sbuf; 897*0Sstevel@tonic-gate 898*0Sstevel@tonic-gate if (stat(dev, &sbuf) < 0) { 899*0Sstevel@tonic-gate error("Can't get device number for %s: %m", dev); 900*0Sstevel@tonic-gate return (-1); 901*0Sstevel@tonic-gate } 902*0Sstevel@tonic-gate if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 903*0Sstevel@tonic-gate error("Can't lock %s: not a character device", dev); 904*0Sstevel@tonic-gate return (-1); 905*0Sstevel@tonic-gate } 906*0Sstevel@tonic-gate (void) slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 907*0Sstevel@tonic-gate LOCK_DIR, major(sbuf.st_dev), 908*0Sstevel@tonic-gate major(sbuf.st_rdev), minor(sbuf.st_rdev)); 909*0Sstevel@tonic-gate #else 910*0Sstevel@tonic-gate char *p; 911*0Sstevel@tonic-gate 912*0Sstevel@tonic-gate if ((p = strrchr(dev, '/')) != NULL) 913*0Sstevel@tonic-gate dev = p + 1; 914*0Sstevel@tonic-gate (void) slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 915*0Sstevel@tonic-gate #endif 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 918*0Sstevel@tonic-gate if (errno != EEXIST) { 919*0Sstevel@tonic-gate error("Can't create lock file %s: %m", lock_file); 920*0Sstevel@tonic-gate break; 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate /* Read the lock file to find out who has the device locked. */ 924*0Sstevel@tonic-gate fd = open(lock_file, O_RDONLY, 0); 925*0Sstevel@tonic-gate if (fd < 0) { 926*0Sstevel@tonic-gate if (errno == ENOENT) /* This is just a timing problem. */ 927*0Sstevel@tonic-gate continue; 928*0Sstevel@tonic-gate error("Can't open existing lock file %s: %m", lock_file); 929*0Sstevel@tonic-gate break; 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate #ifndef LOCK_BINARY 932*0Sstevel@tonic-gate n = read(fd, lock_buffer, 11); 933*0Sstevel@tonic-gate #else 934*0Sstevel@tonic-gate n = read(fd, &pid, sizeof(pid)); 935*0Sstevel@tonic-gate #endif /* LOCK_BINARY */ 936*0Sstevel@tonic-gate (void) close(fd); 937*0Sstevel@tonic-gate fd = -1; 938*0Sstevel@tonic-gate if (n <= 0) { 939*0Sstevel@tonic-gate error("Can't read pid from lock file %s", lock_file); 940*0Sstevel@tonic-gate break; 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate /* See if the process still exists. */ 944*0Sstevel@tonic-gate #ifndef LOCK_BINARY 945*0Sstevel@tonic-gate lock_buffer[n] = 0; 946*0Sstevel@tonic-gate pid = atoi(lock_buffer); 947*0Sstevel@tonic-gate #endif /* LOCK_BINARY */ 948*0Sstevel@tonic-gate if (pid == getpid()) 949*0Sstevel@tonic-gate return (1); /* somebody else locked it for us */ 950*0Sstevel@tonic-gate if (pid == 0 951*0Sstevel@tonic-gate || (kill(pid, 0) == -1 && errno == ESRCH)) { 952*0Sstevel@tonic-gate if (unlink (lock_file) == 0) { 953*0Sstevel@tonic-gate notice("Removed stale lock on %s (pid %d)", dev, pid); 954*0Sstevel@tonic-gate continue; 955*0Sstevel@tonic-gate } 956*0Sstevel@tonic-gate warn("Couldn't remove stale lock on %s", dev); 957*0Sstevel@tonic-gate } else 958*0Sstevel@tonic-gate notice("Device %s is locked by pid %d", dev, pid); 959*0Sstevel@tonic-gate break; 960*0Sstevel@tonic-gate } 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate if (fd < 0) { 963*0Sstevel@tonic-gate lock_file[0] = 0; 964*0Sstevel@tonic-gate return (-1); 965*0Sstevel@tonic-gate } 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate pid = getpid(); 968*0Sstevel@tonic-gate #ifndef LOCK_BINARY 969*0Sstevel@tonic-gate (void) slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 970*0Sstevel@tonic-gate (void) write (fd, lock_buffer, 11); 971*0Sstevel@tonic-gate #else 972*0Sstevel@tonic-gate (void) write(fd, &pid, sizeof (pid)); 973*0Sstevel@tonic-gate #endif 974*0Sstevel@tonic-gate (void) close(fd); 975*0Sstevel@tonic-gate return (0); 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate #endif 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * relock - called to update our lockfile when we are about to detach, 982*0Sstevel@tonic-gate * thus changing our pid (we fork, the child carries on, and the parent dies). 983*0Sstevel@tonic-gate * Note that this is called by the parent, with pid equal to the pid 984*0Sstevel@tonic-gate * of the child. This avoids a potential race which would exist if 985*0Sstevel@tonic-gate * we had the child rewrite the lockfile (the parent might die first, 986*0Sstevel@tonic-gate * and another process could think the lock was stale if it checked 987*0Sstevel@tonic-gate * between when the parent died and the child rewrote the lockfile). 988*0Sstevel@tonic-gate */ 989*0Sstevel@tonic-gate int 990*0Sstevel@tonic-gate relock(pid) 991*0Sstevel@tonic-gate int pid; 992*0Sstevel@tonic-gate { 993*0Sstevel@tonic-gate #ifdef LOCKLIB 994*0Sstevel@tonic-gate /* XXX is there a way to do this? */ 995*0Sstevel@tonic-gate return (-1); 996*0Sstevel@tonic-gate #else /* LOCKLIB */ 997*0Sstevel@tonic-gate 998*0Sstevel@tonic-gate int fd; 999*0Sstevel@tonic-gate char lock_buffer[12]; 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate if (lock_file[0] == 0) 1002*0Sstevel@tonic-gate return (-1); 1003*0Sstevel@tonic-gate fd = open(lock_file, O_WRONLY, 0); 1004*0Sstevel@tonic-gate if (fd < 0) { 1005*0Sstevel@tonic-gate error("Couldn't reopen lock file %s: %m", lock_file); 1006*0Sstevel@tonic-gate lock_file[0] = 0; 1007*0Sstevel@tonic-gate return (-1); 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate #ifndef LOCK_BINARY 1011*0Sstevel@tonic-gate (void) slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 1012*0Sstevel@tonic-gate (void) write (fd, lock_buffer, 11); 1013*0Sstevel@tonic-gate #else 1014*0Sstevel@tonic-gate (void) write(fd, &pid, sizeof(pid)); 1015*0Sstevel@tonic-gate #endif /* LOCK_BINARY */ 1016*0Sstevel@tonic-gate (void) close(fd); 1017*0Sstevel@tonic-gate return (0); 1018*0Sstevel@tonic-gate 1019*0Sstevel@tonic-gate #endif /* LOCKLIB */ 1020*0Sstevel@tonic-gate } 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate /* 1023*0Sstevel@tonic-gate * unlock - remove our lockfile 1024*0Sstevel@tonic-gate */ 1025*0Sstevel@tonic-gate void 1026*0Sstevel@tonic-gate unlock() 1027*0Sstevel@tonic-gate { 1028*0Sstevel@tonic-gate if (lock_file[0]) { 1029*0Sstevel@tonic-gate #ifdef LOCKLIB 1030*0Sstevel@tonic-gate (void) rmlock(lock_file, (void *) 0); 1031*0Sstevel@tonic-gate #else 1032*0Sstevel@tonic-gate (void) unlink(lock_file); 1033*0Sstevel@tonic-gate #endif 1034*0Sstevel@tonic-gate lock_file[0] = 0; 1035*0Sstevel@tonic-gate } 1036*0Sstevel@tonic-gate } 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate const char * 1039*0Sstevel@tonic-gate signal_name(int signum) 1040*0Sstevel@tonic-gate { 1041*0Sstevel@tonic-gate #if defined(SOL2) || defined(__linux__) || defined(_linux_) 1042*0Sstevel@tonic-gate const char *cp; 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate if ((cp = strsignal(signum)) != NULL) 1045*0Sstevel@tonic-gate return (cp); 1046*0Sstevel@tonic-gate #else 1047*0Sstevel@tonic-gate extern char *sys_siglist[]; 1048*0Sstevel@tonic-gate extern int sys_nsig; 1049*0Sstevel@tonic-gate 1050*0Sstevel@tonic-gate if (signum >= 0 && signum < sys_nsig && sys_siglist[signum] != NULL) 1051*0Sstevel@tonic-gate return (sys_siglist[signum]); 1052*0Sstevel@tonic-gate #endif 1053*0Sstevel@tonic-gate return ("??"); 1054*0Sstevel@tonic-gate } 1055