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
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to