UNIXpc Error Logger daemon

David Klann dklann at heurikon.UUCP
Sat Apr 22 01:08:54 AEST 1989


I have been collecting, and using the sources contributed to the Net for
quite a while now.  It's my turn to contribute (in a small way :-).

After reading John Milton's article of a few weeks ago concerning the
error logger portion of smgr, I decided that it would be a good idea to
track error coming from UNIX (I don't run UA/smgr/wmgr).

Here's the source to an Error Logger daemon.

Enjoy-
David Klann
Heurikon Corporation
{backbone}!uwvax!heurikon!dklann

----------------------  cut --------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST Makefile er.1 er.c
# Wrapped by dklann at grunch on Wed Apr 19 22:57:31 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(220 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	
X Makefile                   1	
X er.1                       1	
X er.c                       1	
END_OF_FILE
if test 220 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(436 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile for error daemon, er(1).
X#
XCC = shcc
XCFLAGS = -O
XINSDIR = /etc/daemons
X
Xer:	er.c
X	$(CC) $(CFLAGS) -o er er.c
X
Xclean:
X	rm -f *.o er
X
Xinstall: er
X	strip er
X	cp er $(INSDIR)
X	if [ -d usr/man/man1 ]; \
X	then \
X		cp er.1 /usr/man/man1; \
X	fi
X
Xer.c: \
X	/usr/include/stdio.h \
X	/usr/include/sys/types.h \
X	/usr/include/sys/err.h \
X	/usr/include/sys/signal.h \
X	/usr/include/fcntl.h \
X	/usr/include/time.h \
X	/usr/include/status.h
END_OF_FILE
if test 436 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'er.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'er.1'\"
else
echo shar: Extracting \"'er.1'\" \(815 characters\)
sed "s/^X//" >'er.1' <<'END_OF_FILE'
X.\" This program is in the public domain.
X.TH er 1 "UNIX PC Local"
X.SH NAME
X.I
Xer
X\- error daemon
X.SH SYNOPSIS
X.I
Xer
X.B [
X-t
X.B ]
X.SH OPTIONS
XThe single option
X.B
Xt
Xinstructs
X.I
Xer
Xto truncate log files before
Xwriting them.
X.SH DESCRIPTION
X.I
XEr
Xreplaces part of the functionality of the
Xsmgr(1) program.
X.I
XEr's
Xgoal in life is to read the file
X/dev/error, and write messages to one of
Xtwo files.
XMessages originating in the kernel (PID
X\=\= 0) are written to the file
X/usr/adm/unix.log.
XMessages originating in user space (PID
X\> 0) are written to the file
X/usr/adm/err.log.
X.I
XEr
Xforks itself, and changes its process
Xgroup.
XThis means that the program can be run
Xas a daemon at boot time by placing it in
X/etc/daemons.
X.SH "FILES"
X/usr/adm/unix.log,
X/usr/adm/err.log.
X.SH "SEE ALSO"
Xerror(7), stdio(3), /etc/rc
END_OF_FILE
if test 815 -ne `wc -c <'er.1'`; then
    echo shar: \"'er.1'\" unpacked with wrong size!
fi
# end of 'er.1'
fi
if test -f 'er.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'er.c'\"
else
echo shar: Extracting \"'er.c'\" \(3505 characters\)
sed "s/^X//" >'er.c' <<'END_OF_FILE'
X/*
X * Kernel error logger daemon.
X * This program is in the public domain.
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/err.h>
X#include <sys/signal.h>
X#include <fcntl.h>
X#include <time.h>
X#include <status.h>
X
Xint fd;
Xvoid eprintf();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	register short truncate = 0;
X	register struct err *err;
X	register FILE *fp;
X	register c;
X	int getopt();
X	time_t now;
X	void die();
X	void quit();
X	extern int optind;
X	extern char *optarg;
X
X	/*
X	 * Allow truncation of the log files.
X	 */
X	while ((c = getopt(argc, argv, "t")) != EOF) {
X		switch (c) {
X			case 't':
X				truncate++;
X				break;
X			default:
X				fprintf(stderr, "%s: usage: %s [ -t ]\n",
X					argv[0], argv[0]);
X				exit(1);
X		}
X	}
X
X	if (fork() != 0) {
X		exit(0);
X	} else {
X		/*
X		 * Get the error logger device.
X		 */
X		if ((fd = open("/dev/error", O_RDONLY)) == NULL) {
X			perror("open /dev/error");
X			quit();
X		}
X
X		/*
X		 * Close these, so setpgrp() will work.
X		 */
X		(void)fclose(stdin);
X		(void)fclose(stdout);
X		(void)fclose(stderr);
X
X		/*
X		 * Change the process group to disassociate us with windows.
X		 */
X		(void)setpgrp();
X
X		/*
X		 * Set up signal handlers.
X		 */
X		signal(SIGINT, SIG_IGN);
X		signal(SIGHUP, SIG_IGN);
X		signal(SIGQUIT, SIG_IGN);
X		signal(SIGTERM, SIG_IGN);
X		signal(SIGUSR1, die);
X
X		/*
X		 * Write the initial message to the log file
X		 */
X		time(&now);
X		if ((fp = fopen("/usr/adm/unix.log",
X				(truncate ? "w" : "a+"))) == NULL) {
X			eprintf(ST_LOG, ST_LOGFILE, "root",
X				"err.log : cannot fopen /usr/adm/unix.log");
X			quit();
X		}
X		(void)fprintf(fp, "Error Logger started: (%d) %s",
X			getpid(), asctime(localtime(&now)));
X		(void)fclose(fp);
X
X		/*
X		 * Do the same for the non-kernel message file
X		 */
X		if ((fp = fopen("/usr/adm/err.log",
X				(truncate ? "w" : "a+"))) == NULL) {
X			eprintf(ST_LOG, ST_LOGFILE, "root",
X				"err.log : cannot fopen /usr/adm/err.log");
X			quit();
X		}
X		(void)fprintf(fp, "Error Logger started: (%d) %s",
X			getpid(), asctime(localtime(&now)));
X		(void)fclose(fp);
X
X		/*
X		 * Get some space for the error messages
X		 */
X		err = (struct err *)malloc(sizeof(struct err));
X		if (err == NULL) {
X			eprintf(ST_LOG, ST_LOGFILE, "root",
X				"err.log : cannot malloc struct err");
X			quit();
X		}
X
X		/*
X		 * Loop forever
X		 */
X		while (1) {
X			if (read(fd,(char *)err,sizeof(struct err)) != sizeof(struct err)) {
X				eprintf(ST_LOG, ST_LOGFILE, "root",
X					"err.log : cannot read /dev/error");
X				quit();
X			}
X			time(&now);
X			if (err->e_pid == 0) {
X				if ((fp = fopen("/usr/adm/unix.log", "a+")) == NULL) {
X					eprintf(ST_LOG, ST_LOGFILE, "root",
X						"err.log : cannot fopen /usr/adm/unix.log");
X					quit();
X				}
X				(void)fprintf(fp, "%s: %s",
X					err->e_text, asctime(localtime(&now)));
X				(void)fflush(fp);
X				(void)fclose(fp);
X			} else {
X				if ((fp = fopen("/usr/adm/err.log", "a+")) == NULL) {
X					eprintf(ST_LOG, ST_LOGFILE, "root",
X						"err.log : cannot fopen /usr/adm/err.log");
X					quit();
X				}
X				(void)fprintf(fp, "%s (%d): %s",
X					err->e_text, err->e_pid, asctime(localtime(&now)));
X				(void)fflush(fp);
X				(void)fclose(fp);
X			}
X		}
X	}
X}
X
Xvoid
Xdie()
X{
X	register FILE *fp;
X	time_t now;
X	void quit();
X
X	if ((fp = fopen("/usr/adm/unix.log", "a+")) == NULL) {
X		eprintf(ST_LOG, ST_LOGFILE, "root",
X			"err.log : cannot fopen /usr/adm/unix.log");
X		quit();
X	}
X	time(&now);
X	(void)fprintf(fp, "er: exiting SIGUSR1: %s", asctime(localtime(&now)));
X	close(fd);
X	exit(2);
X}
X
Xvoid
Xquit()
X{
X	close(fd);
X	exit(1);
X}
END_OF_FILE
if test 3505 -ne `wc -c <'er.c'`; then
    echo shar: \"'er.c'\" unpacked with wrong size!
fi
# end of 'er.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Comp.sys.att mailing list