-/* $Id: initlog.c,v 1.2 1999/09/02 12:11:06 misiek Exp $ */
+/*
+ * 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>
#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_LOCAL7;
+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;
-
- for (x = *data; *x && (*x != '\n'); x++);
+ 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 {
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
+ close(fd);
/* kid */
execlp("minilogd","minilogd",NULL);
perror("exec");
}
}
+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 || errno == ECONNREFUSED) {
+ 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=0,y=0,z=0;
+ 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) ||(access("/",W_OK)==-1))
+
+ if ( ((stat(_PATH_LOG,&statbuf)==-1) || trySocket())
&& startDaemon()
) {
DDEBUG("starting daemon failed, pooling entry %d\n",logEntries);
struct logInfo logentry;
if (cmd) {
- logentry.cmd = strdup((char *)basename(cmd));
- if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
- && ( 30 <= logentry.cmd[2] <= 39 ) )
+ 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)"));
struct logInfo logentry;
if (cmd) {
- logentry.cmd = strdup((char *)basename(cmd));
- if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
- && ( 30 <= logentry.cmd[2] <= 39 ) )
+ 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(_(""));
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
},
"string to log", NULL
},
{ "facility", 'f', POPT_ARG_STRING, &fac, 1,
- "facility to log at (default: 'daemon')", NULL
+ "facility to log at (default: 'local7')", NULL
},
{ "priority", 'p', POPT_ARG_STRING, &pri, 2,
"priority to log at (default: 'notice')", NULL
while ((rc = poptGetNextOpt(context)) > 0) {
switch (rc) {
case 1:
- logfacility=atoi(fac);
- if ((logfacility == 0) && strcmp(fac,"0")) {
+ lfac=atoi(fac);
+ if ((lfac == 0) && strcmp(fac,"0")) {
int x =0;
- logfacility = LOG_DAEMON;
+ lfac = LOG_DAEMON;
for (x=0;facilitynames[x].c_name;x++) {
if (!strcmp(fac,facilitynames[x].c_name)) {
- logfacility = facilitynames[x].c_val;
+ lfac = facilitynames[x].c_val;
break;
}
}
}
break;
case 2:
- logpriority = atoi(pri);
- if ((logpriority == 0) && strcmp(pri,"0")) {
+ lpri = atoi(pri);
+ if ((lpri == 0) && strcmp(pri,"0")) {
int x=0;
- logpriority = LOG_NOTICE;
+ lpri = LOG_NOTICE;
for (x=0;prioritynames[x].c_name;x++) {
if (!strcmp(pri,prioritynames[x].c_name)) {
- logpriority = prioritynames[x].c_val;
+ lpri = prioritynames[x].c_val;
break;
}
}
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 ) {
+ } else if ( cmd && *cmd) {
return(runCommand(cmd,reexec,quiet,debug));
} else {
if (!silent)