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