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

📄 im_linux.c

📁 MSyslog是一个允许在Linux下运行的网络系统日志程序
💻 C
字号:
/*	$CoreSDI: im_linux.c,v 1.60 2002/03/01 08:43:37 alejo Exp $	*//* * Copyright (c) 2001, Core SDI S.A., Argentina * 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. Neither name of the Core SDI S.A. 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 AUTHOR ``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 AUTHOR 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. *//* *  im_linux -- input module to log linux kernel messages *       * Author: Claudio Castiglia, Core-SDI S.A. *     */#include "config.h"#include <sys/types.h>#include <sys/uio.h>#include <sys/klog.h>#include <sys/param.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <err.h>#include <paths.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <unistd.h>#include <time.h>#include "../modules.h"#include "../syslogd.h"#define	KSYM_TRANSLATE		0x01#define KSYM_READ_TABLE		0x02#define KLOG_USE_SYSCALL	0x04#define KLOG_HAVE_NEWLINE	0x08int	linux_flags;char	*linux_input_module = "linux input module";/* * kernel symbols */#define PATH_KSYM	"/proc/ksyms"#define MAX_ADDR_LEN	16#define MAX_NAME_LEN	80#define MAX_MNAME_LEN	20typedef struct _Symbol {	char addr[MAX_ADDR_LEN + 1];	char name[MAX_NAME_LEN + 1];	char mname[MAX_MNAME_LEN + 1];	struct _Symbol *next;} Symbol;FILE	*ksym_fd = NULL;char	*ksym_path = PATH_KSYM;Symbol	*ksym_first = NULL;Symbol	*ksym_current = NULL;char	saveline[MAXLINE + 1];int	savelen;int	 ksym_init();void	 ksym_close();int	 ksym_snprintf (char*, int, char*);Symbol	*ksym_lookup (Symbol*, char*);int	 ksym_get_symbol (Symbol*);int	 ksym_parseline (char*, Symbol*);char	*ksym_copyword (char*, char*, int);/* * Usage */voidim_linux_usage(){	dprintf(MSYSLOG_INFORMATIVE, "linux input module options:\n"	    "   [ -k file ]    Use the specified file as source of kernel\n"	    "                  symbol information instead of %s.\n"	    "   [ -r ]         Force read symbol table on memory.\n"	    "   [ -s ]         Force to use syscall instead of %s\n"	    "                  to log kernel messages.\n"	    "   [ -x ]         Do not translate kernel symbols.\n"	    "Defaults:\n"	    "   Reads kernel messages from %s; "#if 0	    " if this file doesn't exists\n"	    "   it uses the syscall method.\n"#endif	    "   Symbols are translated only if %s exists.\n\n",	    PATH_KSYM, _PATH_KLOG, _PATH_KLOG, PATH_KSYM);}/* * getLine: * Search for a line on a string buffer * returns a pointer to the line or NULL if the buffer is empty */char*getLine (char *buf, int *i){	if (*buf == '\0')		return (NULL);	while (buf[*i] != '\n' && buf[*i] != '\0')		(*i)++;	if (buf[*i] == '\0') {		(*i)--;	} else {		if (buf[*i] == '\n')			linux_flags |= KLOG_HAVE_NEWLINE;		buf[*i] = '\0';	}	return (buf);}/* * Sets console loglevel */intim_linux_set_console_loglevel (char *strlv){	char		*err;	unsigned long	 loglevel;	if ( (loglevel = strtoul(strlv, &err, 10)) < 0 ||	      loglevel > 7 || *err != '\0') {		warnx("%s: invalid loglevel <%s>", linux_input_module, strlv);		return (-1);	}	warnx("%s: setting console loglevel to <%lu>", linux_input_module,	      loglevel);	if (klogctl(8, NULL, loglevel) < 0) {		warn("%s", linux_input_module);		return (-1);	}	return (0);}/* * Initialize linux input module */intim_linux_init (struct i_module *I, char **argv, int argc){	int ch;	int argcnt;	dprintf(MSYSLOG_INFORMATIVE, "im_linux_init: Entering\n");	/* parse command line */	/* syslogd calls im_linux_init when	 * parsing command line	 * This should be changed	 */	linux_flags = KSYM_TRANSLATE;	if (argc > 1) {		argcnt = 1; /* skip module name */		while ((ch = getxopt(argc, argv, "c!console: C!setconsole:"		    " k!symbolfile: r!readsymbols s!syscalls x!notranslate"		    " h!help", &argcnt)) != -1) {			switch(ch) {			case 'c': /* specify console loglevel */				if (im_linux_set_console_loglevel(argv[argcnt])				    < 0)					return (-1);				break;			case 'C': /* specify console loglevel and force exit */				im_linux_set_console_loglevel(argv[argcnt]);				return (-1);			case 'k': /* specify symbol file */				if (strcmp(ksym_path, argv[argcnt]) != 0 ||				    (ksym_path = strdup(argv[argcnt])) == NULL) {					warn("%s", linux_input_module);					return (-1);				    }				break;			case 'r': /* force to read symbol table and keep				   * it in memory				   */				linux_flags |= KSYM_READ_TABLE;				break;/* not supported yet, we need to talk about somethings */#if 0			case 's': /* force to use syscall instead				   * of _PATH_KLOG				   */				linux_flags |= KLOG_USE_SYSCALL;				break;#endif			case 'x': /* do not translate kernel symbols */				linux_flags &= ~KSYM_TRANSLATE;				break;			case 'h': /* usage */			case '?':			default:				im_linux_usage();				return (-1);			}			argcnt++;		}	}	I->im_path = NULL;	I->im_fd = 0;	if (!(linux_flags & KLOG_USE_SYSCALL)) {		if ( (I->im_fd = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)			I->im_path = _PATH_KLOG;/* if /proc not mounted.. sorry: syscall not supported yet */#if 0		else if (errno != ENOENT) {			warn("%s: %s: %s\n",			     linux_input_module, _PATH_KLOG, strerror(errno));			return (-1);		} else			/* /proc not mounted, use syscall */			I->im_fd = 0;#endif#if 1		else {			warn("%s: %s: %s\n",			     linux_input_module, _PATH_KLOG, strerror(errno));			return (-1);		}#endif	}	/* open/read symbol table file */	if ((linux_flags & KSYM_TRANSLATE) && ksym_init() < 0)		return (-1);        I->im_flags |= IMODULE_FLAG_KERN;	saveline[0] = '\0';	/* yes, globals are zeroed, but... */	savelen = 0;	add_fd_input(I->im_fd , I);        return (I->im_fd);}/* * get kernel message: * take input line from _PATH_KLOG or klogctl(2) * and log it. */intim_linux_read (struct i_module *im, int infd, struct im_msg *ret){	int   i;	char *ptr;	if (im->im_fd < 0)		return (-1);	/* read message from kernel *//* syscall not supported yet */#if 0	if (im->im_path == NULL || linux_flags & KLOG_USE_SYSCALL)		/* this blocks */		/* i = klogctl(2, im->im_buf, sizeof(im->im_buf)-1);		 */		/* ;;;this don't block... testing */		i = klogctl(4, im->im_buf, sizeof(im->im_buf)-1);	else#endif		i = read(im->im_fd, im->im_buf, sizeof(im->im_buf)-1);	if (i < 0 && errno != EINTR) {		logerror("im_linux_read");		return (-1);	}	if (i) {		im->im_buf[i] = '\0';		/* log each msg line */		i = 0;		ptr = im->im_buf;		while ( (ptr = getLine(ptr, &i)) != NULL) {			char	*msg;			int	buflen;						/* get priority */			if (i >= 3 && ptr[0] == '<' &&			    ptr[2] == '>' && isdigit(ptr[1])) {				ret->im_pri = ptr[1] - '0';				ptr += 3;				i -= 3;			}			else				/* from printk.c: DEFAULT_MESSAGE_LOGLEVEL */				ret->im_pri = LOG_WARNING;			msg = &saveline[savelen];			buflen = sizeof(saveline) - savelen;			/*			 * Parse kernel/module symbols and print.			 */			if (linux_flags & KSYM_TRANSLATE)				savelen = ksym_snprintf(msg, buflen, ptr);			else				savelen = snprintf(msg, buflen,				    savelen == 0 ? "kernel: %s" : "%s", ptr);			ret->im_host[0] = '\0';			if (linux_flags & KLOG_HAVE_NEWLINE) {				logmsg(ret->im_pri, saveline, ret->im_host, im->im_flags);				saveline[0] = '\0';				savelen = 0;				linux_flags &= ~KLOG_HAVE_NEWLINE;			}			ptr += i + 1;			i = 0;		}	}	return (0);}/* * Close linux input module */intim_linux_close (struct i_module *im){	ksym_close();	if (im->im_path != NULL) 		return (close(im->im_fd));	return (0);}/* * Open/load symbol table * Returns 0 on success and -1 on error */intksym_init(){	char	 buf[128];	Symbol	*last;	Symbol	*next;	ksym_close();	if ( (ksym_fd = fopen(ksym_path, "r")) == NULL) {		warn("%s: ksym_init: %s", linux_input_module, ksym_path);		return (-1);	}	if (linux_flags & KSYM_READ_TABLE) {		last = NULL;		while (fgets(buf, sizeof(buf), ksym_fd) != NULL) {			if ( (next = (Symbol*) malloc(sizeof(Symbol))) == NULL) {				warn("%s: ksym_init", linux_input_module);				ksym_close();				return (-1);			}			next->next = NULL;			if (last)				last->next = next;			else				ksym_first = next;			if (ksym_parseline(buf, next) < 0) {				warnx("%s: ksym_init: incorrect symbol file: %s"				      , linux_input_module, ksym_path);				ksym_close(); /* this also frees *next */				return (-1);			}			last = next;		}		fclose(ksym_fd);		ksym_fd = NULL;	}	return (0);}/* * Close/delete symbol table */voidksym_close(){	Symbol *s;	if (ksym_fd != NULL) {		fclose(ksym_fd);		ksym_fd = NULL;	}	while (ksym_first) {		s = ksym_first->next;		free(ksym_first);		ksym_first = s;	}	if (ksym_path != PATH_KSYM)		free(ksym_path);}/* * ksym_snprintf */intksym_snprintf (char *buf, int bufsize, char *raw){	int     i;	int	printed;	char   *p1;	char   *p2;	Symbol  sym;	if ( (printed = snprintf(buf, bufsize, "kernel: ")) < 0)		return (-1);	bufsize -= printed;	while (bufsize && *raw != '\0') {		if ( (p1 = strstr(raw, "[<")) != NULL &&		     (p2 = strstr(p1, ">]")) != NULL) {			for (i = 2; p1+i < p2 && isxdigit(p1[i]); i++);			if (p1+i == p2) {				*p2 = '\0';				if (ksym_lookup(&sym, p1+2) != NULL) {					*p1 = '\0';					if ( (printed +=					    snprintf(buf+printed, bufsize,					    "%s [<%s> %s.%s ]", raw, sym.addr,					    sym.mname, sym.name)) < 0)						return (-1);					bufsize -= printed;					/* we need to solve some things 					 * about buf and msg params on					 * im_xxxxx_read.					 * so, i think that is better					 * not to change raw data ;;;					 */					*p1 = '[';					*p2 = '>';					raw = p2+2;					continue;				}				*p2 = '>';			} 		} 		break;	}	if (*raw) {		/* kernel message without symbols */		if ( (i = snprintf(buf+printed, bufsize, "%s", raw)) < 0)			return (-1);		else			printed += i;	}	return (printed);}/* * Lookup symbol: * search for a symbol on internal table/file that * matches an address. * If the symbol does not exists it returns NULL */Symbol*ksym_lookup (Symbol *sym, char *addr){	/* reset symbol table/file pointer */	if (ksym_fd == NULL)		ksym_current = ksym_first;	else		fseek(ksym_fd, 0, SEEK_SET);	/* search for symbol */	while (!ksym_get_symbol(sym))		if (!strcasecmp(sym->addr, addr))			return (sym);	return (NULL);}/* * Get a symbol from table/file * returns 0 on success and -1 on end of file/table */intksym_get_symbol (Symbol *sym){	char msg[MAXLINE];	if (ksym_fd == NULL) {		if (ksym_current != NULL) {			*sym = *ksym_current;			ksym_current = ksym_current->next;			return (0);		}	} else if (fgets(msg, sizeof(msg), ksym_fd) != NULL)			return (ksym_parseline(msg, sym));	return (-1);}/* * ksym_parseline: converts a line onto a Symbol * returns 0 on success and -1 on error */#define QUIT_BLANK(a)	while (*a == ' ' || *a == '\t') a++;intksym_parseline (char *p, Symbol *sym){	if (sym == NULL || p == NULL || p[0] == '\0')		return (-1);	sym->addr[0] = sym->name[0] = sym->mname[0] = '\0';	/* copy address */	QUIT_BLANK(p);	if (*p == '\0' || *p == '\n')		return (-1); 	p = ksym_copyword(sym->addr, p, MAX_ADDR_LEN);	/* copy name */	QUIT_BLANK(p);	if (*p == '\0' || *p == '\n')		return (-1);	p = ksym_copyword(sym->name, p, MAX_NAME_LEN);	/* copy module name (if any) */	QUIT_BLANK(p);	ksym_copyword(sym->mname, p, MAX_MNAME_LEN);	return (0);}/* * copyword(dst, src, len) * Copy from src to dst until reaches * len bytes or '\0' or '\n' */char*ksym_copyword (char *dst, char *src, int max){	int i = 0;	if (max) {		max--;		while (*src != ' ' && *src != '\t' &&		       *src != '\0' && *src != '\n' && i < max)			dst[i++] = *src++;		dst[i] = '\0';	}	return (src);}

⌨️ 快捷键说明

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