Ultrix-3.1/src/cmd/el/elc.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

static char Sccsid[] = "@(#)elc.c	3.0	4/21/86";
/*
 * ULTRIX-11 error logging copy program (elc).
 *
 * Copies error log records from the kernel buffer
 * to the error log device `/dev/errlog', usually
 * located in a protion of the swap area.
 *
 * Fred Canter 5/11/83
 */

#include <sys/param.h>	/* does not matter which one */
#include <sys/tmscp.h>	/* must preceed errlog.h (EL_MAXSZ) */
#include <sys/errlog.h>
#include <a.out.h>
#include <stdio.h>
#include <signal.h>

#define	R	0
#define	W	1
#define	RW	2

/*
 * System error log information,
 * obtained from unix via the errlog system call (EL_INFO).
 */

struct	el_data	el_data;
dev_t	el_dev;		/* major/minor device of error log device */
daddr_t	el_sb;		/* error log starting block number */
int	el_nb;		/* error log length in blocks */

/* input buffer, holds one record from the kernel buffer. */

int	ibuf[EL_MAXSZ];

/* output buffer, disk i/o buffer for error log device. */

int	obuf[256+1];

int	elbn;	/* current active block # on error log device */
int	fio;
int	elfirst;

char	*errdev = "/dev/errlog";

main ()
{
	register struct elrhdr *ehp;
	register *bpi, *bpo;
	int bwflag, d, i;
	int elb, sz;
	int mem;

	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	close(stdin);
	close(stdout);
/*
 * Make this a system process, so that it will not
 * be swapped (locked in memory).
 */
	lock(1);

/* Give this process a hi priority. */

/* only SU can execute /etc/elc 
	if(getuid()) {
		fprintf(stderr,"\nelc: not SU\n");
		exit(1);
	}
 */
	nice((int) -20);
/*
 * Wait for the first error to be logged,
 * this will always be and error log startup.
 * This is done to insure that the unix monitor
 * is named unix and that the /dev/errlog file
 * is set up for the correct device.
 * If this was not done elc would fail when
 * attempting to locate the first free record in the
 * error log.
 */
/*	errlog(EL_WAIT, 0);	*/	
/*
 * Get error log information from unix
 * via the errlog system call.
 */
	errlog(EL_INFO, &el_data);
	el_dev = el_data.el_dev;
	el_sb = el_data.el_sb;
	el_nb = el_data.el_nb;
/*
 * Make the special file `/dev/errlog',
 * this insures that it is always the correct
 * major/minor device. 
 */
	unlink(errdev);
	if(mknod(errdev, 020600, el_dev) < 0) {
		fprintf(stderr, "\nelc: Can't mknod %s\n", errdev);
		exit(1);	/* FATAL ! */
	}

/* open error log device for read & write */

	if((fio = open(errdev, RW)) < 0) {
		fprintf(stderr, "\nelc: Can't open %s\n", errdev);
		exit(1);	/* FATAL ! */
		}

/*
 * Find the block in the error log that contains the next 
 * open slot, read it into the disk i/o buffer and
 * set the disk i/o buffer pointer.
 */

elinit:
	for(bpo = &obuf; bpo < &obuf[256]; *bpo++ = 0);
	lseek(fio, (long)(el_sb * 512), 0);
	for(i=0; i<el_nb; i++) {
		if(read(fio, (char *)&obuf, 512) != 512) {
			fprintf(stderr,"\nelc: read error bn = %D,", i+el_sb);
			goto elwait;
			}
		bpo = &obuf;
		ehp = bpo;
		while((bpo < &obuf[256]) && (ehp->e_type != E_EOB)) {
		if(ehp->e_type == E_EOF)	/* empty slot */
			goto out;
		if(elfirst++ == 0) {	/* check for error log initialized */
		 if((ehp->e_type != E_SU) ||
		  (ehp->e_size != (sizeof(struct elrhdr)+sizeof(struct el_su))))
			goto elwait1;
		}
		if((ehp->e_type < 0) ||
			(ehp->e_type > E_BD) ||
			(ehp->e_size == 0) ||
			(ehp->e_size & 1) ||
			(ehp->e_size > EL_MAXSZ)) {
	badrec:
			fprintf(stderr, "\7\7\7elc: bad error record, ");
			goto elwait;
			}
		bpo += (ehp->e_size / 2);	/* not empty, adjust pointer */
		ehp = bpo;
		}
	}
out:
	elbn = i;	/* save block number */

/*
 * Get one record from the kernel error buffer,
 * move it to the disk I/O buffer,
 * and write to the error log device as required.
 */

ecloop:

	bpi = &ibuf;
	ehp = bpi;
	errlog(EL_REC, (caddr_t)&ibuf);		/* get one record */
	if(ehp->e_type == E_INIT)	/* error log has been reinitialized */
		goto elinit;	/* reset error log file pointers. */
	if(ehp->e_type == E_BADR)
		goto badrec;		/* bad error record detected */
	if(ehp->e_type == E_EOF) {	/* kernel buffer is empty */
		if(bwflag) {	/* if record added to block */
		if(bwrite(elbn))	/* update error log */
			goto elwait;	/* write error on error log */
		bwflag = 0;
		if((el_nb - elbn) < 4) {
/*
 * Only 3 free blocks remain in the error log,
 * print the number of blocks used message
 * as a warning.
 */
			elb = elbn;
			if(elb >= el_nb)
				elb = el_nb - 1;
			fprintf(stderr,"\n\07\07\07elc: ERROR LOG has - ");
			fprintf(stderr,"%d of %d blocks used\n",++elb,el_nb);
			}
		}
		errlog(EL_WAIT, 0);	/* sleep at hi priority */
					/* awaken when errors to log */
		goto ecloop;
		}
	
/*
 * Move the record to the disk buffer
 */

	/* d is set to amount of space remaining in */
	/* obuf and checked to see if the record will fit. */

	sz = ehp->e_size / 2;	/* size of error log record */
	d = (&obuf[256] - (bpo + sz));
	if(d == 0) {	/* buffer will be exactly full */
		for(i=sz; i; i--)
			*bpo++ = *bpi++;
		if(elwb())
			goto elwait;	/* write error on error log */
		bpo = &obuf;
		bwflag = 0;	/* error log updated */
		}
	else if(d > 0) {	/* record fits, buffer not full */
		for(i=sz; i; i--)
			*bpo++ = *bpi++;
		bwflag++;	/* error log will require update */
		}
	else {			/* record will not fit */
		*bpo = E_EOB;	/* fake end of block */
		if(elwb())
			goto elwait;	/* write error on error log */
		bpo = &obuf;
		for(i=sz; i; i--)
			*bpo++ = *bpi++;
		bwflag++;
		}
	goto ecloop;
/*
 * Come here on error log errors.
 * Cause ELC to hang until the error log 
 * file is reinitialized.
 */

elwait:
	fprintf(stderr, " error logging disabled\n");
elwait1:
	errlog(EL_OFFNL, 0);	/* disable error logging, don't log it ! */
	errlog(EL_WAIT, 0);	/* wait for next error log record */
	ehp = &ibuf;
	errlog(EL_REC, (caddr_t)&ibuf);	/* fetch record */
	if(ehp->e_type == E_INIT)	/* is it error log init */
		goto elinit;		/* yes, restart ELC */
	goto elwait1;			/* no, wait for init record */

}

/* write a block to the error log device */

bwrite(bno)
{
	if(bno >= el_nb) {	/* don't allow write past end of error log */
		errlog(EL_OFFNL, 0);	/* turn logging off !!! */
		fprintf(stderr,"\nelc: error log full,");
		return(1);
		}
	lseek(fio, (long)((bno + el_sb) * 512), 0);
	if(write(fio, (char *)&obuf, 512) != 512) {
		fprintf(stderr,"\nelc: write error bn = %D,",bno+el_sb);
		errlog(EL_OFFNL, 0);	/* turn error logging off */
		return(1);
	}
	return(0);
}

/*
 * Write the disk buffer out to the current block,
 * zero the disk buffer,
 * and increment the block number (elbn).
 */

elwb()
{
	register int *p;

	if(bwrite(elbn))
		return(1);	/* write error on error log */
	elbn++;
	for(p = &obuf; p < &obuf[256]; *p++ = 0);
	return(0);
}