rc-scripts/branches/vserver: man/Makefile.am man/initlog.1 rc.d/init.d/functions rc.d/rc.sysinit src...

baggins cvs at pld-linux.org
Mon Oct 17 15:17:16 CEST 2005


Author: baggins
Date: Mon Oct 17 15:17:11 2005
New Revision: 6449

Added:
   rc-scripts/branches/vserver/man/initlog.1
   rc-scripts/branches/vserver/src/initlog.c
   rc-scripts/branches/vserver/src/initlog.conf
   rc-scripts/branches/vserver/src/initlog.h
   rc-scripts/branches/vserver/src/process.c
   rc-scripts/branches/vserver/src/process.h
Modified:
   rc-scripts/branches/vserver/man/Makefile.am
   rc-scripts/branches/vserver/rc.d/init.d/functions
   rc-scripts/branches/vserver/rc.d/rc.sysinit
   rc-scripts/branches/vserver/src/Makefile.am
Log:
- reverted initlog removal, but without minilogd,
  now initlog uses syslog



Modified: rc-scripts/branches/vserver/man/Makefile.am
==============================================================================
--- rc-scripts/branches/vserver/man/Makefile.am	(original)
+++ rc-scripts/branches/vserver/man/Makefile.am	Mon Oct 17 15:17:11 2005
@@ -6,6 +6,7 @@
 	consoletype.1 \
 	doexec.1 \
 	genhostid.1 \
+	initlog.1 \
 	ipcalc.1 \
 	netreport.1 \
 	usleep.1 \

Added: rc-scripts/branches/vserver/man/initlog.1
==============================================================================
--- (empty file)
+++ rc-scripts/branches/vserver/man/initlog.1	Mon Oct 17 15:17:11 2005
@@ -0,0 +1,84 @@
+.TH initlog 8 "Sun Jan 24 1999"
+.SH NAME
+initlog \- log messages and events to the system logger
+.SH SYNOPSIS
+.B initlog
+[\-cefnpqrs] [\-\-cmd=ARG] [\-\-event=ARG] [\-\-facility=ARG]
+[\-\-name=ARG] [\-\-priority=ARG] [\-\-run=ARG] [\-\-string=ARG]
+.SH DESCRIPTION
+\fBinitlog\fR logs messages and events to the system logger.
+It is mainly designed for use in init scripts. initlog
+reads a configuration file
+.I /etc/initlog.conf
+by default, to determine its settings. Any line preceded with a 
+.I #
+is a comment, and the following configuration directives
+are recognized:
+.TP
+.I facility <logging facility>
+Sets the default logging facility
+.TP
+.I priority <logging priority>
+Sets the default logging priority
+.TP
+.I ignore <regexp>
+Messages that match the regular expression will not be logged.
+.TP
+initlog behavior can also be configured by command-line options.
+
+.SS OPTIONS
+.TP
+.I "\-c, \-\-cmd=[program]"
+Execute the specified program, logging anything output to
+stdout or stderr.
+.TP
+.I "\-e, \-\-event=[number]"
+Logs that the specified event happened. Used in conjuction
+with \fB\-\-name\fR. Currently specified events are:
+.PD 0
+.RS 8n
+.TP 3n
+.B 1
+the action completed successfully
+.TP
+.B 2
+the action failed
+.TP
+.B 3
+the action was cancelled at user request
+.TP
+.B 4
+the action failed due to the failure of a dependent action
+.RE
+.PD
+.TP
+.I "\-f, \-\-facility=[facility]"
+Log at the specified syslog facility. The default
+is \fBdaemon\fR (see syslog(3)).
+.TP
+.I "\-n, \-\-name=[string]"
+Log the event under the specified string, such as
+"inetd".
+.TP
+.I "\-p, \-\-priority=[priority]"
+Log at the specified syslog priority. The default
+is \fBnotice\fR (see syslog(3)).
+.TP
+.I "\-q"
+Do not print the program's output, unless it exits
+with a non-zero exit code.
+.TP
+.I "\-r, \-\-run=[program]"
+Execute the specified program, with an open file
+descriptor so that the program can pass back
+commands to initlog.
+.TP
+.I "\-s, \-\-string=[string]"
+Log the specified string to the logger.
+.TP
+.I "\-\-conf=[file]"
+Specifies an alternate configuration file.
+.SH FILES
+.I /etc/initlog.conf
+.SH "SEE ALSO"
+syslog(3), logger(1)

Modified: rc-scripts/branches/vserver/rc.d/init.d/functions
==============================================================================
--- rc-scripts/branches/vserver/rc.d/init.d/functions	(original)
+++ rc-scripts/branches/vserver/rc.d/init.d/functions	Mon Oct 17 15:17:11 2005
@@ -93,6 +93,24 @@
 
 if is_yes "$FASTRC"; then
 	INIT_DOTS=$(awk "BEGIN{for(\$i=0;\$i<$INIT_COL;\$i++)printf(\".\");}")
+	initlog()
+	{
+		RESULT=0
+		while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do
+			case $1 in
+				-c)
+					shift
+					$1
+					RESULT=$?
+					break
+					;;
+				 *)
+					shift
+					;;
+			esac
+		done
+		return $RESULT
+	}
 fi
 
 kernelver()
@@ -388,10 +406,12 @@
 	show "$message"; busy
 	shift
 	cd /
-	if errors=$(HOME=/tmp TMPDIR=/tmp $* 2>&1); then
+	if errors=$(HOME=/tmp TMPDIR=/tmp initlog -c "$*" 2>&1); then
 		ok
+		log_success "$1 $message"
 	else
 		fail
+		log_failed "$1 $message"
 		exit_code=1
 	fi
 	[ -n "$errors" ] && [ $exit_code -eq 1 -o $force_err -eq 1 ] && echo "$errors"
@@ -471,7 +491,7 @@
 	# And start it up.
 	busy
 	cd /
-	if errors=$(umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK}; USER=root HOME=/tmp TMPDIR=/tmp nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} $prog 2>&1); then
+	if errors=$(umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK}; USER=root HOME=/tmp TMPDIR=/tmp nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} initlog -c "$prog" 2>&1); then
 		if [ -n "$waitname" -a -n "$waittime" ]; then
 			# Save basename.
 			base=$(basename "$waitname")
@@ -484,10 +504,12 @@
 				checkpid $pid && sleep 1 || break
 			done
 		fi
+		log_success "$1 startup"
 		ok
 	else
 		exit_code=1
 		fail
+		log_failed "$1 startup"
 		[ -n "$errors" ] && echo "$errors"
 	fi
 	return $exit_code
@@ -559,8 +581,10 @@
 			result=$?
 			if [ "$result" -eq 0 ]; then
 				fail
+				log_failed "$1 shutdown"
 			else
 				ok
+				log_success "$1 shutdown"
 			fi
 			result=$(( ! $result ))
 		else
@@ -570,17 +594,21 @@
 				result=$?
 				if [ "$result" -eq 0 ]; then
 					ok
+					log_success "$1 got $killlevel"
 				else
 					result=7
 					fail
+					log_failed "$1 didn't get $killlevel"
 				fi
 			else
 				result=7
 				died
+				log_failed "$1 shutdown"
 			fi
 		fi
 	else
 		died
+		log_failed "$1 shutdown"
 		result=7
 	fi
 	
@@ -755,10 +783,12 @@
 
 log_success ()
 {
+	initlog -n $0 -s "$1 $2" -e 1
 }
 
 log_failed ()
 {
+	initlog -n $0 -s "$1 $2" -e 2
 }
 
 # RedHat/Mandrake specific functions

Modified: rc-scripts/branches/vserver/rc.d/rc.sysinit
==============================================================================
--- rc-scripts/branches/vserver/rc.d/rc.sysinit	(original)
+++ rc-scripts/branches/vserver/rc.d/rc.sysinit	Mon Oct 17 15:17:11 2005
@@ -103,6 +103,12 @@
 	ok
 fi
 
+# The root filesystem is now read-write, so we can now log via
+# syslog() directly...
+if [ -n "$IN_INITLOG" ]; then
+	IN_INITLOG=""
+fi
+
 [ -n "$SELINUX" ] && [ -f /.autorelabel ] && relabel_selinux
 
 # Turn on process accounting

Modified: rc-scripts/branches/vserver/src/Makefile.am
==============================================================================
--- rc-scripts/branches/vserver/src/Makefile.am	(original)
+++ rc-scripts/branches/vserver/src/Makefile.am	Mon Oct 17 15:17:11 2005
@@ -6,6 +6,9 @@
 
 DEFS = @DEFS@ -D_GNU_SOURCE=1 -DSBINDIR=\""@sbindir@"\"
 
+sysconf_DATA = \
+	initlog.conf
+
 bin_PROGRAMS = \
 	doexec \
 	ipcalc \
@@ -16,6 +19,7 @@
 	consoletype \
 	genhostid \
 	getkey \
+	initlog \
 	loglevel \
 	netreport \
 	start-stop-daemon
@@ -43,6 +47,9 @@
 
 loglevel_SOURCES = loglevel.c
 
+initlog_SOURCES = initlog.c initlog.h process.c process.h
+initlog_LDADD = -lpopt
+
 getkey_SOURCES = getkey.c
 getkey_LDADD = -lpopt
 

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

Added: rc-scripts/branches/vserver/src/initlog.conf
==============================================================================
--- (empty file)
+++ rc-scripts/branches/vserver/src/initlog.conf	Mon Oct 17 15:17:11 2005
@@ -0,0 +1,21 @@
+# /etc/initlog.conf
+#
+# initlog configuration file
+# 
+# lines preceded by a '#' are comments
+#
+# anything not recognized is ignored. :)
+
+# This sets the default logging facility. (can override with command line arguments)
+facility local7
+
+# This sets the default logging priority. (can override with command line arguments)
+priority notice
+
+# ignore foo
+# means to discard any output lines that match the regular expression foo
+
+# This regexp is useful if you use fsck's -C option. 
+ignore [^:]+: \|[=]+
+# This regexp is useful for quotacheck
+ignore ^[-\\\|\/]$

Added: rc-scripts/branches/vserver/src/initlog.h
==============================================================================
--- (empty file)
+++ rc-scripts/branches/vserver/src/initlog.h	Mon Oct 17 15:17:11 2005
@@ -0,0 +1,20 @@
+
+#define _GNU_SOURCE	1
+
+#ifndef INITLOG_H
+#define INITLOG_H
+
+struct logInfo {
+    char *cmd;
+    char *line;
+    int fac;
+    int pri;
+};
+
+char *getLine(char **data);
+int logString(char *cmd, char *string);
+int processArgs(int argc, char **argv, int silent);
+
+#define DDEBUG  if (debug) printf
+
+#endif

Added: rc-scripts/branches/vserver/src/process.c
==============================================================================
--- (empty file)
+++ rc-scripts/branches/vserver/src/process.c	Mon Oct 17 15:17:11 2005
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/signal.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <popt.h>
+
+#include <regex.h>
+
+#include "initlog.h"
+#include "process.h"
+
+extern regex_t **regList;
+
+int forkCommand(char **args, int *outfd, int *errfd, int *cmdfd, int quiet) {
+   /* Fork command 'cmd', returning pid, and optionally pointer
+    * to open file descriptor fd */
+    int fdout=-1, fderr=-1, fdcmd=-1, pid;
+    int outpipe[2], errpipe[2], fdpipe[2];
+    int ourpid;
+    
+    if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
+	perror("pipe");
+	return -1;
+    }
+    
+    if (outfd) {
+       fdout = outpipe[1];
+      *outfd = outpipe[0];
+    } else {
+       if (!quiet)
+	 fdout=dup(1);
+    }
+    if (errfd) {
+       fderr = errpipe[1];
+      *errfd = errpipe[0];
+    } else {
+       if (!quiet)
+	 fderr=dup(2);
+    }
+    
+    if (cmdfd) {
+	*cmdfd = fdpipe[0];
+	fdcmd = fdpipe[1];
+    } else {
+        fdcmd = open("/dev/null",O_WRONLY);
+    }
+    if (fdout==-1 || fderr==-1 || fdcmd==-1)
+	return -1;
+    ourpid = getpid();
+    if ((pid = fork())==-1) {
+	perror("fork");
+	return -1;
+    }
+    /* We exec the command normally as the child. However, if we're getting passed
+     * back arguments via an fd, we'll exec it as the parent. Therefore, if Bill
+     * fucks up and we segfault or something, we don't kill rc.sysinit. */
+    if ( (cmdfd&&!pid) || (pid &&!cmdfd)) {
+	/* parent */
+	close(fdout);
+	close(fderr);
+	close(fdcmd);
+	if (!pid)
+	  return ourpid;
+	else
+	  return pid;
+    } else {
+	/* kid */
+       int sc_open_max;
+
+       if (outfd) { 
+	 if ( (dup2(fdout,1)==-1) ) {
+	    perror("dup2");
+	    exit(-1);
+	 }
+       } else if (quiet)
+	    if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
+	     perror("dup2");
+	     exit(-1);
+	    }
+
+       if (errfd)  {
+	 if ((dup2(fderr,2)==-1)) {
+	    perror("dup2");
+	    exit(-1);
+	 }
+       } else if (quiet) 
+	    if ((dup2(open("/dev/null",O_WRONLY),2))==-1)  {
+	       perror("dup2");
+	       exit(-1);
+	    }
+
+ 
+       if ((dup2(fdcmd,CMD_FD)==-1)) {
+	    perror("dup2");
+	    exit(-1);
+	}
+	close(fdout);
+	close(fderr);
+	close(fdcmd);
+	if (outfd)
+	  close(*outfd);
+	if (errfd)
+	  close(*errfd);
+	if (cmdfd)
+	  close(*cmdfd);
+
+        /* close up extra fds, and hope this doesn't break anything */
+	sc_open_max = sysconf(_SC_OPEN_MAX);
+	if(sc_open_max > 1) {
+	    int fd;
+	    for(fd = 3; fd < sc_open_max; fd++) {
+		    if (!(cmdfd && fd == CMD_FD))
+		      close(fd);
+	    }
+	}
+
+	execvp(args[0],args);
+	perror("execvp");
+	exit(-1);
+    }
+}
+
+int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
+    struct pollfd *pfds;
+    char *outbuf=NULL;
+    char *tmpstr=NULL;
+    int x,y,rc=-1;
+    int done=0;
+    int output=0;
+    char **cmdargs=NULL;
+    char **tmpargs=NULL;
+    int cmdargc;
+    char *procpath = NULL;
+    
+    if (reexec) {
+	procpath=malloc(20*sizeof(char));
+	snprintf(procpath,20,"/proc/%d",pid);
+    }
+    
+    pfds = malloc(numfds*sizeof(struct pollfd));
+    for (x=0;x<numfds;x++) {
+	pfds[x].fd = fds[x];
+	pfds[x].events = POLLIN | POLLPRI;
+    }
+	
+    while (!done) {
+       usleep(500);
+       if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
+	  perror("poll");
+          free(pfds);
+          if (procpath)
+             free(procpath);
+	  return -1;
+       }
+       if (!reexec) {
+	  if (waitpid(pid,&rc,WNOHANG))
+	    done=1;
+       } else {
+	   struct stat sbuf;
+	   /* if /proc/pid ain't there and /proc is, it's dead... */
+	   if (stat(procpath,&sbuf)&&!stat("/proc/cpuinfo",&sbuf))
+	     done=1;
+       }
+       if (x<0)
+          continue;
+       y=0;
+       while (y<numfds) {
+	  if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
+	     int bytesread = 0;
+	     
+	     do {
+		char *buf=calloc(8192,sizeof(char));
+		bytesread = read(pfds[y].fd,buf,8192);
+		if (bytesread==-1) {
+		   perror("read");
+                   free(pfds);
+                   if (procpath)
+                      free(procpath);
+                   free(buf);
+		   return -1;
+		}
+		if (bytesread) {
+		  if (!quiet && !reexec)
+		    write(1,buf,bytesread);
+		  if (quiet) {
+			  outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
+			  if (!output) outbuf[0]='\0';
+			  strcat(outbuf,buf);
+			  output = 1;
+		  }
+		  while ((tmpstr=getLine(&buf))) {
+		      int ignore=0;
+		      
+		      if (regList) {
+			  int count=0;
+			 
+			  while (regList[count]) {
+			      if (!regexec(regList[count],tmpstr,0,NULL,0)) {
+				  ignore=1;
+				  break;
+			      }
+			      count++;
+			  }
+		      }
+		      if (!ignore) {
+			  if (!reexec) {
+			      if (getenv("IN_INITLOG")) {
+				  char *buffer=calloc(8192,sizeof(char));
+				  DDEBUG("sending =%s= to initlog parent\n",tmpstr);
+				  snprintf(buffer,8192,"-n %s -s \"%s\"\n",
+					   cmdname,tmpstr);
+				  /* don't blow up if parent isn't there */
+				  signal(SIGPIPE,SIG_IGN);
+				  write(CMD_FD,buffer,strlen(buffer));
+				  signal(SIGPIPE,SIG_DFL);
+				  free(buffer);
+			      } else {
+				  logString(cmdname,tmpstr);
+			      }
+			  } else {
+			      int z; 
+			
+			      cmdargs=NULL;
+			      tmpargs=NULL;
+			      cmdargc=0;
+			      
+			      poptParseArgvString(tmpstr,&cmdargc,&tmpargs);
+			      cmdargs=malloc( (cmdargc+2) * sizeof(char *) );
+			      cmdargs[0]=strdup("initlog");
+			      for (z=0;z<(cmdargc);z++) {
+				  cmdargs[z+1]=tmpargs[z];
+			      }
+			      cmdargs[cmdargc+1]=NULL;
+			      processArgs(cmdargc+1,cmdargs,1);
+			  }
+		      }
+		  }
+		}
+                free(buf);
+	     } while ( bytesread==8192 );
+	  }
+	  y++;
+       }
+    }
+    if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
+      /* If there was an error and we're quiet, be loud */
+      
+      if (quiet && output) {
+	    write(1,outbuf,strlen(outbuf));
+      }
+      free(pfds);
+      if (procpath)
+         free(procpath);
+      if(outbuf)
+         free(outbuf);
+      return (rc);
+   }
+   free(pfds);
+   if (procpath)
+      free(procpath);
+   if(outbuf)
+      free(outbuf);
+   return 0;
+}
+
+int runCommand(char *cmd, int reexec, int quiet, int debug) {
+    int fds[2];
+    int pid,x;
+    char **args, **tmpargs;
+    char *cmdname;
+    
+    poptParseArgvString(cmd,&x,&tmpargs);
+    args = malloc((x+1)*sizeof(char *));
+    for ( pid = 0; pid < x ; pid++) {
+	args[pid] = strdup(tmpargs[pid]);
+    }
+    args[pid] = NULL;
+    if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh")) 
+      cmdname = basename(args[0]);
+    else
+      cmdname = basename(args[1]);
+    if ((cmdname[0] =='K' || cmdname[0] == 'S') && 
+        ( cmdname[1] >= '0' && cmdname[1] <= '9' ) &&
+        ( cmdname[2] >= '0' && cmdname[2] <= '9' ) )
+      cmdname+=3;
+    if (!reexec) {
+       pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
+       if (pid == -1)
+          return -1;
+       x=monitor(cmdname,pid,2,fds,reexec,quiet,debug);
+    } else {
+       setenv("IN_INITLOG","yes",1);
+       pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
+       if (pid == -1)
+          return -1;
+       unsetenv("IN_INITLOG");
+       x=monitor(cmdname,pid,1,&fds[0],reexec,quiet,debug);
+    }
+    return x;
+}

Added: rc-scripts/branches/vserver/src/process.h
==============================================================================
--- (empty file)
+++ rc-scripts/branches/vserver/src/process.h	Mon Oct 17 15:17:11 2005
@@ -0,0 +1,9 @@
+#ifndef PROCESS_H
+#define PROCESS_H
+
+
+#define CMD_FD	21
+
+int runCommand(char *cmd, int reexec, int quiet, int debug);
+
+#endif



More information about the pld-cvs-commit mailing list