Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
     5         kx /*
     5         kx  * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
     5         kx  *
     5         kx  * This software may be freely redistributed under the terms of the GNU
     5         kx  * public license.
     5         kx  *
     5         kx  * You should have received a copy of the GNU General Public License
     5         kx  * along with this program; if not, write to the Free Software
     5         kx  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     5         kx  *
     5         kx  */
     5         kx 
     5         kx #include <ctype.h>
     5         kx #include <errno.h>
     5         kx #include <fcntl.h>
     5         kx #include <libintl.h>
     5         kx #include <locale.h>
     5         kx #include <stdio.h>
     5         kx #include <stdlib.h>
     5         kx #include <string.h>
     5         kx #include <unistd.h>
     5         kx 
     5         kx #define SYSLOG_NAMES
     5         kx #include <syslog.h>
     5         kx 
     5         kx #include <sys/socket.h>
     5         kx #include <sys/stat.h>
     5         kx #include <sys/un.h>
     5         kx #include <sys/wait.h>
     5         kx 
     5         kx #define _(String) gettext((String))
     5         kx 
     5         kx #include <popt.h>
     5         kx 
     5         kx #include <regex.h>
     5         kx 
     5         kx #include "initlog.h"
     5         kx #include "process.h"
     5         kx 
     5         kx static int logfacility=LOG_DAEMON;
     5         kx static int logpriority=LOG_NOTICE;
     5         kx static int reexec=0;
     5         kx static int quiet=0;
     5         kx int debug=0;
     5         kx 
     5         kx regex_t  **regList = NULL;
     5         kx 
     5         kx static int logEntries = 0;
     5         kx struct logInfo *logData = NULL;
     5         kx 
     5         kx void readConfiguration(char *fname) {
     5         kx     int fd,num=0;
     5         kx     struct stat sbuf;
     5         kx     char *data,*line, *d;
     5         kx     regex_t *regexp;
     5         kx     int lfac=-1,lpri=-1;
     5         kx     
     5         kx     if ((fd=open(fname,O_RDONLY))==-1) return;
     5         kx     if (fstat(fd,&sbuf)) {
     5         kx 	    close(fd);
     5         kx 	    return;
     5         kx     }
     5         kx     d = data=malloc(sbuf.st_size+1);
     5         kx     if (read(fd,data,sbuf.st_size)!=sbuf.st_size) {
     5         kx 	    close(fd);
     5         kx 	    free(data);
     5         kx 	    return;
     5         kx     }
     5         kx     close(fd);
     5         kx     data[sbuf.st_size] = '\0';
     5         kx     while ((line=getLine(&data))) {
     5         kx 	if (line[0]=='#') continue;
     5         kx 	if (!strncmp(line,"ignore ",7)) {
     5         kx 	    regexp = malloc(sizeof(regex_t));
     5         kx 	    if (!regcomp(regexp,line+7,REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) {
     5         kx 		regList = realloc(regList,(num+2) * sizeof(regex_t *));
     5         kx 		regList[num] = regexp;
     5         kx 		regList[num+1] = NULL;
     5         kx 		num++;
     5         kx 	    }
     5         kx 	}
     5         kx 	if (!strncmp(line,"facility ",9)) {
     5         kx 	    lfac=atoi(line+9);
     5         kx 	    if ((lfac == 0) && strcmp(line+9,"0")) {
     5         kx 		int x =0;
     5         kx 		
     5         kx 		lfac = LOG_DAEMON;
     5         kx 		for (x=0;facilitynames[x].c_name;x++) {
     5         kx 		    if (!strcmp(line+9,facilitynames[x].c_name)) {
     5         kx 			lfac = facilitynames[x].c_val;
     5         kx 			break;
     5         kx 		    }
     5         kx 		}
     5         kx 	    }
     5         kx 	}
     5         kx 	if (!strncmp(line,"priority ",9)) {
     5         kx 	    lpri = atoi(line+9);
     5         kx 	    if ((lpri == 0) && strcmp(line+9,"0")) {
     5         kx 		int x=0;
     5         kx 		
     5         kx 		lpri = LOG_NOTICE;
     5         kx 		for (x=0;prioritynames[x].c_name;x++) {
     5         kx 		    if (!strcmp(line+9,prioritynames[x].c_name)) {
     5         kx 			lpri = prioritynames[x].c_val;
     5         kx 			break;
     5         kx 		    }
     5         kx 		}
     5         kx 	    }
     5         kx 	}
     5         kx     }
     5         kx     if (lfac!=-1) logfacility=lfac;
     5         kx     if (lpri!=-1) logpriority=lpri;
     5         kx     free(d);
     5         kx }
     5         kx     
     5         kx char *getLine(char **data) {
     5         kx     /* Get one line from data */
     5         kx     /* Anything up to a carraige return (\r) or a backspace (\b) is discarded. */
     5         kx     /* If this really bothers you, mail me and I might make it configurable. */
     5         kx     /* It's here to avoid confilcts with fsck's progress bar. */
     5         kx     char *x, *y;
     5         kx     
     5         kx     if (!*data) return NULL;
     5         kx     x=*data;
     5         kx     while (*x && (*x != '\n')) {
     5         kx 	while (*x && (*x != '\n') && (*x != '\r') && (*x != '\b')) x++;
     5         kx 	if (*x && (*x=='\r' || *x =='\b')) {
     5         kx 		*data = x+1;
     5         kx 		x++;
     5         kx 	}
     5         kx     }
     5         kx     if (*x) {
     5         kx 	x++;
     5         kx     } else {
     5         kx 	if (x-*data) {
     5         kx 	    y=malloc(x-*data+1);
     5         kx 	    y[x-*data] = 0;
     5         kx 	    y[x-*data-1] = '\n';
     5         kx 	    memcpy(y,*data,x-*data);
     5         kx 	} else {
     5         kx 	    y=NULL;
     5         kx 	}
     5         kx 	*data = NULL;
     5         kx 	return y;
     5         kx     }
     5         kx     y = malloc(x-*data);
     5         kx     y[x-*data-1] = 0;
     5         kx     memcpy(y,*data,x-*data-1);
     5         kx     *data = x;
     5         kx     return y;
     5         kx }
     5         kx 
     5         kx char **toArray(char *line, int *num) {
     5         kx     /* Converts a long string into an array of lines. */
     5         kx     char **lines;
     5         kx     char *tmpline;
     5         kx     
     5         kx     *num = 0;
     5         kx     lines = NULL;
     5         kx     
     5         kx     while ((tmpline=getLine(&line))) {
     5         kx 	if (!*num)
     5         kx 	  lines = (char **) malloc(sizeof(char *));
     5         kx 	else
     5         kx 	  lines = (char **) realloc(lines, (*num+1)*sizeof(char *));
     5         kx 	lines[*num] = tmpline;
     5         kx 	(*num)++;
     5         kx     }
     5         kx     return lines;
     5         kx }
     5         kx 
     5         kx int trySocket() {
     5         kx 	int s;
     5         kx 	struct sockaddr_un addr;
     5         kx  	
     5         kx 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
     5         kx 	if (s<0)
     5         kx 	  return 1;
     5         kx    
     5         kx 	bzero(&addr,sizeof(addr));
     5         kx 	addr.sun_family = AF_LOCAL;
     5         kx 	strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
     5         kx 
     5         kx 	if (connect(s,(struct sockaddr *) &addr,sizeof(addr))<0) {
     5         kx 		if (errno == EPROTOTYPE || errno == ECONNREFUSED) {
     5         kx 			DDEBUG("connect failed (EPROTOTYPE), trying stream\n");
     5         kx 			close(s);
     5         kx 			s = socket(AF_LOCAL, SOCK_STREAM, 0);
     5         kx 			if (connect(s,(struct sockaddr *) &addr, sizeof(addr)) < 0) {
     5         kx 				DDEBUG("connect failed: %s\n",strerror(errno));
     5         kx 				close(s);
     5         kx 				return 1;
     5         kx 			} 
     5         kx 			close(s);
     5         kx 			return 0;
     5         kx 		}
     5         kx 		close(s);
     5         kx 		DDEBUG("connect failed: %s\n",strerror(errno));
     5         kx 		return 1;
     5         kx 	} else {
     5         kx 		close(s);
     5         kx 		return 0;
     5         kx 	}
     5         kx }
     5         kx 
     5         kx int logLine(struct logInfo *logEnt) {
     5         kx     /* Logs a line... somewhere. */
     5         kx     int x;
     5         kx     struct stat statbuf;
     5         kx     
     5         kx     /* Don't log empty or null lines */
     5         kx     if (!logEnt->line || !strcmp(logEnt->line,"\n")) return 0;
     5         kx     
     5         kx 	
     5         kx     if  ((stat(_PATH_LOG,&statbuf)==-1) || trySocket()) {
     5         kx 	DDEBUG("starting daemon failed, pooling entry %d\n",logEntries);
     5         kx 	logData=realloc(logData,(logEntries+1)*sizeof(struct logInfo));
     5         kx 	logData[logEntries].fac = logEnt->fac;
     5         kx 	logData[logEntries].pri = logEnt->pri;
     5         kx 	logData[logEntries].cmd = strdup(logEnt->cmd);
     5         kx 	logData[logEntries].line = strdup(logEnt->line);
     5         kx 	logEntries++;
     5         kx     } else {
     5         kx 	if (logEntries>0) {
     5         kx 	    for (x=0;x<logEntries;x++) {
     5         kx 		DDEBUG("flushing log entry %d =%s=\n",x,logData[x].line);
     5         kx 		openlog(logData[x].cmd,0,logData[x].fac);
     5         kx 		syslog(logData[x].pri,"%s",logData[x].line);
     5         kx 		closelog();
     5         kx 	    }
     5         kx 	    free(logData);
     5         kx 	    logEntries = 0;
     5         kx 	}
     5         kx 	DDEBUG("logging =%s= via syslog\n",logEnt->line);
     5         kx 	openlog(logEnt->cmd,0,logEnt->fac);
     5         kx 	syslog(logEnt->pri,"%s",logEnt->line);
     5         kx 	closelog();
     5         kx     }
     5         kx     return 0;
     5         kx }
     5         kx 
     5         kx int logEvent(char *cmd, int eventtype,char *string) {
     5         kx     char *eventtable [] = {
     5         kx 	_("%s babbles incoherently"),
     5         kx 	_("%s succeeded"),
     5         kx 	_("%s failed"),
     5         kx 	_("%s cancelled at user request"),
     5         kx 	_("%s failed due to a failed dependency"),
     5         kx 	/* insert more here */
     5         kx 	NULL
     5         kx     };
     5         kx     int x=0,len, rc;
     5         kx     struct logInfo logentry;
     5         kx     
     5         kx     if (cmd) {
     5         kx 	logentry.cmd = basename(cmd);
     5         kx 	if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') &&
     5         kx 	    ( logentry.cmd[1] >= '0' && logentry.cmd[1] <= '9' ) &&
     5         kx 	    ( logentry.cmd[2] >= '0' && logentry.cmd[2] <= '9' ) )
     5         kx 	  logentry.cmd+=3;
     5         kx 	logentry.cmd = strdup(logentry.cmd);
     5         kx     } else
     5         kx       logentry.cmd = strdup(_("(none)"));
     5         kx     if (!string) {
     5         kx       string = alloca(strlen(cmd)+1);
     5         kx       strcpy(string,cmd);
     5         kx     }
     5         kx     
     5         kx     while (eventtable[x] && x<eventtype) x++;
     5         kx     if (!(eventtable[x])) x=0;
     5         kx     
     5         kx     len=strlen(eventtable[x])+strlen(string);
     5         kx     logentry.line=malloc(len);
     5         kx     snprintf(logentry.line,len,eventtable[x],string);
     5         kx     
     5         kx     logentry.pri = logpriority;
     5         kx     logentry.fac = logfacility;
     5         kx     
     5         kx     rc = logLine(&logentry);
     5         kx     free(logentry.line);
     5         kx     free(logentry.cmd);
     5         kx     return rc;
     5         kx }
     5         kx 
     5         kx int logString(char *cmd, char *string) {
     5         kx     struct logInfo logentry;
     5         kx     int rc;
     5         kx     
     5         kx     if (cmd) {
     5         kx 	logentry.cmd = basename(cmd);
     5         kx 	if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && 
     5         kx 	    ( logentry.cmd[1] >= '0' && logentry.cmd[1] <= 0x39 ) &&
     5         kx 	    ( logentry.cmd[2] >= '0' && logentry.cmd[2] <= 0x39 ) )
     5         kx 	  logentry.cmd+=3;
     5         kx 	logentry.cmd = strdup(logentry.cmd);
     5         kx     } else
     5         kx       logentry.cmd = strdup(_(""));
     5         kx     logentry.line = strdup(string);
     5         kx     logentry.pri = logpriority;
     5         kx     logentry.fac = logfacility;
     5         kx     
     5         kx     rc = logLine(&logentry);
     5         kx     free(logentry.line);
     5         kx     free(logentry.cmd);
     5         kx     return rc;
     5         kx }
     5         kx 
     5         kx int processArgs(int argc, char **argv, int silent) {
     5         kx     char *cmdname=NULL;
     5         kx     char *conffile=NULL;
     5         kx     int cmdevent=0;
     5         kx     char *cmd=NULL;
     5         kx     char *logstring=NULL;
     5         kx     char *fac=NULL,*pri=NULL;
     5         kx     int lfac=-1, lpri=-1;
     5         kx     poptContext context;
     5         kx     int rc;
     5         kx     struct poptOption optTable[] = {
     5         kx 	POPT_AUTOHELP
     5         kx 	{ "conf", 0, POPT_ARG_STRING, &conffile, 0,
     5         kx 	  "configuration file (default: /etc/initlog.conf)", NULL
     5         kx 	},
     5         kx 	{ "name", 'n', POPT_ARG_STRING, &cmdname, 0,
     5         kx 	  "name of service being logged", NULL 
     5         kx 	},
     5         kx 	{ "event", 'e', POPT_ARG_INT, &cmdevent, 0,
     5         kx 	  "event being logged (see man page)", NULL
     5         kx 	},
     5         kx 	{ "cmd", 'c', POPT_ARG_STRING, &cmd, 0,
     5         kx 	  "command to run, logging output", NULL
     5         kx 	},
     5         kx         { "debug", 'd', POPT_ARG_NONE, &debug, 0,
     5         kx 	  "print lots of verbose debugging info", NULL
     5         kx 	},
     5         kx 	{ "run", 'r', POPT_ARG_STRING, &cmd, 3,
     5         kx 	  "command to run, accepting input on open fd", NULL
     5         kx 	},
     5         kx 	{ "string", 's', POPT_ARG_STRING, &logstring, 0,
     5         kx 	  "string to log", NULL
     5         kx 	},
     5         kx 	{ "facility", 'f', POPT_ARG_STRING, &fac, 1,
     5         kx 	  "facility to log at (default: 'local7')", NULL
     5         kx 	},
     5         kx 	{ "priority", 'p', POPT_ARG_STRING, &pri, 2,
     5         kx 	  "priority to log at (default: 'notice')", NULL
     5         kx 	},
     5         kx         { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
     5         kx 	  "suppress stdout/stderr", NULL
     5         kx 	},
     5         kx         { 0, 0, 0, 0, 0, 0 }
     5         kx     };
     5         kx     
     5         kx     context = poptGetContext("initlog", argc, (const char **)argv, optTable, 0);
     5         kx     
     5         kx     while ((rc = poptGetNextOpt(context)) > 0) {
     5         kx 	switch (rc) {
     5         kx 	 case 1:
     5         kx 	    lfac=atoi(fac);
     5         kx 	    if ((lfac == 0) && strcmp(fac,"0")) {
     5         kx 		int x =0;
     5         kx 		
     5         kx 		lfac = LOG_DAEMON;
     5         kx 		for (x=0;facilitynames[x].c_name;x++) {
     5         kx 		    if (!strcmp(fac,facilitynames[x].c_name)) {
     5         kx 			lfac = facilitynames[x].c_val;
     5         kx 			break;
     5         kx 		    }
     5         kx 		}
     5         kx 	    }
     5         kx 	    break;
     5         kx 	 case 2:
     5         kx 	    lpri = atoi(pri);
     5         kx 	    if ((lpri == 0) && strcmp(pri,"0")) {
     5         kx 		int x=0;
     5         kx 		
     5         kx 		lpri = LOG_NOTICE;
     5         kx 		for (x=0;prioritynames[x].c_name;x++) {
     5         kx 		    if (!strcmp(pri,prioritynames[x].c_name)) {
     5         kx 			lpri = prioritynames[x].c_val;
     5         kx 			break;
     5         kx 		    }
     5         kx 		}
     5         kx 	    }
     5         kx 	    break;
     5         kx 	 case 3:
     5         kx 	    reexec = 1;
     5         kx 	    break;
     5         kx 	 default:
     5         kx 	    break;
     5         kx 	}
     5         kx     }
     5         kx       
     5         kx     if ((rc < -1)) {
     5         kx        if (!silent)
     5         kx 	 fprintf(stderr, "%s: %s\n",
     5         kx 		poptBadOption(context, POPT_BADOPTION_NOALIAS),
     5         kx 		poptStrerror(rc));
     5         kx        
     5         kx 	return -1;
     5         kx     }
     5         kx     if ( (cmd && logstring) || (cmd && cmdname) ) {
     5         kx         if (!silent)
     5         kx 	 fprintf(stderr, _("--cmd and --run are incompatible with --string or --name\n"));
     5         kx 	return -1;
     5         kx     }
     5         kx     if ( cmdname && (!logstring && !cmdevent)) {
     5         kx         if (!silent)
     5         kx 	 fprintf(stderr, _("--name requires one of --event or --string\n"));
     5         kx 	return -1;
     5         kx     }
     5         kx     if (cmdevent && cmd) {
     5         kx 	    if (!silent)
     5         kx 	      fprintf(stderr, _("--cmd and --run are incompatible with --event\n"));
     5         kx 	    return -1;
     5         kx     }
     5         kx     if (conffile) {
     5         kx 	readConfiguration(conffile);
     5         kx     } else {
     5         kx 	readConfiguration("/etc/initlog.conf");
     5         kx     }
     5         kx     if (cmd) {
     5         kx 	    while (isspace(*cmd)) cmd++;
     5         kx     }
     5         kx     if (lpri!=-1) logpriority=lpri;
     5         kx     if (lfac!=-1) logfacility=lfac;
     5         kx     if (cmdevent) {
     5         kx 	logEvent(cmdname,cmdevent,logstring);
     5         kx     } else if (logstring) {
     5         kx 	logString(cmdname,logstring);
     5         kx     } else if ( cmd && *cmd) {
     5         kx 	return(runCommand(cmd,reexec,quiet,debug));
     5         kx     } else {
     5         kx         if (!silent)
     5         kx 	 fprintf(stderr,"nothing to do! (see \"initlog --help\")\n");
     5         kx 	return -1;
     5         kx     }
     5         kx    return 0;
     5         kx }
     5         kx 
     5         kx int main(int argc, char **argv) {
     5         kx 
     5         kx     setlocale(LC_ALL,"");
     5         kx     bindtextdomain("initlog","/etc/locale");
     5         kx     textdomain("initlog");
     5         kx     /* Well this seems pretty damn dumb */
     5         kx     /* fprintf(stderr, _("WARNING: initlog is deprecated and will be removed in a future release\n")); */
     5         kx     exit(processArgs(argc,argv,0));
     5         kx }