[comp.sys.att] phdaemon.c

lenny@icus.UUCP (Lenny Tropiano) (12/06/87)

I finally got around to posting my version of the phone daemon program
that was on the net about a month ago.  Enjoy the program!

--- cut here --- --- cut here --- --- cut here --- --- cut here --- 
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile phdaemon.c
# Wrapped by lenny@icus.UUCP on Sun Dec  6 21:12:58 EST 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(4692 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThe phone daemon program was written to keep all those people who jump
Xto login when they hear the relay click on the UNIX pc.  The program
Xwas first written by Paul Condie (pcbox!pjc) for this exact reason!
X
XI give thanks to Paul and Michael Ditto (ford@crash.CTS.COM) for his
Xexpertise in the internals of the AT&T UNIX pc kernel.
X
XAfter unpacking the shar file, "su" and become root.  Then type:
X
X	# make install
X
XThis will create the phdaemon executable and copy it into /etc/daemons/.
XThis directory is looked at by /etc/rc apon boot-up to start all system
Xdaemons.  If the directory doesn't exist, it will be created.  Make sure 
Xthe following code is in /etc/rc somewhere:
X
X
Xif [ -d /etc/daemons ]
Xthen
X	DAEMONS=`ls /etc/daemons/*`
X	if [ $? != 0 ] ; then DAEMONS=""; fi
X	for i in $DAEMONS
X	do
X		if [ -x $i ]
X		then	nohup $i > /dev/null 2>&1 &
X		fi
X	done
Xfi
X
XThings to know about the Phone Daemon.  This program is configured
Xfor a multi-line system, where ph0 is the VOICE only line, and ph1 is
Xthe DATA/VOICE line.  The program will need a few revisions to allow
Xto work with a ONE line system.  If someone cares to do this, please
Xmail me the context diffs.
X
XThe program will display:
X
X	DATA 2:IDLE	- obviously when the line is idle.
X	DATA 2:<LOGIN	- Login process (don't know who or what it is yet)
X
X	DATA 2:>PENDING	- A process is going out, not sure what it is.
X	DATA 2:<PENDING	- A process is coming in, not sure what it is.
X
X		The following "user" is in INVERSE video.
X
X	DATA 2:>user	- When a user locks the modem for outgoing calls
X	DATA 2:<user	- When a user locks the modem when coming in.
X	DATA 2:>ph1	- When a user locks (not sure what user) going out
X			  (Generally happens when the user uses the async_main
X			  program to dial out) -- The lock file doesn't reflect
X			  the pid of the locking process. -- POSSIBLE BUG?
X
X		The following "machine" is in BOLD video.
X
X	DATA 2:<UUCICO	- It is a uucico process but don't know what machine
X			  as of yet. (coming in)
X	DATA 2:>machine	- When a uucico process locks modem going out. 
X	DATA 2:<machine	- When a uucico process locks modem coming in. 
X
X---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
X
XThe program doesn't allocate another window, it just uses the window 
Xallocated to the /etc/ph process.  This will not waste another window.
X
XThe following parameters can be changed to your liking:
X
X#define	SLEEP	15			/* Sleep time (interval between)*/
X#define	SNOOZE	5			/* Short Sleep time (short time)*/
X#define	NICE	5			/* Niceness value		*/
X
XThe program is set to a nice value of 25, and it sleeps for 15 seconds 
Xbetween checks.  This will keep the process from bogging down the CPU with 
Xwasted cycles.  When there is a "LOGIN or UUCICO" process that is still
Xundetermined, the program will only SNOOZE for 5 seconds, to try to catch
Xwho or what is logging in before they logout.
X
X
XThe following is a table of the programs to determine what kind of process
Xis going using the modem.  The following are my choices, more can be added
Xto match what you system requires.  Each program must have a type for either
X
X			IN_USER		- user login
X			OUT_USER	- user dialing out
X			UUCP		- uucp process
X			LPROCESS	- login process
X
X	{ "sh",		IN_USER },	/* User program when logged in */
X	{ "ksh",	IN_USER },	/* User program when logged in */
X	{ "cu",		OUT_USER },	/* Program used to dial out    */
X	{ "kermit",	OUT_USER },	/* Program used to dial out    */
X	{ "async_main",	OUT_USER },	/* Program used to dial out    */
X	{ "term",	OUT_USER },	/* Program used to dial out    */
X	{ "uucico",	UUCP },		/* UUCP program dial-in/out    */
X	{ "uusched",	UUCP },		/* UUCP program dial-in/out    */
X	{ "login",	LPROCESS },	/* Login process               */
X	{ "getty",	LPROCESS },	/* Login process               */
X	{ "uugetty",	LPROCESS },	/* Login process               */
X	{ "",           PPROCESS },	/* FAILS all cases:   PENDING  */
X
XNote:  term is a program I wrote that acts as a terminal program, I left
Xit there for example purposes.
X
XPlease report any bugs, suggestions and problems to me:
X
X============================ US MAIL:   Lenny Tropiano, ICUS Computer Group
X IIIII   CCC   U   U   SSSS             PO Box 1
X   I    C   C  U   U  S                 Islip Terrace, New York  11752
X   I    C      U   U   SSS   PHONE:     (516) 968-8576 [H] (516) 582-5525 [W] 
X   I    C   C  U   U      S  AT&T MAIL: ...attmail!icus!lenny  TELEX: 154232428
X IIIII   CCC    UUU   SSSS   UUCP:
X============================    ...{uunet!godfre, harvard!talcott}!\
X                         ...{ihnp4, boulder, mtune, skeeve, ptsfa}! >icus!lenny 
X"Usenet the final frontier"        ...{cmcl2!phri, hoptoad}!dasys1!/
END_OF_README
if test 4692 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(663 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile to compile phdaemon.c  (Phone Daemon)
X# By Lenny Tropiano
X# (c)1987 ICUS Computer Group     UUCP:  ...icus!lenny
X#
XCFLAGS=-v -O
XLDFLAGS=-s
XLIBS=/lib/crt0s.o /lib/shlib.ifile
XDEST=/etc/daemons/
X#
Xphdaemon.o:
X	$(CC) $(CFLAGS) -c phdaemon.c
X#
Xphdaemon:  phdaemon.o
X	@echo "Loading ..."
X	$(LD) $(LDFLAGS) $(LIBS) phdaemon.o -o phdaemon
X#
X# You need to be super-user to do this.
X#
X/etc/daemons:
X	mkdir /etc/daemons
X	chmod 755 /etc/daemons
X#
Xinstall: phdaemon /etc/daemons
X	cp phdaemon /etc/daemons/
X	chown root /etc/daemons/phdaemon
X	chgrp bin  /etc/daemons/phdaemon
X	chmod 4750 /etc/daemons/phdaemon
X	@echo "Phone Daemon started."
X	/etc/daemons/phdaemon
END_OF_Makefile
if test 663 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f phdaemon.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"phdaemon.c\"
else
echo shar: Extracting \"phdaemon.c\" \(14239 characters\)
sed "s/^X//" >phdaemon.c <<'END_OF_phdaemon'
X/************************************************************************\
X**                                                                      **
X** Program name: phdaemon.c (Phone Daemon)                              **
X** Programmer:   Lenny Tropiano            UUCP: ...icus!lenny          **
X** Organization: ICUS Computer Group                                    **
X** Date:         November 8, 1987                                       **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X** Credits:      Thanks to Michael Ditto (ford@crash.CTS.COM) for his   **
X**               Programs fuser and renice which aided me to write the  **
X**               Kernel accessing routines.                             **
X**                                                                      **
X**               Again I want to *THANK* Mike Ditto for his infinite    **
X**               wisdom when it came to the "internals" of the UNIXPC   **
X**                                                                      **
X**               Thanks to Paul J. Condie (pcbox!pjc) for his original  **
X**               idea of the phdaemon program and some tips on writing  **
X**               my own.                                                **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X** Program use:  Program is run as a daemon process from the boot       **
X**               procedure /etc/rc.  It can be placed in /etc/daemons/  **
X**               and will be started up apon system boot.  This program **
X**               monitors the data line (defined as /dev/ph1) for       **
X**               any kind of activity (or lack thereof) and displays    **
X**               the information in the Phone Managers window. Freeing  **
X**               up any other windows from being allocated for that use **
X**                                                                      **
X**               This program checks for DATA or VOICE, UUCP logins,    **
X**               User logins, UUCP outgoing, Internal use of outgoing   **
X**               modem.  This process will terminate if the /etc/ph     **
X**               process is terminated.                                 **
X**                                                                      **
X\************************************************************************/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <signal.h>
X#include <status.h>
X#include <sys/types.h>
X#include <sys/window.h>
X#include <sys/stat.h>
X#include <sys/tune.h>
X#include <sys/proc.h>
X#include <sys/user.h>
X#include <sys/dir.h>
X#include <sys/ph.h>
X#include <sys/phone.h>
X#include <nlist.h>
X#include <pwd.h>
X#include <utmp.h>
X
X#define	SLEEP	15			/* Sleep time (interval between)*/
X#define	SNOOZE	5			/* Short Sleep time (short time)*/
X#define	NICE	5			/* Niceness value		*/
X#define	PHPID	"/usr/lib/ua/phpid"	/* File has pid of /etc/ph	*/
X#define	DEVICE	"/dev/ph1"		/* Phone line do checking on	*/
X#define LINE	"ph1"			/* Phone line yet another way	*/
X					/* Lock file for modem		*/
X#define	LOCKPH	"/usr/spool/uucp/LCK..ph1"
X#define	LOCKDIR	"/usr/spool/uucp"	/* UUCP Lock Directory		*/
X#define	LOCKFIL	"LCK.."			/* Lock file prefix		*/
X#define	OFFSET	sizeof(struct phdef)	/* kernel offset (0 for ph0)	*/
X
X		/* Command to locate window device in use by /etc/ph */
X
X#define	WINDCMD	"ps -p%d | grep ph | cut -c9-11"
X
X#define	ESC	27
X#define	BOLD	1
X#define	REV	7
X#define	ROW	1
X#define	COL	24
X#define	WINSIZE	9
X#define	ATTSIZE	8
X
X#define	INCOMING "<%c[%dm%-8.8s%c[0m"	/* Incoming call string		*/
X#define	OUTGOING ">%c[%dm%-8.8s%c[0m"	/* Outgoing call string		*/
X#define	IDLE	 ":IDLE    "		/* Idle phone device 		*/
X#define	PENDING	 ":PENDING "		/* Incoming/Outgoing pending    */
X#define	BLANK 	 ":        "
X#define	LOGIN  	 "<LOGIN   "		/* Incoming login    		*/
X#define	UUCICO 	 "%c[%dm%cUUCICO  %c[0m"/* Incoming undetermined uucico	*/
X#define	LOCKED 	 ">ph1     "		/* Locked outgoing no process 	*/
X#define	HOME     "%c[%d;%dH"		/* Position cursor in a window	*/
X
X					/* Types of calls		*/
X#define	IN_USER	 1			/* User login 			*/
X#define	OUT_USER 2 			/* User use of on board modem   */
X#define	UUCP	 3 			/* UUCP login or dial out	*/
X#define	LPROCESS 4 			/* Login login 			*/
X#define	PPROCESS 5 			/* Pending login 		*/
X
Xint	wfd;				/* Window file descriptor	*/
Xint	phfd;				/* Phone line file descriptor	*/
Xint	kmemfd;				/* /dev/kmem file descriptor	*/
Xint	memfd;				/* /dev/mem file descriptor	*/
Xint    	MAXPROC;			/* max processes available	*/
X
Xextern	long lseek();			/* lseek(2) function		*/
Xvoid	read_kmem();			/* function to read memory	*/
Xvoid	read_mem();			/* function to read memory	*/
Xchar	*progname;			/* program name			*/
Xchar	buffer[BUFSIZ];			/* buffer for strings		*/
Xchar	userlogin[12];			/* user login name		*/
Xchar	windev[10];			/* window device of /etc/ph	*/
Xstruct	proc 	proc;			/* Process block read from kmem	*/
Xint	phpid;				/* Process id of /etc/ph	*/
X
Xstruct nlist unixsym[] = {		/* /unix name list of symbols	*/
X    { "tuhi", },
X    { "proc", },
X    { "phndef", },
X    { NULL, },
X};
X
X		/* Program lists for identification */
X
Xstruct	programs {			/* CUSTOMIZE TO FIT YOUR NEEDS */
X	char	*name;
X	int	type;
X} prog[] = {
X	{ "sh",		IN_USER },	/* User program when logged in */
X	{ "ksh",	IN_USER },	/* User program when logged in */
X	{ "cu",		OUT_USER },	/* Program used to dial out    */
X	{ "kermit",	OUT_USER },	/* Program used to dial out    */
X	{ "async_main",	OUT_USER },	/* Program used to dial out    */
X	{ "term",	OUT_USER },	/* Program used to dial out    */
X	{ "uucico",	UUCP },		/* UUCP program dial-in/out    */
X	{ "uusched",	UUCP },		/* UUCP program dial-in/out    */
X	{ "login",	LPROCESS },	/* Login process               */
X	{ "getty",	LPROCESS },	/* Login process               */
X	{ "uugetty",	LPROCESS },	/* Login process               */
X	{ "",           PPROCESS },	/* FAILS all cases:   PENDING  */
X};
X
X
X/************************************************************************/
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*fp, *pfp;
X	int	terminate();
X
X	if (fork() != 0) 		/* detach process-daemon */
X		exit(0);
X		
X	nice(NICE);			/* Be a little nice	*/
X	signal (SIGHUP, SIG_IGN);	
X 	signal (SIGINT, SIG_IGN);
X 	signal (SIGTERM, terminate);
X
X    	progname = *argv;
X
X	setup();			/* setup /dev/kmem and /unix */
X
X	if (access(PHPID, 0) == -1) {
X		sprintf(buffer, "phone manager file %s does not exist", PHPID);
X		werror(buffer,0);
X    	}
X	if ((fp = fopen(PHPID,"r")) == NULL) {
X		sprintf(buffer, "can't open file %s", PHPID);
X		werror(buffer,0);
X    	}
X	fscanf(fp,"%d",&phpid);		/* read the process id of /etc/ph */
X	fclose(fp);
X
X	if (!findproc(phpid)) {
X		errno = ESRCH;
X		werror("phone manager /etc/ph not running",0);
X	}
X
X	sprintf(buffer,WINDCMD,phpid);
X	if ((pfp = popen(buffer,"r")) == NULL) 
X		werror("can't open pipe to 'ps' command",0);
X
X	if (fgets(buffer,3,pfp) == NULL) 
X		werror("nothing returned from pipe",1);
X
X	pclose(pfp);
X	sprintf(windev,"/dev/%s",buffer);
X
X	setpgrp();
X	if ((wfd = open(windev,O_RDWR)) == -1) {
X		sprintf(buffer, "can't open %s", windev);
X		werror(buffer,0);
X    	}
X	close(0); dup(wfd);
X	close(1); dup(wfd);
X	close(2); dup(wfd);
X
X	daemon_process();
X
X	terminate();
X
X}
X
Xdaemon_process()
X{
X	register i;
X	int	 lockfd, calltype;
X	short 	 lockpid;
X	char	 command[DIRSIZ],	/* Command of program running	*/
X		 *findmachine(), 
X		 *getcommand(),
X		 machine[12];
X    	struct   phdef   phblock;
X	struct	 passwd *pwent, 
X			*getpwnam(), 
X			*getpwuid();
X
X	while (findproc(phpid)) {		/* Process still exists */
X   		 read_kmem(&phblock, 
X			   (unixsym[2].n_value + OFFSET), 
X			   (long)sizeof (struct phdef));
X
X		 if (phblock.p_lineparam & DATA) {
X					     /* Check lock file existence */
X			if (access(LOCKPH,0) == -1) {
X			   home_cursor();
X			   write(0,IDLE,WINSIZE);
X			   sleep(SLEEP);
X			   continue;	     /* no file found             */
X			}
X
X			if ((lockfd = open(LOCKPH, O_RDONLY)) == -1) {
X			   sprintf(buffer, "can't open %s", LOCKPH);
X			   werror(buffer,0);
X			}
X			read(lockfd,&lockpid,sizeof(short));	
X			read(lockfd,&lockpid,sizeof(short));	/* HDB UUCP   */
X			close(lockfd);
X
X			if (!findproc(lockpid)) {
X			   	home_cursor();
X			   	write(0,LOCKED,WINSIZE);
X			   	sleep(SLEEP);    
X			        close(lockfd);
X			   	continue;
X			}
X
X			sprintf(command,"%s",getcommand());
X			calltype = check_command(command);
X
X			if (calltype == LPROCESS || calltype == PPROCESS) {
X			   home_cursor();
X			   write(0,(calltype == LPROCESS) ? LOGIN : PENDING,
X				 WINSIZE);
X			   sleep(SNOOZE);
X			   continue;
X			}
X
X			setpwent();	/* rewind /etc/passwd */
X			if (calltype == OUT_USER) {
X			   if ((pwent = getpwuid(proc.p_uid)) == NULL) {
X				sprintf(buffer,
X					"cannot locate uid %d in /etc/passwd",
X					proc.p_uid);
X				werror(buffer,1);
X			   }
X			} else if (calltype == IN_USER) {
X			   utmpentry(LINE);
X			   if (*userlogin == NULL) {
X			      write(0, LOGIN, WINSIZE);
X			      sleep(SNOOZE); 
X			      continue;
X			   }
X			   if ((pwent = getpwnam(userlogin)) == NULL) {
X				sprintf(buffer,
X					"cannot locate user %s in /etc/passwd",
X					userlogin);
X				werror(buffer,1);
X			   }
X			}
X			endpwent();	/* close /etc/passwd */
X
X			home_cursor();
X			switch (calltype) {
X			   case IN_USER:
X				sprintf(buffer,INCOMING,ESC,REV,pwent->pw_name,
X					ESC);
X				write(0,buffer,WINSIZE+ATTSIZE);
X				break;
X			   case OUT_USER:
X				sprintf(buffer,OUTGOING,ESC,REV,pwent->pw_name,
X					ESC);
X				write(0,buffer,WINSIZE+ATTSIZE);
X				break;
X			   case UUCP:
X			        sprintf(machine,"%s",(char *)findmachine());
X			   	utmpentry(LINE);
X			   	if (*userlogin == NULL) {
X				   if (*machine != NULL) 
X				      sprintf(buffer,OUTGOING,ESC,BOLD,machine,
X					      ESC);
X				   else
X				      sprintf(buffer,UUCICO,ESC,BOLD,'>',ESC);
X				} else {
X				   if (*machine != NULL) 
X				      sprintf(buffer,INCOMING,ESC,BOLD,machine,
X					      ESC);
X				   else
X				      sprintf(buffer,UUCICO,ESC,BOLD,'<',ESC);
X				}
X			        endutent();
X				write(0,buffer,WINSIZE+ATTSIZE);
X				break;
X			   case LPROCESS:
X				write(0,LOGIN,WINSIZE);
X				break;
X			   default:
X				sprintf(buffer,"calltype is incorrect = %d",
X					calltype);
X				werror(buffer, 1);
X				break;
X			}
X		} 
X		if (calltype == UUCP && *machine == NULL)
X		   sleep(SNOOZE);		/* Take a few short ZZzzz... */
X		else
X		   sleep(SLEEP);		/* Take a few ZZzzz...       */
X	}
X}
X
Xcheck_command(cmd)			/* Check the list of commands */
Xchar *cmd;
X{
X	register i;
X
X	i = 0;
X	while (*(prog[i].name) != NULL) {
X	   if (strcmp(prog[i].name, cmd) == 0)
X		return(prog[i].type);
X	   i++;
X	}
X	return(PPROCESS);
X}
X
Xutmpentry(line)
Xchar *line;
X{
X	struct	utmp   *utent, *getutent();
X
X	setutent();
X	while ((utent = getutent()) != NULL) {
X	   if (strncmp(utent->ut_line,line,strlen(line)) == 0 && 
X	       utent->ut_type == USER_PROCESS) {
X		sprintf(userlogin,"%s",utent->ut_user);
X		endutent();
X		return;
X	   }
X	}
X	endutent();
X	*userlogin = NULL;
X}
X
Xhome_cursor()
X{
X	sprintf(buffer,HOME,ESC,ROW,COL);
X	write(0,buffer,7);
X}
X
Xint terminate()
X{
X	home_cursor();
X	write(0,BLANK,WINSIZE);
X	close(wfd);
X	close(kmemfd);
X	close(memfd);
X	exit(0);
X}
X
Xsetup()
X{
X	struct tunable tune;
X
X	if ((kmemfd=open("/dev/kmem", O_RDWR)) == -1) 
X	   werror("can't open /dev/kmem",0);
X
X	if ((memfd=open("/dev/mem", O_RDWR)) == -1) 
X	   werror("can't open /dev/mem",0);
X
X	if (nlist("/unix", unixsym)) 
X	   werror("can't nlist /unix",0);
X
X	read_kmem((char *)&tune, (unixsym[0].n_value), (long) sizeof tune);
X	read_kmem((char *)&(unixsym[1].n_value), (unixsym[1].n_value), 
X		  (long)sizeof (unixsym[1].n_value));
X
X	MAXPROC = tune.nproc;
X
X}
X
Xvoid read_kmem(caddr, kaddr, nbytes)
Xchar *caddr;
Xlong kaddr;
Xlong nbytes;
X{
X	if (lseek(kmemfd, kaddr, 0)<0L ||
X	    read(kmemfd, caddr, (unsigned)nbytes) != nbytes ) 
X	      werror("can't read /dev/kmem",0);
X}
X
Xvoid read_mem(caddr, paddr, nbytes)
Xchar *caddr;
Xlong paddr;
Xlong nbytes;
X{
X    if (lseek(memfd, paddr, 0)<0L ||
X	read(memfd, caddr, (unsigned)nbytes) != nbytes) 
X	      werror("can't read /dev/mem",0);
X}
X
Xint findproc(pid)
Xint pid;
X{
X	register i;
X
X	for (i=0 ; i<MAXPROC ; ++i) {
X	   read_kmem((char *)&proc,
X		  (long)&((struct proc *)(unixsym[1].n_value))[i],
X		  (long)sizeof proc);
X	   if (proc.p_pid == pid)
X		return 1;
X	}
X	return 0;
X}
X
Xchar *findmachine()
X{
X	int	dfd;			/* Directory file descriptor	*/
X	static  struct	direct	dirbuf;	/* Directory entry buffer	*/
X
X	if ((dfd = open(LOCKDIR, O_RDONLY)) == -1) 
X	      werror("can't open lock directory",0);
X	
X	while (read(dfd, &dirbuf, sizeof (struct direct)) == 
X	      (sizeof (struct direct))) {
X	   if ((dirbuf.d_ino != 0) && (strncmp(dirbuf.d_name,LOCKFIL,5) == 0)) {
X		if ((strncmp((char *)&dirbuf.d_name[5],"ph",2)  != 0) &&
X		    (strncmp((char *)&dirbuf.d_name[5],"tty",3) != 0)) {
X			close(dfd);
X			return((char *)&dirbuf.d_name[5]);
X		}
X	   }
X	}
X
X	close(dfd);
X	return(NULL);
X}
X
Xwerror(errstr,mode)
Xchar *errstr;
Xint   mode;
X{
X	extern	char	*sys_errlist[];
X
X		/* Warn user about error */
X
X	if (mode == 0)
X	   eprintf(ST_SYS, ST_DISPLAY, NULL, "%s: %s: %s",
X		progname, errstr, sys_errlist[errno]);
X	else
X	   eprintf(ST_SYS, ST_DISPLAY, NULL, "%s: %s",
X		progname, errstr);
X
X		/* Log message in /usr/adm/logfile */
X
X	if (mode == 0)
X	   eprintf(ST_LOG, ST_DISPLAY, NULL, "logfile %s: %s: %s",
X		progname, errstr, sys_errlist[errno]);
X	else
X	   eprintf(ST_LOG, ST_DISPLAY, NULL, "logfile %s: %s",
X		progname, errstr);
X
X	home_cursor();
X	write(0,BLANK,WINSIZE);
X	exit(1);
X}
X
Xchar *getcommand()
X{
X    static struct user users;
X    long   upage;
X
X    if (!proc.p_stat || proc.p_stat == SIDL || proc.p_stat == SZOMB)
X	return 0;
X
X    if (!(proc.p_flag & SLOAD)) {
X	sprintf(buffer,"can't handle swapped process %d (flag=%05x)",
X		proc.p_pid, proc.p_flag);
X	werror(buffer,1);
X    }
X
X    upage = (long)ctob(proc.p_addr[0]);
X    read_mem((char *)&users, upage + U_OFFSET, (long) sizeof (struct user));
X
X    return(users.u_comm);
X}
END_OF_phdaemon
fi
if test 14239 -ne `wc -c <phdaemon.c`; then
    echo shar: \"phdaemon.c\" unpacked with wrong size!
fi
# end of overwriting check
echo shar: End of shell archive.
exit 0
--- cut here too --- --- cut here too --- --- cut here too --- --- cut here too
-- 
============================ US MAIL:   Lenny Tropiano, ICUS Computer Group
 IIIII   CCC   U   U   SSSS             PO Box 1
   I    C   C  U   U  S                 Islip Terrace, New York  11752
   I    C      U   U   SSS   PHONE:     (516) 968-8576 [H] (516) 582-5525 [W] 
   I    C   C  U   U      S  AT&T MAIL: ...attmail!icus!lenny  TELEX: 154232428
 IIIII   CCC    UUU   SSSS   UUCP:
============================    ...{uunet!godfre, harvard!talcott}!\
                         ...{ihnp4, boulder, mtune, skeeve, ptsfa}! >icus!lenny 
"Usenet the final frontier"        ...{cmcl2!phri, hoptoad}!dasys1!/