mikel@flmis06.codas.att.com (Mikel Manitius) (02/15/88)
[ Here's my "vulture" program, it tells time, load average, login/out activity, who your mail is from when it arrives, and a few other things. It should run on any System V, and I've even convinved it to run on BSD, fairly easily. It needs an ANSI terminal with a 25th status line, or a UNIX Pc console. ] #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # README # vulture.1 # path.c # vulture.c # This archive created: Mon Feb 15 10:42:22 1988 # By: Mikel Manitius (mikel@codas.att.com) # export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Makefile'" '(175 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else cat << \SHAR_EOF > 'Makefile' CFLAGS = -O DFLAGS = -DMAXUSERS=8 -Du3b1 LFLAGS = BINDIR = /usa/mikel/bin PROGRM = vulture $(PROGRM): $(PROGRM).c cc $(CFLAGS) $(DFLAGS) -o $(PROGRM) $(PROGRM).c $(LFLAGS); SHAR_EOF if test 175 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 175 characters)' fi fi echo shar: "extracting 'README'" '(1366 characters)' if test -f 'README' then echo shar: "will not over-write existing file 'README'" else cat << \SHAR_EOF > 'README' this is a breif explanation of some of the tuneable constants in the source. Please not that you may have to tune MAXUSERS to the maximum number of users that can simultanously log onto your system, it is by default set to a very low number (ie: workstation). NRUN - scan for idle terminals every (NRUN * TIME_INTERVAL) seconds. TIME_INTERVAL - how often timestamps are printed. CRUISE_CONTROL - how often the main loop is executted (seconds). IDLE_UNIT - unit of idle time for new footnote to be printed. MAX_IDLE - maximum number of idle footnote messages defined. LOGOUT_TIME - number of seconds a user must be idle to be logged off. PF_SIZE - size (in spaces) of a PF key label). STAMP_COL - At what collumn to print the timestamp. NCOLS - number of collumns on the status line. MSG_START - starting position of a normal message. MSG_MAXLEN - maximum length of a normal message. MSG_INTERVAL - minimum interval (in seconds) between messages. MAX_MSG_AGE - maximum age of message before it is erased. MAIL - name of enviorment variable pointing to mail file. INFO_MSG - message to use when informing of new mail. MAIL_DIR - directory of mail queue file (if no MAIL in enviorment). Mikel Manitius +1 305 869-2462 mikel@codas.att.com AT&T (Network Operations Group) 151 S. Wymore Rd. (Rm 349) Altamonte Springs, FL 32714 SHAR_EOF if test 1366 -ne "`wc -c < 'README'`" then echo shar: "error transmitting 'README'" '(should have been 1366 characters)' fi fi echo shar: "extracting 'vulture.1'" '(3142 characters)' if test -f 'vulture.1' then echo shar: "will not over-write existing file 'vulture.1'" else cat << \SHAR_EOF > 'vulture.1' .TH VULTURE 1 "mikel" .SH NAME vulture \- monitor incomming mail and login/logout activity .SH SYNOPSIS vulture [ \-t ] [ \-k ] [ \-f ] [ \-s ] [ \-i ] .PP vulture [ \-tkfsi ] .SH DESCRIPTION .I Vulture is a system status program that monitors certain activity in the system, or activity related to it's user. This activity is reported on the 25th status line of a capable ANSI terminal, or an AT&T 3b1 console. .PP If desired, the file .I /etc/utmp is monitored for login and logout information. It is also scanned periodically even if not touched, to check for other users enabeling or disableing messages (ie: via the .I mesg command) .PP The file .I /usr/mail/$LOGNAME is monitored for the arrival of new mail. If new mail arrives for the invoking user, a message annoucing such mail, including the path of the originating author will be printed on the status line. Network mail headers will also be parsed to determine paths. If a path is too long to fit neatly on the status line, the path will be truncated to the form "...!host!user". .PP If a user reads his mail (ie: the queue file shrinks) the contents of the status line will be erased. The status line will also be erased if it contains a message older than 5 minutes. .PP If desired, .I vulture will print a timestamp every 37 seconds on the status line, this is very handy if the user needs to keep track of time. A "status word" will be printed at the beginning of the status line to indicate if the user is active or idle. Normally the word will show .I "On Line", however if the user becomes idle, it may show such words as .I "comatose" or a flashing .I "idle". The amount of time used to determine if a user is idle, and the messages printed, are configurable within the source. .I Vulture may be given several arguments on the command line, these may be any of: .TP 5 .B \-l Print information about users loging on or off of the system. .TP 5 .B \-t Print the timestamp every 37 seconds. .PP .TP 5 .B \-i Inform about other users being idle. This option will not work without an the .B \-l option being selected. .PP .TP 5 .B \-f Aupon startup, don't fork off into the background. .PP .TP 5 .B \-k If the user becomes idle, warn him, and then terminte his session. .PP .TP 5 .B \-s Do not print the "status word". .PP .TP 5 .B \-w The console is a 3b1 monitor, use appropriate ioctl(2) calls to put the message on the footer line. .PP All output on the status line is done in half intesity video (assuming the terminal is capable). Messages are announced with a bell (^G) being sent to terminal. Multiple mesasges will be delayed at least 5 seconds to give the user time to see each one. .SH BUGS Doesn't always parse complicated ">From" lines proprerly. Doesn't always warn about other users being idle. .SH FILES .nf /etc/utmp list of users currently logged in /usr/mail/$LOGNAME mail queued for user /dev/tty* used to figure out other's idle time .fi .SH SEE ALSO mail(1), who(1), mesg(1), date(1), stty(1) .SH DIAGNOSTICS Any error messages after startup will be printed on the 25th status line. .SH AUTHOR Mikel Manitius \- AT&T Information Systems SHAR_EOF if test 3142 -ne "`wc -c < 'vulture.1'`" then echo shar: "error transmitting 'vulture.1'" '(should have been 3142 characters)' fi fi echo shar: "extracting 'path.c'" '(798 characters)' if test -f 'path.c' then echo shar: "will not over-write existing file 'path.c'" else cat << \SHAR_EOF > 'path.c' #include <stdio.h> #include <ctype.h> char *getaddr(fp) FILE *fp; { char x[25]; char y[25]; char line[BUFSIZ]; char user[BUFSIZ]; char host[BUFSIZ]; static char path[BUFSIZ]; path[0] = '\0'; for(;;) { if(fgets(line, BUFSIZ, fp) == NULL) break; if(strncmp(line, ">From ", 6) != 0) break; sscanf(line, ">From %s%s%s%s%s%s%s%s%s%s", user, x, x, x, x, y, x, x, x, host); if(isdigit(y[0])) strcpy(host, x); if(strcmp(user, "uucp") == 0 || strcmp(user, "3bnet") == 0) { if(path[0] == '\0') strcpy(path, host); else sprintf(path, "%s!%s", path, host); } else if(path[0] == '\0') sprintf(path, "%s!%s", host, user); else sprintf(path, "%s!%s!%s", path, host, user); } if(strncmp(path, "3bnet!", 6) == 0) return(path + 6); else return(path); } SHAR_EOF if test 798 -ne "`wc -c < 'path.c'`" then echo shar: "error transmitting 'path.c'" '(should have been 798 characters)' fi fi echo shar: "extracting 'vulture.c'" '(16067 characters)' if test -f 'vulture.c' then echo shar: "will not over-write existing file 'vulture.c'" else cat << \SHAR_EOF > 'vulture.c' static char *sccsid = "@(#)vulture.c Mikel Manitius AT&T 86-07-25"; #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/sysinfo.h> #include <sys/stat.h> #include <signal.h> #include <nlist.h> #include <fcntl.h> #include <time.h> #include <utmp.h> #include <pwd.h> #ifdef u3b1 #include <sys/window.h> #endif /* * vulture - drive the status line with system info messages. * * Mikel Manitius (mikel@codas.att.com) */ #ifdef BUFSIZ #undef BUFSIZ #endif #ifndef MAXUSERS #define MAXUSERS 8 #endif #define BUFSIZ 256 #define TRUE 1 #define FALSE 0 #define NRUN 3 #define TIME_INTERVAL 37 #define CRUISE_CONTROL 5 #define IDLE_UNIT 120 #define MAX_IDLE 4 #define LOGOUT_TIME 10*60*60 #define PF_SIZE 8 #define NCOLS 78 #define STAMP_COL 10 #define MSG_START 19 #define MSG_MAXLEN 42 #define MSG_INTERVAL 5 #define MAX_MSG_AGE 5*60 #define MAIL "MAIL" #define INFO_MSG "New mail arrived from" #define MAIL_DIR "/usr/mail" #define KMEM "/dev/kmem" #define SYSTEM "/unix" #define EQ(x,y) (strcmp(x,y) == 0) #ifdef u3b1 char date_str[100]; /* date information */ char info_str[100]; /* information string */ struct utdata utd; #endif struct sysinfo sinf; struct footnote { int how; char *word; } footnote[] = { { 0, "On Line " }, { 0, " idle " }, { 0, "sleeping" }, { 0, "comatose" }, { 1, " idle " }, 0, }; struct list { int u_msg; /* are messages enabled */ int u_idle; /* is user's terminal idle */ char u_user[8]; /* name of user */ char u_line[12]; /* user's tty */ }; struct nlist nl[] = { { "sysinfo" }, #define NL_SYSINFO 0 { 0 } }; int u_fd; int n_old; /* number of entries in old user list */ int n_new; /* number of entries in new user linst */ int memfd; /* file descriptor for /dev/kmem */ int count = 0; /* number of cycles to 5 min load avg */ int aflag = FALSE; /* report load average instead of stat wosd */ int tflag = FALSE; /* print time stamp */ int iflag = FALSE; /* report idle users */ int fflag = FALSE; /* don't fork */ int kflag = FALSE; /* kill if idle */ int sflag = FALSE; /* don't print status word */ int lflag = FALSE; /* report logins and logouts */ int wflag = FALSE; /* a 3b1 window */ int m_open = FALSE; /* is the mail file open */ int loginsh; /* pid of envoking user's login shell */ int lastlong = FALSE; /* was the last message a long one */ int msg_age = 0; /* age of message currently displayed */ int idle_count = 0; /* how long since last utmp read */ int expire(); long now_occ; long now_que; double now_load; char *mail; char *pname; /* set to addr of argv[0] */ char *getenv(); char *getaddr(); FILE *m_fp; /* file pointer to mail file */ struct list old[MAXUSERS]; /* list of users on before new scan */ struct list new[MAXUSERS]; /* list of users on after new scan */ struct utmp ut; struct stat st; struct passwd *pw; struct passwd *getpwuid(); quit(qc) int qc; { utd.ut_text[0] = '\0'; ioctl(0, WIOCSETTEXT, &utd); exit(qc); } hour() { int now; char obuff[100]; struct tm *tm; struct tm *localtime(); if(tflag) { time(&now); tm = localtime(&now); if(aflag) { load(); #ifdef u3b1 if(wflag) sprintf(date_str, "L: %5.2f %2d:%02d:%02d", now_load, tm->tm_hour, tm->tm_min, tm->tm_sec); else #endif sprintf(obuff, "\0337\033[2m\033[25HL: %5.2f %2d:%02d:%02d \033[0m\0338", now_load, tm->tm_hour, tm->tm_min, tm->tm_sec); } else #ifdef u3b1 if(wflag) sprintf(date_str, " %2d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); else #endif sprintf(obuff, "\0337\033[2m\033[25;%dH%2d:%02d:%02d \033[0m\0338", STAMP_COL, tm->tm_hour, tm->tm_min, tm->tm_sec); #ifdef u3b1 if(wflag) { sprintf(utd.ut_text, "%s %s", date_str, info_str); ioctl(0, WIOCSETTEXT, &utd); } else #endif write(1, obuff, strlen(obuff)); } else if(aflag) { load(); #ifdef u3b1 if(wflag) sprintf(date_str, "L: %5.2f ", now_load); else #endif sprintf(obuff, "\0337\033[2m\033[25HL: %5.2f\033[0m\0338", now_load); #ifdef u3b1 if(wflag) { sprintf(utd.ut_text, "%s %s", date_str, info_str); ioctl(0, WIOCSETTEXT, &utd); } else #endif write(1, obuff, strlen(obuff)); } if(msg_age) { msg_age += TIME_INTERVAL; if(msg_age >= MAX_MSG_AGE) expire(); } idle_count++; signal(SIGALRM, hour); alarm(TIME_INTERVAL); } populate(pp) struct list pp[MAXUSERS]; { int n = 0; int now; char perm[10]; char file[BUFSIZ]; time(&now); lseek(u_fd, 0L, 0); while(read(u_fd, (char *)&ut, sizeof(ut))) if(ut.ut_type == USER_PROCESS) { ut.ut_user[7] = '\0'; ut.ut_line[11] = '\0'; strcpy(pp[n].u_user, ut.ut_user); strcpy(pp[n].u_line, ut.ut_line); sprintf(file, "/dev/%s", pp[n].u_line); stat(file, &st); sprintf(perm, "%o", st.st_mode); switch(perm[4]) { case '2': case '3': case '6': case '7': pp[n].u_msg = TRUE; break; default: pp[n].u_msg = FALSE; break; } if((now - st.st_mtime) >= IDLE_UNIT) pp[n].u_idle = TRUE; else pp[n].u_idle = FALSE; n++; } return(n); } char *fname(user) char *user; { int i; i = strlen(user) - 1; while(user[i] != '!') i--; return(user + i+1); } hunt() { int o; /* index to old user list */ int n; /* index to new user list */ int found; /* has what we're looking for been found */ n_new = populate(new); for(o=0;o < n_old;o++) { found = FALSE; for(n=0;n < n_new;n++) if(EQ(new[n].u_user, old[o].u_user) && EQ(new[n].u_line, old[o].u_line)) found = TRUE; if(!found && strncmp(old[o].u_line, "sxt", 3) != 0) logout(o); } for(n=0;n < n_new;n++) { found = FALSE; for(o=0;o < n_old;o++) if(EQ(new[n].u_user, old[o].u_user) && EQ(new[n].u_line, old[o].u_line)) { if(new[n].u_msg != old[o].u_msg) message(n); if((new[n].u_idle != old[o].u_idle) && iflag) do_idle(n); found = TRUE; } if(!found && strncmp(new[n].u_line, "sxt", 3) != 0) login(n); } } message(n) int n; { char buff[BUFSIZ]; sprintf(buff, "User %s on %s now has messages %s", new[n].u_user, new[n].u_line, (new[n].u_msg) ? "on" : "off"); yelp(buff); } do_idle(n) int n; { char buff[BUFSIZ]; if(new[n].u_idle) sprintf(buff, "User %s on %s has now gone idle", new[n].u_user, new[n].u_line); else sprintf(buff, "User %s on %s is no longer idle", new[n].u_user, new[n].u_line); yelp(buff); } login(n) int n; { char buff[BUFSIZ]; sprintf(buff, "User %s just logged in on %s%s", new[n].u_user, new[n].u_line, (new[n].u_msg) ? "" : " (msg n)"); yelp(buff); } logout(o) int o; { char buff[BUFSIZ]; sprintf(buff, "User %s just logged off of %s.", old[o].u_user, old[o].u_line); yelp(buff); } main(argc, argv) int argc; char *argv[]; { int i; int j; int fk; long now; long idle; long oidle; long old_time; long old_mail; long old_size; pname = argv[0]; #ifdef u3b1 utd.ut_num = WTXTSLK2; strcpy(date_str, " "); #endif for(i=1;i < argc;i++) switch(argv[i][0]) { case '-': for(j=1;argv[i][j] != '\0';j++) switch(argv[i][j]) { case 't': tflag++; break; case 'f': fflag++; break; case 'k': kflag++; break; case 'a': aflag++; sflag++; break; case 's': sflag++; break; case 'i': iflag++; break; case 'l': lflag++; break; #ifdef u3b1 case 'P': wflag++; utd.ut_num = WTXTPROMPT; break; case 'C': wflag++; utd.ut_num = WTXTCMD; break; case '1': wflag++; utd.ut_num = WTXTSLK1; break; case '2': wflag++; utd.ut_num = WTXTSLK2; break; case 'w': wflag++; break; #endif default: usage(); break; } break; default: usage(); break; } u_fd = open(UTMP_FILE, 0); if(u_fd < 0) { perror(UTMP_FILE); exit(u_fd); } loginsh = getppid(); if(!fflag) { fk = fork(); if(fk) { #ifdef DEBUG printf("%d\n", fk); #endif exit(0); } } if(aflag) { memfd = open(KMEM, O_RDONLY); if(memfd < 0) { yelp("open /dev/kmem failed!"); exit(-1); } if(nlist(SYSTEM, nl) < 0) { yelp("nlist /unix failed!"); exit(-1); } if(nl[NL_SYSINFO].n_value == 0) { yelp("No namelist member for load average!"); exit(-1); } do_read(); now_occ = sinf.runocc; now_que = sinf.runque; } #ifdef JERK chdir("/dev"); #endif mail = getenv(MAIL); if(mail == NULL) { pw = getpwuid(getuid()); if(pw == NULL) { printf("%s: cannot determine mail file.\n", pname); exit(-1); } sprintf(mail, "%s/%s", MAIL_DIR, pw->pw_name); } n_old = populate(old); stat(UTMP_FILE, &st); old_time = st.st_mtime; if(stat(mail, &st) == 0) { old_mail = st.st_mtime; old_size = st.st_size; m_fp = fopen(mail, "r"); if(m_fp != NULL) { #ifdef DEBUG yelp("mail open succeeded"); #endif m_open = TRUE; fseek(m_fp, 0L, 2); } #ifdef DEBUG else yelp("mail open fail"); #endif } else { old_mail = 0; old_size = 0; } signal(SIGALRM, hour); signal(SIGUSR1, expire); alarm(TIME_INTERVAL); alarm(TIME_INTERVAL); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); #ifdef u3b1 if(wflag) signal(SIGTERM, quit); #endif if(!sflag) squeal(footnote[0].word, footnote[0].how); if(tflag) { msg_age = MAX_MSG_AGE; /* to clear screen initially */ hour(); } else { lastlong = TRUE; expire(); } for(;;) { for(;;) { if(lflag && stat(UTMP_FILE, &st) == 0 &&(st.st_mtime > old_time || idle_count >= NRUN)) { old_time = st.st_mtime; idle_count = 0; break; } if(stat(mail, &st) == 0) { if((st.st_mtime > old_mail && st.st_size > old_size) || !m_open) { #ifdef DEBUG yelp("new mail"); #endif old_mail = st.st_mtime; old_size = st.st_size; newmail(); } else if(st.st_size < old_size) { fclose(m_fp); m_open = FALSE; m_fp = fopen(mail, "r"); if(m_fp == NULL) { yelp("* Warning: Cannot open mail file!"); continue; } fseek(m_fp, 0L, 2); stat(mail, &st); old_mail = st.st_mtime; old_size = st.st_size; m_open = TRUE; expire(); } #ifdef DEBUG else yelp("no new mail"); #endif } else { #ifdef DEBUG yelp("can't stat mail file"); #endif fclose(m_fp); m_open = FALSE; old_mail = 0; old_size = 0; } fstat(0, &st); time(&now); idle = now - st.st_atime; status(idle); oidle = idle; sleep(CRUISE_CONTROL); } if(lflag) { n_new = populate(new); hunt(); n_old = populate(old); } } } yelp(buff) char *buff; { int i; int start; /* starting collumn of message on screen */ int length; /* length of string to be printed */ int adjust; /* length of adjustment to center message */ char num[25]; char obuff[BUFSIZ]; /* output buffer */ #ifdef u3b1 if(wflag) { info_str[0] = '\0'; length = strlen(buff); adjust = (MSG_MAXLEN - length) / 2; for(i=0;i < adjust;i++) strcat(info_str, " "); strcat(info_str, buff); sprintf(utd.ut_text, "%s %s", date_str, info_str); write(1, "\7", 1); ioctl(0, WIOCSETTEXT, &utd); sleep(MSG_INTERVAL); msg_age = MSG_INTERVAL; return; } #endif obuff[0] = '\0'; if(lastlong) { strcat(obuff, "\0337\033[25;"); sprintf(num, "%d", MSG_START - (PF_SIZE+1)); strcat(obuff, num); strcat(obuff, "H \0338"); lastlong = FALSE; } length = strlen(buff); if(length > MSG_MAXLEN) { adjust = ((MSG_MAXLEN + PF_SIZE+1) - length) / 2; start = MSG_START - (PF_SIZE+1); lastlong = TRUE; } else { adjust = (MSG_MAXLEN - length) / 2; start = MSG_START; } strcat(obuff, "\7\0337\033[2m\033[25;"); sprintf(num, "%d", start); strcat(obuff, num); strcat(obuff, "H"); for(i=0;i < adjust;i++) strcat(obuff, " "); strcat(obuff, buff); adjust = NCOLS - (start + adjust + length); for(i=0;i < adjust;i++) strcat(obuff, " "); strcat(obuff, "\033[m\0338"); write(1, obuff, strlen(obuff)); sleep(MSG_INTERVAL); msg_age = MSG_INTERVAL; } newmail() { int i; char *path; char who[BUFSIZ]; char msg[BUFSIZ]; char user[BUFSIZ]; char host[BUFSIZ]; char line[BUFSIZ]; if(!m_open) { m_fp = fopen(mail, "r"); if(m_fp == NULL) { yelp("* Warning: Cannot open mail file!"); return; } m_open = TRUE; } while(fgets(line, BUFSIZ, m_fp) != NULL) if(strncmp(line, "From", 4) == 0) { if(line[4] == ':') continue; sscanf(line + 5, "%s", who); if(strcmp(who, "uucp") == 0 || strcmp(who, "pedns") == 0 || strcmp(who, "3bnet") == 0 || strcmp(who, "usenet") == 0) { path = getaddr(m_fp); if(path[0] == '\0') { sprintf(msg, "%s %s", INFO_MSG, who); yelp(msg); continue; } i = rindex2(path, '!') + 1; if(strlen(path)+strlen(INFO_MSG)+6 > MSG_MAXLEN) sprintf(msg, "%s ...!%s", INFO_MSG, path + i); else sprintf(msg, "%s %s", INFO_MSG, path); } else { sscanf(line, "From %s", user); sprintf(msg, "%s %s", INFO_MSG, user); } yelp(msg); } } usage() { #ifdef u3b1 fprintf(stderr, "usage: %s [ -listkf ] [ -w [ -1 | -2 | -P | -C ] ]\n", pname); #else fprintf(stderr, "usage: %s [ -listkf ] \n", pname); #endif exit(-1); } squeal(buff, flash) int flash; char *buff; { char obuff[BUFSIZ]; #ifdef u3b1 if(wflag) return; #endif sprintf(obuff, "\0337\033[%cm\033[25H%s\033[m\0338", (flash) ? '5' : '2', buff); write(1, obuff, strlen(obuff)); } status(idle) long idle; { static long oidle; if(idle > (LOGOUT_TIME - 60) && idle < LOGOUT_TIME && kflag) yelp("Warning: Terminate if idle for 1 more minute"); else if(idle >= LOGOUT_TIME && kflag) { yelp("Terminated due to rigormourtis of the hand"); kill(loginsh, SIGHUP); } else if(!sflag) { idle /= IDLE_UNIT; if(idle > MAX_IDLE) idle = MAX_IDLE; if(idle != oidle) squeal(footnote[idle].word, footnote[idle].how); oidle = idle; } } char *getaddr(fp) FILE *fp; { char x[25]; char y[25]; char line[BUFSIZ]; char user[BUFSIZ]; char host[BUFSIZ]; static char path[BUFSIZ]; path[0] = '\0'; for(;;) { if(fgets(line, BUFSIZ, fp) == NULL) break; if(strncmp(line, ">From ", 6) != 0) { if(strcmp(user, "uucp") == 0) sprintf(path, "%s!%s", path, user); break; } sscanf(line, ">From %s%s%s%s%s%s%s%s%s%s", user, x, x, x, x, y, x, x, x, host); if(isdigit(y[0])) strcpy(host, x); if(strcmp(user, "uucp") == 0) { if(path[0] == '\0') strcpy(path, host); else sprintf(path, "%s!%s", path, host); } else if(path[0] == '\0') sprintf(path, "%s!%s", host, user); else sprintf(path, "%s!%s!%s", path, host, user); } return(path); } index(str, ch) char ch; char *str; { int i; int len; len = strlen(str) - 1; for(i=0;str[i] != ch;i++) if(len == i) return(-1); return(i); } rindex2(str, ch) char ch; char *str; { int i; for(i=strlen(str) - 1;str[i] != ch;i--) if(i == 0) return(-1); for(--i;str[i] != ch;i--) if(i == 0) return(-1); return(i); } expire() { int i; int start; char obuff[BUFSIZ]; signal(SIGUSR1, expire); #ifdef u3b1 if(wflag) { info_str[0] = '\0'; strcpy(utd.ut_text, date_str); ioctl(0, WIOCSETTEXT, &utd); msg_age = 0; return; } #endif if(lastlong && !tflag) start = MSG_START - (PF_SIZE + 1); else start = MSG_START; sprintf(obuff, "\0337\033[25;%dH", start); for(i=0;i < (NCOLS - start);i++) strcat(obuff, " "); strcat(obuff, "\0338"); write(1, obuff, strlen(obuff)); lastlong = FALSE; msg_age = 0; } load() { long nocc, nque; do_read(); nocc = sinf.runocc; nque = sinf.runque; now_load = ((double) (nque - now_que)) / ((double) (nocc - now_occ)); now_occ = nocc; now_que = nque; } do_read() { if(lseek(memfd, (long)nl[NL_SYSINFO].n_value, 0) < 0) { yelp("Cannot seek /dev/kmem!"); exit(-1); } if(read(memfd, (char *)&sinf, sizeof(sinf)) != sizeof(sinf)) { yelp("Cannot read /dev/kmem!"); exit(-1); } } SHAR_EOF if test 16067 -ne "`wc -c < 'vulture.c'`" then echo shar: "error transmitting 'vulture.c'" '(should have been 16067 characters)' fi fi exit 0 # End of shell archive -- Mikel Manitius @ AT&T mikel@codas.att.com