⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syslogd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983, 1988, 1993, 1994 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1988, 1993, 1994\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)syslogd.c	8.3 (Berkeley) 4/4/94";#endif /* not lint *//* *  syslogd -- log system messages * * This program implements a system log. It takes a series of lines. * Each line may have a priority, signified as "<n>" as * the first characters of the line.  If this is * not present, a default priority is used. * * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will * cause it to reread its configuration file. * * Defined Constants: * * MAXLINE -- the maximimum line length that can be handled. * DEFUPRI -- the default priority for user messages * DEFSPRI -- the default priority for kernel messages * * Author: Eric Allman * extensive changes by Ralph Campbell * more extensive changes by Eric Allman (again) */#define	MAXLINE		1024		/* maximum line length */#define	MAXSVLINE	120		/* maximum saved line length */#define DEFUPRI		(LOG_USER|LOG_NOTICE)#define DEFSPRI		(LOG_KERN|LOG_CRIT)#define TIMERINTVL	30		/* interval for checking flush, mark */#include <sys/param.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/socket.h>#include <sys/msgbuf.h>#include <sys/uio.h>#include <sys/un.h>#include <sys/time.h>#include <sys/resource.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <utmp.h>#include "pathnames.h"#define SYSLOG_NAMES#include <sys/syslog.h>char	*LogName = _PATH_LOG;char	*ConfFile = _PATH_LOGCONF;char	*PidFile = _PATH_LOGPID;char	ctty[] = _PATH_CONSOLE;#define FDMASK(fd)	(1 << (fd))#define	dprintf		if (Debug) printf#define MAXUNAMES	20	/* maximum number of user names *//* * Flags to logmsg(). */#define IGN_CONS	0x001	/* don't print on console */#define SYNC_FILE	0x002	/* do fsync on file after printing */#define ADDDATE		0x004	/* add a date to the message */#define MARK		0x008	/* this message is a mark *//* * This structure represents the files that will have log * copies printed. */struct filed {	struct	filed *f_next;		/* next in linked list */	short	f_type;			/* entry type, see below */	short	f_file;			/* file descriptor */	time_t	f_time;			/* time this was last written */	u_char	f_pmask[LOG_NFACILITIES+1];	/* priority mask */	union {		char	f_uname[MAXUNAMES][UT_NAMESIZE+1];		struct {			char	f_hname[MAXHOSTNAMELEN+1];			struct sockaddr_in	f_addr;		} f_forw;		/* forwarding address */		char	f_fname[MAXPATHLEN];	} f_un;	char	f_prevline[MAXSVLINE];		/* last message logged */	char	f_lasttime[16];			/* time of last occurrence */	char	f_prevhost[MAXHOSTNAMELEN+1];	/* host from which recd. */	int	f_prevpri;			/* pri of f_prevline */	int	f_prevlen;			/* length of f_prevline */	int	f_prevcount;			/* repetition cnt of prevline */	int	f_repeatcount;			/* number of "repeated" msgs */};/* * Intervals at which we flush out "message repeated" messages, * in seconds after previous message is logged.  After each flush, * we move to the next interval until we reach the largest. */int	repeatinterval[] = { 30, 120, 600 };	/* # of secs before flush */#define	MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)#define	REPEATTIME(f)	((f)->f_time + repeatinterval[(f)->f_repeatcount])#define	BACKOFF(f)	{ if (++(f)->f_repeatcount > MAXREPEAT) \				 (f)->f_repeatcount = MAXREPEAT; \			}/* values for f_type */#define F_UNUSED	0		/* unused entry */#define F_FILE		1		/* regular file */#define F_TTY		2		/* terminal */#define F_CONSOLE	3		/* console terminal */#define F_FORW		4		/* remote machine */#define F_USERS		5		/* list of users */#define F_WALL		6		/* everyone logged on */char	*TypeNames[7] = {	"UNUSED",	"FILE",		"TTY",		"CONSOLE",	"FORW",		"USERS",	"WALL"};struct	filed *Files;struct	filed consfile;int	Debug;			/* debug flag */char	LocalHostName[MAXHOSTNAMELEN+1];	/* our hostname */char	*LocalDomain;		/* our local domain name */int	InetInuse = 0;		/* non-zero if INET sockets are being used */int	finet;			/* Internet datagram socket */int	LogPort;		/* port number for INET connections */int	Initialized = 0;	/* set when we have initialized ourselves */int	MarkInterval = 20 * 60;	/* interval between marks in seconds */int	MarkSeq = 0;		/* mark sequence number */void	cfline __P((char *, struct filed *));char   *cvthname __P((struct sockaddr_in *));int	decode __P((const char *, CODE *));void	die __P((int));void	domark __P((int));void	fprintlog __P((struct filed *, int, char *));void	init __P((int));void	logerror __P((char *));void	logmsg __P((int, char *, char *, int));void	printline __P((char *, char *));void	printsys __P((char *));void	reapchild __P((int));char   *ttymsg __P((struct iovec *, int, char *, int));void	usage __P((void));void	wallmsg __P((struct filed *, struct iovec *));intmain(argc, argv)	int argc;	char *argv[];{	int ch, funix, i, inetm, fklog, klogm, len;	struct sockaddr_un sunx, fromunix;	struct sockaddr_in sin, frominet;	FILE *fp;	char *p, line[MSG_BSIZE + 1];	while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)		switch(ch) {		case 'd':		/* debug */			Debug++;			break;		case 'f':		/* configuration file */			ConfFile = optarg;			break;		case 'm':		/* mark interval */			MarkInterval = atoi(optarg) * 60;			break;		case 'p':		/* path */			LogName = optarg;			break;		case '?':		default:			usage();		}	if ((argc -= optind) != 0)		usage();	if (!Debug)		(void)daemon(0, 0);	else		setlinebuf(stdout);	consfile.f_type = F_CONSOLE;	(void)strcpy(consfile.f_un.f_fname, ctty);	(void)gethostname(LocalHostName, sizeof(LocalHostName));	if ((p = strchr(LocalHostName, '.')) != NULL) {		*p++ = '\0';		LocalDomain = p;	} else		LocalDomain = "";	(void)signal(SIGTERM, die);	(void)signal(SIGINT, Debug ? die : SIG_IGN);	(void)signal(SIGQUIT, Debug ? die : SIG_IGN);	(void)signal(SIGCHLD, reapchild);	(void)signal(SIGALRM, domark);	(void)alarm(TIMERINTVL);	(void)unlink(LogName);#ifndef SUN_LEN#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)#endif	memset(&sunx, 0, sizeof(sunx));	sunx.sun_family = AF_UNIX;	(void)strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path));	funix = socket(AF_UNIX, SOCK_DGRAM, 0);	if (funix < 0 ||	    bind(funix, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 ||	    chmod(LogName, 0666) < 0) {		(void) sprintf(line, "cannot create %s", LogName);		logerror(line);		dprintf("cannot create %s (%d)\n", LogName, errno);		die(0);	}	finet = socket(AF_INET, SOCK_DGRAM, 0);	inetm = 0;	if (finet >= 0) {		struct servent *sp;		sp = getservbyname("syslog", "udp");		if (sp == NULL) {			errno = 0;			logerror("syslog/udp: unknown service");			die(0);		}		memset(&sin, 0, sizeof(sin));		sin.sin_family = AF_INET;		sin.sin_port = LogPort = sp->s_port;		if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {			logerror("bind");			if (!Debug)				die(0);		} else {			inetm = FDMASK(finet);			InetInuse = 1;		}	}	if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)		klogm = FDMASK(fklog);	else {		dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);		klogm = 0;	}	/* tuck my process id away */	fp = fopen(PidFile, "w");	if (fp != NULL) {		fprintf(fp, "%d\n", getpid());		(void) fclose(fp);	}	dprintf("off & running....\n");	init(0);	(void)signal(SIGHUP, init);	for (;;) {		int nfds, readfds = FDMASK(funix) | inetm | klogm;		dprintf("readfds = %#x\n", readfds);		nfds = select(20, (fd_set *)&readfds, (fd_set *)NULL,		    (fd_set *)NULL, (struct timeval *)NULL);		if (nfds == 0)			continue;		if (nfds < 0) {			if (errno != EINTR)				logerror("select");			continue;		}		dprintf("got a message (%d, %#x)\n", nfds, readfds);		if (readfds & klogm) {			i = read(fklog, line, sizeof(line) - 1);			if (i > 0) {				line[i] = '\0';				printsys(line);			} else if (i < 0 && errno != EINTR) {				logerror("klog");				fklog = -1;				klogm = 0;			}		}		if (readfds & FDMASK(funix)) {			len = sizeof(fromunix);			i = recvfrom(funix, line, MAXLINE, 0,			    (struct sockaddr *)&fromunix, &len);			if (i > 0) {				line[i] = '\0';				printline(LocalHostName, line);			} else if (i < 0 && errno != EINTR)				logerror("recvfrom unix");		}		if (readfds & inetm) {			len = sizeof(frominet);			i = recvfrom(finet, line, MAXLINE, 0,			    (struct sockaddr *)&frominet, &len);			if (i > 0) {				line[i] = '\0';				printline(cvthname(&frominet), line);			} else if (i < 0 && errno != EINTR)				logerror("recvfrom inet");		} 	}}voidusage(){	(void)fprintf(stderr,	    "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n");	exit(1);}/* * Take a raw input line, decode the message, and print the message * on the appropriate log files. */voidprintline(hname, msg)	char *hname;	char *msg;{	int c, pri;	char *p, *q, line[MAXLINE + 1];	/* test for special codes */	pri = DEFUPRI;	p = msg;	if (*p == '<') {		pri = 0;		while (isdigit(*++p))			pri = 10 * pri + (*p - '0');		if (*p == '>')			++p;	}	if (pri &~ (LOG_FACMASK|LOG_PRIMASK))		pri = DEFUPRI;	/* don't allow users to log kernel messages */	if (LOG_FAC(pri) == LOG_KERN)		pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));	q = line;	while ((c = *p++ & 0177) != '\0' &&	    q < &line[sizeof(line) - 1])		if (iscntrl(c))			if (c == '\n')				*q++ = ' ';			else if (c == '\t')				*q++ = '\t';			else {				*q++ = '^';				*q++ = c ^ 0100;			}		else			*q++ = c;	*q = '\0';	logmsg(pri, line, hname, 0);}/* * Take a raw input line from /dev/klog, split and format similar to syslog(). */voidprintsys(msg)	char *msg;{	int c, pri, flags;	char *lp, *p, *q, line[MAXLINE + 1];	(void)strcpy(line, "vmunix: ");	lp = line + strlen(line);	for (p = msg; *p != '\0'; ) {		flags = SYNC_FILE | ADDDATE;	/* fsync file after write */		pri = DEFSPRI;		if (*p == '<') {			pri = 0;			while (isdigit(*++p))				pri = 10 * pri + (*p - '0');			if (*p == '>')				++p;		} else {			/* kernel printf's come out on console */			flags |= IGN_CONS;		}		if (pri &~ (LOG_FACMASK|LOG_PRIMASK))			pri = DEFSPRI;		q = lp;		while (*p != '\0' && (c = *p++) != '\n' &&		    q < &line[MAXLINE])			*q++ = c;		*q = '\0';		logmsg(pri, line, LocalHostName, flags);	}}time_t	now;/* * Log a message to the appropriate log files, users, etc. based on * the priority. */voidlogmsg(pri, msg, from, flags)	int pri;	char *msg, *from;	int flags;{	struct filed *f;	int fac, msglen, omask, prilev;	char *timestamp;	dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",	    pri, flags, from, msg);	omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));	/*	 * Check to see if msg looks non-standard.	 */	msglen = strlen(msg);	if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||	    msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')		flags |= ADDDATE;	(void)time(&now);	if (flags & ADDDATE)		timestamp = ctime(&now) + 4;	else {		timestamp = msg;		msg += 16;		msglen -= 16;	}	/* extract facility and priority level */	if (flags & MARK)		fac = LOG_NFACILITIES;	else		fac = LOG_FAC(pri);	prilev = LOG_PRI(pri);	/* log the message to the particular outputs */	if (!Initialized) {		f = &consfile;		f->f_file = open(ctty, O_WRONLY, 0);		if (f->f_file >= 0) {			fprintlog(f, flags, msg);			(void)close(f->f_file);		}		(void)sigsetmask(omask);		return;	}	for (f = Files; f; f = f->f_next) {		/* skip messages that are incorrect priority */		if (f->f_pmask[fac] < prilev ||		    f->f_pmask[fac] == INTERNAL_NOPRI)			continue;		if (f->f_type == F_CONSOLE && (flags & IGN_CONS))			continue;		/* don't output marks to recently written files */		if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)			continue;		/*		 * suppress duplicate lines to this file		 */		if ((flags & MARK) == 0 && msglen == f->f_prevlen &&		    !strcmp(msg, f->f_prevline) &&		    !strcmp(from, f->f_prevhost)) {			(void)strncpy(f->f_lasttime, timestamp, 15);			f->f_prevcount++;			dprintf("msg repeated %d times, %ld sec of %d\n",			    f->f_prevcount, now - f->f_time,			    repeatinterval[f->f_repeatcount]);			/*			 * If domark would have logged this by now,			 * flush it now (so we don't hold isolated messages),			 * but back off so we'll flush less often			 * in the future.			 */			if (now > REPEATTIME(f)) {				fprintlog(f, flags, (char *)NULL);				BACKOFF(f);			}		} else {			/* new line, save it */			if (f->f_prevcount)				fprintlog(f, 0, (char *)NULL);			f->f_repeatcount = 0;			(void)strncpy(f->f_lasttime, timestamp, 15);			(void)strncpy(f->f_prevhost, from,					sizeof(f->f_prevhost));			if (msglen < MAXSVLINE) {				f->f_prevlen = msglen;				f->f_prevpri = pri;				(void)strcpy(f->f_prevline, msg);				fprintlog(f, flags, (char *)NULL);			} else {				f->f_prevline[0] = 0;				f->f_prevlen = 0;				fprintlog(f, flags, msg);			}		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -