1
0
Files
irix-657m-src/eoe/cmd/availmon/amreport.c
2022-09-29 17:59:04 +03:00

3438 lines
86 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* amreport.c
*
* availmon local/site log viewing system
*/
#ident "$Revision: 1.23 $"
/*
* To do list:
*
* 1. a better data structure for event_t, eventname, shorteventname
* and event code should be defined so that the handling routine
* can be simpler and easy to read.
*
* one good advantage is that event code does not have special
* ordering, but event_t can have special order for easy processing
*
* 2. statname and availstat_t's nstat, stuptime, stdntime is another
* ugly implementation of processing and showing stats. A better
* data structure should be defined.
*
* 3. since registration and deregistration are events, there is no
* need to have regist in arm_t. replace regist with bad or duplicate
* for bad or duplicate reports (currently use regist).
*
* 4. if -f and/or -t are defined, total elapsed time, uptime, and
* downtime should be changed accordingly. the stats shown are
* based on the epoches included.
*
* 5. currently, -f/-t and resend can be used for locallog only. it
* would be better to enhance it for sitelog also.
*
* 6. currently, diag info is not shown because it is too lengthy.
* it would be nice to be able to handle multiple-page display.
*
* 7. amreport used curses, so it is for dump terminal. if necessary,
* it can have a gui option.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <curses.h>
#include <term.h>
#include <fcntl.h>
#include <signal.h>
#include <values.h>
#include <time.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
#include "defs.h"
#include <sys/syssgi.h>
#define MAXHOSTS 1024 /* no. of distinct hosts that can be monitored */
#define LINELEN 256
#define DASH '-'
#define EQUALS '='
#define PIPE '|' /* the field separator for availlog records */
#define REPORT_WIDTH 79
#define NREASONS 7
#define MAXEVENTCODE 26
#define MINEVENTCODE -19
#define NSTATS 16
#define PAGERTYPE 6
typedef enum {
/* --- */ ev_unknown,
/* -19 */ ev_livenotification,
/* -18 */ ev_systemid_change,
/* -17 */ ev_pwer_cycle,
/* -16 */ ev_reset,
/* -15 */ ev_nmi,
/* -14 */ ev_software_panic,
/* -13 */ ev_status_report,
/* -12 */ ev_software_error,
/* -11 */ ev_hardware_error,
/* -10 */ ev_no_error,
/* -9 */ ev_registration,
/* -8 */ ev_deregistration,
/* -7 */ ev_power_failure,
/* -6 */ ev_system_off,
/* -5 */ ev_interrupt,
/* -4 */ ev_hardware_panic,
/* -3 */ ev_panic,
/* -2 */ ev_reboot_unconfigured,
/* -1 */ ev_reboot_timeout,
/* 0 */ ev_reboot_unknown,
/* 1 */ ev_reboot_environment,
/* 2 */ ev_reboot_upgrade_hw,
/* 3 */ ev_reboot_replace_hw,
/* 4 */ ev_reboot_install_sw,
/* 5 */ ev_reboot_scheduled,
/* 6 */ ev_reboot_sw_problem,
/* 7 */ ev_reboot_other,
/* 8 */ ev_reboot_pad1,
/* 9 */ ev_reboot_pad2,
/* 10 */ ev_reboot_pad3,
/* 11 */ ev_reboot_admin,
/* 12 */ ev_reboot_hw_upgrade,
/* 13 */ ev_reboot_sw_upgrade,
/* 14 */ ev_reboot_fix_hw,
/* 15 */ ev_reboot_install_patch,
/* 16 */ ev_reboot_fix_sw,
/* 17 */ ev_reboot_pad4,
/* 18 */ ev_reboot_pad5,
/* 19 */ ev_single_timeout,
/* 20 */ ev_single_unconfigured,
/* 21 */ ev_single_admin,
/* 22 */ ev_single_hw_upgrade,
/* 23 */ ev_single_sw_upgrade,
/* 24 */ ev_single_fix_hw,
/* 25 */ ev_single_install_patch,
/* 26 */ ev_single_fix_sw,
/* --- */ ev_num
} event_t;
typedef struct {
/* int majorversion; * version of Avail mon */
/* int minorversion; * version of Avail mon */
time_t prevstarttime;
time_t eventtime;
time_t starttime;
time_t lasttick;
int noprevstart;
int uptime;
int dntime;
int bound;
event_t event;
int regist; /* should get rid of this hack */
int sysidlen;
char *sysid;
int hostnamelen;
char *hostname;
int summarylen;
char *summary;
} amr_t;
typedef struct {
char *sysid;
char *hostname;
int nev[ev_num];
int nsr[ev_num];
int evuptime[ev_num];
int evdntime[ev_num];
int nstat[NSTATS];
int stuptime[NSTATS];
int stdntime[NSTATS];
int unschedules;
int unschedulesuptime;
int unschedulesdntime;
int sruptime[ev_num];
int srdntime[ev_num];
int service;
int serviceuptime;
int servicedntime;
int upleast; /* in minutes */
int upmost; /* in minutes */
int dnleast; /* in minutes */
int dnmost; /* in minutes */
int thisepoch; /* in minutes */
int total; /* in minutes, should get rid of this one */
/* because total is the same as stuptime[15] */
int possibleuptime; /* in minutes */
time_t lastboot; /* since 1970 */
time_t thebeginning; /* since 1970 */
int nepochs;
int ndowns;
} availstat_t;
char cmd[MAX_STR_LEN];
char *tfile = NULL;
char file[MAXPATHLEN];
amr_t *amrs; /* space will be dynamically allocated */
int *amrmarks; /* amr marks */
int statmarks[MAXHOSTS+1]; /* stat marks */
amr_t *samrs[MAXHOSTS+1]; /* an array of pointers into amrs, which mark
* the start position of the amrs array
* sorted by hostname */
int nsamrs; /* no. of sorted groups */
availstat_t availstats[MAXHOSTS+1];
time_t now;
/*
* following used for options processing
*/
int sitelog = 0;
int locallog = 0;
int printversion = 0;
int printflag = 0;
int statflag = 0;
int eventlistflag = 0;
int detailflag = 0;
time_t fromtime = 0, totime = 0;
char fromdate[MAX_STR_LEN] = "", todate[MAX_STR_LEN] = "";
int countthisepoch = 1;
int singlereport = 0;
int listmachines = 0;
int dupepochs = 0;
char machinename[MAXHOSTS+1];
int systemidlen;
char systemid[MAXSYSIDSIZE + 1];
int lhostnamelen;
char lhostname[MAXHOSTNAMELEN+1];
int nreports;
char *cfile = NULL;
char *usage =
"Usage: %s [{ -l <locallogfile> | -s <sitelogfile> }] [-c]\n"
" %s [{ -l <locallogfile> | -s <sitelogfile> }] [-p] [-r] [-e] [-d] [-c]\n"
" %s [-l <locallogfile>] [-f <fromtime>] [-t <totime>] [-e] [-d] [-c]\n"
" %s { -1 | -v }\n";
int errmsg = -1;
int outistty = 1; /* zero if output is a not a tty */
char *eventname[] = {
/* --- */ "Unknown reasons",
/* -19 */ "Real-time Notification of critical Messages",
/* -18 */ "Serial number/hostname change",
/* -17 */ "Power cycle",
/* -16 */ "System reset",
/* -15 */ "NMI",
/* -14 */ "Panic due to software fault",
/* -13 */ "Status report",
/* -12 */ "Software error",
/* -11 */ "Hardware error",
/* -10 */ "No error",
/* -9 */ "Registration",
/* -8 */ "Deregistration",
/* -7 */ "Power failure",
/* -6 */ "System off",
/* -5 */ "Interrupt",
/* -4 */ "Panic due to hardware fault",
/* -3 */ "Panic",
/* -2 */ "Controlled shutdown: shutdown reason unknown (not configured)",
/* -1 */ "Controlled shutdown: timed-out while waiting for operator to enter stop reason",
/* 0 */ "Controlled shutdown: system shutdown, cause unknown",
/* 1 */ "Controlled shutdown: environmental reasons (move system, planned power outage, ...)",
/* 2 */ "Controlled shutdown: upgrade/add hardware or peripherals",
/* 3 */ "Controlled shutdown: replace failed hardware component",
/* 4 */ "Controlled shutdown: install software that requires reboot",
/* 5 */ "Controlled shutdown: scheduled reboot/Routine maintenance",
/* 6 */ "Controlled shutdown: software problem",
/* 7 */ "Controlled shutdown: other unclassified reasons",
/* 8 */ "",
/* 9 */ "",
/* 10 */ "",
/* 11 */ "Controlled shutdown: administrative",
/* 12 */ "Controlled shutdown: hardware upgrade",
/* 13 */ "Controlled shutdown: software upgrade",
/* 14 */ "Controlled shutdown: fix/replace hardware",
/* 15 */ "Controlled shutdown: install patch",
/* 16 */ "Controlled shutdown: fix software problem",
/* 17 */ "",
/* 18 */ "",
/* 19 */ "Single-user mode: timed-out while waiting for operator to enter stop reason",
/* 20 */ "Single-user mode: shutdown reason unknown (not configured)",
/* 21 */ "Single-user mode: administrativ",
/* 22 */ "Single-user mode: hardware upgrade",
/* 23 */ "Single-user mode: software upgrade",
/* 24 */ "Single-user mode: fix/replace hardware",
/* 25 */ "Single-user mode: install patch",
/* 26 */ "Single-user mode: fix software problem",
/* --- */ ""
};
char *shorteventname[] = {
/* --- */ "Unknown",
/* -19 */ "Live Event",
/* -18 */ "SysID change",
/* -17 */ "Power cycle",
/* -16 */ "System reset",
/* -15 */ "NMI",
/* -14 */ "Panic (S/W)",
/* -13 */ "Status report",
/* -12 */ "Software error",
/* -11 */ "Hardware error",
/* -10 */ "No error",
/* -9 */ "Registration",
/* -8 */ "Deregistration",
/* -7 */ "Power failure",
/* -6 */ "System off",
/* -5 */ "Interrupt",
/* -4 */ "Panic (H/W)",
/* -3 */ "Panic",
/* -2 */ "Controlled",
/* -1 */ "Controlled",
/* 0 */ "Controlled",
/* 1 */ "Controlled",
/* 2 */ "Controlled",
/* 3 */ "Controlled",
/* 4 */ "Controlled",
/* 5 */ "Controlled",
/* 6 */ "Controlled",
/* 7 */ "Controlled",
/* 8 */ "",
/* 9 */ "",
/* 10 */ "",
/* 11 */ "Controlled",
/* 12 */ "Controlled",
/* 13 */ "Controlled",
/* 14 */ "Controlled",
/* 15 */ "Controlled",
/* 16 */ "Controlled",
/* 17 */ "",
/* 18 */ "",
/* 19 */ "Single-User",
/* 20 */ "Single-User",
/* 21 */ "Single-User",
/* 22 */ "Single-User",
/* 23 */ "Single-User",
/* 24 */ "Single-User",
/* 25 */ "Single-User",
/* 26 */ "Single-User",
/* --- */ ""
};
char *statname[] = {
"Unscheduled ....................",
" panic due to hardware ........",
" panic due to software ........",
" panic due to unknown reason ..",
" reset action .................",
" power interruption ...........",
"Service action .................",
" fix/replace hardware .........",
" upgrade hardware .............",
" upgrade software .............",
" fix software .................",
" install patch ................",
" administrative: singe-user ...",
" administrative: reboot .......",
" unknown ......................",
"Total .........................."
};
/*
* Forward declarations.
*/
void getlocalreports(FILE *, amr_t *);
void getsitereports(FILE *, amr_t *);
void collect_stats(amr_t *amrs, int n, availstat_t *s);
char *extracthostname(char *iname, char *hname);
void prettyshow_centered(char *s, char c, int spaces);
void aggregatestats(availstat_t *as, int n, availstat_t *result,
char *upleasthost, char *upmosthost,
char *dnleasthost, char *dnmosthost);
void sort_by_hosts(amr_t *amrs, int *n);
int getword(char *line, int wno, char *word);
void fillhostinfo(amr_t *amr, int hostlen, char *host);
char getchoice(char *prompt, char *choices);
void showstatline(availstat_t *s);
void showstat(availstat_t *s);
void showamrline(amr_t *amr);
char showamrs(int begin, int end);
void showamr(amr_t *amr);
void sendamrs(int begin, int end);
void sendamr(amr_t *amr);
char *pretty_minutes(int m, char *s);
void prettyprint_centered(char *s, char c, int spaces);
void printstatlist(int all);
void printstatline(availstat_t *s);
void printstat(availstat_t *s);
void printamrlist(int mach);
void printamrline(amr_t *amr);
void printamrs(int mach);
void printamr(amr_t *amr);
void
errorexit(char *s, char *msg)
{
if (msg)
fprintf(stderr, "%s:%s\n", s, msg);
else
perror(s);
if (tfile) unlink(tfile);
exit(-1);
}
void
repaint()
{
clearok(curscr,TRUE);
wrefresh(curscr);
}
int
getkey()
{
int c;
while ((c = getch()) == 12)
repaint();
return c;
}
void
getret()
{
int c;
do {
c = getkey();
printw("[%o]<%c>\n", c, c);
} while (c != '\n' && c != KEY_ENTER);
}
/*
* copy gtime from touch.c originally,
* but then feel it is too ugly, so rewrite it
*/
time_t
gtime(char *date)
{
int i, y, t;
int d, h, m;
size_t len;
struct tm tm;
long nt;
int c = 0; /* entered century value */
int s = 0; /* entered seconds value */
int point = 0; /* relative byte position of decimal point */
int ssdigits = 0; /* count seconds digits include decimal pnt */
int noyear = 1; /* 0 means year is entered; 1 means none */
/*
* mmddhhmm is a total of 8 bytes min
* [[cc]yy]mmddhhmm[.ss] is a total of 15 bytes max
*/
len = strlen(date);
if ((len < 8) || (len > 15))
return(-1);
/*
* determine the decimal point position, if any.
* check if there are more than one decimal point.
* check if all the rest are digits.
*/
for (i=0; i<len; i++) {
if (date[i] == '.') {
if (point) {
return(-1);
} else {
point = i;
}
} else if (!isdigit(date[i]))
return(-1);
}
switch(len) {
case 8:
case 10:
case 12:
if (point)
return(-1);
tm.tm_sec = 0;
break;
case 11:
case 13:
case 15:
if (!point || ((len - point) != 3))
return(-1);
t = (date[point + 1] - '0') * 10 + date[point + 2] - '0';
if (t > 61)
return(-1);
else
tm.tm_sec = t;
date[point] = '\0';
len -= 3;
break;
default:
return(-1);
}
if (len == 12) {
/*
* ccyymmddhhmm is the input
*/
y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 +
(date[2] - '0') * 10 + date[3] - '0';
if ((y < 1969) || (y > 2068))
return(-1);
tm.tm_year = y - 1900;
date += 4;
len -= 4;
} else if (len == 10) {
/*
* yymmddhhmm is the input
*/
/* detemine yy -- year number */
y = (date[0] - '0') * 10 + date[1] - '0';
if (y >= 69)
tm.tm_year = y; /* 19th century */
else
tm.tm_year = y + 100; /* 20th century */
date += 2;
len -= 2;
} else {
(void) time(&nt);
tm.tm_year = localtime(&nt)->tm_year;
}
t = (date[0] - '0') * 10 + date[1] - '0';
if (t > 12)
return(-1);
else
tm.tm_mon = t - 1;
t = (date[2] - '0') * 10 + date[3] - '0';
if (t > 31)
return(-1);
else
tm.tm_mday = t;
t = (date[4] - '0') * 10 + date[5] - '0';
if(t > 24)
return(-1);
else
tm.tm_hour = t;
t = (date[6] - '0') * 10 + date[7] - '0';
if (t > 59)
return(-1);
else
tm.tm_min = t;
tm.tm_isdst = -1;
return(mktime(&tm));
}
void
processoptions(int argc, char **argv)
{
int c;
int errflg = 0;
/* process online options */
while ((c = getopt(argc, argv, "1cdeprvl:s:f:t:M")) != EOF)
switch (c) {
case '1':
singlereport = 1;
break;
case 'M':
listmachines = 1 ;
if ((optind == argc) || (argv[optind][0] == '-')) {
/* no file was specified */
strcpy(machinename, "");
} else {
strcpy(machinename, argv[optind]);
optind++;
}
break;
case 's':
sitelog = 1;
if (locallog) {
errflg++;
break;
}
if ((optind - 1 == argc) || (optarg[0] == '-')) {
/* no file was specified */
errflg++;
} else {
strcpy(file, optarg);
}
break;
case 'l':
locallog = 1;
if (sitelog) {
errflg++;
break;
}
if ((optind - 1 == argc) || (optarg[0] == '-')) {
/* no file was specified */
errflg++;
} else {
strcpy(file, optarg);
}
break;
case 'f':
if ((optind - 1 == argc) || (optarg[0] == '-')) {
/* no file was specified */
errflg++;
} else {
strcpy(fromdate, optarg);
if ((fromtime = gtime(fromdate)) == -1) {
fprintf(stderr, "Error: %s: incorrect time in -f option.\n", cmd);
exit(-1);
}
}
break;
case 't':
if ((optind - 1 == argc) || (optarg[0] == '-')) {
/* no file was specified */
errflg++;
} else {
strcpy(todate, optarg);
if ((totime = gtime(todate)) == -1) {
fprintf(stderr, "Error: %s: incorrect time in -t option.\n", cmd);
exit(-1);
}
}
break;
case 'c':
countthisepoch = 0;
break;
case 'p':
printflag = statflag = eventlistflag = 1;
break;
case 'r':
printflag = statflag = 1;
break;
case 'e':
printflag = eventlistflag = 1;
break;
case 'd':
printflag = detailflag = 1;
break;
case 'v':
printversion = 1;
break;
case '?':
default:
errflg++;
}
if (errflg) {
fprintf(stderr, usage, cmd, cmd, cmd, cmd);
exit(-1);
} else if (!locallog && !sitelog && !singlereport) {
/* no option was given, default to -l /var/adm/avail/availlog */
locallog = 1;
strcpy(file, "/var/adm/avail/availlog");
return;
}
if (fromtime && fromtime > now) {
fprintf(stderr, "Error: %s: bad -f time (later than current time).\n",
cmd);
exit(-1);
}
if (totime && totime > now) {
fprintf(stderr, "Error: %s: bad -t time (later than current time).\n",
cmd);
exit(-1);
}
if (fromtime && totime && (fromtime >= totime)) {
fprintf(stderr, "Error: %s: bad -f and -t time specifications.\n", cmd);
exit(-1);
}
}
void
printlist()
{
int i;
printf("\n\n");
printf("%-35s %-20s\n", "Machine Name", "No. of reports");
printf("%-35s %-20s\n", "------------", "--------------");
for (i = 0; i < nsamrs; i++)
printf("%-40s %d\n", samrs[i]->hostname, samrs[i+1] - samrs[i]);
printf("\n\n");
}
main(int argc, char *argv[])
{
FILE *fp, *fp1;
char linebuf[MAX_LINE_LEN];
int i, j;
char hostname[MAXHOSTNAMELEN+1];
amr_t *amr, amr1;
struct termio tty;
outistty = (ioctl(1, TCGETA, &tty) == 0);
strcpy(cmd, basename(argv[0]));
now = time(0);
/* sets file & format */
processoptions(argc, argv);
if (printversion) {
printf("Availmon version %s\n", AMRVERSIONNUM);
return(0);
}
if (singlereport) {
if (sitelog || locallog) {
fprintf(stderr, usage, cmd, cmd, cmd, cmd);
exit(-1);
}
getsitereports(stdin, &amr1);
amr1.dntime = (amr1.starttime - amr1.prevstarttime + 30)/60
- amr1.uptime;
printamr(&amr1);
return(0);
}
fprintf(stderr, "Using %s format with file %s ... \n",
(locallog ? "local log" : "site log"), file);
if (listmachines)
fprintf(stderr, "Listing machine %s ... \n", machinename);
if ((fp = fopen(file, "r")) == NULL)
errorexit(file, NULL);
fprintf(stderr, "Counting Reports ... ");
nreports = countreports(fp);
fprintf(stderr, "done.\n");
if (nreports <= 0) {
fprintf(stderr, "%s: no reports gathered (is %s in %s format?)\n",
cmd, file, locallog? "local log": "site log");
exit(-1);
}
fprintf(stderr, "Total of %d reports.\n", nreports);
if ((amrs = (amr_t *) calloc(nreports + 1, sizeof(amr_t))) == NULL)
errorexit("calloc", "can't allocate space for amr's");
if ((amrmarks = (int *) calloc(nreports + 1, sizeof(int))) == NULL)
errorexit("calloc", "can't allocate space for amr marks");
fprintf(stderr, "Reading reports ...");
if (locallog) {
if (fp1 = fopen("/var/adm/avail/.save/serialnum", "r")) {
fscanf(fp1, "%s", systemid);
fclose(fp1);
} else if (fp1 = fopen("/var/adm/avail/.save/sysid", "r")) {
fscanf(fp1, "%s", systemid);
fclose(fp1);
} else {
strcpy(systemid, "unknown");
}
systemidlen = strlen(systemid);
fillhostinfo(NULL, lhostnamelen, lhostname);
getlocalreports(fp, amrs);
fprintf(stderr, "done.\n");
if (nreports == 0) {
fprintf(stderr, "%s: no reports gathered (check -f/-t option)\n",
cmd);
exit(-1);
}
nsamrs = 1;
samrs[0] = &amrs[0];
samrs[1] = &amrs[nreports];
} else {
getsitereports(fp, amrs);
fprintf(stderr, "done.\nSorting reports ...");
sort_by_hosts(amrs, &nreports);
fprintf(stderr, "done.\n");
}
if (listmachines) {
if (machinename[0] == NULL) {
printlist();
exit(0);
} else {
for (j = 0; j < nsamrs; j++)
if (strcmp(extracthostname(samrs[j]->hostname,
hostname), machinename) == 0)
break;
if (j == nsamrs) {
printf("Cannot find <%s>\n", machinename);
printlist();
exit(-1);
}
i = samrs[j] - &amrs[0];
nreports = i + samrs[j+1] - samrs[j];
}
} else
i = 0;
if (errmsg && printflag == 0) {
printf("errmsg=%d\n", errmsg);
printf("Press <enter> to display summary ... ");
fgets(linebuf, MAX_LINE_LEN, stdin);
}
if (printflag == 0) {
/*
* enter curse display session
*/
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
if (LINES < 23 || COLS < 80) {
endwin();
fprintf(stderr, "Error: %s: This program needs a screen size at"
" least 23 by 80.\n", cmd);
exit(1);
}
}
if (locallog) {
collect_stats(amrs, nreports, &availstats[0]);
availstats[0].sysid = systemid;
if (printflag) {
if (statflag)
printstatlist(0);
if (eventlistflag)
printamrlist(0);
if (detailflag)
printamrs(0);
} else {
statmarks[0] = 1;
showstats();
}
} else {
char upleasthost[MAXHOSTNAMELEN+1], upmosthost[MAXHOSTNAMELEN+1];
char dnleasthost[MAXHOSTNAMELEN+1], dnmosthost[MAXHOSTNAMELEN+1];
int k, dup = 0;
for (i = 0; i < nsamrs; i++) {
collect_stats(samrs[i],
samrs[i+1] - samrs[i], /* pointer arithmetic */
&availstats[i]);
}
aggregatestats(availstats, nsamrs, &availstats[nsamrs],
upleasthost, upmosthost, dnleasthost, dnmosthost);
for (i = 0, j = 0; i < nreports; i++)
if (amrs[i].regist == 1) {
dup = 1;
for (k = 0; k < nsamrs; k++)
if (samrs[k] > &amrs[j])
break;
for (; k <= nsamrs; k++)
samrs[k]--;
} else if (dup)
amrs[j++] = amrs[i];
else
j++;
nreports = j;
if (printflag) {
if (statflag)
printstatlist(1);
if (eventlistflag)
for (i = 0; i < nsamrs; i++)
printamrlist(i);
if (detailflag)
for (i = 0; i < nsamrs; i++)
printamrs(i);
} else
showoverall(upleasthost, upmosthost, dnleasthost, dnmosthost);
}
if (printflag == 0) {
/*
* exit curse display session
*/
endwin();
printf("\n");
}
if (cfile)
unlink(cfile);
}
char *
extracthostname(char *iname, char *hname)
{
char *p;
int len;
if ((p = strchr(iname, '.')) == NULL)
p = iname + strlen(iname);
len = p - iname;
bcopy(iname, hname, len);
hname[len] = NULL;
return(hname);
}
int
countreports(FILE *fp)
{
int nreports, bad= 1, t;
char linebuf[MAX_LINE_LEN];
char word[LINELEN], word1[LINELEN];
nreports = 0;
if (locallog) {
while (fgets(linebuf, MAX_LINE_LEN, fp) != NULL)
if ((strncmp("EVENT|", linebuf, 6) == 0) ||
(strncmp("STOP|", linebuf, 5) == 0))
nreports++;
if (nreports == 0) {
time_t insttime;
if (fseek(fp, 0L, SEEK_SET) != 0)
errorexit("fseek error", "when rewinding file");
fgets(linebuf, MAX_LINE_LEN, fp);
if (getword(linebuf, 1, word) == -1)
errorexit("getword error", "when extracting installation time");
insttime = atol(word);
printf("\nNo event recorded since installation of availmon at %s",
ctime(&insttime));
printf("(100%% Availability)\n");
exit(0);
}
} else {
while (fgets(linebuf, MAX_LINE_LEN, fp) != NULL)
if ((strncmp("SERIALNUM|", linebuf, 10) == 0) ||
(strncmp("SYSID|", linebuf, 6) == 0))
nreports++;
}
return nreports;
}
void
initamr(amr_t *amr, int local)
{
amr->prevstarttime = 0;
amr->noprevstart = 0;
amr->eventtime = -1;
amr->event = ev_interrupt;
amr->lasttick = -1;
amr->uptime = -1;
amr->dntime = 0;
amr->bound = -1;
amr->regist = 0;
amr->summarylen = 0;
amr->summary = NULL;
if (local) {
amr->sysidlen = systemidlen;
amr->sysid = systemid;
amr->hostnamelen = lhostnamelen;
amr->hostname = lhostname;
} else {
amr->hostnamelen = 0;
amr->hostname = NULL;
}
}
void
getlocalreports(FILE *fp, amr_t *amr)
{
int bad = 1, inputsum = 0, t, t1, sumlen = 0, haslivediag = 0;
int garbage = 0, nrpts = 0;
char linebuf[MAX_LINE_LEN], linebuf1[MAX_LINE_LEN], sumbuf[BUFSIZ];
char word[MAX_LINE_LEN], word1[MAX_LINE_LEN];
amr_t *amr1;
rewind(fp);
sumbuf[0] = '\0';
/*
* skipped events before from date
*/
if (fromtime) {
while (fgets(linebuf, MAX_LINE_LEN, fp) != NULL)
if (strncmp("START|", linebuf, 6) == 0) {
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in START:\n%s",
cmd, linebuf);
continue;
} else {
if (bad) {
errmsg++;
bad = 0;
}
strcpy(linebuf1, linebuf);
t = atol(word);
if (t > fromtime)
goto start;
}
} else if (bad) {
continue;
} else if (strncmp("EVENT|", linebuf, 6) == 0) {
if (getword(linebuf, 2, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in EVENT:\n%s",
cmd, linebuf);
continue;
}
t1 = atol(word1);
if (t1 > fromtime) {
initamr(amr, 1);
amr->prevstarttime = t;
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
garbage = 0;
haslivediag = 0;
goto start1;
}
} else if (strncmp("STOP|", linebuf, 5) == 0) {
if (getword(linebuf, 1, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in STOP:\n%s",
cmd, linebuf);
continue;
}
t1 = atol(word1);
if (t1 > fromtime) {
initamr(amr, 1);
amr->prevstarttime = t;
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
garbage = 0;
haslivediag = 0;
goto start1;
}
}
}
while (fgets(linebuf, MAX_LINE_LEN, fp) != NULL)
if (strncmp("START|", linebuf, 6) == 0) {
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in START:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
if (bad) {
errmsg++;
bad = 0;
} else {
amr->starttime = t;
t1 = amr->event;
if (((t1 <= ev_deregistration) && (t1 >= ev_status_report)) ||
(t1 == ev_systemid_change) || (t1 == ev_livenotification))
amr->dntime = 0;
else
amr->dntime = (amr->starttime - amr->prevstarttime + 30)/60
- amr->uptime;
if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
amr++;
nrpts++;
}
start:
if (totime && (totime < t))
goto end;
initamr(amr, 1);
amr->prevstarttime = t;
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
garbage = 0;
haslivediag = 0;
} else if (bad) {
continue;
} else if (strncmp("SUMMARY|", linebuf, 8) == 0) {
inputsum = !inputsum;
} else if (inputsum) {
t = strlen(linebuf);
if (sumlen + t < BUFSIZ) {
strcat(sumbuf, linebuf);
sumlen += t;
}
} else if (strncmp("EVENT|", linebuf, 6) == 0) {
start1:
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get event code in EVENT:\n%s",
cmd, linebuf);
continue;
}
if (getword(linebuf, 2, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in EVENT:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
t1 = atol(word1);
if (haslivediag) {
if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
amr1 = amr;
amr++;
nrpts++;
initamr(amr, 1);
if (amr1->event >= ev_single_timeout) {
amr->noprevstart = 1;
amr1->starttime = t1;
amr->prevstarttime = t1;
} else {
amr->noprevstart = 0;
amr->prevstarttime = amr1->prevstarttime;
}
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
}
if (totime && (totime < t1))
goto end;
if (t > MAXEVENTCODE || t < MINEVENTCODE)
t = amr->event = ev_unknown;
else
t = amr->event = (event_t)(t - MINEVENTCODE + 1);
if (((t <= ev_deregistration) && (t >= ev_status_report)) ||
(t == ev_systemid_change) || (t == ev_livenotification)) {
haslivediag = 1;
amr->uptime = 0;
amr->noprevstart = 1;
} else if (t >= ev_single_timeout)
haslivediag = 1;
else
haslivediag = 0;
amr->eventtime = t1;
if ((t >= ev_reboot_unconfigured) || (t == ev_panic) ||
(t == ev_software_panic) || ( t == ev_hardware_panic)) {
if (amr->eventtime > 0)
amr->uptime = (amr->eventtime - amr->prevstarttime + 30)/60;
}
} else if (strncmp("STOP|", linebuf, 5) == 0) {
if (getword(linebuf, 2, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get stop code in STOP:\n%s",
cmd, linebuf);
continue;
}
if (getword(linebuf, 1, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in STOP:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
t1 = atol(word1);
if (haslivediag) {
if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
amr1 = amr;
amr++;
nrpts++;
initamr(amr, 1);
if (amr1->event >= ev_single_timeout) {
amr->noprevstart = 1;
amr1->starttime = t1;
amr->prevstarttime = t1;
} else {
amr->noprevstart = 0;
amr->prevstarttime = amr1->prevstarttime;
}
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
}
if (totime && (totime < t1))
goto end;
if (t > MAXEVENTCODE || t < MINEVENTCODE)
t = amr->event = ev_unknown;
else
t = amr->event = (event_t)(t - MINEVENTCODE + 1);
if (((t <= ev_deregistration) && (t >= ev_status_report)) ||
(t == ev_systemid_change) || (t == ev_livenotification)) {
haslivediag = 1;
amr->uptime = 0;
amr->noprevstart = 1;
} else if (t >= ev_single_timeout) {
haslivediag = 1;
} else
haslivediag = 0;
amr->eventtime = t1;
if ((t >= ev_reboot_unconfigured) || (t == ev_panic) ||
(t == ev_software_panic) || ( t == ev_hardware_panic)) {
if (amr->eventtime > 0)
amr->uptime = (amr->eventtime - amr->prevstarttime + 30)/60;
}
} else if (strncmp("UPTIME|", linebuf, 7) == 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get time in UPTIME:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
if (t >= 0)
amr->lasttick = amr->prevstarttime + t * 60;
if (amr->uptime < 0) {
amr->uptime = t;
}
} else if (strncmp("LASTTICK|", linebuf, 9) == 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get time in UPTIME:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
amr->lasttick = t;
if (amr->uptime < 0) {
amr->uptime = (t - amr->prevstarttime + 30) / 60;
}
} else if (strncmp("BOUND|", linebuf, 6) == 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get bound in BOUND:\n%s",
cmd, linebuf);
continue;
}
amr->bound = atol(word);
/*
* Moved garbage check from before UPTIME to here since the value
* of LASTTICK is not being read-in if the garbage flag is set
*/
} else if (garbage) {
continue;
} else if (strncmp("UNAME|", linebuf, 6) == 0) {
continue;
} else if (strncmp("VERSIONS|", linebuf, 9) == 0) {
garbage = 1;
} else if (strncmp("HINV|", linebuf, 5) == 0) {
garbage = 1;
} else if (strncmp("GFXINFO|", linebuf, 8) == 0) {
garbage = 1;
} else if (strncmp("REGISTRATION|", linebuf, 13) == 0) {
amr->regist = 1;
} else if (strncmp("DEREGISTRATION|", linebuf, 15) == 0) {
amr->regist = -1;
} else if (strncmp("OLDSERIALNUM|", linebuf, 13) == 0) {
continue;
} else if (strncmp("OLDHOSTNAME|", linebuf, 12) == 0) {
continue;
} else {
errmsg++;
fprintf(stderr, "Error: %s: garbage in local log file:\n%s",
cmd, linebuf);
}
end:
if (bad)
errmsg++;
else if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
nreports = nrpts;
fclose(fp);
}
void
getsitereports(FILE *fp, amr_t *amr)
{
int linenum = 0, oldsysid = 0;
int bad = 1, inputsum = 0, t, len, sumlen = 0, garbage = 0;
char linebuf[MAX_LINE_LEN], sumbuf[BUFSIZ];
char word[MAX_LINE_LEN], word1[MAX_LINE_LEN];
rewind(fp);
sumbuf[0] = '\0';
while (fgets(linebuf, MAX_LINE_LEN, fp) != NULL) {
linenum++;
if ((strncmp("SYSID|", linebuf, 6) == 0) ||
(strncmp("SERIALNUM|", linebuf, 10) == 0)) {
if (bad) {
errmsg++;
bad = 0;
} else {
if (singlereport)
return;
t = amr->event;
if (((t <= ev_deregistration) && (t >= ev_status_report)) ||
(t == ev_systemid_change) || (t == ev_livenotification))
amr->dntime = 0;
else
amr->dntime = (amr->starttime - amr->prevstarttime + 30)/60
- amr->uptime;
if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
amr++;
}
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get serial number:\n%s",
cmd, linebuf);
continue;
}
initamr(amr, 0);
len = strlen(word);
amr->sysidlen = len;
amr->sysid = malloc(len + 1);
strcpy(amr->sysid, word);
sumlen = 0;
sumbuf[0] = '\0';
inputsum = 0;
garbage = 0;
oldsysid = 1;
} else if (bad) {
continue;
} else if (strncmp("SUMMARY|", linebuf, 8) == 0) {
inputsum = !inputsum;
} else if (inputsum) {
len = strlen(linebuf);
if (sumlen + len < BUFSIZ) {
strcat(sumbuf, linebuf);
sumlen += len;
}
} else if (garbage) {
continue;
} else if (strncmp("HOSTNAME|", linebuf, 9) == 0) {
len = strlen(linebuf);
linebuf[len - 1] = '\0';
amr->hostnamelen = len - 9;
amr->hostname = malloc(len - 9);
strcpy(amr->hostname, linebuf + 9);
oldsysid = 0;
} else if (strncmp("AMRVERSION|", linebuf, 11) == 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get version number in AMRVERSION:\n%s",
cmd, linebuf);
continue;
}
} else if (strncmp("PREVSTART|", linebuf, 10) == 0) {
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in PREVSTART:\n%s",
cmd, linebuf);
continue;
} else if (strstr(linebuf, "|NOTMULTIUSER"))
amr->noprevstart = 1;
amr->prevstarttime = atol(word);
} else if (strncmp("EVENT|", linebuf, 6) == 0) {
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get event code in EVENT:\n%s",
cmd, linebuf);
continue;
}
if (getword(linebuf, 2, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in EVENT:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
if (t > MAXEVENTCODE || t < MINEVENTCODE)
t = amr->event = ev_unknown;
else
t = amr->event = (event_t)(t - MINEVENTCODE + 1);
if (((t <= ev_deregistration) && (t >= ev_status_report)) ||
(t == ev_systemid_change) || (t == ev_livenotification)) {
amr->uptime = 0;
amr->noprevstart = 1;
}
amr->eventtime = atol(word1);
if ((t >= ev_reboot_unconfigured) || (t == ev_panic) ||
(t == ev_software_panic) || ( t == ev_hardware_panic) ||
(t == ev_deregistration)) {
if (amr->eventtime > 0)
amr->uptime = (amr->eventtime - amr->prevstarttime + 30)/60;
}
} else if (strncmp("STOP|", linebuf, 5) == 0) {
if (getword(linebuf, 2, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get stop code in STOP:\n%s",
cmd, linebuf);
continue;
}
if (getword(linebuf, 1, word1) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in STOP:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
if (t > MAXEVENTCODE || t < MINEVENTCODE)
t = amr->event = ev_unknown;
else
t = amr->event = (event_t)(t - MINEVENTCODE + 1);
if (((t <= ev_deregistration) && (t >= ev_status_report)) ||
(t == ev_systemid_change) || (t == ev_livenotification)) {
amr->uptime = 0;
amr->noprevstart = 1;
}
amr->eventtime = atol(word1);
if ((t >= ev_reboot_unconfigured) || (t == ev_panic) ||
(t == ev_software_panic) || ( t == ev_hardware_panic) ||
(t == ev_deregistration)) {
if (amr->eventtime > 0)
amr->uptime = (amr->eventtime - amr->prevstarttime + 30)/60;
}
} else if (strncmp("UPTIME|", linebuf, 7) == 0) {
if (amr->uptime < 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get time in UPTIME:\n%s",
cmd, linebuf);
continue;
}
amr->uptime = atol(word);
}
} else if (strncmp("LASTTICK|", linebuf, 9) == 0) {
if (amr->uptime < 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get time in UPTIME:\n%s",
cmd, linebuf);
continue;
}
t = atol(word);
amr->uptime = (t - amr->prevstarttime + 30) / 60;
}
} else if (strncmp("START|", linebuf, 6) == 0) {
if (getword(linebuf, 1, word) == -1) {
bad = 1;
fprintf(stderr, "Error: %s: cannot get time in START:\n%s",
cmd, linebuf);
continue;
}
amr->starttime = atol(word);
} else if (strncmp("REGISTRATION|", linebuf, 13) == 0) {
amr->regist = 1;
if (amr->prevstarttime == 0)
amr->prevstarttime = amr->starttime;
} else if (strncmp("DEREGISTRATION|", linebuf, 15) == 0) {
amr->regist = -1;
amr->starttime = amr->eventtime;
} else if (strncmp("BOUNDS|", linebuf, 7) == 0) {
if (getword(linebuf, 2, word) == -1) {
fprintf(stderr, "Error: %s: cannot get bound in BOUND:\n%s",
cmd, linebuf);
continue;
}
amr->bound = atol(word);
} else if (strncmp("STATUSINTERVAL|", linebuf, 15) == 0) {
if (getword(linebuf, 1, word) == -1) {
fprintf(stderr, "Error: %s: cannot get status interval in STATUSINTERVAL:\n%s",
cmd, linebuf);
continue;
}
} else if (strncmp("AMRVERSION|", linebuf, 11) == 0) {
continue;
} else if (strncmp("UNAME|", linebuf, 6) == 0) {
continue;
} else if (strncmp("STATUSINTERVAL|", linebuf, 15) == 0) {
continue;
} else if (strncmp("OLDSERIALNUM|", linebuf, 13) == 0) {
continue;
} else if (strncmp("OLDHOSTNAME|", linebuf, 12) == 0) {
continue;
} else if (strncmp("VERSIONS|", linebuf, 9) == 0) {
garbage = 1;
} else if (strncmp("HINV|", linebuf, 5) == 0) {
garbage = 1;
} else if (strncmp("GFXINFO|", linebuf, 8) == 0) {
garbage = 1;
} else if (strncmp("ICRASH|", linebuf, 7) == 0) {
garbage = 1;
} else if (strncmp("SYSLOG|", linebuf, 7) == 0) {
garbage = 1;
} else if (oldsysid && (*linebuf == 'K')) {
continue;
} else {
errmsg++;
garbage = 1;
fprintf(stderr, "Error: %s: garbage in site log file:\nline %d:%s",
cmd, linenum, linebuf);
}
}
if (bad)
errmsg++;
else {
amr->dntime = (amr->starttime - amr->prevstarttime + 30)/60
- amr->uptime;
if (sumlen) {
amr->summary = malloc(sumlen + 1);
strcpy(amr->summary, sumbuf);
amr->summarylen = sumlen;
}
}
fclose(fp);
}
/*
* words are numbered 0,1,2 and are in format 0|1|2\n (vertical bar is
* the field separator)
*/
int
getword(char *line, int wno, char *word)
{
int i = 0;
char *p, *p1;
if (wno) {
i = wno;
for (p = line; *p; p++)
if (*p == '|')
if (--i == 0)
break;
}
if (i)
return(-1); /* not enough fields */
p1 = ++p;
for (; *p; p++)
if (*p == '|') {
*p = NULL;
strcpy(word, p1);
*p = PIPE;
return(0);
}
if (*(--p) == '\n') {
*p = NULL;
strcpy(word, p1);
*p = '\n';
} else
strcpy(word, p1);
return(0);
}
/*
* old getword implementation
*/
int
getword1(char *line, int wno, char *word)
{
int i;
char *p1, *p2;
for (i = 0, p1 = line; i < wno; i++)
if ((p2 = strchr(p1, PIPE)) == NULL)
break;
else
p1 = ++p2; /* start looking from next field */
if (i != wno)
return -1;
/*
* we have looked at wno-1 separators (wno-1 words), p1 points
* at beginnig of wno'th word; find end of wno'th word
*/
if ((p2 = strchr(p1, PIPE)) == NULL) { /* was the last word in line */
strcpy(word, p1);
i = strlen(word);
word[i - 1] = '\0'; /* get rid of '\n' */
} else {
*p2 = NULL; /* will repair after copying */
strcpy(word, p1);
*p2 = PIPE;
}
return 0;
}
void
fillhostinfo(amr_t *amr, int hostlen, char *host)
{
struct hostent *hent;
char hostname[MAXHOSTNAMELEN + 1];
char **p;
int i;
if (gethostname (hostname, MAXHOSTNAMELEN) != 0) {
perror("gethostname");
exit(-1);
}
i = 0;
while (1) {
hent = gethostbyname(hostname);
if (hent != NULL)
break;
if (h_errno == TRY_AGAIN) {
printf("TRY_AGAIN for gethostbyname()\n");
i++;
if (i > 3) {
herror(hostname);
errorexit(hostname, "Failed after 3 tries");
}
continue;
} else { /* some irrecorverable error */
herror(hostname);
exit(-1);
}
}
if (amr) {
amr->hostnamelen = strlen(hent->h_name) + 1;
amr->hostname = malloc(amr->hostnamelen);
strcpy(amr->hostname, hent->h_name);
} else {
hostlen = strlen(hent->h_name) + 1;
strcpy(host, hent->h_name);
}
}
int
compare_by_hostname(const void *amr1, const void *amr2)
{
return(strcmp(((amr_t *) amr1)->hostname, ((amr_t *) amr2)->hostname));
}
int
compare_by_prev_starts(const void *amr1, const void *amr2)
{
if (((amr_t *) amr1)->prevstarttime < ((amr_t *) amr2)->prevstarttime)
return -1;
else if (((amr_t *) amr1)->prevstarttime > ((amr_t *) amr2)->prevstarttime)
return 1;
else if (((amr_t *) amr1)->starttime < ((amr_t *) amr2)->starttime)
return -1;
else if (((amr_t *) amr1)->starttime > ((amr_t *) amr2)->starttime)
return 1;
else if (((amr_t *) amr1)->regist == 2)
return -1;
else if (((amr_t *) amr2)->regist == 2)
return 1;
else {
fprintf(stderr, "Warning: Duplicate records with the same prestart"
" time and start time");
printamr((amr_t *) amr1);
printamr((amr_t *) amr2);
((amr_t *) amr1)->regist = 2;
dupepochs++;
return 0;
}
}
void
setindex(amr_t *amrs, int n)
{
int i, j;
for (i = 0, j = 1; i < n - 1; i++)
if (strcmp(amrs[i].hostname, amrs[i+1].hostname) != 0)
samrs[j++] = &amrs[i+1];
samrs[j] = &amrs[n]; /* this pointer is not valid, but marks just past
* the end of the amrs array
*/
nsamrs = j;
}
void
sort_by_hosts(amr_t *amrs, int *n)
{
int i, j, dup;
amr_t *b, *e;
qsort(amrs, *n, sizeof(amr_t), compare_by_hostname);
samrs[0] = &amrs[0];
setindex(amrs, *n);
/* make sure that records for a given host are sorted */
for (i = 0; i < nsamrs; i++)
qsort(samrs[i], samrs[i+1] - samrs[i] /* pointer arithmetic */,
sizeof(amr_t), compare_by_prev_starts);
if (dupepochs) {
dup = 0;
for (i = 0, j = 0; i < *n; i++)
if (amrs[i].regist == 2)
dup = 1;
else if (dup)
amrs[j++] = amrs[i];
else
j++;
*n = j;
setindex(amrs, *n);
}
}
char
getchoice(char *prompt, char *choices)
{
char c;
if (!outistty) /* non-interactive invocation */
return(choices[0]);
printw("\n\n");
while (1) {
printw("%s [%s] ? ", prompt, choices);
c = getkey();
if (c == '\n' || c == ' ')
return(choices[0]);
if (strchr (choices, c))
return c;
beep();
}
}
void
initstat(availstat_t *s)
{
int i;
for (i = 0; i < ev_num; i++)
s->nev[i] = s->evuptime[i] = s->evdntime[i] = 0;
for (i = 0; i < NSTATS; i++)
s->nstat[i] = s->stuptime[i] = s->stdntime[i] = 0;
s->total = 0;
s->upleast = MAXINT;
s->upmost = 0;
s->dnleast = MAXINT;
s->dnmost = 0;
s->thisepoch = 0;
s->possibleuptime = 0;
s->nepochs = 0;
}
void
collect_stats(amr_t *amrs, int n, availstat_t *s)
{
int i, u = 0, d = 0, ev, offtime = 0, t, pre = -1, lessdntime = 0;
FILE tmp;
amr_t *amr;
initstat(s);
s->sysid = amrs[0].sysid;
s->hostname = amrs[0].hostname;
for (i = 0; i < n; i++) {
ev = amrs[i].event;
s->nev[ev]++;
if (ev <= ev_registration && ev >= ev_status_report)
continue;
if (pre >= 0) {
if (amrs[i].regist <= 0) {
if (amrs[i].prevstarttime < amrs[pre].starttime)
offtime += amrs[i].prevstarttime - amrs[pre].starttime;
} else if (amrs[i].regist == 1) {
if (amrs[pre].regist == -1) {
offtime += amrs[i].prevstarttime - amrs[pre].eventtime;
} else {
fprintf(stderr, "Error: re-registration without "
"deregistration first.\n");
tmp = *stdout;
*stdout = *stderr;
printamr(&amrs[i]);
*stdout = tmp;
if (amrs[i].prevstarttime < amrs[pre].starttime)
offtime += amrs[i].prevstarttime - amrs[pre].starttime;
}
pre = -1;
continue;
} else /* if (amrs[i].regist == 2) ---> duplicate */
continue;
} else if (amrs[i].regist > 0)
continue;
if (amrs[i].uptime < 0) {
t = amrs[i].starttime - amrs[i].prevstarttime - 60;
amrs[i].uptime = (t < 30) ? 0 : ((t + 30) / 60);
amrs[i].dntime = 1;
}
if (amrs[i].regist < 0)
amrs[i].dntime = 0;
if (amrs[i].regist <= 0) {
u++;
s->evuptime[ev] += amrs[i].uptime;
s->total += amrs[i].uptime;
if (amrs[i].uptime < s->upleast)
s->upleast = amrs[i].uptime;
if (amrs[i].uptime > s->upmost)
s->upmost = amrs[i].uptime;
}
if (amrs[i].regist >= 0) {
d++;
s->evdntime[ev] += amrs[i].dntime;
if (amrs[i].dntime < s->dnleast)
s->dnleast = amrs[i].dntime;
if (amrs[i].dntime > s->dnmost)
s->dnmost = amrs[i].dntime;
}
pre = i;
}
/*
* Fix for Bug # 668431 (sri), amreport shows bogus numbers :
*
* Problem : If the last event recorded is a live event which
* doesn't have a START time, then, the value of
* s->lastboot is being set to 0. This is resulting
* in a huge time value (Jan 1 1970).
* Fix : Added a check to see if the last event recorded
* is a live event. In such cases, we take the
* PREVSTART value as s->lastboot.
* Since the event is a live event, machine actually
* booted up at PREVSTART time.
* Testing : Tested it on customer provided availlog files and
* some of my own combinations.
*
*/
if (amrs[n-1].regist >= 0) {
s->lastboot = amrs[n-1].starttime;
if ( s->lastboot <= 0 ) {
switch(amrs[n-1].event) {
case ev_registration:
if ( amrs[n-1].eventtime >= 0 ) {
s->lastboot = amrs[n-1].eventtime;
} else {
s->lastboot = amrs[n-1].prevstarttime;
}
break;
case ev_livenotification:
case ev_no_error:
case ev_hardware_error:
case ev_software_error:
case ev_status_report:
s->lastboot = amrs[n-1].prevstarttime;
break;
}
}
} else {
s->lastboot = amrs[n-1].eventtime;
}
amr = &amrs[0];
if (fromtime && fromtime > amr->prevstarttime) {
s->thebeginning = fromtime;
if (amr->eventtime > 0) {
if (fromtime > amr->eventtime) {
s->evdntime[amr->event] -=
(fromtime - amr->eventtime + 30) / 60;
s->evuptime[amr->event] -= amr->uptime;
s->total -= amr->uptime;
} else {
s->evuptime[amr->event] -=
(fromtime - amr->prevstarttime + 30) / 60;
s->total -= (fromtime - amr->prevstarttime + 30) / 60;
}
} else if (fromtime - amr->prevstarttime > amr->uptime * 60) {
s->evdntime[amr->event] -=
(fromtime - amr->prevstarttime + 30) / 60 - amr->uptime;
s->evuptime[amr->event] -= amr->uptime;
s->total -= amr->uptime;
} else {
s->evuptime[amr->event] -=
(fromtime - amr->prevstarttime + 30) / 60;
s->total -= (fromtime - amr->prevstarttime + 30) / 60;
}
} else {
s->thebeginning = amr->prevstarttime;
}
amr = &amrs[n - 1];
if (totime) {
if (amr->regist < 0) {
if (amr->eventtime < totime) {
s->possibleuptime = (s->lastboot - s->thebeginning - offtime
+ 30) / 60;
s->nepochs = u;
} else {
s->possibleuptime = (totime - s->thebeginning - offtime + 30)
/ 60;
s->nepochs = u;
}
} else {
s->possibleuptime = (totime - s->thebeginning - offtime + 30) / 60;
s->nepochs = u;
if (amr->eventtime > 0) {
if (totime > amr->eventtime) {
s->evdntime[amr->event] -=
(amr->starttime - totime + 30) / 60;
} else {
s->evdntime[amr->event] -= amr->dntime;
s->evuptime[amr->event] -=
(amr->eventtime - totime + 30) / 60;
s->total -= (amr->eventtime - totime + 30) / 60;
}
} else if (totime - amr->prevstarttime > amr->uptime * 60) {
s->evdntime[amr->event] -= (amr->starttime - totime + 30) / 60;
} else {
s->evdntime[amr->event] -= amr->dntime;
s->evuptime[amr->event] -=
amr->uptime - (totime - amr->prevstarttime + 30) / 60;
s->total -=
amr->uptime - (totime - amr->prevstarttime + 30) / 60;
}
}
} else if (countthisepoch && amr->regist >= 0) {
s->thisepoch = (now - s->lastboot + 30)/60;
if (amr->regist > 0)
amr->uptime = s->thisepoch;
s->total += s->thisepoch;
if (s->thisepoch < s->upleast)
s->upleast = s->thisepoch;
if (s->thisepoch > s->upmost)
s->upmost = s->thisepoch;
s->nepochs = u + 1; /* +1 for thisepoch */
s->possibleuptime = (now - s->thebeginning - offtime + 30) / 60;
} else {
s->possibleuptime = (s->lastboot - s->thebeginning - offtime + 30) / 60;
s->nepochs = u;
}
s->ndowns = d;
s->nstat[1] = s->nev[ev_hardware_panic];
s->nstat[2] = s->nev[ev_software_panic];
s->nstat[3] = s->nev[ev_panic];
s->nstat[4] = s->nev[ev_interrupt] + s->nev[ev_system_off] + s->nev[ev_nmi]
+ s->nev[ev_reset] + s->nev[ev_pwer_cycle];
s->nstat[5] = s->nev[ev_power_failure];
s->nstat[0] = s->nstat[1] + s->nstat[2] + s->nstat[3] + s->nstat[4]
+ s->nstat[5];
s->nstat[7] = s->nev[ev_reboot_replace_hw] + s->nev[ev_reboot_fix_hw]
+ s->nev[ev_single_fix_hw];
s->nstat[8] = s->nev[ev_reboot_upgrade_hw] + s->nev[ev_reboot_hw_upgrade]
+ s->nev[ev_single_hw_upgrade];
s->nstat[9] = s->nev[ev_reboot_install_sw] + s->nev[ev_reboot_sw_upgrade]
+ s->nev[ev_single_sw_upgrade];
s->nstat[10] = s->nev[ev_reboot_sw_problem] + s->nev[ev_reboot_fix_sw]
+ s->nev[ev_single_fix_sw];
s->nstat[11] = s->nev[ev_reboot_install_patch]
+ s->nev[ev_single_install_patch];
s->nstat[12] = s->nev[ev_single_admin];
s->nstat[13] = s->nev[ev_reboot_environment] + s->nev[ev_reboot_scheduled]
+ s->nev[ev_reboot_admin];
s->nstat[14] = s->nev[ev_reboot_unconfigured] + s->nev[ev_reboot_timeout]
+ s->nev[ev_reboot_unknown] + s->nev[ev_reboot_other]
+ s->nev[ev_single_timeout] + s->nev[ev_single_unconfigured];
s->nstat[6] = s->nstat[7] + s->nstat[8] + s->nstat[9] + s->nstat[10]
+ s->nstat[11] + s->nstat[12] + s->nstat[13] + s->nstat[14];
s->nstat[15] = s->nstat[0] + s->nstat[6];
s->stuptime[1] = s->evuptime[ev_hardware_panic];
s->stuptime[2] = s->evuptime[ev_software_panic];
s->stuptime[3] = s->evuptime[ev_panic];
s->stuptime[4] = s->evuptime[ev_interrupt] + s->evuptime[ev_system_off]
+ s->evuptime[ev_nmi] + s->evuptime[ev_reset]
+ s->evuptime[ev_pwer_cycle];
s->stuptime[5] = s->evuptime[ev_power_failure];
s->stuptime[0] = s->stuptime[1] + s->stuptime[2] + s->stuptime[3]
+ s->stuptime[4] + s->stuptime[5];
s->stuptime[7] = s->evuptime[ev_reboot_replace_hw]
+ s->evuptime[ev_reboot_fix_hw] + s->evuptime[ev_single_fix_hw];
s->stuptime[8] = s->evuptime[ev_reboot_upgrade_hw]
+ s->evuptime[ev_reboot_hw_upgrade]
+ s->evuptime[ev_single_hw_upgrade];
s->stuptime[9] = s->evuptime[ev_reboot_install_sw]
+ s->evuptime[ev_reboot_sw_upgrade]
+ s->evuptime[ev_single_sw_upgrade];
s->stuptime[10] = s->evuptime[ev_reboot_sw_problem]
+ s->evuptime[ev_reboot_fix_sw] + s->evuptime[ev_single_fix_sw];
s->stuptime[11] = s->evuptime[ev_reboot_install_patch]
+ s->evuptime[ev_single_install_patch];
s->stuptime[12] = s->evuptime[ev_single_admin];
s->stuptime[13] = s->evuptime[ev_reboot_environment]
+ s->evuptime[ev_reboot_scheduled]
+ s->evuptime[ev_reboot_admin];
s->stuptime[14] = s->evuptime[ev_reboot_unconfigured]
+ s->evuptime[ev_reboot_timeout]
+ s->evuptime[ev_reboot_unknown] + s->evuptime[ev_reboot_other]
+ s->evuptime[ev_single_timeout]
+ s->evuptime[ev_single_unconfigured];
s->stuptime[6] = s->stuptime[7] + s->stuptime[8] + s->stuptime[9]
+ s->stuptime[10] + s->stuptime[11] + s->stuptime[12]
+ s->stuptime[13] + s->stuptime[14];
s->stuptime[15] = s->stuptime[0] + s->stuptime[6];
s->stdntime[1] = s->evdntime[ev_hardware_panic];
s->stdntime[2] = s->evdntime[ev_software_panic];
s->stdntime[3] = s->evdntime[ev_panic];
s->stdntime[4] = s->evdntime[ev_interrupt] + s->evdntime[ev_system_off]
+ s->evdntime[ev_nmi] + s->evdntime[ev_reset]
+ s->evdntime[ev_pwer_cycle];
s->stdntime[5] = s->evdntime[ev_power_failure];
s->stdntime[0] = s->stdntime[1] + s->stdntime[2] + s->stdntime[3]
+ s->stdntime[4] + s->stdntime[5];
s->stdntime[7] = s->evdntime[ev_reboot_replace_hw]
+ s->evdntime[ev_reboot_fix_hw] + s->evdntime[ev_single_fix_hw];
s->stdntime[8] = s->evdntime[ev_reboot_upgrade_hw]
+ s->evdntime[ev_reboot_hw_upgrade]
+ s->evdntime[ev_single_hw_upgrade];
s->stdntime[9] = s->evdntime[ev_reboot_install_sw]
+ s->evdntime[ev_reboot_sw_upgrade]
+ s->evdntime[ev_single_sw_upgrade];
s->stdntime[10] = s->evdntime[ev_reboot_sw_problem]
+ s->evdntime[ev_reboot_fix_sw] + s->evdntime[ev_single_fix_sw];
s->stdntime[11] = s->evdntime[ev_reboot_install_patch]
+ s->evdntime[ev_single_install_patch];
s->stdntime[12] = s->evdntime[ev_single_admin];
s->stdntime[13] = s->evdntime[ev_reboot_environment]
+ s->evdntime[ev_reboot_scheduled]
+ s->evdntime[ev_reboot_admin];
s->stdntime[14] = s->evdntime[ev_reboot_unconfigured]
+ s->evdntime[ev_reboot_timeout]
+ s->evdntime[ev_reboot_unknown] + s->evdntime[ev_reboot_other]
+ s->evdntime[ev_single_timeout]
+ s->evdntime[ev_single_unconfigured];
s->stdntime[6] = s->stdntime[7] + s->stdntime[8] + s->stdntime[9]
+ s->stdntime[10] + s->stdntime[11] + s->stdntime[12]
+ s->stdntime[13] + s->stdntime[14];
s->stdntime[15] = s->stdntime[0] + s->stdntime[6];
}
void
aggregatestats(availstat_t *as, int n, availstat_t *result, char *upleasthost,
char *upmosthost, char *dnleasthost, char *dnmosthost)
{
int i, j;
initstat(result);
for (i = 0; i < n; i++) {
for (j = 0; j < ev_num; j++) {
result->nev[j] += as[i].nev[j];
result->evuptime[j] += as[i].evuptime[j];
result->evdntime[j] += as[i].evdntime[j];
}
for (j = 0; j < NSTATS; j++) {
result->nstat[j] += as[i].nstat[j];
result->stuptime[j] += as[i].stuptime[j];
result->stdntime[j] += as[i].stdntime[j];
}
if (as[i].nepochs) {
if (as[i].upleast < result->upleast) {
result->upleast = as[i].upleast;
strcpy(upleasthost, as[i].hostname);
}
if (as[i].upmost > result->upmost) {
result->upmost = as[i].upmost;
strcpy(upmosthost, as[i].hostname);
}
}
if (as[i].ndowns) {
if (as[i].dnleast < result->dnleast) {
result->dnleast = as[i].dnleast;
strcpy(dnleasthost, as[i].hostname);
}
if (as[i].dnmost > result->dnmost) {
result->dnmost = as[i].dnmost;
strcpy(dnmosthost, as[i].hostname);
}
}
result->total += as[i].total;
result->possibleuptime += as[i].possibleuptime;
result->nepochs += as[i].nepochs;
result->ndowns += as[i].ndowns;
}
}
#define highlight(s) standout(); printw(s); standend()
#define printkey(k, c) standout(); printw(k); standend(); printw(c)
int
showoverall(char *upleasthost, char *upmosthost, char *dnleasthost,
char *dnmosthost)
{
int i;
availstat_t *s = &availstats[nsamrs];
float ftotal, fpossible;
char temp[MAXHOSTNAMELEN+64];
loop:
clear();
ftotal = s->total;
fpossible = s->possibleuptime;
strcpy(temp, "OVERALL SUMMARY");
prettyshow_centered(temp, EQUALS, 1);
printw("Machines Recorded .............. %d\n", nsamrs);
printw(" Count Downtime MTBI Availability\n");
for (i = 0; i < NSTATS; i++) {
if (s->nstat[i]) {
printw("%s %5d %6d %7d", statname[i], s->nstat[i],
s->stdntime[i], s->possibleuptime / s->nstat[i]);
if (i == 0 || i == 6 || i == 15)
printw(" %3.2f\n",
(fpossible - s->stdntime[i]) / fpossible * 100.0);
else
printw("\n");
}
}
/*
* print out count, uptime, and downtime for each event
*
for (i = 1; i < ev_num; i++)
if (s->nev[i])
printw("%4d %6d %5d %s\n", s->nev[i], s->evuptime[i],
s->evdntime[i], eventname[i]);
*/
printw("\nAverage Uptime ................. %s\n",
pretty_minutes(s->total/s->nepochs, temp));
printw("Least Uptime ................... %s\n", pretty_minutes(s->upleast, temp));
printw(" Recorded at .............. %s\n", upleasthost);
printw("Most Uptime .................... %s\n", pretty_minutes(s->upmost, temp));
printw(" Recorded at .............. %s\n", upmosthost);
if (s->ndowns) {
printw("Average Downtime ............... %s\n",
pretty_minutes((s->possibleuptime - s->total) / s->ndowns, temp));
printw("Least Downtime ................. %s\n", pretty_minutes(s->dnleast, temp));
printw(" Recorded at .............. %s\n", dnleasthost);
printw("Most Downtime .................. %s\n", pretty_minutes(s->dnmost, temp));
printw(" Recorded at .............. %s\n", dnmosthost);
}
printw("Availability ................... %3.2f%% based on %d machines\n",
(ftotal/fpossible) * 100.0, nsamrs);
prettyshow_centered("=", EQUALS, 0); /* print 80 char '=' line */
refresh();
move(LINES - 1, 0);
printkey("<SPACE>", ":stat list ");
printkey("<RETURN>", ":stat list ");
printkey("V", ":stat list ");
printkey("Q", ":quit ");
refresh();
while (1)
switch (getkey()) {
case KEY_ENTER:
case '\n':
case ' ':
case 'V':
case 'v':
if (showstatlist() == 'q')
return 'q';
else
goto loop;
case 'Q':
case 'q':
return 'q';
default:
beep();
}
}
#define STATTOP 2
int
showstatlist()
{
int i, j;
availstat_t *s = &availstats[0];
availstat_t *stat_b, *stat_e, *stat_t, *stat;
int row, entry, begin, end, num;
int top, numshow, perc;
stat_t = stat_b = &availstats[0];
stat_e = &availstats[nsamrs];
top = begin = 0;
num = end = nsamrs;
numshow = LINES - 7;
if (numshow > num)
numshow = num;
loop:
clear();
standout();
printw("SERIAL NUMBER HOSTNAME UNSCHEDULED SEVICE"
" TOTAL \n\n");
standend();
refresh();
move(LINES - 2, 0);
printkey("A", ":mark all ");
printkey("C", ":unmark all ");
printkey("M", ":mark ");
printkey("U", ":unmark ");
printkey("V", ":view marked entries\n");
printkey("J", ":up ");
printkey("K", ":down ");
printkey("<UP>", ":up ");
printkey("<DOWN>", ":down ");
printkey("N", ":next page ");
printkey("P", ":prev page ");
printkey("B", ":back ");
printkey("Q", ":quit ");
refresh();
show:
for (i = 0, stat = stat_t; i < numshow && stat < stat_e; i++, stat++) {
move(i + STATTOP, 0);
showstatline(stat);
}
if (num <= numshow)
printw("\n-- ALL --");
else if (stat == stat_e)
printw("\n-- BOTTOM --");
else {
perc = (stat - stat_b) * 100 / num;
if (stat_t == stat_b)
printw("\n-- TOP %d%%", perc);
else
printw("\n-- %d%%", perc);
}
row = STATTOP;
entry = top;
move(row, 0);
while (1)
switch (getkey()) {
case 'A':
case 'a':
move(STATTOP, 0);
for (j = begin; j < end; j++)
statmarks[j] = 1;
goto show;
case 'C':
case 'c':
move(STATTOP, 0);
for (j = begin; j < end; j++)
statmarks[j] = 0;
goto show;
case 'M':
case 'm':
statmarks[entry] = 1;
showstatline(&availstats[entry]);
row++;
entry++;
if (row >= numshow + STATTOP) {
row = STATTOP;
entry = top;
move(row, 0);
}
break;
case 'U':
case 'u':
statmarks[entry] = 0;
showstatline(&availstats[entry]);
row++;
entry++;
if (row >= numshow + STATTOP) {
row = STATTOP;
entry = top;
move(row, 0);
}
break;
case 'V':
case 'v':
if (showstats() == 'q')
return 'q';
else
goto loop;
case 'K':
case 'k':
case KEY_UP:
row--;
entry--;
if (row < STATTOP) {
row = numshow + STATTOP - 1;
entry = top + numshow - 1;
}
move(row, 0);
break;
case 'J':
case 'j':
case KEY_DOWN:
row++;
entry++;
if (row >= numshow + STATTOP) {
row = STATTOP;
entry = top;
}
move(row, 0);
break;
case ' ':
case '\n':
case KEY_ENTER:
case 'N':
case 'n':
if (num > numshow) {
if (top + numshow >= end) {
top = begin;
stat_t = stat_b;
} else {
top += numshow;
stat_t += numshow;
}
goto loop;
} else
break;
case 'P':
case 'p':
if (num > numshow) {
if (top == begin) {
top = end - numshow;
stat_t = stat_e - numshow;
} else if (top - numshow <= begin) {
top = begin;
stat_t = stat_b;
} else {
top -= numshow;
stat_t -= numshow;
}
goto loop;
} else
break;
case 'B':
case 'b':
return 'b';
case 'Q':
case 'q':
return 'q';
default:
beep();
}
}
void
showstatline(availstat_t *s)
{
int hilite;
float ftotal, fpossible;
char temp[MAXHOSTNAMELEN+64];
hilite = statmarks[s - availstats];
if (hilite)
standout();
ftotal = s->total;
fpossible = s->possibleuptime;
strcpy(temp, s->hostname); temp[20] = '\0';
printw("%-12s %-20s ", s->sysid, temp);
if (s->nstat[0])
printw("%5d %6.2f%% ", s->nstat[0],
(fpossible - s->stdntime[0]) / fpossible * 100.0);
else
printw("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[6])
printw("%5d %6.2f%% ", s->nstat[6],
(fpossible - s->stdntime[6]) / fpossible * 100.0);
else
printw("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[15])
printw("%5d %6.2f%%\n", s->nstat[15],
(fpossible - s->stdntime[15]) / fpossible * 100.0);
else
printw("%5d %6.2f%%\n", 0, 100.0);
if (hilite)
standend();
}
int
showstats()
{
int i, begin, end;
begin = 0;
end = nsamrs;
for (i = begin; i < end; i++) {
if (statmarks[i] == 0)
continue;
loop:
clear();
showstat(&availstats[i]);
if (locallog) {
move(LINES - 1, 0);
printkey("<SPACE>", ":amr list ");
printkey("<RETURN>", ":amr list ");
printkey("V", ":amr list ");
printkey("Q", ":quit ");
refresh();
while (1)
switch (getkey()) {
case KEY_ENTER:
case '\n':
case ' ':
case 'V':
case 'v':
if (showamrlist(0) == 'q')
return 'q';
else
goto loop;
case 'Q':
case 'q':
return 'q';
default:
beep();
}
} else {
move(LINES - 2, 0);
printkey("<SPACE>", ":next ");
printkey("<RETURN>", ":next ");
printkey("N", ":next ");
printkey("V", ":amr list ");
printkey("P", ":previous ");
printkey("B", ":back ");
printkey("Q", ":quit ");
refresh();
while (1)
switch (getkey()) {
case KEY_ENTER:
case '\n':
case ' ':
case 'N':
case 'n':
goto out;
case 'P':
case 'p':
for (i--; i >= begin; i--)
if (statmarks[i])
goto loop;
return 'b';
case 'V':
case 'v':
if (showamrlist(i) == 'q')
return 'q';
else
goto loop;
case 'B':
case 'b':
return 'b';
case 'Q':
case 'q':
return 'q';
default:
beep();
}
out:
if (i == end - 1)
return 'b';
}
}
return 'b';
}
void
showstat(availstat_t *s)
{
int i;
float ftotal, fpossible;
char temp[MAXHOSTNAMELEN+64];
ftotal = s->total;
fpossible = s->possibleuptime;
sprintf(temp, "SUMMARY for %s", s->hostname);
prettyshow_centered(temp, EQUALS, 1);
printw(" Count Downtime MTBI Availability\n");
for (i = 0; i < NSTATS; i++) {
if (s->nstat[i]) {
printw("%s %5d %6d %7d", statname[i], s->nstat[i],
s->stdntime[i], s->possibleuptime / s->nstat[i]);
if (i == 0 || i == 6 || i == 15)
printw(" %3.2f\n",
(fpossible - s->stdntime[i]) / fpossible * 100.0);
else
printw("\n");
}
}
/*
* print out count, uptime, and downtime for each event
*
for (i = 0; i < ev_num; i++)
if (s->nev[i])
printw("%4d %6d %5d %s\n", s->nev[i], s->evuptime[i],
s->evdntime[i], eventname[i]);
*/
printw("\n%s %s\n", "Average Uptime .................",
pretty_minutes(s->total/s->nepochs, temp));
printw("Least Uptime ................... %s %s\n", pretty_minutes(s->upleast, temp),
(s->thisepoch == s->upleast) ? "(current epoch)":"");
printw("Most Uptime .................... %s %s\n", pretty_minutes(s->upmost, temp),
(s->thisepoch == s->upmost) ? "(current epoch)":"");
if (s->ndowns) {
printw("Average Downtime ............... %s\n",
pretty_minutes((s->possibleuptime - s->total) / s->ndowns, temp));
printw("Least Downtime ................. %s %s\n", pretty_minutes(s->dnleast, temp),
(s->thisepoch == s->dnleast) ? "(current epoch)":"");
printw("Most Downtime .................. %s %s\n", pretty_minutes(s->dnmost, temp),
(s->thisepoch == s->dnmost) ? "(current epoch)":"");
}
/* printw("Availability ................... %3.2f%%\n", (ftotal/fpossible) * 100.0); */
printw("\nLogging started at ............. %s", ctime(&(s->thebeginning)));
i = s - availstats;
if ((samrs[i + 1] - 1)->regist < 0)
printw("Deregistered at ................ %s", ctime(&(s->lastboot)));
else {
printw("Last boot at ................... %s", ctime(&(s->lastboot)));
if (countthisepoch)
printw("System has been up for ......... %s\n",
pretty_minutes(s->thisepoch, temp));
}
prettyshow_centered("=", EQUALS, 0); /* print 80 char '=' line */
refresh();
}
void
prettyshow_centered(char *s, char c, int spaces)
{
int slen, lflen, rflen, i;
char obuf[REPORT_WIDTH], *p;
slen = strlen(s);
if (slen >= (REPORT_WIDTH - 5)) {
printw("<%s>\n", s);
return;
}
lflen = (REPORT_WIDTH - (spaces ? 2 : 0) - slen)/2;
rflen = (REPORT_WIDTH - (spaces ? 2 : 0) - slen) - lflen;
p = obuf;
for (i = 0; i < lflen; i++)
*p++ = c;
if (spaces) {
sprintf(p, " %s ", s);
p += (slen + 2);
} else {
sprintf(p, "%s", s);
p += slen;
}
for (i = 0; i < rflen; i++)
*p++ = c;
*p = NULL;
printw("%s\n", obuf);
}
void
waitforenter(char *msg) /* debugging: to stop output stream */
{
char linebuf[LINELEN+1], c;
if (!outistty) return;
printw("%s", msg);
refresh();
getret();
/* fgets(linebuf, LINELEN, stdin); */
}
#define AMRTOP 3
int
showamrlist(int mach)
{
int row, i, j, entry, begin, end, num;
int top, numshow, perc;
char hostname[MAXHOSTNAMELEN+1];
amr_t *amr, *amrb, *amre, *amrt;
amrt = amrb = samrs[mach];
amre = samrs[mach + 1];
top = begin = amrb - amrs;
end = amre - amrs;
num = end - begin;
if (num == 0) {
clear();
printw("\nNo shutdown report\n\nPress any key to continue.\n");
getkey();
return 'b';
}
numshow = LINES - 4 - AMRTOP;
if (numshow > num)
numshow = num;
loop:
clear();
prettyshow_centered(amrs[begin].hostname, DASH, 1);
standout();
printw(" Start Time Incident Time UpTm DnTm"
" Reason ");
standend();
refresh();
move(LINES - 2, 0);
printkey("A", ":mark all ");
printkey("C", ":unmark all ");
printkey("M", ":mark ");
printkey("U", ":unmark ");
printkey("V", ":view ");
printkey("S", ":send\n");
printkey("J", ":up ");
printkey("K", ":down ");
printkey("<UP>", ":up ");
printkey("<DOWN>", ":down ");
printkey("N", ":next page ");
printkey("P", ":prev page ");
printkey("B", ":back ");
printkey("Q", ":quit ");
refresh();
show:
for (i = 0, amr = amrt; i < numshow && amr < amre; i++, amr++) {
move(i + AMRTOP, 0);
showamrline(amr);
}
if (num <= numshow)
printw("\n-- ALL --");
else if (amr == amre)
printw("\n-- BOTTOM --");
else {
perc = (amr - amrb) * 100 / num;
if (amrt == amrb)
printw("\n-- TOP %d%%", perc);
else
printw("\n-- %d%%", perc);
}
row = AMRTOP;
entry = top;
move(row, 0);
while (1)
switch (getkey()) {
case 'A':
case 'a':
move(AMRTOP, 0);
for (j = begin; j < end; j++)
amrmarks[j] = 1;
goto show;
case 'C':
case 'c':
move(AMRTOP, 0);
for (j = begin; j < end; j++)
amrmarks[j] = 0;
goto show;
case 'M':
case 'm':
amrmarks[entry] = 1;
showamrline(&amrs[entry]);
row++;
entry++;
if (row >= numshow + AMRTOP) {
row = AMRTOP;
entry = top;
move(row, 0);
}
break;
case 'U':
case 'u':
amrmarks[entry] = 0;
showamrline(&amrs[entry]);
row++;
entry++;
if (row >= numshow + AMRTOP) {
row = AMRTOP;
entry = top;
move(row, 0);
}
break;
case 'V':
case 'v':
if (showamrs(begin, end) == 'q')
return 'q';
else
goto loop;
case 'S':
case 's':
sendamrs(begin, end);
goto loop;
case 'K':
case 'k':
case KEY_UP:
row--;
entry--;
if (row < AMRTOP) {
row = numshow + AMRTOP - 1;
entry = top + numshow - 1;
}
move(row, 0);
break;
case 'J':
case 'j':
case KEY_DOWN:
row++;
entry++;
if (row >= numshow + AMRTOP) {
row = AMRTOP;
entry = top;
}
move(row, 0);
break;
case ' ':
case '\n':
case KEY_ENTER:
case 'N':
case 'n':
if (num > numshow) {
if (top + numshow >= end) {
top = begin;
amrt = amrb;
} else {
top += numshow;
amrt += numshow;
}
goto loop;
} else
break;
case 'P':
case 'p':
if (num > numshow) {
if (top == begin) {
top = end - numshow;
amrt = amre - numshow;
} else if (top - numshow <= begin) {
top = begin;
amrt = amrb;
} else {
top -= numshow;
amrt -= numshow;
}
goto loop;
} else
break;
case 'B':
case 'b':
return 'b';
case 'Q':
case 'q':
return 'q';
default:
beep();
}
}
void
showamrline(amr_t *amr)
{
int hilite;
char tmp1[30], tmp2[30];
time_t t;
hilite = amrmarks[amr - amrs];
if (hilite)
standout();
if (amr->noprevstart) {
tmp1[0] = '\0';
} else {
strcpy(tmp1, ctime(&(amr->prevstarttime)));
tmp1[24] = '\0';
}
if (amr->eventtime > 0) {
tmp2[0] = ' ';
strcpy(tmp2 + 1, ctime(&(amr->eventtime)));
tmp2[25] = '\0';
} else {
tmp2[0] = '*';
t = amr->prevstarttime + amr->uptime * 60;
strcpy(tmp2 + 1, ctime(&t));
tmp2[25] = '\0';
}
printw("%-24s %-25s ", tmp1, tmp2);
if ((amr->event > ev_deregistration || amr->event < ev_status_report)
&& amr->event != ev_livenotification)
printw("%6d %5d ", amr->uptime, amr->dntime);
else
printw(" - - ");
printw("%s\n", shorteventname[amr->event]);
if (hilite)
standend();
}
char
showamrs(int begin, int end)
{
int i;
for (i = begin; i < end; i++) {
if (amrmarks[i] == 0)
continue;
loop:
clear();
showamr(&amrs[i]);
move(LINES - 2, 0);
printkey("<SPACE>", ":next ");
printkey("<RETURN>", ":next ");
printkey("N", ":next ");
printkey("P", ":previous ");
printkey("B", ":back ");
printkey("Q", ":quit ");
refresh();
while (1)
switch (getkey()) {
case KEY_ENTER:
case '\n':
case ' ':
case 'N':
case 'n':
goto out;
case 'P':
case 'p':
for (i--; i >= begin; i--)
if (amrmarks[i])
goto loop;
return 'b';
case 'B':
case 'b':
return 'b';
case 'Q':
case 'q':
return 'q';
default:
beep();
}
out:
if (i == end - 1)
return 'b';
}
return 'b';
}
void
showamr(amr_t *amr)
{
char s[128], hostname[MAXHOSTNAMELEN+1];
time_t t;
prettyshow_centered(amr->hostname, DASH, 1);
printw("Internet address ....... %s\n", amr->hostname);
printw("Reason for shutdown .... %s\n", eventname[amr->event]);
printw("Start time ............. %s", ctime(&(amr->prevstarttime)));
printw("Incident time .......... ");
if (amr->eventtime > 0) {
printw("%s", ctime(&(amr->eventtime)));
} else {
t = amr->prevstarttime + amr->uptime * 60;
printw("around %s", ctime(&t));
}
if ((amr->event > ev_deregistration || amr->event < ev_status_report)
&& amr->event != ev_livenotification) {
printw("Re-start time .......... %s", ctime(&(amr->starttime)));
printw("Uptime ................. %s\n", pretty_minutes(amr->uptime, s));
printw("Downtime ............... %s\n", pretty_minutes(amr->dntime, s));
}
if (amr->summarylen)
printw("Incident summary ....... \n%s\n", amr->summary);
prettyshow_centered("-", DASH, 0); /* print 80 char '-' line */
refresh();
}
/*
* Edit the email list configuration file
*/
void
editaddresses()
{
int pid, s, t;
FILE *fp, *fp1;
char *edit = "/usr/bin/vi";
void (*sig)(), (*scont)(), signull();
sig = sigset(SIGINT, SIG_IGN);
/* fork an editor on the message */
pid = fork();
if (pid == 0) {
/* CHILD - exec the editor. */
if (sig != SIG_IGN)
signal(SIGINT, SIG_DFL);
execl(edit, edit, cfile, 0);
perror(edit);
exit(1);
}
if (pid == -1) {
/* ERROR - issue warning and get out. */
perror("fork");
unlink(cfile);
goto out;
}
/* PARENT - wait for the child (editor) to complete. */
while (wait(&s) != pid)
;
/* Check the results. */
if ((s & 0377) != 0)
printf("Fatal error in \"%s\"\n", edit);
out:
sigset(SIGINT, sig);
}
int
getaddresses()
{
int len;
FILE *fp, *fp1;
char line[MAX_LINE_LEN];
if (cfile == NULL) {
if ((cfile = tempnam(NULL, "amrc")) == NULL) {
fprintf(stderr, "Error: cannot create temp file name\n");
exit(1);
}
if ((fp = fopen(cfile, "w")) == NULL) {
fprintf(stderr, "Error: cannot create temp file\n");
exit(1);
}
if ((fp1 = fopen(amcs[amc_autoemaillist].filename, "r")) == NULL) {
fprintf(stderr, "Error: cannot open file autoemail.list\n");
exit(1);
}
len = strlen(sendtypestr[PAGERTYPE]);
while (fgets(line, MAX_LINE_LEN, fp1)) {
if (strncmp(line, sendtypestr[PAGERTYPE], len) == 0)
continue;
else
fputs(line, fp);
}
fclose(fp);
fclose(fp1);
}
loop:
if ((fp = fopen(cfile, "r")) == NULL) {
fprintf(stderr, "Error: cannot open temp file\n");
exit(1);
}
clear();
while (fgets(line, MAX_LINE_LEN, fp))
printw("%s", line);
fclose(fp);
move(LINES - 1, 0);
printkey("S", ":send ");
printkey("E", ":edit autoemail.list ");
printkey("C", ":cancel ");
while (1)
switch (getkey()) {
case 'C':
case 'c':
return(0);
case 'E':
case 'e':
editaddresses();
goto loop;
case 'S':
case 's':
return(1);
default:
beep();
}
}
void
sendamrs(int begin, int end)
{
int i, count = 0, days = 0, waitinput = 1;
char c;
time_t t;
amr_t *amr;
if (locallog == 0) {
move(LINES - 3, 0);
standout();
printw("Only using locallog can send old availmon reports."
" Press any key to continue.");
standout();
getkey();
return;
}
for (i = begin; i < end; i++)
if (amrmarks[i])
count++;
if (count == 0) {
move(LINES - 3, 0);
printw("No entry marked. Send reports since how many days ago? (30) ");
while (waitinput) {
switch(c = getkey()) {
case KEY_ENTER:
case 87: /* enter key */
case '\n':
waitinput = 0;
if (count == 0)
days = 30;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
printw("%c", c);
days = days * 10 + c - '0';
count++;
break;
case KEY_BACKSPACE:
case 8: /* backspace key */
case KEY_DC:
case 74: /* delete key */
printw("%c%c%c", c, ' ', c);
days /= 10;
count--;
break;
default:
beep();
}
}
/* get the from time */
t = time(0) - days * 86400;
for (amr = &amrs[begin]; amr < &amrs[end]; amr++) {
if (amr->prevstarttime > t) {
break;
} else if (amr->eventtime > t) {
break;
} else if (amr->starttime > t) {
break;
}
}
if (getaddresses())
for ( ; amr < &amrs[end]; amr++)
sendamr(amr);
} else {
if (getaddresses())
for (i = begin; i < end; i++) {
if (amrmarks[i])
sendamr(&amrs[i]);
}
}
}
void
sendamr(amr_t *amr)
{
char *tfn, *tfn1, fname[MAX_LINE_LEN], crashdir[MAX_LINE_LEN] = "";
char line[MAX_LINE_LEN], syscmd[MAX_LINE_LEN];
time_t etime;
FILE *fp, *fp1;
struct stat statbuf;
if (((tfn = tempnam(NULL, "amra")) == NULL) ||
((tfn1 = tempnam(NULL, "amrd")) == NULL)) {
fprintf(stderr, "Error: cannot create temp file name\n");
exit(1);
}
if (((fp = fopen(tfn, "w")) == NULL) ||
((fp1 = fopen(tfn1, "w")) == NULL)) {
fprintf(stderr, "Error: cannot create temp file\n");
exit(1);
}
fprintf(fp, "SERIALNUM|%s\n", amr->sysid);
fprintf(fp1, "SERIALNUM|%s\n", amr->sysid);
fprintf(fp, "HOSTNAME|%s\n", amr->hostname);
fprintf(fp1, "HOSTNAME|%s\n", amr->hostname);
fprintf(fp, "AMRVERSION|%s\n", AMRVERSIONNUM);
fprintf(fp1, "AMRVERSION|%s\n", AMRVERSIONNUM);
fprintf(fp, "RESEND|\n");
fprintf(fp1, "RESEND|\n");
fprintf(fp, "PREVSTART|%d|%s", amr->prevstarttime,
ctime(&(amr->prevstarttime)));
fprintf(fp1, "PREVSTART|%d|%s", amr->prevstarttime,
ctime(&(amr->prevstarttime)));
if (amr->eventtime > 0) {
etime = amr->eventtime;
strcpy(line, ctime(&etime));
} else {
etime = -1;
strcpy(line, "unknown\n");
}
fprintf(fp, "EVENT|%d|%d|%s", amr->event + MINEVENTCODE - 1, etime, line);
fprintf(fp1, "EVENT|%d|%d|%s", amr->event + MINEVENTCODE - 1, etime, line);
if (amr->lasttick > 0) {
fprintf(fp, "LASTTICK|%d|%s", amr->lasttick, ctime(&(amr->lasttick)));
fprintf(fp1, "LASTTICK|%d|%s", amr->lasttick, ctime(&(amr->lasttick)));
} else {
fprintf(fp, "LASTTICK|-1|unknown\n");
fprintf(fp1, "LASTTICK|-1|unknown\n");
}
switch (amr->event) {
case ev_no_error:
case ev_hardware_error:
case ev_software_error:
case ev_systemid_change:
break;
default:
fprintf(fp, "START|%d|%s", amr->starttime, ctime(&(amr->starttime)));
fprintf(fp1, "START|%d|%s", amr->starttime, ctime(&(amr->starttime)));
}
if (amr->summarylen) {
if (amr->event == ev_systemid_change) {
fprintf(fp, "%s", amr->summary);
fprintf(fp1, "%s", amr->summary);
}
fprintf(fp, "SUMMARY|Begin\n%sSUMMARY|End\n", amr->summary);
fprintf(fp1, "SUMMARY|Begin\n%sSUMMARY|End\n", amr->summary);
}
fclose(fp);
if (amr->bound >= 0) {
if (fp = fopen("/etc/config/savecore.options", "r")) {
while (fscanf(fp, "%s ", fname) != EOF)
if (fname[0] == '/') {
stat(fname, &statbuf);
if (S_ISDIR(statbuf.st_mode))
strcpy(crashdir, fname);
}
fclose(fp);
}
if (crashdir[0] == '\0')
strcpy(crashdir, "/var/adm/crash");
sprintf(fname, "%s/analysis.%d", crashdir, amr->bound);
if (fp = fopen(fname, "r")) {
fprintf(fp1, "ICRASH|Begin\n");
while (fgets(line, MAX_LINE_LEN, fp))
fputs(line, fp1);
fprintf(fp1, "ICRASH|End\n");
fclose(fp);
}
sprintf(fname, "%s/syslog.%d", crashdir, amr->bound);
if (fp = fopen(fname, "r")) {
fprintf(fp1, "SYSLOG|Begin\n");
while (fgets(line, MAX_LINE_LEN, fp))
fputs(line, fp1);
fprintf(fp1, "SYSLOG|End\n");
fclose(fp);
}
}
fclose(fp1);
switch (amr->event) {
case ev_no_error:
case ev_hardware_error:
case ev_software_error:
sprintf(syscmd, "/usr/etc/amnotify -c %s -d %s ; rm -f %s %s",
cfile, tfn1, tfn, tfn1);
break;
default:
sprintf(syscmd, "/usr/etc/amnotify -c %s -a %s -d %s ; rm -f %s %s",
cfile, tfn, tfn1, tfn, tfn1);
}
system(syscmd);
}
char *
pretty_minutes(int m, char *s)
{
int days, hrs, mins, tm;
char tempd[32];
char temph[32];
char tempm[32];
tm = m;
days = m / (60 * 24);
m %= (60 * 24);
hrs = m / 60;
m %= 60;
mins = m;
s[0] = tempd[0] = temph[0] = tempm[0] = NULL;
if (days)
sprintf(tempd, "%d day%s", days, (days == 1) ? "" : "s");
if (hrs)
sprintf(temph, "%s%d hr%s", (days ? " " : "") /* space */,
hrs, (hrs == 1)? "":"s");
if (mins)
sprintf(tempm, "%s%d min%s", ((days||hrs) ? " " : "") /* space */,
mins, (mins == 1)? "":"s");
if (days || hrs) /* no point in printing minutes by itself again */
sprintf(s, "%d minutes (%s%s%s)", tm, tempd, temph, tempm);
else
sprintf(s, "%d minute%s", tm, (tm == 1) ? "" : "s");
return(s);
}
void
prettyprint_centered(char *s, char c, int spaces)
{
int slen, lflen, rflen, i;
char obuf[REPORT_WIDTH], *p;
slen = strlen(s);
if (slen >= (REPORT_WIDTH - 5)) {
printf("%s\n", s);
return;
}
lflen = (REPORT_WIDTH - (spaces ? 2 : 0) - slen)/2;
rflen = (REPORT_WIDTH - (spaces ? 2 : 0) - slen) - lflen;
p = obuf;
for (i = 0; i < lflen; i++)
*p++ = c;
if (spaces) {
sprintf(p, " %s ", s);
p += (slen + 2);
} else {
sprintf(p, "%s", s);
p += slen;
}
for (i = 0; i < rflen; i++)
*p++ = c;
*p = NULL;
printf("%s\n", obuf);
}
void
printstatlist(int all)
{
availstat_t *s = &availstats[nsamrs];
availstat_t *stat_b, *stat_e, *stat;
float ftotal, fpossible;
stat_b = &availstats[0];
stat_e = &availstats[nsamrs];
if (all) {
printf("SERIAL NUMBER HOSTNAME UNSCHEDULED SEVICE"
" TOTAL\n\n");
ftotal = s->total;
fpossible = s->possibleuptime;
printf("%-33s ", "Overall Statistics");
if (s->nstat[0])
printf("%5d %6.2f%% ", s->nstat[0],
(fpossible - s->stdntime[0]) / fpossible * 100.0);
else
printf("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[6])
printf("%5d %6.2f%% ", s->nstat[6],
(fpossible - s->stdntime[6]) / fpossible * 100.0);
else
printf("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[15])
printf("%5d %6.2f%%\n\n", s->nstat[15],
(fpossible - s->stdntime[15]) / fpossible * 100.0);
else
printf("%5d %6.2f%%\n\n", 0, 100.0);
for (stat = stat_b; stat < stat_e; stat++)
printstatline(stat);
printf(" \n");
}
for (stat = stat_b; stat < stat_e; stat++)
printstat(stat);
printf(" \n");
}
void
printstatline(availstat_t *s)
{
float ftotal, fpossible;
char temp[MAXHOSTNAMELEN+64];
ftotal = s->total;
fpossible = s->possibleuptime;
strcpy(temp, s->hostname); temp[20] = '\0';
printf("%-12s %-20s ", s->sysid, temp);
if (s->nstat[0])
printf("%5d %6.2f%% ", s->nstat[0],
(fpossible - s->stdntime[0]) / fpossible * 100.0);
else
printf("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[6])
printf("%5d %6.2f%% ", s->nstat[6],
(fpossible - s->stdntime[6]) / fpossible * 100.0);
else
printf("%5d %6.2f%% ", 0, 100.0);
if (s->nstat[15])
printf("%5d %6.2f%%\n", s->nstat[15],
(fpossible - s->stdntime[15]) / fpossible * 100.0);
else
printf("%5d %6.2f%%\n", 0, 100.0);
}
void
printstat(availstat_t *s)
{
int i;
float ftotal, fpossible;
char temp[MAXHOSTNAMELEN+64];
ftotal = s->total;
fpossible = s->possibleuptime;
sprintf(temp, "SUMMARY for %s", s->hostname);
prettyprint_centered(temp, EQUALS, 1);
printf(" Count Downtime MTBI Availability\n");
for (i = 0; i < NSTATS; i++) {
if (s->nstat[i]) {
printf("%s %5d %6d %7d", statname[i], s->nstat[i],
s->stdntime[i], s->possibleuptime / s->nstat[i]);
if (i == 0 || i == 6 || i == 15)
printf(" %3.2f\n",
(fpossible - s->stdntime[i]) / fpossible * 100.0);
else
printf("\n");
}
}
/*
* print out count, uptime, and downtime for each event
*
for (i = 0; i < ev_num; i++)
if (s->nev[i])
printf("%4d %6d %5d %s\n", s->nev[i], s->evuptime[i],
s->evdntime[i], eventname[i]);
*/
printf("\n%s %s\n", "Average Uptime .................",
pretty_minutes(s->total/s->nepochs, temp));
printf("Least Uptime ................... %s %s\n", pretty_minutes(s->upleast, temp),
(s->thisepoch == s->upleast) ? "(current epoch)":"");
printf("Most Uptime .................... %s %s\n", pretty_minutes(s->upmost, temp),
(s->thisepoch == s->upmost) ? "(current epoch)":"");
if (s->ndowns) {
printf("Average Downtime ............... %s\n",
pretty_minutes((s->possibleuptime - s->total) / s->ndowns, temp));
printf("Least Downtime ................. %s %s\n", pretty_minutes(s->dnleast, temp),
(s->thisepoch == s->dnleast) ? "(current epoch)":"");
printf("Most Downtime .................. %s %s\n", pretty_minutes(s->dnmost, temp),
(s->thisepoch == s->dnmost) ? "(current epoch)":"");
}
/* printf("Availability ................... %3.2f%%\n", (ftotal/fpossible) * 100.0); */
printf("\nLogging started at ............. %s", ctime(&(s->thebeginning)));
i = s - availstats;
if ((samrs[i + 1] - 1)->regist < 0)
printf("Deregistered at ................ %s", ctime(&(s->lastboot)));
else {
printf("Last boot at ................... %s", ctime(&(s->lastboot)));
if (countthisepoch)
printf("System has been up for ......... %s\n",
pretty_minutes(s->thisepoch, temp));
}
prettyprint_centered("=", EQUALS, 0); /* print 80 char '=' line */
}
void
printamrlist(int mach)
{
int begin;
char hostname[MAXHOSTNAMELEN+1];
amr_t *amr, *amrb, *amre;
amrb = samrs[mach];
amre = samrs[mach + 1];
begin = amrb - amrs;
prettyprint_centered(amrs[begin].hostname, DASH, 1);
printf(" Start Time Incident Time UpTm DnTm"
" Reason \n");
for (amr = amrb; amr < amre; amr++)
printamrline(amr);
printf(" \n");
}
void
printamrline(amr_t *amr)
{
char tmp1[30], tmp2[30];
time_t t;
if (amr->noprevstart) {
tmp1[0] = '\0';
} else {
strcpy(tmp1, ctime(&(amr->prevstarttime)));
tmp1[24] = '\0';
}
if (amr->eventtime > 0) {
tmp2[0] = ' ';
strcpy(tmp2 + 1, ctime(&(amr->eventtime)));
tmp2[25] = '\0';
} else {
tmp2[0] = '*';
t = amr->prevstarttime + amr->uptime * 60;
strcpy(tmp2 + 1, ctime(&t));
tmp2[25] = '\0';
}
printf("%-24s %-25s ", tmp1, tmp2);
if ((amr->event > ev_deregistration || amr->event < ev_status_report)
&& amr->event != ev_livenotification)
printf("%6d %5d ", amr->uptime, amr->dntime);
else
printf(" - - ");
printf("%s\n", shorteventname[amr->event]);
}
void
printamrs(int mach)
{
int begin;
char hostname[MAXHOSTNAMELEN+1];
amr_t *amr, *amrb, *amre;
amrb = samrs[mach];
amre = samrs[mach + 1];
begin = amrb - amrs;
prettyprint_centered(amrs[begin].hostname, DASH, 1);
printf(" Start Time Incident Time UpTm DnTm"
" Reason \n");
for (amr = amrb; amr < amre; amr++)
printamr(amr);
printf(" \n");
}
void
printamr(amr_t *amr)
{
char s[128], hostname[MAXHOSTNAMELEN+1];
time_t t;
printf("\nSerial number .......... %s\n", amr->sysid);
printf("Internet address ....... %s\n", amr->hostname);
if (amr->regist > 0) {
printf("Started at ............. %s", ctime(&(amr->prevstarttime)));
printf("Registered at .......... %s", ctime(&(amr->starttime)));
} else {
printf("Reason for shutdown .... %s\n", eventname[amr->event]);
printf("Start time ............. %s", ctime(&(amr->prevstarttime)));
printf("Incident time .......... ");
if (amr->eventtime > 0)
printf("%s", ctime(&(amr->eventtime)));
else {
t = amr->prevstarttime + amr->uptime * 60;
printf("around %s", ctime(&t));
}
if ((amr->event > ev_deregistration || amr->event < ev_status_report)
&& amr->event != ev_livenotification) {
printf("Re-start time .......... %s", ctime(&(amr->starttime)));
printf("Uptime ................. %s\n", pretty_minutes(amr->uptime,
s));
printf("Downtime ............... %s\n", pretty_minutes(amr->dntime,
s));
}
if (amr->summarylen)
printf("Incident summary ....... \n%s\n", amr->summary);
}
}