1*b30d1939SAndy Fiddaman /*********************************************************************** 2*b30d1939SAndy Fiddaman * * 3*b30d1939SAndy Fiddaman * This software is part of the ast package * 4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2012 AT&T Intellectual Property * 5*b30d1939SAndy Fiddaman * and is licensed under the * 6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 * 7*b30d1939SAndy Fiddaman * by AT&T Intellectual Property * 8*b30d1939SAndy Fiddaman * * 9*b30d1939SAndy Fiddaman * A copy of the License is available at * 10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html * 11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12*b30d1939SAndy Fiddaman * * 13*b30d1939SAndy Fiddaman * Information and Software Systems Research * 14*b30d1939SAndy Fiddaman * AT&T Research * 15*b30d1939SAndy Fiddaman * Florham Park NJ * 16*b30d1939SAndy Fiddaman * * 17*b30d1939SAndy Fiddaman * Glenn Fowler <gsf@research.att.com> * 18*b30d1939SAndy Fiddaman * David Korn <dgk@research.att.com> * 19*b30d1939SAndy Fiddaman * Phong Vo <kpv@research.att.com> * 20*b30d1939SAndy Fiddaman * * 21*b30d1939SAndy Fiddaman ***********************************************************************/ 22*b30d1939SAndy Fiddaman #pragma prototyped 23*b30d1939SAndy Fiddaman /* 24*b30d1939SAndy Fiddaman * syslog implementation 25*b30d1939SAndy Fiddaman */ 26*b30d1939SAndy Fiddaman 27*b30d1939SAndy Fiddaman #include <ast.h> 28*b30d1939SAndy Fiddaman 29*b30d1939SAndy Fiddaman #if _lib_syslog 30*b30d1939SAndy Fiddaman 31*b30d1939SAndy Fiddaman NoN(syslog) 32*b30d1939SAndy Fiddaman 33*b30d1939SAndy Fiddaman #else 34*b30d1939SAndy Fiddaman 35*b30d1939SAndy Fiddaman #define LOG_TABLES 36*b30d1939SAndy Fiddaman 37*b30d1939SAndy Fiddaman #include "sysloglib.h" 38*b30d1939SAndy Fiddaman 39*b30d1939SAndy Fiddaman #include <error.h> 40*b30d1939SAndy Fiddaman #include <tm.h> 41*b30d1939SAndy Fiddaman 42*b30d1939SAndy Fiddaman Syslog_state_t log = { LOG_USER, -1, 0, ~0 }; 43*b30d1939SAndy Fiddaman 44*b30d1939SAndy Fiddaman static const Namval_t attempt[] = 45*b30d1939SAndy Fiddaman { 46*b30d1939SAndy Fiddaman #if _UWIN 47*b30d1939SAndy Fiddaman "/var/log/syslog", 0, 48*b30d1939SAndy Fiddaman #endif 49*b30d1939SAndy Fiddaman "/dev/log", 0, 50*b30d1939SAndy Fiddaman "var/log/syslog", 0, 51*b30d1939SAndy Fiddaman "lib/syslog/log", 0, 52*b30d1939SAndy Fiddaman "/dev/console", LOG_CONS, 53*b30d1939SAndy Fiddaman }; 54*b30d1939SAndy Fiddaman 55*b30d1939SAndy Fiddaman const Namval_t log_facility[] = 56*b30d1939SAndy Fiddaman { 57*b30d1939SAndy Fiddaman "default", 0, 58*b30d1939SAndy Fiddaman "user", LOG_USER, 59*b30d1939SAndy Fiddaman "kernel", LOG_KERN, 60*b30d1939SAndy Fiddaman "mail", LOG_MAIL, 61*b30d1939SAndy Fiddaman "daemon", LOG_DAEMON, 62*b30d1939SAndy Fiddaman "security", LOG_AUTH, 63*b30d1939SAndy Fiddaman "syslog", LOG_SYSLOG, 64*b30d1939SAndy Fiddaman "lpr", LOG_LPR, 65*b30d1939SAndy Fiddaman "news", LOG_NEWS, 66*b30d1939SAndy Fiddaman "uucp", LOG_UUCP, 67*b30d1939SAndy Fiddaman "cron", LOG_CRON, 68*b30d1939SAndy Fiddaman "audit", LOG_AUDIT, 69*b30d1939SAndy Fiddaman "logalert", LOG_LFMT, 70*b30d1939SAndy Fiddaman #ifdef LOG_SYSTEM2 71*b30d1939SAndy Fiddaman "system2", LOG_SYSTEM2, 72*b30d1939SAndy Fiddaman #endif 73*b30d1939SAndy Fiddaman #ifdef LOG_SYSTEM1 74*b30d1939SAndy Fiddaman "system1", LOG_SYSTEM1, 75*b30d1939SAndy Fiddaman #endif 76*b30d1939SAndy Fiddaman #ifdef LOG_SYSTEM0 77*b30d1939SAndy Fiddaman "system0", LOG_SYSTEM0, 78*b30d1939SAndy Fiddaman #endif 79*b30d1939SAndy Fiddaman 0, 0 80*b30d1939SAndy Fiddaman }; 81*b30d1939SAndy Fiddaman 82*b30d1939SAndy Fiddaman const Namval_t log_severity[] = 83*b30d1939SAndy Fiddaman { 84*b30d1939SAndy Fiddaman "panic", LOG_EMERG, 85*b30d1939SAndy Fiddaman "alert", LOG_ALERT, 86*b30d1939SAndy Fiddaman "critical", LOG_CRIT, 87*b30d1939SAndy Fiddaman "error", LOG_ERR, 88*b30d1939SAndy Fiddaman "warning", LOG_WARNING, 89*b30d1939SAndy Fiddaman "notice", LOG_NOTICE, 90*b30d1939SAndy Fiddaman "info", LOG_INFO, 91*b30d1939SAndy Fiddaman "debug", LOG_DEBUG, 92*b30d1939SAndy Fiddaman 0, 0 93*b30d1939SAndy Fiddaman }; 94*b30d1939SAndy Fiddaman 95*b30d1939SAndy Fiddaman #if _UWIN 96*b30d1939SAndy Fiddaman 97*b30d1939SAndy Fiddaman /* 98*b30d1939SAndy Fiddaman * open /dev/(fdp|tcp|udp)/HOST/SERVICE for read 99*b30d1939SAndy Fiddaman */ 100*b30d1939SAndy Fiddaman 101*b30d1939SAndy Fiddaman #include <ctype.h> 102*b30d1939SAndy Fiddaman #include <ls.h> 103*b30d1939SAndy Fiddaman #include <sys/socket.h> 104*b30d1939SAndy Fiddaman #include <sys/un.h> 105*b30d1939SAndy Fiddaman #include <netdb.h> 106*b30d1939SAndy Fiddaman #include <netinet/in.h> 107*b30d1939SAndy Fiddaman 108*b30d1939SAndy Fiddaman #if !defined(htons) && !_lib_htons 109*b30d1939SAndy Fiddaman # define htons(x) (x) 110*b30d1939SAndy Fiddaman #endif 111*b30d1939SAndy Fiddaman #if !defined(htonl) && !_lib_htonl 112*b30d1939SAndy Fiddaman # define htonl(x) (x) 113*b30d1939SAndy Fiddaman #endif 114*b30d1939SAndy Fiddaman 115*b30d1939SAndy Fiddaman #ifndef INADDR_LOOPBACK 116*b30d1939SAndy Fiddaman #define INADDR_LOOPBACK 0x7f000001L 117*b30d1939SAndy Fiddaman #endif 118*b30d1939SAndy Fiddaman 119*b30d1939SAndy Fiddaman /* 120*b30d1939SAndy Fiddaman * convert s to sockaddr_in 121*b30d1939SAndy Fiddaman * -1 returned on error 122*b30d1939SAndy Fiddaman */ 123*b30d1939SAndy Fiddaman 124*b30d1939SAndy Fiddaman static int 125*b30d1939SAndy Fiddaman str2inet(register char* s, char* prot, struct sockaddr_in* addr) 126*b30d1939SAndy Fiddaman { 127*b30d1939SAndy Fiddaman register int c; 128*b30d1939SAndy Fiddaman register int v; 129*b30d1939SAndy Fiddaman register int n = 0; 130*b30d1939SAndy Fiddaman unsigned long a = 0; 131*b30d1939SAndy Fiddaman unsigned short p = 0; 132*b30d1939SAndy Fiddaman 133*b30d1939SAndy Fiddaman if (!memcmp(s, "local/", 6)) 134*b30d1939SAndy Fiddaman { 135*b30d1939SAndy Fiddaman a = INADDR_LOOPBACK; 136*b30d1939SAndy Fiddaman n = 4; 137*b30d1939SAndy Fiddaman s += 6; 138*b30d1939SAndy Fiddaman } 139*b30d1939SAndy Fiddaman else if (!isdigit(*s)) 140*b30d1939SAndy Fiddaman { 141*b30d1939SAndy Fiddaman struct hostent* hp; 142*b30d1939SAndy Fiddaman char* e = strchr(s, '/'); 143*b30d1939SAndy Fiddaman 144*b30d1939SAndy Fiddaman if (!(e = strchr(s, '/'))) 145*b30d1939SAndy Fiddaman return -1; 146*b30d1939SAndy Fiddaman *e = 0; 147*b30d1939SAndy Fiddaman hp = gethostbyname(s); 148*b30d1939SAndy Fiddaman *e = '/'; 149*b30d1939SAndy Fiddaman if (!hp || hp->h_addrtype != AF_INET || hp->h_length > sizeof(struct in_addr)) 150*b30d1939SAndy Fiddaman return -1; 151*b30d1939SAndy Fiddaman a = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr; 152*b30d1939SAndy Fiddaman n = 6; 153*b30d1939SAndy Fiddaman s = e + 1; 154*b30d1939SAndy Fiddaman } 155*b30d1939SAndy Fiddaman for (;;) 156*b30d1939SAndy Fiddaman { 157*b30d1939SAndy Fiddaman v = 0; 158*b30d1939SAndy Fiddaman while ((c = *s++) >= '0' && c <= '9') 159*b30d1939SAndy Fiddaman v = v * 10 + c - '0'; 160*b30d1939SAndy Fiddaman if (++n <= 4) 161*b30d1939SAndy Fiddaman a = (a << 8) | (v & 0xff); 162*b30d1939SAndy Fiddaman else 163*b30d1939SAndy Fiddaman { 164*b30d1939SAndy Fiddaman if (n <= 5) 165*b30d1939SAndy Fiddaman a = htonl(a); 166*b30d1939SAndy Fiddaman if (c) 167*b30d1939SAndy Fiddaman { 168*b30d1939SAndy Fiddaman struct servent* sp; 169*b30d1939SAndy Fiddaman 170*b30d1939SAndy Fiddaman if (!(sp = getservbyname(s - 1, prot))) 171*b30d1939SAndy Fiddaman return -1; 172*b30d1939SAndy Fiddaman p = sp->s_port; 173*b30d1939SAndy Fiddaman } 174*b30d1939SAndy Fiddaman else 175*b30d1939SAndy Fiddaman p = htons(v); 176*b30d1939SAndy Fiddaman break; 177*b30d1939SAndy Fiddaman } 178*b30d1939SAndy Fiddaman if (c != '.' && c != '/') 179*b30d1939SAndy Fiddaman return -1; 180*b30d1939SAndy Fiddaman } 181*b30d1939SAndy Fiddaman memset((char*)addr, 0, sizeof(*addr)); 182*b30d1939SAndy Fiddaman addr->sin_family = AF_INET; 183*b30d1939SAndy Fiddaman addr->sin_addr.s_addr = a; 184*b30d1939SAndy Fiddaman addr->sin_port = p; 185*b30d1939SAndy Fiddaman return 0; 186*b30d1939SAndy Fiddaman } 187*b30d1939SAndy Fiddaman 188*b30d1939SAndy Fiddaman /* 189*b30d1939SAndy Fiddaman * call this after open fails to see if path is a socket 190*b30d1939SAndy Fiddaman */ 191*b30d1939SAndy Fiddaman 192*b30d1939SAndy Fiddaman int 193*b30d1939SAndy Fiddaman sockopen(const char* path) 194*b30d1939SAndy Fiddaman { 195*b30d1939SAndy Fiddaman int fd; 196*b30d1939SAndy Fiddaman struct sockaddr_in addr; 197*b30d1939SAndy Fiddaman char buf[PATH_MAX]; 198*b30d1939SAndy Fiddaman 199*b30d1939SAndy Fiddaman if (pathgetlink(path, buf, sizeof(buf)) <= 0) 200*b30d1939SAndy Fiddaman { 201*b30d1939SAndy Fiddaman if (strlen(path) >= sizeof(buf)) 202*b30d1939SAndy Fiddaman return -1; 203*b30d1939SAndy Fiddaman strcpy(buf, path); 204*b30d1939SAndy Fiddaman } 205*b30d1939SAndy Fiddaman #if LOCAL 206*b30d1939SAndy Fiddaman { 207*b30d1939SAndy Fiddaman int ul; 208*b30d1939SAndy Fiddaman struct sockaddr_un ua; 209*b30d1939SAndy Fiddaman struct stat st; 210*b30d1939SAndy Fiddaman 211*b30d1939SAndy Fiddaman if ((ul = strlen(buf)) < sizeof(ua.sun_path) && !stat(buf, &st) && S_ISSOCK(st.st_mode)) 212*b30d1939SAndy Fiddaman { 213*b30d1939SAndy Fiddaman if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 214*b30d1939SAndy Fiddaman return -1; 215*b30d1939SAndy Fiddaman ua.sun_family = AF_UNIX; 216*b30d1939SAndy Fiddaman strcpy(ua.sun_path, buf); 217*b30d1939SAndy Fiddaman ul += sizeof(ua.sun_family) + 1; 218*b30d1939SAndy Fiddaman if (!connect(fd, (struct sockaddr*)&ua, ul)) 219*b30d1939SAndy Fiddaman return fd; 220*b30d1939SAndy Fiddaman close(fd); 221*b30d1939SAndy Fiddaman return -1; 222*b30d1939SAndy Fiddaman } 223*b30d1939SAndy Fiddaman } 224*b30d1939SAndy Fiddaman #endif 225*b30d1939SAndy Fiddaman if (!strmatch(buf, "/dev/(tcp|udp)/*/*")) 226*b30d1939SAndy Fiddaman return -1; 227*b30d1939SAndy Fiddaman buf[8] = 0; 228*b30d1939SAndy Fiddaman if (str2inet(buf + 9, buf + 5, &addr)) 229*b30d1939SAndy Fiddaman return -1; 230*b30d1939SAndy Fiddaman if ((fd = socket(AF_INET, buf[5] == 't' ? SOCK_STREAM : SOCK_DGRAM, 0)) < 0) 231*b30d1939SAndy Fiddaman return -1; 232*b30d1939SAndy Fiddaman if (connect(fd, (struct sockaddr*)&addr, sizeof(addr))) 233*b30d1939SAndy Fiddaman { 234*b30d1939SAndy Fiddaman close(fd); 235*b30d1939SAndy Fiddaman return -1; 236*b30d1939SAndy Fiddaman } 237*b30d1939SAndy Fiddaman return fd; 238*b30d1939SAndy Fiddaman } 239*b30d1939SAndy Fiddaman 240*b30d1939SAndy Fiddaman #else 241*b30d1939SAndy Fiddaman 242*b30d1939SAndy Fiddaman int 243*b30d1939SAndy Fiddaman sockopen(const char* path) 244*b30d1939SAndy Fiddaman { 245*b30d1939SAndy Fiddaman return -1; 246*b30d1939SAndy Fiddaman } 247*b30d1939SAndy Fiddaman 248*b30d1939SAndy Fiddaman #endif 249*b30d1939SAndy Fiddaman 250*b30d1939SAndy Fiddaman void 251*b30d1939SAndy Fiddaman sendlog(const char* msg) 252*b30d1939SAndy Fiddaman { 253*b30d1939SAndy Fiddaman register char* s; 254*b30d1939SAndy Fiddaman register Namval_t* p; 255*b30d1939SAndy Fiddaman register int n; 256*b30d1939SAndy Fiddaman 257*b30d1939SAndy Fiddaman n = msg ? strlen(msg) : 0; 258*b30d1939SAndy Fiddaman for (;;) 259*b30d1939SAndy Fiddaman { 260*b30d1939SAndy Fiddaman if (log.fd < 0) 261*b30d1939SAndy Fiddaman { 262*b30d1939SAndy Fiddaman char buf[PATH_MAX]; 263*b30d1939SAndy Fiddaman 264*b30d1939SAndy Fiddaman if (log.attempt >= elementsof(attempt)) 265*b30d1939SAndy Fiddaman break; 266*b30d1939SAndy Fiddaman p = (Namval_t*)&attempt[log.attempt++]; 267*b30d1939SAndy Fiddaman if (p->value && !(p->value & log.flags)) 268*b30d1939SAndy Fiddaman continue; 269*b30d1939SAndy Fiddaman if (*(s = p->name) != '/' && !(s = pathpath(buf, s, "", PATH_REGULAR|PATH_READ, sizeof(buf)))) 270*b30d1939SAndy Fiddaman continue; 271*b30d1939SAndy Fiddaman if ((log.fd = open(s, O_WRONLY|O_APPEND|O_NOCTTY|O_cloexec)) < 0 && (log.fd = sockopen(s)) < 0) 272*b30d1939SAndy Fiddaman continue; 273*b30d1939SAndy Fiddaman #if !O_cloexec 274*b30d1939SAndy Fiddaman fcntl(log.fd, F_SETFD, FD_CLOEXEC); 275*b30d1939SAndy Fiddaman #endif 276*b30d1939SAndy Fiddaman } 277*b30d1939SAndy Fiddaman if (!n || write(log.fd, msg, n) > 0) 278*b30d1939SAndy Fiddaman break; 279*b30d1939SAndy Fiddaman close(log.fd); 280*b30d1939SAndy Fiddaman log.fd = -1; 281*b30d1939SAndy Fiddaman } 282*b30d1939SAndy Fiddaman if (n && (log.flags & LOG_PERROR)) 283*b30d1939SAndy Fiddaman write(2, msg, n); 284*b30d1939SAndy Fiddaman } 285*b30d1939SAndy Fiddaman 286*b30d1939SAndy Fiddaman static int 287*b30d1939SAndy Fiddaman extend(Sfio_t* sp, void* vp, Sffmt_t* dp) 288*b30d1939SAndy Fiddaman { 289*b30d1939SAndy Fiddaman if (dp->fmt == 'm') 290*b30d1939SAndy Fiddaman { 291*b30d1939SAndy Fiddaman dp->flags |= SFFMT_VALUE; 292*b30d1939SAndy Fiddaman dp->fmt = 's'; 293*b30d1939SAndy Fiddaman dp->size = -1; 294*b30d1939SAndy Fiddaman *((char**)vp) = fmterror(errno); 295*b30d1939SAndy Fiddaman } 296*b30d1939SAndy Fiddaman return 0; 297*b30d1939SAndy Fiddaman } 298*b30d1939SAndy Fiddaman 299*b30d1939SAndy Fiddaman void 300*b30d1939SAndy Fiddaman vsyslog(int priority, const char* format, va_list ap) 301*b30d1939SAndy Fiddaman { 302*b30d1939SAndy Fiddaman register int c; 303*b30d1939SAndy Fiddaman register char* s; 304*b30d1939SAndy Fiddaman Sfio_t* sp; 305*b30d1939SAndy Fiddaman Sffmt_t fmt; 306*b30d1939SAndy Fiddaman char buf[16]; 307*b30d1939SAndy Fiddaman 308*b30d1939SAndy Fiddaman if (!LOG_FACILITY(priority)) 309*b30d1939SAndy Fiddaman priority |= log.facility; 310*b30d1939SAndy Fiddaman if (!(priority & log.mask)) 311*b30d1939SAndy Fiddaman return; 312*b30d1939SAndy Fiddaman if (sp = sfstropen()) 313*b30d1939SAndy Fiddaman { 314*b30d1939SAndy Fiddaman sfputr(sp, fmttime("%b %d %H:%M:%S", time(NiL)), -1); 315*b30d1939SAndy Fiddaman if (log.flags & LOG_LEVEL) 316*b30d1939SAndy Fiddaman { 317*b30d1939SAndy Fiddaman if ((c = LOG_SEVERITY(priority)) < elementsof(log_severity)) 318*b30d1939SAndy Fiddaman s = (char*)log_severity[c].name; 319*b30d1939SAndy Fiddaman else 320*b30d1939SAndy Fiddaman sfsprintf(s = buf, sizeof(buf), "debug%d", c); 321*b30d1939SAndy Fiddaman sfprintf(sp, " %-8s ", s); 322*b30d1939SAndy Fiddaman if ((c = LOG_FACILITY(priority)) < elementsof(log_facility)) 323*b30d1939SAndy Fiddaman s = (char*)log_facility[c].name; 324*b30d1939SAndy Fiddaman else 325*b30d1939SAndy Fiddaman sfsprintf(s = buf, sizeof(buf), "local%d", c); 326*b30d1939SAndy Fiddaman sfprintf(sp, " %-8s ", s); 327*b30d1939SAndy Fiddaman } 328*b30d1939SAndy Fiddaman #if _lib_gethostname 329*b30d1939SAndy Fiddaman if (!*log.host && gethostname(log.host, sizeof(log.host)-1)) 330*b30d1939SAndy Fiddaman strcpy(log.host, "localhost"); 331*b30d1939SAndy Fiddaman sfprintf(sp, " %s", log.host); 332*b30d1939SAndy Fiddaman #endif 333*b30d1939SAndy Fiddaman if (*log.ident) 334*b30d1939SAndy Fiddaman sfprintf(sp, " %s", log.ident); 335*b30d1939SAndy Fiddaman if (log.flags & LOG_PID) 336*b30d1939SAndy Fiddaman { 337*b30d1939SAndy Fiddaman if (!*log.ident) 338*b30d1939SAndy Fiddaman sfprintf(sp, " "); 339*b30d1939SAndy Fiddaman sfprintf(sp, "[%d]", getpid()); 340*b30d1939SAndy Fiddaman } 341*b30d1939SAndy Fiddaman if (format) 342*b30d1939SAndy Fiddaman { 343*b30d1939SAndy Fiddaman sfprintf(sp, ": "); 344*b30d1939SAndy Fiddaman memset(&fmt, 0, sizeof(fmt)); 345*b30d1939SAndy Fiddaman fmt.version = SFIO_VERSION; 346*b30d1939SAndy Fiddaman fmt.form = (char*)format; 347*b30d1939SAndy Fiddaman fmt.extf = extend; 348*b30d1939SAndy Fiddaman va_copy(fmt.args, ap); 349*b30d1939SAndy Fiddaman sfprintf(sp, "%!", &fmt); 350*b30d1939SAndy Fiddaman } 351*b30d1939SAndy Fiddaman if ((s = sfstrseek(sp, 0, SEEK_CUR)) && *(s - 1) != '\n') 352*b30d1939SAndy Fiddaman sfputc(sp, '\n'); 353*b30d1939SAndy Fiddaman if (s = sfstruse(sp)) 354*b30d1939SAndy Fiddaman sendlog(s); 355*b30d1939SAndy Fiddaman sfstrclose(sp); 356*b30d1939SAndy Fiddaman } 357*b30d1939SAndy Fiddaman } 358*b30d1939SAndy Fiddaman 359*b30d1939SAndy Fiddaman void 360*b30d1939SAndy Fiddaman syslog(int priority, const char* format, ...) 361*b30d1939SAndy Fiddaman { 362*b30d1939SAndy Fiddaman va_list ap; 363*b30d1939SAndy Fiddaman 364*b30d1939SAndy Fiddaman va_start(ap, format); 365*b30d1939SAndy Fiddaman vsyslog(priority, format, ap); 366*b30d1939SAndy Fiddaman va_end(ap); 367*b30d1939SAndy Fiddaman } 368*b30d1939SAndy Fiddaman 369*b30d1939SAndy Fiddaman #endif 370