2 * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
4 * This software may be freely redistributed under the terms of the GNU
7 * You should have received a copy of the GNU General Public License
8 * along with this program; if not, write to the Free Software
9 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <sys/socket.h>
31 #define _(String) gettext((String))
40 static int logfacility=LOG_DAEMON;
41 static int logpriority=LOG_NOTICE;
46 regex_t **regList = NULL;
48 static int logEntries = 0;
49 struct logInfo *logData = NULL;
51 void readConfiguration(char *fname) {
58 if ((fd=open(fname,O_RDONLY))==-1) return;
59 if (fstat(fd,&sbuf)) {
63 data=malloc(sbuf.st_size+1);
64 if (read(fd,data,sbuf.st_size)!=sbuf.st_size) {
70 data[sbuf.st_size] = '\0';
71 while ((line=getLine(&data))) {
72 if (line[0]=='#') continue;
73 if (!strncmp(line,"ignore ",7)) {
74 regexp = malloc(sizeof(regex_t));
75 if (!regcomp(regexp,line+7,REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) {
76 regList = realloc(regList,(num+2) * sizeof(regex_t *));
77 regList[num] = regexp;
78 regList[num+1] = NULL;
82 if (!strncmp(line,"facility ",9)) {
84 if ((lfac == 0) && strcmp(line+9,"0")) {
88 for (x=0;facilitynames[x].c_name;x++) {
89 if (!strcmp(line+9,facilitynames[x].c_name)) {
90 lfac = facilitynames[x].c_val;
96 if (!strncmp(line,"priority ",9)) {
98 if ((lpri == 0) && strcmp(line+9,"0")) {
102 for (x=0;prioritynames[x].c_name;x++) {
103 if (!strcmp(line+9,prioritynames[x].c_name)) {
104 lpri = prioritynames[x].c_val;
111 if (lfac!=-1) logfacility=lfac;
112 if (lpri!=-1) logpriority=lpri;
115 char *getLine(char **data) {
116 /* Get one line from data */
117 /* Anything up to a carraige return (\r) or a backspace (\b) is discarded. */
118 /* If this really bothers you, mail me and I might make it configurable. */
119 /* It's here to avoid confilcts with fsck's progress bar. */
122 if (!*data) return NULL;
124 while (*x && (*x != '\n')) {
125 while (*x && (*x != '\n') && (*x != '\r') && (*x != '\b')) x++;
126 if (*x && (*x=='\r' || *x =='\b')) {
138 memcpy(y,*data,x-*data);
147 memcpy(y,*data,x-*data-1);
152 char **toArray(char *line, int *num) {
153 /* Converts a long string into an array of lines. */
160 while ((tmpline=getLine(&line))) {
162 lines = (char **) malloc(sizeof(char *));
164 lines = (char **) realloc(lines, (*num+1)*sizeof(char *));
165 lines[*num] = tmpline;
173 struct sockaddr_un addr;
175 s = socket(AF_LOCAL, SOCK_DGRAM, 0);
179 bzero(&addr,sizeof(addr));
180 addr.sun_family = AF_LOCAL;
181 strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
183 if (connect(s,(struct sockaddr *) &addr,sizeof(addr))<0) {
184 if (errno == EPROTOTYPE) {
185 DDEBUG("connect failed (EPROTOTYPE), trying stream\n");
187 s = socket(AF_LOCAL, SOCK_STREAM, 0);
188 if (connect(s,(struct sockaddr *) &addr, sizeof(addr)) < 0) {
189 DDEBUG("connect failed: %s\n",strerror(errno));
197 DDEBUG("connect failed: %s\n",strerror(errno));
205 int logLine(struct logInfo *logEnt) {
206 /* Logs a line... somewhere. */
210 /* Don't log empty or null lines */
211 if (!logEnt->line || !strcmp(logEnt->line,"\n")) return 0;
214 if ( ((stat(_PATH_LOG,&statbuf)==-1) || trySocket())
216 DDEBUG("starting daemon failed, pooling entry %d\n",logEntries);
217 logData=realloc(logData,(logEntries+1)*sizeof(struct logInfo));
218 logData[logEntries]= (*logEnt);
222 for (x=0;x<logEntries;x++) {
223 DDEBUG("flushing log entry %d =%s=\n",x,logData[x].line);
224 openlog(logData[x].cmd,0,logData[x].fac);
225 syslog(logData[x].pri,"%s",logData[x].line);
231 DDEBUG("logging =%s= via syslog\n",logEnt->line);
232 openlog(logEnt->cmd,0,logEnt->fac);
233 syslog(logEnt->pri,"%s",logEnt->line);
239 int logEvent(char *cmd, int eventtype,char *string) {
240 char *eventtable [] = {
241 _("%s babbles incoherently"),
244 _("%s cancelled at user request"),
245 _("%s failed due to a failed dependency"),
246 /* insert more here */
250 struct logInfo logentry;
253 logentry.cmd = strdup(basename(cmd));
254 if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') &&
255 ( logentry.cmd[1] >= '0' && logentry.cmd[1] <= '9' ) &&
256 ( logentry.cmd[2] >= '0' && logentry.cmd[2] <= '9' ) )
259 logentry.cmd = strdup(_("(none)"));
261 string = strdup(cmd);
263 while (eventtable[x] && x<eventtype) x++;
264 if (!(eventtable[x])) x=0;
266 len=strlen(eventtable[x])+strlen(string);
267 logentry.line=malloc(len);
268 snprintf(logentry.line,len,eventtable[x],string);
270 logentry.pri = logpriority;
271 logentry.fac = logfacility;
273 return logLine(&logentry);
276 int logString(char *cmd, char *string) {
277 struct logInfo logentry;
280 logentry.cmd = strdup(basename(cmd));
281 if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') &&
282 ( logentry.cmd[1] >= '0' && logentry.cmd[1] <= 0x39 ) &&
283 ( logentry.cmd[2] >= '0' && logentry.cmd[2] <= 0x39 ) )
286 logentry.cmd = strdup(_(""));
287 logentry.line = strdup(string);
288 logentry.pri = logpriority;
289 logentry.fac = logfacility;
291 return logLine(&logentry);
294 int processArgs(int argc, char **argv, int silent) {
299 char *logstring=NULL;
300 char *fac=NULL,*pri=NULL;
301 int lfac=-1, lpri=-1;
304 struct poptOption optTable[] = {
306 { "conf", 0, POPT_ARG_STRING, &conffile, 0,
307 "configuration file (default: /etc/initlog.conf)", NULL
309 { "name", 'n', POPT_ARG_STRING, &cmdname, 0,
310 "name of service being logged", NULL
312 { "event", 'e', POPT_ARG_INT, &cmdevent, 0,
313 "event being logged (see man page)", NULL
315 { "cmd", 'c', POPT_ARG_STRING, &cmd, 0,
316 "command to run, logging output", NULL
318 { "debug", 'd', POPT_ARG_NONE, &debug, 0,
319 "print lots of verbose debugging info", NULL
321 { "run", 'r', POPT_ARG_STRING, &cmd, 3,
322 "command to run, accepting input on open fd", NULL
324 { "string", 's', POPT_ARG_STRING, &logstring, 0,
325 "string to log", NULL
327 { "facility", 'f', POPT_ARG_STRING, &fac, 1,
328 "facility to log at (default: 'local7')", NULL
330 { "priority", 'p', POPT_ARG_STRING, &pri, 2,
331 "priority to log at (default: 'notice')", NULL
333 { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
334 "suppress stdout/stderr", NULL
339 context = poptGetContext("initlog", argc, argv, optTable, 0);
341 while ((rc = poptGetNextOpt(context)) > 0) {
345 if ((lfac == 0) && strcmp(fac,"0")) {
349 for (x=0;facilitynames[x].c_name;x++) {
350 if (!strcmp(fac,facilitynames[x].c_name)) {
351 lfac = facilitynames[x].c_val;
359 if ((lpri == 0) && strcmp(pri,"0")) {
363 for (x=0;prioritynames[x].c_name;x++) {
364 if (!strcmp(pri,prioritynames[x].c_name)) {
365 lpri = prioritynames[x].c_val;
381 fprintf(stderr, "%s: %s\n",
382 poptBadOption(context, POPT_BADOPTION_NOALIAS),
387 if ( (cmd && logstring) || (cmd && cmdname) ) {
389 fprintf(stderr, _("--cmd and --run are incompatible with --string or --name\n"));
392 if ( cmdname && (!logstring && !cmdevent)) {
394 fprintf(stderr, _("--name requires one of --event or --string\n"));
397 if (cmdevent && cmd) {
399 fprintf(stderr, _("--cmd and --run are incompatible with --event\n"));
403 readConfiguration(conffile);
405 readConfiguration("/etc/initlog.conf");
408 while (isspace(*cmd)) cmd++;
410 if (lpri!=-1) logpriority=lpri;
411 if (lfac!=-1) logfacility=lfac;
413 logEvent(cmdname,cmdevent,logstring);
414 } else if (logstring) {
415 logString(cmdname,logstring);
416 } else if ( cmd && *cmd) {
417 return(runCommand(cmd,reexec,quiet,debug));
420 fprintf(stderr,"nothing to do!\n");
426 int main(int argc, char **argv) {
428 setlocale(LC_ALL,"");
429 bindtextdomain("initlog","/etc/locale");
430 textdomain("initlog");
431 exit(processArgs(argc,argv,0));