"vulture" - status line display program

Mikel Manitius mikel at flmis06.codas.att.com
Tue Feb 16 01:48:36 AEST 1988


[ 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 at 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 at 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 at 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 at codas.att.com



More information about the Unix-pc.sources mailing list