xref: /onnv-gate/usr/src/lib/libast/common/comp/syslog.c (revision 12068:08a39a083754)
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