static char sccsid[] = "@(#)errpt.c 1.3"; /* 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> #ifdef vax #define PNEED 25 /* Space needed for each block device detail report */ #else #define PNEED 24 #endif #define dysize(x) (((x)%4)? 365: 366) #define writout() ((mode==PRINT) && (page<=limit)) #define major(x) (int)((unsigned)(x>>8)&0377) #define minor(x) ((int)x&0377) #define araysz(x) ((sizeof(x)/sizeof(x[0]))-2) #define readrec(x) (fread((char*)&recrd,\ (e_hdr.e_len - sizeof(struct errhdr)), 1, x) ) #define recrd ercd.ebb.block #define erp ercd.parity #define erm ercd.memory #define GDRP04 020 #define GDRP05 021 #define GDRP06 022 #define GDRM03 024 #define GDRM80 026 #define GDRM05 027 #define GDRP07 042 #define GTTM03 050 /* (tu16) */ #define GTTM02 010 #define GTTM78 0100 #ifdef vax #define FORM "%.8X" #define FORM2 "\t%.8X\n" #define DRIVE_REG 6 #else #define FORM "%.6o" #define FORM2 "%16lo\n" #define DRIVE_REG 11 #endif #define DRIVE_TYPE ercd.ebb.reginf[DRIVE_REG] & 0777 char Nl [1]; #define NUL4 Nl,Nl,Nl,Nl #define NUL8 Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl #define NULS Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl,Nl #define INAUG "0301080077" /* start 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 12 #define NMINOR 8 #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 */ #define USAGE1 "errpt [-a] [-d devlist] [-s date]" #define USAGE2 "\n [-e date] [-p n] [-f] [files]" /* NMAJOR devices of NMINOR possible logical units */ struct sums { long soft; long hard; long totalio; long misc; long missing; #ifdef vax int contr; int slave; #endif char *drvname; } sums[NMAJOR][NMINOR]; struct tb_sums { long totalio; long misc; long missing; }; /* structure for maintaining totals across multiple error files: */ struct tb_sums tot_sums[NMAJOR][NMINOR]; struct tb_sums base_sums[NMAJOR][NMINOR]; union ercd { struct estart start; struct eend end; struct etimchg timchg; struct econfchg confchg; struct estray stray; struct eparity parity; struct ememory memory; struct eb { struct eblock block; unsigned short reginf [30]; } ebb; } ercd; struct errhdr e_hdr; int dmsize[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 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; short cputype; int parsum; int straysum; int limit = 10000; /* page limit */ int optdev = 0; /* bit map for device-specific reports */ long readerr = 0; /* input record error count */ FILE *file; time_t atime; time_t xtime = 0L; time_t etime = 017777777777L; time_t fftime = 017777777777L; time_t ltime = 0L; char interp [MAXSTR]; char choice [MAXSTR]; char *strcpy(); char *ctime(); long tloc; long time(); #ifdef vax struct vaxreg { char *regname; char *bitcode [WDLEN*2]; }; int mb_dev; /* True if device is MBA connected */ #endif struct regs { char *regname; char *bitcode [WDLEN]; }; struct regs *regs_ptr; char htime[20]; char *header = "SYSTEM ERROR REPORT"; char *hd1 = "System Error Report - Selected Items"; char *hd2 = "Summary Error Report"; char *dev[] = { "RK05","RP03","RF11","TU10", "TC11","RP04/5/6","TU16","RS03/4", "RL02","TM78","RP05","RP06", 0 }; /* * Register names and bit mnemonics for each * register and bit to be interpreted on detail report. */ struct regs rkregs [] = { "DS",NUL4,Nl,"WPS",Nl,Nl,Nl,"SIN","DRU",NUL4,Nl, "ER","WCE","CSE","","","","NXS","NXC","NXD","TE","DLT", "NXM","PGE","SKE","WLO","OVR","DRE", "CS",NULS, "WC",NULS, "BA",NULS, "DA",NULS, 0 }; struct regs rk2regs [] = { "CS1",NULS, "WC",NULS, "BA",NULS, "DA",NULS, "CS2",NULS, "DS",NULS, "ER",NULS, "ASOF",NULS, "DC",NULS, "Z ",NULS, "DB",NULS, "MR1",NULS, "ECPS",NULS, "ECPT",NULS, "MR2",NULS, "MR3",NULS, 0 }; struct regs rpregs[] = { "DS",NUL8,Nl,"SUFU",Nl,"SUSI","HNF",Nl,Nl,Nl, "ER","DSKERR","EOP","NXME","WCE","TIMEE","CSME", "WPE","LPE","MODE","FMTE","PROG","NXS","NXT","NXC","FUV","WPV", "CS",NULS, "WC",NULS, "BA",NULS, "CA",NULS, "DA",NULS, 0 }; struct regs rfregs[] = { "CS",NUL8,Nl,"MXF","WLO","NED","DPE","WCE",Nl,Nl, "WC",NULS, "BA",NULS, "DA",NULS, "DAE",NUL4,Nl,"DAOVFL",Nl,"DRL",Nl,Nl,"NEM", "CTER","BTER","ATER","APE",Nl, 0 }; struct regs tmregs [] = { "ER",Nl,Nl,"WRL",NUL4,"NXM","BTE","RLE","EOT", "BGL","PAE","CRE",Nl,"ILL", "CS",NULS, "BC",NULS, "BA",NULS, "Z ",NULS, "Z ",NULS, 0 }; struct regs tcregs [] = { "CSR",NUL8,"NEX","DATM","BLKM","SELE","ILO","MTE","PAR",Nl, "CM",NULS, "WC",NULS, "BA",NULS, "Z ",NULS, 0 }; #ifdef vax struct regs hpregs[] = { "CS1","GO","F0","F1","F2","F3","F4",Nl,Nl,NUL8, "DS",NUL4,Nl,Nl,"VV","DRY","DPR",Nl,Nl,Nl,"MOL","PIP","ERR","ATA", "ER1","ILF","ILR","RMR","PAR","FER","WCF","ECH","HCE", "HCRC","AOE","IAE","WLE","DTE","OPI","UNS","DCK", "MR",NULS, "AS","ATA0","ATA1","ATA2","ATA3","ATA4","ATA5","ATA6","ATA7",NUL8, "DA",NULS, "DT",NULS, "LA",NULS, "Z ",NULS, "OF",NULS, "DC",NULS, "CC",NULS, "ER2",NULS, "ER3",NULS, "EC1",NULS, "EC2",NULS, 0 }; struct regs hp2regs[] = { /* RM02/3/5/80 Registers */ "CS1","GO","F0","F1","F2","F3","F4",Nl,Nl,NUL8, "DS",NUL4,Nl,Nl,"VV","DRY","DPR",Nl,Nl,Nl,"MOL","PIP","ERR","ATA", "ER1","ILF","ILR","RMR","PAR","FER","WCF","ECH","HCE", "HCRC","AOE","IAE","WLE","DTE","OPI","UNS","DCK", "MR1",NULS, "AS","ATA0","ATA1","ATA2","ATA3","ATA4","ATA5","ATA6","ATA7",NUL8, "DA",NULS, "DT",NULS, "LA",NULS, "Z ",NULS, "OF",NULS, "DC",NULS, "HR",NULS, "MR2",NULS, "ER2",NULS, "EC1",NULS, "EC2",NULS, 0 }; struct regs htregs[] = { "CS1","GO","F0","F1","F2","F3","F4",NUL4,Nl,"DVA",NUL4, "DS","SLA","BOT","TM","IDB","SDWN","PES","SSC","DRY", "DPR",Nl,"EOT","WRL","MOL","PIP","ERR","ATA", "ER1","ILF","ILR","RMR","CPAR","FMT","DPAR","INC/VPE", "PER/LRC","NSG","FCE","CS/ITM","NEF","DTE","OPI","UNS", "COR/CRC", "MR",NULS, "AS","ATA0","ATA1","ATA2","ATA3","ATA4","ATA5","ATA6","ATA7",NUL8, "FC",NULS, "DT",NUL8,Nl,Nl,"SPR",NUL4,Nl, "CK",NULS, "SN",NULS, "TC","SS0","SS1","SS2","EVPAR","FMT0","FMT1","FMT2", "FMT3","DEN0","DEN1","DEN2",Nl,"EAODTE","TCW","FCS","ACCL", 0 }; struct regs ht2regs[] = { /* TM78 registers: */ "CSR","GO",NUL8,Nl,Nl,"DVA",NUL4, "DTC",NUL8,"DPR",NUL4,Nl,Nl,Nl, "FM",NUL8,NUL4,Nl,Nl,Nl,"SER", "MR1",NULS, "AS",NULS, "FC",NULS, "DT",NUL8,Nl,"WCS",Nl,"DMB",Nl,Nl,"TAP","NSA", "DS",NUL4,"DSE",Nl,"SHR","AVL","FPT","EOT","BOT","PE","REW", "ONL","PRES","RDY", "SN",NULS, "MR2",NULS, "MR3",NULS, "NDC",NULS, "NDT0",NULS, "NDT1",NULS, "NDT2",NULS, "NDT3",NULS, 0 }; struct vaxreg mbareg[] = { "MBACSR",NULS,NUL4,Nl,"OT","PU","PD",Nl,Nl, "XMTFLT","MT",Nl,"URD","WS","SBIPE", "MBACR","INIT","ABRT","IE","MM",NUL8,NUL4,NULS, "MBASR","RDTO","ISTO","RDS","ERCON","INVMAP","MAPPE","MDPE", "MBEXC","MXF","WCLE","WCUE","DLT","DTABT","DTCMP",Nl, Nl,"ATTN","MCPE","NFD","PGE",NUL8,Nl,"CRD","NRC","DTB", "MBAVAR",NULS,NULS, "MBABCR",NULS,NULS, 0 }; struct vaxreg mem780[] = { "SBIER", Nl, "NBSY", "MLTERR", "IBERR", "IBTO0", "IBTO1", "IBTOS", "IBRDS", "CPERR", Nl, "CPTOS0", "CPTOS1", "CPTO", "RDS", "CRD", "RDSEN", NULS, "MCRC", NULS, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, "ELOGRQ", "HERR", "INHCRD", Nl, 0 }; struct vaxreg mem750[] = { "CSR0", NULS, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, Nl, "CRD", "INL", "UERRF", 0 }; struct regs tsregs[] = { /* ts11 tape drive */ "Z ",NULS, "Z ",NULS, "RBPCR",NULS, "XS0","EOT","BOT","WLK",Nl,Nl,"IE","ONL",Nl,"ILA", "ILC",Nl,"WLE","RLL","LET","RLS","TMK", "XS1","MTE","UNC",NUL4,Nl,Nl,Nl,"SCK",Nl,"TIG",Nl,Nl,Nl,"DLT", "XS2",NUL8,"DTP",Nl,"WCF",Nl,Nl,"BPE","SIP","OPM", "XS3","RIB",NUL4,"REV","OPI",Nl,NUL8, "TSSR",NUL4,"FC0","FC1",NUL8,Nl,"SC", 0 }; #else struct regs hpregs[] = { "CS1",NUL8,NUL4,Nl,"MCPE","TRE",Nl, "WC",NULS, "BA",NULS, "DA",NULS, "CS2",NUL8,"MDPE","MXF","PGE","NEM","NED","PE","WCE","DLT", "DS",NUL8,Nl,Nl,Nl,"WRL","MOL",Nl,Nl,Nl, "ER1","ILF","ILR","RMR","PAR","FER","WCF","ECH","HCE", "HCRC","AOE","IAE","WLE","DTE","OPI","UNS","DCK", "AS",NULS, "Z ",NULS, "DB",NULS, "MR",NULS, "DT",NULS, "Z ",NULS, "OF",NULS, "DC",NULS, "CC",NULS, "ER2",NULS, "ER3",NULS, "EC1",NULS, "EC2",NULS, "BAE",NULS, "CS3",NUL8,NUL4,Nl,Nl,Nl,"APE", 0 }; struct regs hp2regs[] = { /* RM02/3/5/80 Registers */ "CS1",NUL8,NUL4,Nl,"MCPE","TRE",Nl, "WC",NULS, "BA",NULS, "DA",NULS, "CS2",NUL8,"MDPE","MXF","PGE","NEM","NED","PE","WCE","DLT", "DS",NUL8,Nl,Nl,Nl,"WRL","MOL",Nl,Nl,Nl, "ER1","ILF","ILR","RMR","PAR","FER","WCF","ECH","HCE", "HCRC","AOE","IAE","WLE","DTE","OPI","UNS","DCK", "AS",NULS, "Z ",NULS, "DB",NULS, "MR1",NULS, "DT",NULS, "Z ",NULS, "OF",NULS, "DC",NULS, "HR",NULS, "MR2",NULS, "ER2",NULS, "EC1",NULS, "EC2",NULS, "BAE",NULS, "CS3",NUL8,NUL4,Nl,Nl,Nl,"APE", 0 }; struct regs htregs [] = { "CS1",NUL8,NUL4,Nl,"MCPE","TRE",Nl, "WC",NULS, "BA",NULS, "FC",NULS, "CS2",NUL8,"MDPE","MXF","PGE","NEM","NED","PE","WCE","DLT", "DS",Nl,"BOT",NUL8,"EOT","WRL","MOL",Nl,Nl,Nl, "ER","ILF","ILR","RMR","CPAR","FMT","DPAR", "INC/VPE","PEF/LRC","NSG","FCE","CS/ITM","NEF", "DTE","OPI","UNS","COR/CRC", "AS",NULS, "CK",NULS, "DB",NULS, "MR",NULS, "DT",NULS, "Z ",NULS, "TC",NUL8,Nl,"NRZ","PE",NUL4,Nl, "BAE",NULS, "CS3",NUL8,NUL4,Nl,Nl,Nl,"APE", 0 }; struct regs ht2regs[] = { "CS1","GO",NUL4,Nl,"IE","RDY",Nl,Nl,"PSEL","DVA",Nl,"MCPE","TRE","SC", "WC",NULS, "BA",NULS, "BCR",NULS, "CS2",Nl,Nl,Nl,"BAI","PAT","CLR","IR","OR","MDPE","MXF","PGE","NEM", "NED","UPE","WCE","DLT", "DTC",NUL8,"DPR",NUL4,Nl,Nl,Nl, "FM",NULS, "AS",NULS, "DS",NUL4,"DSE",Nl,"SHR","AVL","FPT","EOT","BOT",Nl,"REW","PRES","RDY", "DB",NULS, "MR1",NULS, "DT",NUL8,Nl,"WCS",Nl,"DMB",Nl,Nl,"TAP","NSA", "SN",NULS, "MR2",NULS, "MR3",NULS, "NDC",NULS, "NDT0",NULS, "NDT1",NULS, "NDT2",NULS, "NDT3",NULS, 0 }; #endif struct regs hsregs[] = { "CS1",NUL8,NUL4,Nl,"MCPE","TRE","SC", "WC",NULS, "BA",NULS, "DA",NULS, "CS2",NUL8,"MDPE","MXF","PGE","NEM","NED","PE","WCE","DLT", "DS",NUL8,Nl,Nl,Nl,"WRL","MOL",Nl,Nl,Nl, "ER","ILF","ILR","RMR","PAR",Nl,Nl,Nl,Nl,Nl,"AO", "IAE","WLE","DTE","OPI","UNS","DCK", "AS",NULS, "Z ",NULS, "DB",NULS, "MR",NULS, "Z ",NULS, "BAE",NULS, "CS3",NUL8,NUL4,Nl,Nl,Nl,"APE", 0 }; struct regs rlregs[] = { "CS",NUL8,Nl,Nl,"OPI","CRC","DLT/HNF","NXM","DE",Nl, "BA",NULS, "DA",NULS, "MP",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 gdblk(); int hsblk(); int rlblk(); /* Device specification functions */ /* Must remain in same order as true major device numbers */ int (*func[]) () = { rkblk, rpblk, rfblk, tmblk, tcblk, gdblk, gdblk, hsblk, rlblk, gdblk, gdblk, gdblk, 0 }; struct regs *devregs[] = { rkregs, rpregs, rfregs, tmregs, tcregs, hpregs, htregs, hsregs, rlregs, hpregs, hpregs, hpregs, 0 }; struct pos { unsigned flg; unsigned unit; #ifdef vax unsigned controller; /* massbus controller number */ unsigned slave; /* for multiple tape drives on formater */ #endif 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\tError Logged On %s\n", /* 2*/ "\tPhysical Device\t\t\t%u\n", /* 3*/ "\tLogical Device\t\t\t%d (%2.2o)\n", /* 4*/ "\tDevice Address\t\t\t", /* 5*/ "\tRetry Count\t\t\t%u\n", /* 6*/ "\tError Diagnosis\t\t\t%s\n", /* 7*/ "\tSimultaneous Bus Activity\t", /* 8*/ "\tRegisters at Error time\n", /* 9*/ "\t\t%s\t", /*10*/ "\tPhysical Buffer Start Address\t", /*11*/ "\tTransfer Size in Bytes\t\t%16u\n", /*12*/ "\tType of Transfer\t\t\t%8s\n", /*13*/ "\tBlock No. in Logical File System\t%8ld\n", /*14*/ "\tI/O Type\t\t\t\t%8s\n", /*15*/ "\tCylinder\t\t\t\t%8u\n", /*16*/ "\tTrack\t\t\t\t\t%8u\n", /*17*/ "\tSector\t\t\t\t\t%8u\n", /*18*/ "\tStatistics on Device to date:\n", /*19*/ "\t\tR/W Operations\t\t%16ld\n", /*20*/ "\t\tOther Operations\t%16ld\n", /*21*/ "\t\tUnrecorded Errors\t%16u\n", /*9b*/ "%o ", /*23*/ "\tSector Requested\t\t%u\n", /*24*/ "\tUnibus Map Utilization?\t\t\t%3.3s\n", #ifdef vax /*2a*/ "\tController\t\t\t%d\n", /*2b*/ "\tPhysical Device\t\t\t%u\t\tSlave\t%u\n", #endif 0 }; char *xlines [] = { /* 0*/ "\n\nDEVICE CONFIGURATION CHANGE - %s\n", /* 1*/ "\tDEVICE: %s - %s\n", /* 2*/ "\n\nSTRAY INTERRUPT on %s\n", /* 3*/ "\tFor Controller at - ", /* 4*/ "\tAt Location\t", #ifdef pdp11 /* 5*/ "\n\nMEMORY PARITY ERROR at %s\n", /* 6*/ "\tMemory Address of Error - %lo (cycle %d)\n\n", /* 7*/ "\t\tMSER\t%.6o", /* 8*/ "\t\tMSCR\t%.6o", #else /* 5*/ "\n\nMEMORY ECC on %s\n", /* 6*/ "\tError Address (%s)\t%.5X\n", /* 7*/ "\tError Syndrome\t\t\t%.2X\n", /* 8*/ 0, #endif /* 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\tSystem Profile:\n\n", /*14*/ "\t 11/%d Processor\n", /*15*/ "\t System Memory Size - %ld Bytes\n", /*16*/ Nl, /*17*/ "\t UNIX/%s Operating System (%s)\n", /*18*/ "\t %s \n", 0 }; char *sumlines [] = { /* 0*/ "\n\n", #ifdef vax /* 1*/ "%s\tUnit %d\t Controller %d\n", #else /* 1*/ "%s\tUnit %d\n", #endif /* 2*/ "\tHard Errors\t\t- %10ld\n", /* 3*/ "\tSoft Errors\t\t- %10ld\n", /* 4*/ "\tTotal I/O Operations - %10ld\n", /* 5*/ "\tTotal Misc. Operations - %10ld\n", /* 6*/ "\tErrors Missed\t\t- %10ld\n", /* 7*/ "\tTotal Read Errors\t\t- %ld\n", /* 8*/ "\tTotal Memory Parity Errors\t- %d\n", /* 9*/ "\tTotal Stray Interrupts\t\t- %d\n", /*10*/ "\tDate of Earliest Entry: %s", /*11*/ "\tDate of Latest Entry: %s", /*12*/ "\tError Types: %s\n", /*13*/ "\tLimitations: ", /*14*/ "\t\t", #ifdef vax /*15*/ "%s\tUnit %d\t Slave %d\t Controller %d\n", #endif 0 }; /* Correspondence of input requests to major device defines */ struct tab { char *devname ; int devnum; }; struct tab dtab[] = { "rk",RK0, "rk05",RK0, "tc",TC0, "rk07",RK0, "rm80",HP0, "rp",RP0, "rp03",RP0, "rf",RF0, "rf11",RF0, "tm",TM0, "tu",TM0, "mt",TM0, "tu10",TM0, "ts11",TM0, "tc11",TC0, "hp",HP0, "rp04",HP0, "rp05",HP0, "rp07",HP0, "rm05",HP0, "rp06",HP0, "ht",HT0, "te16",HT0, "tm78",HT0, "tu78",HT0, "tu16",HT0, "hs",HS0, "rs03",HS0, "rs04",HS0, "rs",HS0, "rl",RL0, "rl01",RL0, "mem",MEM, "int",INT, 0,0 }; 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(&xtime,*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 (void) fprintf(stderr,"%s?\n",argv); } } for(i = 0;i < NMAJOR;i++) { for(j = 0; j < NMINOR; 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; #ifdef vax sums[i][j].contr = 0; sums[i][j].slave = 0; #endif tot_sums[i][j].totalio = 0; tot_sums[i][j].misc = 0; tot_sums[i][j].missing = 0; base_sums[i][j].totalio = 0; base_sums[i][j].misc = 0; base_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); } /* Associate typed name with a specific bit in "optdev" */ encode(p) char *p; { register struct tab *q; int lower(); lower (p); /* convert device name to lower case */ for(q=dtab;q->devname;q++) { if (!strcmp(q->devname,p)) { if (q->devnum != HP0) return(1<<(q->devnum)); else return (1<<HP0 | 1<<HP1 | 1<<HP2 | 1<<HP3); } } return(0); } report(fp) char *fp; { register int i, j; if ((file = fopen(fp, "r")) == NULL) error("cannot open", fp); inithdng(); if (writout()) puthead(header); putdata(); if (writout()) putft(); for(i = 0; i < NMAJOR; i++) for(j = 0; j < NMINOR; j++) if(sums[i][j].totalio) adjustsum(i, j); } putdata() { while(fread((char*)&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"); } } } /* System Startup Record */ #define est ercd.start up() { register int i; if (!readrec(file)) { fprintf(stderr, "at up = %o\n", est.e_cpu); fprintf(stderr, "%o\n", est.e_mmr3); fprintf(stderr, "%ld\n", est.e_name.release); fprintf(stderr, "%s %s\n", est.e_name.release, est.e_name.sysname); readerr++; return; } cputype = est.e_cpu; if (writout()) { need(13+araysz(msg)); printf(xlines[12], ctime(&e_hdr.e_time)); printf(xlines[13]); printf(xlines[17], est.e_name.release, est.e_name.sysname); printf(xlines[14], est.e_cpu); if (est.e_syssize) printf(xlines[15], est.e_syssize); else line--; for(i = 0; i <= araysz(msg) + 1; i++) if (est.e_mmr3 & (1 << i)) printf(xlines[18], msg[i]); else line--; 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 */ #define estr ercd.stray stray() { if (!readrec(file)) { readerr++; return; } if (!wanted()) return; if (print == YES) { need(6); if (page <= limit) { printf(xlines[2], ctime(&e_hdr.e_time)); if (estr.e_saddr < DEVADR) printf(xlines[4]); else printf(xlines[3]); printf(FORM, estr.e_saddr); printf(lines[0]); printf(lines[7]); if (estr.e_sbacty == 0) printf("None\n"); else afix(araysz(dev)+1, (unsigned) estr.e_sbacty, dev); } } straysum++; } /* Memory Parity Record */ party() { register struct vaxreg *q; char *ctime(); if (!readrec(file)) { readerr++; return; } if (!wanted()) return; if (print == YES) { #ifdef pdp11 need(9); #else need(11); #endif if (page > limit) return; printf(xlines[5], ctime(&e_hdr.e_time)); #ifdef pdp11 printf(xlines[6],(((long)(erp.e_parreg[1]&077))<<WDLEN) + ((long)((unsigned) erp.e_parreg[0])), (erp.e_parreg[1]>>14)&03); printf(lines[0]); printf(lines[8]); printf(xlines[7], erp.e_parreg[2]); printf(lines[0]); printf(xlines[8], erp.e_parreg[3]); #else printf(lines[0]); if (cputype == 780) { printf(xlines[6], "Longword", (erm.e_memcad & 0X0fffff00) >> 6); printf(xlines[7], erm.e_memcad & 0x000000ff); printf(lines[0]); printf(lines[8]); q = mem780; printf("\t %-4.4s\t ", q->regname); printf(FORM, erm.e_sbier); afix(WDLEN*2, erm.e_sbier, q->bitcode); printf("\t %-4.4s\t ", (++q)->regname); printf(FORM, erm.e_memcad); afix(WDLEN*2, erm.e_memcad, q->bitcode); } else { --line; printf(xlines[6], "within page", erm.e_memcad); printf(xlines[7], erm.e_sbier & 0x0000007f); printf(lines[0]); printf(lines[8]); q = mem750; printf("\t %-4.4s\t ", q->regname); printf(FORM, erm.e_sbier); afix(WDLEN*2, erm.e_sbier, q->bitcode); } #endif } parsum++; } /* Device Error Record */ blk() { register union ercd *z; register int i; register struct sums *p; register struct eblock *r; int *mbar; struct vaxreg *q; int ldev; #ifdef vax pos.controller = pos.slave = pos.flg = 0; #else pos.flg = 0; #endif if (!readrec(file)) { readerr++; return; } z = &ercd; maj = major(recrd.e_dev); ldev = min = minor(recrd.e_dev); if ((maj > araysz(func)) | maj < 0) return; if (!wanted()) return; regs_ptr = devregs[maj]; (*func[maj])(); /* Increment summary totals */ p = &sums[maj][min]; r = &recrd; if (r->e_bflags & E_ERROR) p->hard++; else p->soft++; if (r->e_stats.io_ops < p->totalio) adjustsum(maj, min); if (!(p->drvname)) p->drvname = dev[maj]; #ifdef vax p->contr = pos.controller; p->slave = pos.slave; #endif p->totalio = r->e_stats.io_ops; p->misc = r->e_stats.io_misc; p->missing = r->e_stats.io_unlog; if (print == NO) return; #ifdef vax mb_dev = (maj == HP0 || maj == HT0 || maj >= HP1); need(PNEED + r->e_nreg + mb_dev * 5 + pos.flg * 5); #else need(PNEED + r->e_nreg + pos.flg * 5); #endif if (page > limit) return; printf(lines[0]); printf(lines[1], p->drvname, ctime(&e_hdr.e_time)); #ifdef pdp11 printf(lines[2], pos.unit); #else if (pos.slave) printf(lines[26], pos.unit, pos.slave); else printf(lines[2], pos.unit); printf(lines[25], p->contr); #endif printf(lines[3], ldev, ldev); printf(lines[4]); printf(FORM, r->e_regloc); printf(lines[0]); printf(lines[5], r->e_rtry); printf(lines[6], r->e_bflags & E_ERROR ? "Unrecovered" : "Recovered"); printf(lines[7]); if (r->e_bacty == 0) printf("None\n"); else afix(WDLEN, (unsigned) r->e_bacty, dev); printf(lines[0]); printf(lines[8]); #ifdef vax if (mb_dev) { mbar = ((int *) &z->ebb.block.e_mba); q = mbareg; for(i = 0; i < MBAREG; i++, mbar++, q++) { printf("\t %-6.6s %.8X", q->regname, *mbar); afix(WDLEN*2, *mbar, q->bitcode); } } #endif for(i = 0; i < r->e_nreg; i++, regs_ptr++) { if (*regs_ptr->regname != 'Z') { printf("\t %-4.4s\t ", regs_ptr->regname); printf("%8.6o", ercd.ebb.reginf[i]); afix(WDLEN, ercd.ebb.reginf[i], regs_ptr->bitcode); } else line--; /* adjust page-position counter */ } printf(lines[0]); printf(lines[10]); printf(FORM2, r->e_memadd); printf(lines[11], r->e_bytes); i = r->e_bflags; printf(lines[12], (i & E_NOIO) ? "No-op" : ((i & E_READ) ? "Read" : "Write")); printf(lines[13], r->e_bnum); if (Unix) printf(lines[14], i & E_PHYS ? "Physical" : "Buffered"); else line--; printf(lines[0]); if (pos.flg) { printf(lines[0]); if (maj != HS0) printf(lines[15], pos.cyl); else line--; 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], tot_sums[maj][min].totalio+r->e_stats.io_ops); printf(lines[20], tot_sums[maj][min].misc+r->e_stats.io_misc); printf(lines[21], tot_sums[maj][min].missing+r->e_stats.io_unlog); printf(lines[0]); } rkblk() { register int m; register daddr_t d; register int track, sect; pos.flg = 1; m = min - 7; if (m <= 0) { d = recrd.e_bnum; pos.unit = min; } else { d = recrd.e_bnum / m; pos.unit = recrd.e_bnum % m; } if (recrd.e_nreg > 8) { sums[maj][pos.unit].drvname = (ercd.ebb.reginf[0] & 01000) ? "RK06" : "RK07"; regs_ptr = rk2regs; track = 3; sect = 22; } else { track = 2; sect = 12; } min = pos.unit; pos.cyl = d / (track * sect); pos.trk = d % (track * sect) / sect; pos.sector = d % (track * sect) % sect; } rpblk() { pos.flg = 1; min = pos.unit = min>>DSEC; pos.cyl = recrd.e_cyloff; pos.cyl += recrd.e_bnum / (20 * 10); pos.trk = (recrd.e_bnum % (20 * 10)) / 10; pos.sector = (recrd.e_bnum % (20 * 10)) % 10; } rfblk() { pos.flg = 1; min = pos.unit = recrd.e_bnum >> 10; pos.trk = (recrd.e_bnum % 1024) >> 3; pos.cyl = 0; pos.sector = (recrd.e_bnum % 1024) % 8; } tmblk() { min = pos.unit = min & 03; #ifdef vax if (recrd.e_nreg > 6) { regs_ptr = tsregs; sums[maj][pos.unit].drvname = "TS11"; } else sums[maj][pos.unit].drvname = "TU10"; #endif } tcblk() { min = pos.unit = min & 07; } gdblk() { register int track, sect, dt; register struct eblock *r; char *findname(); dt = DRIVE_TYPE; if ( (dt & 0770) == GTTM03 || (dt & 0770) == GTTM78 || maj == HT0) { pos.unit = (min >> 1) & 01; #ifdef vax pos.slave = min & 01; #endif min &= 03; regs_ptr = ((dt & 0770) == GTTM78) ? ht2regs : htregs; } else { switch (dt) { case GDRM03: sect = 32; track = 19; regs_ptr = hp2regs; break; case GDRM05: sect = 32; track = 19; regs_ptr = hp2regs; break; case GDRM80: sect = 32; track = 7; regs_ptr = hp2regs; break; case GDRP07: sect = 50; track = 32; break; default: /* RP04/5/6 */ sect = 22; track = 19; break; } pos.flg = 1; min = pos.unit = (min & 070) >> DSEC; r = &recrd; pos.cyl = r->e_cyloff + r->e_bnum / (track * sect); pos.trk = (r->e_bnum % (track * sect)) / sect; pos.sector = (r->e_bnum % (track * sect)) % sect; } #ifdef vax pos.controller = (min >> 6) & 03; #endif sums[maj][min].drvname = findname(); } hsblk() { register div; if (min & 010) { div = 32L; n = 1; } else { div = 16L; n = 3; } pos.flg = 1; pos.cyl = 0; min = pos.unit = min & 07; pos.trk = recrd.e_bnum / div; pos.sector = (recrd.e_bnum % div) * (n + 1); } rlblk() { pos.flg = 1; pos.unit = min; pos.trk = recrd.e_bnum / (20 * 256); pos.cyl = ((recrd.e_bnum) % (20 * 256)) / 20; pos.sector = ((recrd.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("\t%s\n\t\t\t", interp); line++; cleanse(interp,MAXSTR); } else { if (*interp) concat(",", interp); } concat(c[i], interp); } } if (*interp) printf("\t%s\n", interp); else putchar('\n'); } puthead(h) char *h; { printf("\n\n %s Prepared on %s Page %d\n\n\n\n", h, htime, page); line = 6; } inithdng() { char *cbuf; time(&tloc); cbuf = 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; long nt; 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)->tm_year; } *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 < xtime ) { if (e_hdr.e_type != E_BLK) return 0; (*func[maj])(); base_sums[maj][min].totalio = recrd.e_stats.io_ops; base_sums[maj][min].misc = recrd.e_stats.io_misc; base_sums[maj][min].missing = recrd.e_stats.io_unlog; return (0); } if (e_hdr.e_time > etime) return (0); /* Only fatal error flag? */ if ((fflg) && (e_hdr.e_type == E_BLK) && !(recrd.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); } } lower(str_ptr) char *str_ptr; { for(; *str_ptr; str_ptr++) *str_ptr = tolower(*str_ptr); } char * findname() { switch (DRIVE_TYPE){ case GDRP04: return "RP04"; case GDRP05: return "RP05"; case GDRP06: return "RP06"; case GDRP07: return "RP07"; case GDRM03: return "RM03"; case GDRM05: return "RM05"; case GDRM80: return "RM80"; default: switch (DRIVE_TYPE & 0770){ case GTTM78: return "TM78"; case GTTM02: case GTTM03: #ifdef pdp11 return "TU16"; #else return "TE16"; #endif default: return "UNKNOWN"; } } } 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; } adjustsum(i, j) register int i, j; { tot_sums[i][j].totalio += sums[i][j].totalio; tot_sums[i][j].misc += sums[i][j].misc; tot_sums[i][j].missing += sums[i][j].missing; sums[i][j].totalio = 0; sums[i][j].misc = 0; sums[i][j].missing = 0; if (base_sums[i][j].totalio && base_sums[i][j].totalio < sums[i][j].totalio) { tot_sums[i][j].totalio -= base_sums[i][j].totalio; tot_sums[i][j].misc -= base_sums[i][j].misc; tot_sums[i][j].missing -= base_sums[i][j].missing; base_sums[i][j].totalio = 0; base_sums[i][j].misc = 0; base_sums[i][j].missing = 0; } } printsum() { int i; header = hd2; page = 1; puthead(header); need(11); printf(sumlines[12], choice[0] ? choice : "All"); printf(sumlines[13]); if (xtime) { printf("On or after %s", ctime(&xtime)); 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(<ime)); printf(lines[0]); if (readerr) printf(sumlines[7], readerr); else printf(lines[0]); printf(lines[0]); if ((optdev & (1 << INT)) || !(dflg) || (aflg)) { need(3); printf(lines[0]); printf(sumlines[9], straysum); printf(lines[0]); } if ((optdev & (1 << MEM)) || !(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 < NMINOR; j++) { if (tot_sums[i][j].totalio || sums[i][j].totalio) { need(10); #ifdef vax if (sums[i][j].slave) printf(sumlines[15], sums[i][j].drvname, (j >> 1) & 01, sums[i][j].slave, sums[i][j].contr); else printf(sumlines[1], sums[i][j].drvname, j, sums[i][j].contr); #else printf(sumlines[1], sums[i][j].drvname, j); #endif printf(sumlines[0]); printf(sumlines[2], sums[i][j].hard); printf(sumlines[3], sums[i][j].soft); printf(sumlines[4], tot_sums[i][j].totalio); printf(sumlines[5], tot_sums[i][j].misc); printf(sumlines[6], tot_sums[i][j].missing); printf(sumlines[0]); } } }