aboutsummaryrefslogtreecommitdiffstats
path: root/utils/vmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/vmon.c')
-rw-r--r--utils/vmon.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/utils/vmon.c b/utils/vmon.c
new file mode 100644
index 0000000..e1015b4
--- /dev/null
+++ b/utils/vmon.c
@@ -0,0 +1,442 @@
+/* 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 <std/time.h>
+#include <other/string.h>
+#include <proc/process.h>
+#include <other/config.h>
+#include <net/stream.h>
+#include <std/utmp.h>
+
+/* For systems that use statfs! */
+
+#ifdef __linux__
+#include <sys/vfs.h>
+#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;
+ }
+ }
+ }
+}
+
+