14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * syslog implementation 254887Schin */ 264887Schin 274887Schin #include <ast.h> 284887Schin 294887Schin #if _lib_syslog 304887Schin 314887Schin NoN(syslog) 324887Schin 334887Schin #else 344887Schin 354887Schin #define LOG_TABLES 364887Schin 374887Schin #include "sysloglib.h" 384887Schin 394887Schin #include <error.h> 404887Schin #include <tm.h> 414887Schin 424887Schin Syslog_state_t log = { LOG_USER, -1, 0, ~0 }; 434887Schin 444887Schin static const Namval_t attempt[] = 454887Schin { 464887Schin "/dev/log", 0, 474887Schin "lib/syslog/log", 0, 484887Schin "/dev/console", LOG_CONS, 494887Schin }; 504887Schin 514887Schin const Namval_t log_facility[] = 524887Schin { 534887Schin "default", 0, 544887Schin "user", LOG_USER, 554887Schin "kernel", LOG_KERN, 564887Schin "mail", LOG_MAIL, 574887Schin "daemon", LOG_DAEMON, 584887Schin "security", LOG_AUTH, 594887Schin "syslog", LOG_SYSLOG, 604887Schin "lpr", LOG_LPR, 614887Schin "news", LOG_NEWS, 624887Schin "uucp", LOG_UUCP, 634887Schin "cron", LOG_CRON, 644887Schin "audit", LOG_AUDIT, 654887Schin "logalert", LOG_LFMT, 664887Schin #ifdef LOG_SYSTEM2 674887Schin "system2", LOG_SYSTEM2, 684887Schin #endif 694887Schin #ifdef LOG_SYSTEM1 704887Schin "system1", LOG_SYSTEM1, 714887Schin #endif 724887Schin #ifdef LOG_SYSTEM0 734887Schin "system0", LOG_SYSTEM0, 744887Schin #endif 754887Schin 0, 0 764887Schin }; 774887Schin 784887Schin const Namval_t log_severity[] = 794887Schin { 804887Schin "panic", LOG_EMERG, 814887Schin "alert", LOG_ALERT, 824887Schin "critical", LOG_CRIT, 834887Schin "error", LOG_ERR, 844887Schin "warning", LOG_WARNING, 854887Schin "notice", LOG_NOTICE, 864887Schin "info", LOG_INFO, 874887Schin "debug", LOG_DEBUG, 884887Schin 0, 0 894887Schin }; 904887Schin 914887Schin #if _UWIN 924887Schin 934887Schin /* 944887Schin * open /dev/(fdp|tcp|udp)/HOST/SERVICE for read 954887Schin */ 964887Schin 974887Schin #include <ctype.h> 984887Schin #include <ls.h> 994887Schin #include <sys/socket.h> 1004887Schin #include <sys/un.h> 1014887Schin #include <netdb.h> 1024887Schin #include <netinet/in.h> 1034887Schin 1044887Schin #if !defined(htons) && !_lib_htons 1054887Schin # define htons(x) (x) 1064887Schin #endif 1074887Schin #if !defined(htonl) && !_lib_htonl 1084887Schin # define htonl(x) (x) 1094887Schin #endif 1104887Schin 1114887Schin #ifndef INADDR_LOOPBACK 1124887Schin #define INADDR_LOOPBACK 0x7f000001L 1134887Schin #endif 1144887Schin 1154887Schin /* 1164887Schin * convert s to sockaddr_in 1174887Schin * -1 returned on error 1184887Schin */ 1194887Schin 1204887Schin static int 1214887Schin str2inet(register char* s, char* prot, struct sockaddr_in* addr) 1224887Schin { 1234887Schin register int c; 1244887Schin register int v; 1254887Schin register int n = 0; 1264887Schin unsigned long a = 0; 1274887Schin unsigned short p = 0; 1284887Schin 1294887Schin if (!memcmp(s, "local/", 6)) 1304887Schin { 1314887Schin a = INADDR_LOOPBACK; 1324887Schin n = 4; 1334887Schin s += 6; 1344887Schin } 1354887Schin else if (!isdigit(*s)) 1364887Schin { 1374887Schin struct hostent* hp; 1384887Schin char* e = strchr(s, '/'); 1394887Schin 1404887Schin if (!(e = strchr(s, '/'))) 1414887Schin return -1; 1424887Schin *e = 0; 1434887Schin hp = gethostbyname(s); 1444887Schin *e = '/'; 1454887Schin if (!hp || hp->h_addrtype != AF_INET || hp->h_length > sizeof(struct in_addr)) 1464887Schin return -1; 1474887Schin a = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr; 1484887Schin n = 6; 1494887Schin s = e + 1; 1504887Schin } 1514887Schin for (;;) 1524887Schin { 1534887Schin v = 0; 1544887Schin while ((c = *s++) >= '0' && c <= '9') 1554887Schin v = v * 10 + c - '0'; 1564887Schin if (++n <= 4) 1574887Schin a = (a << 8) | (v & 0xff); 1584887Schin else 1594887Schin { 1604887Schin if (n <= 5) 1614887Schin a = htonl(a); 1624887Schin if (c) 1634887Schin { 1644887Schin struct servent* sp; 1654887Schin 1664887Schin if (!(sp = getservbyname(s - 1, prot))) 1674887Schin return -1; 1684887Schin p = sp->s_port; 1694887Schin } 1704887Schin else 1714887Schin p = htons(v); 1724887Schin break; 1734887Schin } 1744887Schin if (c != '.' && c != '/') 1754887Schin return -1; 1764887Schin } 1774887Schin memset((char*)addr, 0, sizeof(*addr)); 1784887Schin addr->sin_family = AF_INET; 1794887Schin addr->sin_addr.s_addr = a; 1804887Schin addr->sin_port = p; 1814887Schin return 0; 1824887Schin } 1834887Schin 1844887Schin /* 1854887Schin * call this after open fails to see if path is a socket 1864887Schin */ 1874887Schin 1884887Schin int 1894887Schin sockopen(const char* path) 1904887Schin { 1914887Schin int fd; 1924887Schin struct sockaddr_in addr; 1934887Schin char buf[PATH_MAX]; 1944887Schin 1954887Schin if (pathgetlink(path, buf, sizeof(buf)) <= 0) 1964887Schin { 1974887Schin if (strlen(path) >= sizeof(buf)) 1984887Schin return -1; 1994887Schin strcpy(buf, path); 2004887Schin } 2014887Schin #if LOCAL 2024887Schin { 2034887Schin int ul; 2044887Schin struct sockaddr_un ua; 2054887Schin struct stat st; 2064887Schin 2074887Schin if ((ul = strlen(buf)) < sizeof(ua.sun_path) && !stat(buf, &st) && S_ISSOCK(st.st_mode)) 2084887Schin { 2094887Schin if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 2104887Schin return -1; 2114887Schin ua.sun_family = AF_UNIX; 2124887Schin strcpy(ua.sun_path, buf); 2134887Schin ul += sizeof(ua.sun_family) + 1; 2144887Schin if (!connect(fd, (struct sockaddr*)&ua, ul)) 2154887Schin return fd; 2164887Schin close(fd); 2174887Schin return -1; 2184887Schin } 2194887Schin } 2204887Schin #endif 2214887Schin if (!strmatch(buf, "/dev/(tcp|udp)/*/*")) 2224887Schin return -1; 2234887Schin buf[8] = 0; 2244887Schin if (str2inet(buf + 9, buf + 5, &addr)) 2254887Schin return -1; 2264887Schin if ((fd = socket(AF_INET, buf[5] == 't' ? SOCK_STREAM : SOCK_DGRAM, 0)) < 0) 2274887Schin return -1; 2284887Schin if (connect(fd, (struct sockaddr*)&addr, sizeof(addr))) 2294887Schin { 2304887Schin close(fd); 2314887Schin return -1; 2324887Schin } 2334887Schin return fd; 2344887Schin } 2354887Schin 2364887Schin #else 2374887Schin 2384887Schin int 2394887Schin sockopen(const char* path) 2404887Schin { 2414887Schin return -1; 2424887Schin } 2434887Schin 2444887Schin #endif 2454887Schin 2464887Schin void 2474887Schin sendlog(const char* msg) 2484887Schin { 2494887Schin register char* s; 2504887Schin register Namval_t* p; 2514887Schin register int n; 2524887Schin 2534887Schin n = msg ? strlen(msg) : 0; 2544887Schin for (;;) 2554887Schin { 2564887Schin if (log.fd < 0) 2574887Schin { 2584887Schin char buf[PATH_MAX]; 2594887Schin 2604887Schin if (log.attempt >= elementsof(attempt)) 2614887Schin break; 2624887Schin p = (Namval_t*)&attempt[log.attempt++]; 2634887Schin if (p->value && !(p->value & log.flags)) 2644887Schin continue; 2654887Schin if (*(s = p->name) != '/' && !(s = pathpath(buf, s, "", PATH_REGULAR|PATH_READ))) 2664887Schin continue; 2674887Schin if ((log.fd = open(s, O_WRONLY|O_APPEND|O_NOCTTY)) < 0 && (log.fd = sockopen(s)) < 0) 2684887Schin continue; 2694887Schin fcntl(log.fd, F_SETFD, FD_CLOEXEC); 2704887Schin } 2714887Schin if (!n || write(log.fd, msg, n) > 0) 2724887Schin break; 2734887Schin close(log.fd); 2744887Schin log.fd = -1; 2754887Schin } 2764887Schin if (n && (log.flags & LOG_PERROR)) 2774887Schin write(2, msg, n); 2784887Schin } 2794887Schin 2804887Schin static int 2814887Schin extend(Sfio_t* sp, void* vp, Sffmt_t* dp) 2824887Schin { 2834887Schin if (dp->fmt == 'm') 2844887Schin { 2854887Schin dp->flags |= SFFMT_VALUE; 2864887Schin dp->fmt = 's'; 2874887Schin dp->size = -1; 2884887Schin *((char**)vp) = fmterror(errno); 2894887Schin } 2904887Schin return 0; 2914887Schin } 2924887Schin 2934887Schin void 2944887Schin vsyslog(int priority, const char* format, va_list ap) 2954887Schin { 2964887Schin register int c; 2974887Schin register char* s; 2984887Schin Sfio_t* sp; 2994887Schin Sffmt_t fmt; 3004887Schin char buf[16]; 3014887Schin 3024887Schin if (!LOG_FACILITY(priority)) 3034887Schin priority |= log.facility; 3044887Schin if (!(priority & log.mask)) 3054887Schin return; 3064887Schin if (sp = sfstropen()) 3074887Schin { 3084887Schin sfputr(sp, fmttime("%b %d %H:%M:%S", time(NiL)), -1); 3094887Schin if (log.flags & LOG_LEVEL) 3104887Schin { 3114887Schin if ((c = LOG_SEVERITY(priority)) < elementsof(log_severity)) 3124887Schin s = (char*)log_severity[c].name; 3134887Schin else 3144887Schin sfsprintf(s = buf, sizeof(buf), "debug%d", c); 3154887Schin sfprintf(sp, " %-8s ", s); 3164887Schin if ((c = LOG_FACILITY(priority)) < elementsof(log_facility)) 3174887Schin s = (char*)log_facility[c].name; 3184887Schin else 3194887Schin sfsprintf(s = buf, sizeof(buf), "local%d", c); 3204887Schin sfprintf(sp, " %-8s ", s); 3214887Schin } 3224887Schin #if _lib_gethostname 3234887Schin if (!*log.host && gethostname(log.host, sizeof(log.host)-1)) 3244887Schin strcpy(log.host, "localhost"); 3254887Schin sfprintf(sp, " %s", log.host); 3264887Schin #endif 3274887Schin if (*log.ident) 3284887Schin sfprintf(sp, " %s", log.ident); 3294887Schin if (log.flags & LOG_PID) 3304887Schin { 3314887Schin if (!*log.ident) 3324887Schin sfprintf(sp, " "); 3334887Schin sfprintf(sp, "[%d]", getpid()); 3344887Schin } 3354887Schin if (format) 3364887Schin { 3374887Schin sfprintf(sp, ": "); 3384887Schin memset(&fmt, 0, sizeof(fmt)); 3394887Schin fmt.version = SFIO_VERSION; 3404887Schin fmt.form = (char*)format; 3414887Schin fmt.extf = extend; 3424887Schin va_copy(fmt.args, ap); 3434887Schin sfprintf(sp, "%!", &fmt); 3444887Schin } 3454887Schin if ((s = sfstrseek(sp, 0, SEEK_CUR)) && *(s - 1) != '\n') 3464887Schin sfputc(sp, '\n'); 3474887Schin if (s = sfstruse(sp)) 3484887Schin sendlog(s); 3494887Schin sfstrclose(sp); 3504887Schin } 3514887Schin } 3524887Schin 3534887Schin void 3544887Schin syslog(int priority, const char* format, ...) 3554887Schin { 3564887Schin va_list ap; 3574887Schin 3584887Schin va_start(ap, format); 3594887Schin vsyslog(priority, format, ap); 3604887Schin va_end(ap); 3614887Schin } 3624887Schin 3634887Schin #endif 364