/* Verbal monitor system status. * $Id: vmon.c 1.2 Mon, 24 Mar 1997 12:25:37 -0500 dyfet $ * Copyright (c) 1997 by Tycho Softworks. * For conditions on distribution and reuse see product license. * * Abstract: * Monitor system status in background. This service is normally * started with the speech server. It may also be ran as 'vstat' * to perform immediate notification. */ #include #include #include #include #include #include /* For systems that use statfs! */ #ifdef __linux__ #include #define __statfs__ #endif typedef struct _MAILBOX { struct _MAILBOX *next; time_t update; ulong size; char name[0]; } MAILBOX; static int freq = 3600; static int timer = 3600; static int interval = 300; static int iter; static int orig_timer; static int alert = 90; /* warn on 90% full */ static char alertmsg[] = "emergency alert emergency alert \r\n"; static char **fs; static char host[128] = "localhost"; static int mute[2] = {24, 0}; static char *vmailbox(MAILBOX *mbox) { struct stat ino; static char buf[80]; if(stat(mbox->name, &ino)) return NULL; if(!ino.st_size) { mbox->size = 0; return NULL; } if(ino.st_size == mbox->size) return NULL; if(mbox->size == -1) { mbox->size = ino.st_size; return NULL; } mbox->size = ino.st_size; sprintf(buf, "User %s has new mail\n", mbox->name); return buf; } static void vmbox(MAILBOX *box, int port) { STREAM fp = NULL; char *p; time_t now; struct tm *dt; char buf[128]; time(&now); dt = localtime(&now); if(dt->tm_hour > mute[0] || dt->tm_hour < mute[1]) return; while(box) { p = vmailbox(box); if(!p) { box = box->next; continue; } if(!fp) { fp = opentcp(host, port); if(!fp) return; gettcp(buf, sizeof(buf) - 1, fp); } puttcp(p, fp); box = box->next; } if(fp) closetcp(fp); } static int vstat(int port) { int i = 0; char *f; long btotal = 0; long bfree = 0; bool failed = FALSE; STREAM fp = NULL; #ifdef __statfs__ struct statfs fnode; #endif int blocks, inodes; char buf[128]; int newtimer = orig_timer; time_t now; static prior = -1; struct tm *dt; int apm, hour; char *apmstr[] = {" A M ", " P M "}; int fd; struct utmp *utmp, uptime; int users = 0; int utcnt = 0; #ifdef __statfs__ while(fs[i]) { if(!statfs(fs[i], &fnode)) { btotal += fnode.f_blocks; bfree += fnode.f_bfree; blocks = 100 - (int)(fnode.f_ffree / (fnode.f_files / 100l)); inodes = 100 - (int)(fnode.f_bfree / (fnode.f_blocks / 100l)); if((blocks < alert) && (inodes < alert)) { ++i; continue; } } else { inodes = 0; blocks = 0; failed = TRUE; } if(!fp) { fp = opentcp(host, port); if(!fp) { newtimer = 300; break; } gettcp(buf, 128, fp); puttcp(alertmsg, fp); } if(blocks > alert) fprintf(fp, "File system %s is %d percent full.\r\n", fs[i], blocks); if(inodes > alert) fprintf(fp, "File system %s i-node table is %d percent full.\r\n", fs[i], inodes); if(failed) fprintf(fp, "File system %s is dismounted or failed\r\n", fs[i]); fflush(fp); newtimer = 60; ++i; } #endif if(fp) closetcp(fp); time(&now); if(prior == (now / freq)) return newtimer; if(prior == -1) prior = now / freq - 1; else prior = now / freq; dt = localtime(&now); hour = dt->tm_hour % 12; if(dt->tm_hour > mute[0] || dt->tm_hour < mute[1]) return newtimer; if(!hour) hour = 12; if(dt->tm_hour > 11) apm = 1; else apm = 0; fp = opentcp(host, port); if(!fp) return newtimer; gettcp(buf, 128, fp); fprintf(fp, "It is %d:%d %s \r\n", hour, dt->tm_min, apmstr[apm]); fflush(fp); fd = open("/proc/uptime", O_RDONLY); hour = -1; if(fd > -1) { read(fd, buf, 128); close(fd); hour = atol(buf) / 3600; } #if defined(BOOT_TIME) || defined(RUN_LVL) if(hour == -1) { utmp = NULL; memset(&uptime, 0, sizeof(uptime)); #ifdef BOOT_TIME setutent(); uptime.ut_type = BOOT_TIME; utmp = getutid(&uptime); #endif #ifdef RUN_LVL if(!utmp) { setutent(); uptime.ut_type = RUN_LVL; utmp = getutid(&uptime); } #endif if(utmp) hour = (now - utmp->ut_time) / 3600l; endutent(); } #endif if(hour > -1) { if(hour == 1) fprintf(fp, "The system has been up 1 hour\r\n"); else if(hour < 48) fprintf(fp, "The system has been up %d hours\r\n", hour); else fprintf(fp, "The system has been up %d days\r\n", hour / 24); fflush(fp); } setutent(); while(NULL != (utmp = getutent())) { ++utcnt; #ifdef USER_PROCESS if(utmp->ut_type != USER_PROCESS) continue; #endif utmp->ut_user[sizeof(utmp->ut_user)] = 0; if(!strcmp(utmp->ut_user, "root")) continue; if(!utmp->ut_user[0]) continue; if(!utmp->ut_line[0]) continue; #ifdef USER_PROCESS if(kill(utmp->ut_pid, 0)) continue; #endif ++users; } endutent(); if(utcnt) { if(!users) fprintf(fp, "There are no users online\r\n"); else if(users == 1) fprintf(fp, "There is 1 user online\r\n"); else fprintf(fp, "There are %d users online\r\n", users); fflush(fp); } if(btotal) { fprintf(fp, "The main system drives are at %d percent of capacity\r\n", 100 - (int)(bfree / (btotal / 100))); fflush(fp); } closetcp(fp); return newtimer; } void main(int argc, char **argv) { int port = getservice("speak"); char *maildir = getenv("MAILDIR"); MAILBOX *mbox = NULL, *newbox; char *prog = basename(*argv); CONFIG *cfg = sys_config("speak"); time_t now; char *p; if(argc < 2) fatal(EX_USAGE, "use %s filesystems...\n", prog); if(!maildir) maildir = "/var/spool/mail"; fs = ++argv; if(!port) fatal(EX_UNAVAILABLE, "%s: speak: service unavailable\n", prog); if(!cfg) fatal(EX_UNAVAILABLE, "%s: speak.conf: missing\n", prog); seek_config(cfg, "vmon"); while(read_config(cfg)) { if(NULL != (p = get_config(cfg, "mailbox"))) { p = strtok(p, __SPACES); while(p) { newbox = (MAILBOX *)malloc(sizeof(MAILBOX) + strlen(p) + 1); newbox->next = mbox; time(&newbox->update); newbox->size = -1l; strcpy(newbox->name, p); mbox = newbox; p = strtok(NULL, __SPACES); } continue; } if(NULL != (p = get_config(cfg, "interval"))) { interval = atoi(p) * 60; continue; } if(NULL != (p = get_config(cfg, "frequency"))) { timer = 3600 / atoi(p); continue; } if(NULL != (p = get_config(cfg, "server"))) { strcpy(host, p); continue; } if(NULL != (p = get_config(cfg, "host"))) { strcpy(host, p); continue; } if(NULL != (p = get_config(cfg, "alert"))) { alert = atoi(p); continue; } if(NULL != (p = get_config(cfg, "timer"))) { timer = atoi(p) * 60; continue; } if(NULL != (p = get_config(cfg, "mute"))) { mute[0] = atoi(p); p = strchr(p, '-'); if(p) mute[1] = atoi(strtrim(++p, __SPACES)); continue; } if(NULL != (p = get_config(cfg, "maildir"))) { maildir = strdup(p); continue; } } close_config(cfg); if(stricmp(prog, "vmon")) { vstat(port); exit(0); } pdetach(D_KEEPNONE); chdir(maildir); freq = timer; orig_timer = timer; time(&now); for(;;) { timer = vstat(port); iter = interval; for(;;) { vmbox(mbox, port); sleep(iter); time(&now); iter = timer - (now % timer) - 1; if(iter > interval) iter = interval; if(iter < 2) { sleep(iter + 2); break; } } } }