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