SysIII/usr/src/cmd/errpt.c

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

/* Format and interpret the error log file */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#ifdef vax
#include <sys/mba.h>
#endif
#include <sys/map.h>
#include <sys/elog.h>
#include <sys/err.h>
#include <sys/erec.h>
#include <time.h>

#define writout()	((page<=limit) && (mode==PRINT))
#define major(x)	(int)((unsigned)(x>>8)&0377)
#define minor(x)	((int)x&0377)
#define araysz(x)	((sizeof(x)/sizeof(x[0]))-1)
#define readrec(x)	(fread(&ercd.ebb.block,\
			(e_hdr.e_len - sizeof(struct errhdr)),1,x) )

char Nl [1];
#ifdef vax
#define FORM "%08X"
#define FORM2 "%08X\n"
#else
#define FORM "%06o"
#define FORM2 "%16lo\n"
#endif
#define NULS	 Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl

#define INAUG "0301080077"	/* roughly the inception of error logging [mmddhhmmyy] */
#define WDLEN 16
#define MINREC 8
#define MAXREC 74
#define DEVADR ((physadr)(0160000))
#define MAXLEN 66
#define MAXSTR 40
#define NMAJOR 16
#define PGLEN 60
#define MBAREG 5
#define INT  15

#define MEM  14
#define YES 1
#define NO 0
#define PRINT 1
#define NOPRINT 0
#define DSEC 3	/* 2**DSEC is the number of logical
			partitions on RP03/4/5/6 as defined
			in the device driver. */

/* Space needed for each block device in detail report. */
int pneed[9] = {31,31,31,24,25,29,25,28,31};

/* NMAJOR devices of 9 possible logical units */
struct sums {
	long	soft;
	long	hard;
	long	totalio;
	long	misc;
	long	missing;
} sums[NMAJOR][9];

union ercd {
	struct  estart start;
	struct	eend end;
	struct	etimchg timchg;
	struct	econfchg confchg;
	struct	estray stray;
	struct	eparity parity;
	struct  eb {
		struct	eblock block;
		unsigned short reginf [30];
	} ebb;
} ercd;

struct errhdr e_hdr;


int dmsize [];
int MAJ;
int MIN;
int page=1;
int print;
int mode = NOPRINT;
int line;
int n = 0;
int aflg;
int dflg;
int fflg;
int Unix = 1;
int parsum;
int straysum;
int limit = 10000;
int optdev = 0;
long readerr = 0;
FILE	*file;
time_t	atime;
time_t	stime = 0L;
time_t	etime = 017777777777L;
time_t	fftime = 017777777777L;
time_t	ltime = 0L;
char interp [MAXSTR];
char choice [MAXSTR];
long tloc;
char cbuf[];
#ifdef vax
struct vaxreg {
	char *regnam;
	char *bitcod [WDLEN*2];
};
#endif
struct regs {
	char *regname;
	char *bitcode [WDLEN];
};

char *htime[20];
char *header = "SYSTEM ERROR REPORT";
char *hd1 = "System Error Report - Selected Items";
char *hd2 = "Summary Error Report";
/* Must be same order as "true" major device numbers */
char *dev[] = {
	"RK05",
	"RP03",
	"RF11",
	"TU10",
	"TC11",
	"RP04/5/6",
	"TU16",
	"RS03/4",
	"RL01",
	0
};
/* Register names and bit mnemonics for each */
/* register and bit to be interpreted on detail report. */

struct regs rkregs [] = {
	"RKDS",Nl,Nl,Nl,Nl,Nl,"WPS",Nl,Nl,Nl,"SIN","DRU",
		Nl,Nl,Nl,Nl,Nl,
	"RKER","WCE","CSE","","","","NXS","NXC","NXD","TE","DLT",
		"NXM","PGE","SKE","WLO","OVR","DRE",
	"RKCS",NULS,
	"RKWC",NULS,
	"RKBA",NULS,
	"RKDA",NULS,
	0
};
struct regs rpregs[] = {
	"RPDS",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"SUFU",Nl,
		"SUSI","HNF",Nl,Nl,Nl,
	"RPER","DSKERR","EOP","NXME","WCE","TIMEE","CSME",
		"WPE","LPE","MODE","FMTE","PROG","NXS","NXT","NXC","FUV","WPV",
	"RPCS",NULS,
	"RPWC",NULS,
	"RPBA",NULS,
	"RPCA",NULS,
	"RPDA",NULS,
	0
};
struct regs rfregs[] = {
	"RFCS",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"MXF","WLO",
		"NED","DPE","WCE",Nl,Nl,
	"RFWC",NULS,
	"RFBA",NULS,
	"RFDA",NULS,
	"RFDAE",Nl,Nl,Nl,Nl,Nl,"DAOVFL",Nl,"DRL",Nl,Nl,"NEM",
		"CTER","BTER","ATER","APE",
	0
};
struct regs tmregs [] = {
	"TMER",Nl,Nl,"WRL",Nl,Nl,Nl,Nl,"NXM","BTE","RLE","EOT",
		"BGL","PAE","CRE",Nl,"ILL",
	"TMCS",NULS,
	"TMBC",NULS,
	"TMBA",NULS,
	"Z   ",NULS,
	"Z   ",NULS,
	0
};
struct regs tcregs [] = {
	"TCCSR",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"NEX","DATM","BLKM",
		"SELE","ILO","MTE","PAR",Nl,
	"TCCM",NULS,
	"TCWC",NULS,
	"TCBA",NULS,
	"Z   ",NULS,
	0
};
#ifdef vax
struct regs hpregs[] = {
	"HPCS1","GO","F0","F1","F2","F3","F4",Nl,Nl,
		Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
	"HPDS",Nl,Nl,Nl,Nl,Nl,Nl,"VV","DRY",
		"DPR",Nl,Nl,Nl,"MOL","PIP","ERR","ATA",
	"HPER1",NULS,
	"HPMR",NULS,
	"HPAS","ATA0","ATA1","ATA2","ATA3","ATA4","ATA5","ATA6","ATA7",
		Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
	"HPDA",NULS,
	"HPDT",NULS,
	"HPLA",NULS,
	"Z   ",NULS,
	"HPOF",NULS,
	"HPDC",NULS,
	"HPCC",NULS,
	"HPER2",NULS,
	"HPER3",NULS,
	"HPEC1",NULS,
	"HPEC2",NULS,
	0
};
struct regs htregs[] = {
	"HTCS1","GO","F0","F1","F2","F3","F4",Nl,Nl,
		Nl,Nl,Nl,"DVA",Nl,Nl,Nl,Nl,
	"HTDS","SLA","BOT","TM","IDB","SDWN","PES","SSC","DRY",
		"DPR",Nl,"EOT","WRL","MOL","PIP","ERR","ATA",
	"HTER1","ILF","ILR","RMR","CPAR","FMT","DPAR","INC/VPE",
		"PER/LRC","NSG","FCE","CS/ITM","NEF","DTE","OPI","UNS",
		"COR/CRC",
	"HTMR",NULS,
	"HTAS","ATA0","ATA1","ATA2","ATA3","ATA4","ATA5","ATA6",
		"ATA7",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
	"HTFC",NULS,
	"HTDT",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"SPR",Nl,Nl,Nl,Nl,Nl,
	"HTCK",NULS,
	"HTSN",NULS,
	"HTTC","SS0","SS1","SS2","EVPAR","FMT0","FMT1","FMT2",
		"FMT3","DEN0","DEN1","DEN2",Nl,"EAODTE","TCW","FCS",
		"ACCL",
	0
};
struct vaxreg mbareg[] = {
	"MBACSR",NULS,Nl,Nl,Nl,Nl,Nl,"OTMP","APU","APD",Nl,Nl,
		"XDF","MXE",Nl,"UXRDE","WDSE","SBIPE",
	"MBACR","INIT","ABRT","IE","MM",Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,Nl,Nl,NULS,
	"MBASR","RDTO","IFSQTO","RDSUB","ERCON","UNVMP","MPPAR","MBDPAR",
		"MBEXC","MXF","WCLE","WCVE","DTL","DTABT","DTCOMP",Nl,
		Nl,"MATA","MCWE","NED","PGE",Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,"CRD","NRC","DTB",
	"MBAVAR",NULS,NULS,
	"MBABCR",NULS,NULS,
	0
};
#else
struct regs hpregs[] = {
	"HPCS1",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,"MCPE","TRE",Nl,
	"HPWC",NULS,
	"HPBA",NULS,
	"HPDA",NULS,
	"HPCS2",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"MDPE","MXF","PGE",
		"NEM","NED","PE","WCE","DLT",
	"HPDS",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,"WRL","MOL",Nl,Nl,Nl,
	"HPER1","ILF","ILR","RMR","PAR","FER","WCF","ECH","HCE",
		"HCRC","AOE","IAE","WLE","DTE","OPI","UNS","DCK",
	"HPAS",NULS,
	"Z   ",NULS,
	"HPDB",NULS,
	"HPMR",NULS,
	"HPDT",NULS,
	"Z   ",NULS,
	"HPOF",NULS,
	"HPDC",NULS,
	"HPCC",NULS,
	"HPER2",NULS,
	"HPER3",NULS,
	"HPEC1",NULS,
	"HPEC2",NULS,
	"HPBAE",NULS,
	"HPCS3",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,Nl,"APE",
	0
};
struct regs htregs [] = {
	"HTCS1",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,"MCPE","TRE",Nl,
	"HTWC",NULS,
	"HTBA",NULS,
	"HTFC",NULS,
	"HTCS2",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"MDPE","MXF","PGE",
		"NEM","NED","PE","WCE","DLT",
	"HTDS",Nl,"BOT",Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,"EOT","WRL","MOL",Nl,Nl,Nl,
	"HTER","ILF","ILR","RMR","CPAR","FMT","DPAR",
		"INC/VPE","PEF/LRC","NSG","FCE","CS/ITM","NEF",
		"DTE","OPI","UNS","COR/CRC",
	"HTAS",NULS,
	"HTCK",NULS,
	"HTDB",NULS,
	"HTMR",NULS,
	"HTDT",NULS,
	"Z   ",NULS,
	"HTTC",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"NRZ",
		"PE",Nl,Nl,Nl,Nl,Nl,
	"HTBAE",NULS,
	"HTCS3",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,Nl,"APE",
	0
};
#endif
struct regs hsregs[] = {
	"HSCS1",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,"MCPE","TRE","SC",
	"HSWC",NULS,
	"HSBA",NULS,
	"HSDA",NULS,
	"HSCS2",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"MDPE","MXF","PGE",
	"NEM","NED","PE","WCE","DLT",
	"HSDS",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,"WRL","MOL",Nl,Nl,Nl,
	"HSER","ILF","ILR","RMR","PAR",Nl,Nl,Nl,Nl,Nl,"AO",
		"IAE","WLE","DTE","OPI","UNS","DCK",
	"HSAS",NULS,
	"Z   ",NULS,
	"HSDB",NULS,
	"HSMR",NULS,
	"Z   ",NULS,
	"HSBAE",NULS,
	"HSCS3",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,
		Nl,Nl,Nl,Nl,Nl,"APE",
	0
};
struct regs rlregs[] = {
	"RLCS",Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,"OPI","CRC","DLT/HNF","NXM","DE",Nl,
	"RLBS",NULS,
	"RLDA",NULS,
	"RLMP",Nl,Nl,Nl,"BH","HO","CO","HS",Nl,"DSE","VC","WGE","SPE",
		"SKTO","WL","CHE","WDE",
	0
};
int rkblk();
int rpblk();
int rfblk();
int tmblk();
int tcblk();
int hpblk();
int htblk();
int hsblk();
int rlblk();

/* Device specification functions */
/* Must remain in same order as true major device numbers */
int (*func[]) () = {
	rkblk,
	rpblk,
	rfblk,
	tmblk,
	tcblk,
	hpblk,
	htblk,
	hsblk,
	rlblk,
	0
};
struct regs  *devregs[] = {
	rkregs,
	rpregs,
	rfregs,
	tmregs,
	tcregs,
	hpregs,
	htregs,
	hsregs,
	rlregs,
	0
};
struct pos {
	unsigned flg;
	unsigned unit;
	unsigned cyl;
	unsigned trk;
	unsigned sector;
} pos;
/* Array order directed by MMR3 */
char *msg[] = {
	"User D Space Enabled",
	"Supervisor D Space Enabled",
	"Kernel D Space Enabled",
	Nl,
	"22 bit mapping Enabled",
	"UNIBUS MAP relocation Enabled",
	0
};


char *lines [] = {
/* 0*/	"\n",
/* 1*/	"%s     ERROR LOGGED ON   %s\n",
/* 2*/	"       Physical Device                  %u\n",
/* 3*/	"       Logical Device                   %d (%2.2o)\n",
/* 4*/	"       Device Address                   ",
/* 5*/	"       Retry Count                      %u\n",
/* 6*/	"       Error Diagnosis                  %s\n",
/* 7*/	"       Simultaneous Bus Activity        ",
/* 8*/	"       Registers at Error time\n",
/* 9*/	"               %s          ",
/*10*/	"       Physical Buffer Start Address         ",
/*11*/	"       Transfer Size in Bytes                     %11u\n",
/*12*/	"       Type of Transfer                              %8s\n",
/*13*/	"       Block No. in Logical File System      %16ld\n",
/*14*/	"       I/O Type                                      %8s\n",
/*15*/	"       Cylinder Requested              %11u\n",
/*16*/	"       Track Requested                 %11u\n",
/*17*/	"       Sector Requested                %11u\n",
/*18*/	"       Statistics on Device to date:\n",
/*19*/	"               No. of R/W Operations          %16ld\n",
/*20*/	"               No. of Other Operations        %16ld\n",
/*21*/	"               No. of Unrecorded Errors            %11u\n",
/*9b*/	"%o      ",
/*23*/	"       Sector Requested                  %4u-%u\n",
/*24*/  "       Unibus Map Utilization?                            %3.3s\n",
		0
		};

char *xlines [] = {
/* 0*/  "\n\nDEVICE CONFIGURATION CHANGE   - %s\n",
/* 1*/	"     	DEVICE: %s - %s\n",
/* 2*/	"\n\nSTRAY INTERRUPT on %s\n",
/* 3*/  "       For Controller at - ",
/* 4*/	"       At Location     ",
/* 5*/	"\n\nMEMORY PARITY ERROR at %s\n",
/* 6*/	"       Memory Address of Error - %lo (cycle %d)\n\n",
/* 7*/	"                MSER        %06o",
/* 8*/	"                MSCR        %06o",
/* 9*/	"\n\nTIME CHANGE ***** FROM %s",
/*10*/  "\t\t   TO  %s \n\n\n\n",
/*11*/  "\nERROR LOGGING SYSTEM SHUTDOWN - %s\n\n\n",
/*12*/	"\nERROR LOGGING SYSTEM STARTED - %s \n",
/*13*/	"\n\n	System Profile:\n\n",
/*14*/	"             11/%d  Processor\n",
/*15*/	"\t     System Memory Size - %ld Bytes\n",
/*16*/	"\n	Configured with:",
/*17*/	"             UNIX/%s  Operating System (%s)\n",
/*18*/  "             %s \n",
	0
};

char *sumlines [] = {
/* 0*/	"\n\n",
/* 1*/	"%s     UNIT  %d   \n",
/* 2*/	"                       Hard Errors             -   %ld\n",
/* 3*/	"                       Soft Errors             -   %ld\n",
/* 4*/	"                       Total I/O Operations    -   %ld\n",
/* 5*/	"                       Total Misc. Operations  -   %ld\n",
/* 6*/	"                       No. of Errors Missed    -   %ld\n",
/* 7*/	"            Total Read Errors                  -   %ld\n",
/* 8*/	"            Total Memory Parity Errors         -   %d\n",
/* 9*/	"            Total Stray Interrupts             -   %d\n",
/*10*/	"       Date of Earliest Entry: %s",
/*11*/	"       Date of Latest   Entry: %s",
/*12*/  "       Error Types: %s\n",
/*13*/  "       Limitations: ",
/*14*/  "                    ",
0
};


/* Correspondence of input requests to major device defines */
struct tab {
	char *devname ;
	int devnum;
};
struct tab dtab[] = {
	"rk",RK0,	"RK",RK0,	"RK05",RK0,	"rk05",RK0,
	"rp",RP0,	"RP",RP0,	"RP03",RP0,	"rp03",RP0,
	"rf",RF0,	"rf11",RF0,	"RF",RF0,	"RF11",RF0,
	"tm",TM0,	"TM",TM0,	"tu",TM0,	"TU10",TM0,
	"mt",TM0,	"tu10",TM0,	"tc",TC0,	"TC",TC0,
	"tc11",TC0,	"TC11",TC0,	"hp",HP0,	"HP",HP0,
	"RP04",HP0,	"rp04",HP0,	"rp05",HP0,	"RP05",HP0,
	"RP06",HP0,	"rp06",HP0,	"ht",HT0,	"HT",HT0,
	"TU16",HT0,	"tu16",HT0,	"TJU16",HT0,	"hs",HS0,
	"HS",HS0,	"rs03",HS0,	"RS03",HS0,	"RS04",HS0,
	"rs04",HS0,	"rs",HS0,	"RS",HS0,	"rl",RL0,
	"RL",RL0,	"rl01",RL0,	"RL01",RL0,	"MEM",MEM,
	"mem",MEM,	"int",INT,	"INT",INT,	0,0
};

char *ctime();
main (argc,argv)
char *argv[];
int argc;
{
	register i,j;
	print = NO;
	while (--argc>0 && **++argv =='-') {
		switch (*++*argv) {
		case 's':	/* starting at a specified time */
			header = hd1;
			if((--argc <=0) || (**++argv == '-'))
			error("Date required for -s option",(char *)NULL);
			if(gtime(&stime,*argv))
			 error("Invalid Start time",*argv);
			break;
		case 'e':	/* ending at a specified time */
			header = hd1;
			if((--argc<=0) || (**++argv =='-'))
			error("Date required for -e option\n",(char *)NULL);
			if(gtime(&etime,*argv)) error("Invalid End time.",(char *)NULL);
			break;
		case 'a':	/* print all devices*/
			aflg++;
			mode = PRINT;
			break;
		case 'p':	/* limit total no. of pages */
			if((--argc<=0) || (**++argv == '-'))
				error("Page limit not supplied.\n",(char *)NULL);
			limit = atoi(*argv);
			break;
		case 'f':	/* fatal errors */
			header = hd1;
			fflg++;
			break;

		default:
			if(j=encode(*argv)) {
				optdev = (optdev |= j);
				dflg++;
				header = hd1;
				mode = PRINT;
				if(strlen(choice)) concat(",",choice);
				concat(*argv,choice);
				}
			else
			fprintf(stderr,"%s?\n",argv);
		}
	}
	for(i=0;i<NMAJOR;i++) {
		for(j=0;j<9;j++) {
			sums[i][j].hard = 0;
			sums[i][j].soft = 0;
			sums[i][j].totalio = 0;
			sums[i][j].misc = 0;
			sums[i][j].missing = 0;
		}
	}
	parsum=0;
	straysum=0;
	if(gtime(&atime,INAUG)) error("Invalid INAUG time",INAUG);
	if (argc ==0)
		report("/usr/adm/errfile");
	else while(argc--) 
		report(*argv++);
	printsum();
	putft();
	exit(0);
}
report(fp)
char *fp;
{

	if((file = fopen(fp,"r"))== NULL) {
		fprintf(stderr,"Cannot open %s\n",fp);
		return;
	}
	inithdng();
	if(writout()) puthead(header);
	putdata();
	if(writout()) putft();
	return;
}
putdata()
{
	while(fread(&e_hdr.e_type,sizeof(struct errhdr),1,file)) {
newtry:
		switch(e_hdr.e_type) {
		
		case E_GOTS:
			setime();
			up();
			break;

		case E_GORT:
			setime();
			up();
			break;

		case E_STOP:
			setime();
			down();
			break;

		case E_TCHG:
			setime();
			timecg();
			break;

		case E_BLK:
			setime();
			blk();
			break;
		
		case E_STRAY:
			setime();
			stray();
			break;

		case E_PRTY:
			setime();
			party();
			break;

		case E_CCHG:
			cconfig();
			setime();
			break;
		default:
			fprintf(stderr,"%d\n",e_hdr.e_len);
			fprintf(stderr,"%d\n",e_hdr.e_type);
			readerr++;
			if(recov()) {
				goto newtry;
			}
			fprintf (stderr,"Unrecovered read error.\n");
		}
	}

	return;
}
/* System Startup Record */

up()
{
register int i;

	if (!readrec(file)) {
		fprintf(stderr,"at up = %o\n",ercd.start.e_cpu);
		fprintf(stderr,"%o\n",ercd.start.e_mmr3);
		fprintf(stderr,"%ld\n",ercd.start.e_name.release);
		fprintf(stderr,"%s %s\n",ercd.start.e_name.release,ercd.start.e_name.sysname);
		readerr++;
		return;
	}
	if(writout()) {
		need(14+araysz(msg));
		printf(xlines[12],ctime(&e_hdr.e_time));
		printf(xlines[13]);
		printf(xlines[17],ercd.start.e_name.release,ercd.start.e_name.sysname);
		printf(xlines[14],ercd.start.e_cpu);
		if(ercd.start.e_syssize) {
			printf(xlines[15],ercd.start.e_syssize);
			}
		else line--;
		for(i=0;i<=araysz(msg);i++) {
				if(ercd.start.e_mmr3 & (1<<i)){
				printf(xlines[18],msg[i]);
				}
				else line--;
			}
		printf(xlines[16]);
		afix(araysz(dev),(unsigned) ercd.start.e_bconf,dev);
		printf(lines[0]);
	}
}
/* System Shutdown Record */

down()
{
	if(writout()) {
		need(5);
		printf(xlines[11],ctime(&e_hdr.e_time));
	}
}
/* Time Change Record */

timecg()
{
	if(!readrec(file)) {
		readerr++;
		return;
	}
	if(writout()) {
		need(8);
		printf(xlines[9],ctime(&e_hdr.e_time));
		printf(xlines[10],ctime(&ercd.timchg.e_ntime));
	}
}
/* Handle a MERT configuration change */
cconfig() 
{

	if (!readrec(file)) {
		readerr++;
		return;
	}
	if(writout()) {
		need(7);
		printf(xlines[0],ctime(&e_hdr.e_time));
		printf(lines[0]);
		printf(xlines[1],dev[ercd.confchg.e_trudev],
			ercd.confchg.e_cflag?"Attached":"Detached");
	
		printf(lines[0]);
	}
}

/* Stray Interrupt Record */

stray()
{
	if (!readrec(file)) {
		readerr++;
		return;
	}
	if(!wanted()) return;
	if(print==YES) {
		need(7);
		if(page<=limit) {
		printf(xlines[2],ctime(&e_hdr.e_time));
		if(ercd.stray.e_saddr < DEVADR) printf(xlines[4]);
		else
		printf(xlines[3]);
		printf(FORM,ercd.stray.e_saddr);
		printf(lines[0]);
		printf(lines[7]);
		if(ercd.stray.e_sbacty == 0) printf("None\n");
		else
		afix(araysz(dev),(unsigned) ercd.stray.e_sbacty,dev);
		}
	}
	straysum++;
}

/* Memory Parity Record */

party()
{
	if (!readrec(file)) {
		readerr++;
		return;
		}
	if(!wanted())  return;
	if(print==YES) {
		need(9);
		if(page<=limit) {
		printf(xlines[5],ctime(&e_hdr.e_time));
		printf(xlines[6],(((long)(ercd.parity.e_parreg[1]&077))<<WDLEN) +
			((long)((unsigned) ercd.parity.e_parreg[0])),
			(ercd.parity.e_parreg[1]>>14)&03);
		printf(lines[8]);
		printf(xlines[7],ercd.parity.e_parreg[2]);
		printf(lines[0]);
		printf(xlines[8],ercd.parity.e_parreg[3]);
		printf(lines[0]);
		}
	}
	parsum++;
}
/* Device Error Record */

blk()
{
	register union ercd *z;
	register int i;
	struct regs *p;
	int *mbar;
	struct vaxreg *q;

	pos.flg = 0;
	if (!readrec(file)) {
		readerr++;
		return;
	}
	z = &ercd;
	MAJ=major(ercd.ebb.block.e_dev);
	MIN=minor(ercd.ebb.block.e_dev);
	if((MAJ>araysz(func)) | MAJ<0) return;
	if(!wanted()) return;
	(*func[MAJ])();
	/* Increment summary totals */
	
	if(ercd.ebb.block.e_bflags &E_ERROR)
	sums[MAJ][pos.unit].hard++;
	else
	sums[MAJ][pos.unit].soft++;
	sums[MAJ][pos.unit].totalio = ercd.ebb.block.e_stats.io_ops;
	sums[MAJ][pos.unit].misc = ercd.ebb.block.e_stats.io_misc;
	sums[MAJ][pos.unit].missing = ercd.ebb.block.e_stats.io_unlog;
	if(print==NO) return;
	need(pneed[MAJ]+ercd.ebb.block.e_nreg);
	if(page <= limit) {
		printf(lines[0]);
		printf(lines[1],dev[MAJ],ctime(&e_hdr.e_time));
		printf(lines[2],pos.unit);
		printf(lines[3],MIN,MIN);
		printf(lines[4]);
		printf(FORM,ercd.ebb.block.e_regloc);
		printf(lines[0]);
		printf(lines[5],ercd.ebb.block.e_rtry);
		printf(lines[6],ercd.ebb.block.e_bflags&E_ERROR?
			"Unrecovered":"Recovered");
		printf(lines[7]);
		if(ercd.ebb.block.e_bacty == 0) printf("None\n");
		else
		afix(araysz(dev),(unsigned) ercd.ebb.block.e_bacty,dev);
		printf(lines[0]);
		printf(lines[8]);
#ifdef vax
		mbar = ((int *) &z-> e_mba);
		q=mbareg;
		for(i=0;i<MBAREG;i++,mbar++,q++) {
			printf("\t  %-6.6s   %08X",q->regnam,*mbar);
			afix(WDLEN*2,*mbar,q->bitcod);
		}
#endif
		p=devregs[MAJ];
		for(i=0;i<ercd.ebb.block.e_nreg;i++,p++) {
			if(*p->regname != 'Z') {
				printf("\t  %-5.5s    ",p->regname);
				printf(FORM,ercd.ebb.reginf[i]);
				afix(WDLEN,ercd.ebb.reginf[i],p->bitcode);
			}
		}
		printf(lines[0]);
		printf(lines[10]);
		printf(FORM2,ercd.ebb.block.e_memadd);
		printf(lines[11],ercd.ebb.block.e_bytes);
		i=ercd.ebb.block.e_bflags;
		printf(lines[12],
		(i&E_NOIO)?"No-op":((i&E_READ)?"Read":"Write"));
		printf(lines[13],ercd.ebb.block.e_bnum);
		if(Unix) printf(lines[14],
			i&E_PHYS? "Physical":"Buffered");
		else line--;
		/* Not valid in this implementation; the line
		   following is inserted in its place.
		printf(lines[24],i&E_MAP?"Yes":"No");
		*/
		line--;
		printf(lines[0]);
		if(pos.flg) {
			printf(lines[0]);
			if(MAJ != HS0)
			printf(lines[15],pos.cyl);
			printf(lines[16],pos.trk);
			if(MAJ==HS0)
				printf(lines[23],pos.sector,pos.sector+n);
			else
				printf(lines[17],pos.sector);
			printf(lines[0]);
			}
		printf(lines[0]);
		printf(lines[18]);
		printf(lines[19],ercd.ebb.block.e_stats.io_ops);
		printf(lines[20],ercd.ebb.block.e_stats.io_misc);
		printf(lines[21],ercd.ebb.block.e_stats.io_unlog);
		printf(lines[0]);
	}
}
rkblk()
{
	register int m;
	daddr_t d;

	pos.flg = 1;
	m = MIN - 7;
	if(m<=0) {
		d = ercd.ebb.block.e_bnum;
		pos.unit = MIN;
	}
	else {
		d = (ercd.ebb.block.e_bnum/m);
		pos.unit =  (ercd.ebb.block.e_bnum%m);
		}
	pos.cyl = d/24;
	pos.trk = (d%24)/12;
	pos.sector = (d%24)%12;
}
rpblk()
{

	pos.flg=1;
	pos.unit = (MIN>>DSEC);
	pos.cyl=ercd.ebb.block.e_cyloff;
	pos.cyl += (ercd.ebb.block.e_bnum/(20*10));
	pos.trk = (ercd.ebb.block.e_bnum%(20*10))/10;
	pos.sector = ((ercd.ebb.block.e_bnum%(20*10))%10);
}

rfblk()
{
	pos.flg=1;
	pos.unit=(ercd.ebb.block.e_bnum/1024);
	pos.trk=((ercd.ebb.block.e_bnum%1024)/8);
	pos.cyl=0;
	pos.sector=((ercd.ebb.block.e_bnum%1024)%8);
}
tmblk()
{
	pos.unit = (MIN&03);
}
tcblk()
{
	pos.unit = (MIN&07);
}
hpblk()
{

	pos.flg = 1;
	pos.unit=(MIN>>DSEC);
	pos.cyl = ercd.ebb.block.e_cyloff;
	pos.cyl += (ercd.ebb.block.e_bnum/(19*22));
	pos.trk = ((ercd.ebb.block.e_bnum%(19*22))/22);
	pos.sector=((ercd.ebb.block.e_bnum%(19*22))%22);
}
htblk()
{
	pos.unit=(MIN&03);
}
hsblk()
{
	register div;

	if(MIN & 010) {
		div=32L;
		n=1;
		}
		else {
		div=16L;
		n=3;
		}
	pos.flg = 1;
	pos.cyl=0;
	pos.unit=MIN&07;
	pos.trk = (ercd.ebb.block.e_bnum/div);
	pos.sector = ercd.ebb.block.e_bnum%div;
	pos.sector *= (n+1);
}
rlblk()
{
	pos.flg = 1;
	pos.unit = MIN;
	pos.trk = (ercd.ebb.block.e_bnum/(20*256));
	pos.cyl = ((ercd.ebb.block.e_bnum)%(20*256))/20;
	pos.sector = ((ercd.ebb.block.e_bnum)%(20*256))%20;
	pos.sector *= 2;
}
cleanse(p,q)
	register char *p;
	register int q;
{
	while(q--)
		*p++='\0';
}

afix(a,b,c)
int a;
unsigned b;
char **c;
{
	register i;
	cleanse(interp,MAXSTR);
	for(i=0;i<a;i++)  {
		if((b & (1<<i)) && (*c[i]))    {
			if((strlen(c[i])+strlen(interp))>=MAXSTR) {
				concat(",",interp);
				printf("          %s\n\t\t\t",interp);
				line++;
				cleanse(interp,MAXSTR);
			}
			else {
				if(strlen(interp)) concat(",",interp);
			}
			concat(c[i],interp);
		}
	}
	printf("      %s\n",interp);
}
puthead(h)
char *h;
{
	printf("\n\n   %s   Prepared on %s     Page  %d\n\n\n\n",
		h,htime,page);
	line = 6;
}
inithdng()
{

	time(&tloc);
	ctime(&tloc);
	cbuf[16] = '\0';
	strcpy(htime,cbuf+4);
}
putft()
{
	while (line++<MAXLEN) {
		putchar('\n');
	}
	page++;
}
trnpg()
{
	if( line >= MAXLEN) page++;
	else putft();
	if(page<=limit) puthead(header);
}
need(a)			/* acts like ".ne" command of nroff */
int a;
{
	if( line>(PGLEN-a)) trnpg();
	line += a;
}
gtime(tptr,pt)
char *pt;
time_t	*tptr;
{
	register int i;
	register int y, t;
	int d, h, m;
	extern	int	dmsize [];
	extern int *localtime();
	extern long timezone;
	extern long timezone;
	int nt[2];

	t = gpair(pt++);
	if(t<1 || t>12)
		return(1);
	pt++;
	d = gpair(pt++);
	if(d<1 || d>31)
		return (1);
	pt++;
	h = gpair(pt++);
	if(h == 24) {
		h = 0;
		d++;
	}
	pt++;
	m = gpair(pt++);
	if(m<0 || m>59)
		return (1);
	pt++;
	y = gpair(pt++);
	if (y<0) {
		time(nt);
		y = localtime(nt)[5];
	}
	*tptr = 0;
	y += 1900;
	for(i=1970; i<y; i++)
		*tptr += dysize(i);
	/* Leap year */
	if (dysize(y)==366 && t >= 3)
		*tptr += 1;
	while(--t)
		*tptr += dmsize[t-1];
	*tptr += (d-1);
	*tptr = (*tptr *24) + h;
	*tptr = (*tptr*60) + m;
	*tptr *= 60;
	*tptr += timezone;
	if(localtime(tptr)->tm_isdst)
		*tptr -= 60*60;
	return(0);

}
gpair(pt)
char *pt;
{
	register int c, d;
	register char *cp;

	cp = pt;
	if(*cp == 0)
		return(-1);
	c = (*cp++ - '0') * 10;
	if (c<0 || c>100)
		return(-1);
	if(*cp == 0)
		return(-1);
	if ((d = *cp++ - '0') < 0 || d > 9)
		return(-1);
	return (c+d);
}

wanted ()
{
	/* Starting - ending limitations? */
	if(e_hdr.e_time <stime ) return (0);
	if(e_hdr.e_time > etime) return (0);
	/* Only fatal error flag? */
	if((fflg) && (e_hdr.e_type==E_BLK) && !(ercd.ebb.block.e_bflags&E_ERROR)) return(0);
	/* Stray interrupts or parity errors to be considered */
	if((aflg) || ((e_hdr.e_type==E_STRAY)&&(optdev&(1<<INT))) ||
		((e_hdr.e_type==E_PRTY)&&(optdev&(1<<MEM)))) {
		print=YES;
		return (1);
		}
	/* Device chosen for consideration or printing? */
	if(dflg == 0) {
		print=NO;
		return(1);
		}
	if((1<<MAJ)&optdev) {
		print=YES;
		return(1);
		}
	print=NO;
	return(0);
}
error(s1,s2)
char *s1, *s2;
{
	fprintf(stderr,"errpt:%s %s \n",s1,s2);
	exit(16);
}


recov()
{
	struct errhdr *p,*q;
	int i;
	for(;;) {
		p = q = &e_hdr;
		q++;
		for(i=0;i<((sizeof(struct errhdr) /2)-1);i++)
			*p++ = *q++;
		fread(p,2,1,file);
		if(feof(file))return(0);
		if(valid()) return (1);
	}
}
valid()
{
	switch(e_hdr.e_type) {
		default:
			return(0);
		case E_GOTS:
		case E_GORT:
		case E_STOP:
		case E_TCHG:
		case E_BLK:
		case E_STRAY:
		case E_CCHG:
		case E_PRTY:
	if((e_hdr.e_len <MINREC) ||
		 (e_hdr.e_len > MAXREC) ) return (0);
	if((e_hdr.e_time < atime) ||
		 (e_hdr.e_time > tloc))  return(0);
	return (1);
}
}
printsum()
{
	int i;
	header = hd2;
	page = 1;
	puthead(header);
	need(11);
	printf(sumlines[12],choice[0]?choice:"All");
	printf(sumlines[13]);
	if(stime) {
		printf("On or after %s",ctime(&stime));
		printf(sumlines[14]);
	}
	else line--;
	if(etime!=017777777777L) {
		printf("On or before %s",ctime(&etime));
		printf(sumlines[14]);
	}
	else line--;
	if(fflg) {
		printf("Only fatal errors are printed.\n");
		printf(sumlines[14]);
	}
	else line--;
	if(limit != 10000) printf("Printing suppressed after page %d.\n",limit);
	else line--;
	printf(lines[0]);
	printf(sumlines[10],ctime(&fftime));
	printf(sumlines[11],ctime(&ltime));
	printf(lines[0]);
	if(readerr) printf(sumlines[7],readerr);
	else printf(lines[0]);
	printf(lines[0]);
	if((optdev&(1<<14)) || !(dflg) || (aflg)) {
		need(3);
		printf(lines[0]);
		printf(sumlines[9],straysum);
		printf(lines[0]);
		}
	if((optdev&(1<<13)) || !(dflg) || (aflg)) {
		need(3);
		printf(lines[0]);
		printf(sumlines[8],parsum);
		printf(lines[0]);
		}
	if ((dflg == 0)||(aflg)) {
		for(i=0;i<NMAJOR;i++) (prsum(i)); }
	else
	for(i=0;i<NMAJOR;i++)
		if(optdev & (1<<i)) prsum(i);
	if(line == 7) printf("No errors for this report\n");
}

prsum(i)
register int i;
{
	register int j;

	for(j=0;j<8;j++) {
		if(sums[i][j].totalio) {
			need(10);
			printf(sumlines[1],dev[i],j);
			printf(sumlines[0]);
			printf(sumlines[2],sums[i][j].hard);
			printf(sumlines[3],sums[i][j].soft);
			printf(sumlines[4],sums[i][j].totalio);
			printf(sumlines[5],sums[i][j].misc);
			printf(sumlines[6],sums[i][j].missing);
			printf(sumlines[0]);
		}
	}
}
/* Associate typed name with a specific bit in "optdev" */
encode(p)
char  *p;
{
	register struct tab *q;
	for(q=dtab;q->devname;q++) {
		if (!strcmp(q->devname,p))
			return(1<<(q->devnum));
	}
	return(0);
}

concat(a,b)
	register char *a,*b;
{
	while (*b) b++;
	while (*b++ = *a++);
}
setime()
{
	if(e_hdr.e_time < fftime)
	fftime = e_hdr.e_time;
	if(e_hdr.e_time > ltime)
	ltime = e_hdr.e_time;
}