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