Newsgroups: comp.sources.unix From: phil@Shiva.COM (Phil Budne) Subject: v25i168: finger - Phil's Finger Program, Part05/07 Sender: unix-sources-moderator@pa.dec.com Approved: vixie@pa.dec.com Submitted-By: phil@Shiva.COM (Phil Budne) Posting-Number: Volume 25, Issue 168 Archive-Name: finger/part05 #! /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 args.c <<'END_OF_args.c' X/* X * args.c -- process arguments for finger / whoj X * January 1986 -- Year of the Commet X * X * Copyright (C) 1986, 1990 Philip L. Budne X * X * This file is part of "Phil's Finger Program". X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X */ X X# ifndef lint Xstatic char *rcsid = "$Id: args.c,v 3.0 90/07/06 13:10:18 budd Rel $"; X# endif /* lint not defined */ X X# include X# include X# include X# include X# include /* to get cannonical name */ X X# include "args.h" X# include "remote.h" X# include "finger.h" X# include "inquire.h" X Xextern dowhoj(), dofinger(); /* from output.c */ Xextern void ini_select(), addlocal(); /* from select.c */ Xextern BOOL have_local(); /* from select.c */ Xextern void ini_tsel(), addtty(); /* from getent.c */ Xextern char *ttyname(); /* from libc */ Xextern void doswitch(); /* from switch.c */ X XLOCAL RHOST *host_chain, *end_host_chain; /* chain of 4n hosts */ XGLOBAL int netfinger; /* input from socket */ XGLOBAL BOOL useinquire; /* have inquire database */ X XLOCAL void finger(); /* forward */ XLOCAL int isasocket(); /* forward */ XGLOBAL void add4n(); /* forward */ X XGLOBAL char localhost[ MAXHOSTLEN+1 ]; /* system /bin/hostname */ XGLOBAL char officialhostname[ MAXHOSTLEN*2 ]; /* official name from host table*/ XGLOBAL char OFFICIALhostname[ MAXHOSTLEN*2 ]; /* upper case copy */ XGLOBAL char **aliases; /* aliases for this host */ X XGLOBAL int main( argc, argv ) Xint argc; Xchar *argv[]; X{ X char *prog; X X netfinger = isasocket(0) && isasocket(1); /* are stdin and X * stdout sockets (pipes)? */ X X if( !netfinger && getuid() == 0 ) { /* if superuser */ X nice( -120 ); /* run fast */ X nice( 20 - 10 ); /* (absolute -10) */ X } /* superuser */ X X if( gethostname( localhost, MAXHOSTLEN ) == 0 ) { X struct hostent *h; X if( (h = gethostbyname( localhost )) != NULL ) { X int c; X char **a, **b; X X strcpy( officialhostname, h->h_name ); X strupcpy( OFFICIALhostname, officialhostname ); X X c = 0; X a = h->h_aliases; X while( *a++ != NULL ) /* count aliases */ X c++; X X a = h->h_aliases; X aliases = b = (char **) calloc( c + 1, sizeof( char * ) ); X while( (*b++ = savestr( *a++ )) != NULL ) X ; X } /* got host entry */ X } /* gethostname */ X X getterm(); /* get terminal stuff */ X X host_chain = end_host_chain = NULL; /* clear 4n host chain */ X X if( (prog = rindex(argv[0], '/')) != NULL ) /* isolate last part of path */ X prog++; /* skip slash */ X else X prog = argv[0]; X X init_tsel(); /* clear tty selectors */ X X finger(prog, argc, argv); X return( 0 ); /* ANSI conforming */ X} /* main */ X XLOCAL int isasocket( s ) Xint s; X{ X int l; X char sa[ 200 ]; /* bogus sockaddr struct */ X X l = sizeof( sa ); /* pass length by reference */ X if( getpeername( s, sa, &l ) < 0 ) X return( FALSE ); X else X return( TRUE ); X} /* isasocket */ X XLOCAL void unswitch( str ) X char *str; X{ X register char *cp; X if( (cp = index(str, '/')) != NULL ) { X *cp++ = EOS; X doswitch( cp ); X } /* found a slash */ X} /* unswitch */ X X XLOCAL void adduser( user ) Xchar *user; X{ X char *tp; /* char pointer */ X struct switches SavedSw; X X for( ; user != NULL; user = rindex(user, ',') ) { X X if( !skipwhite( &user ) ) /* remove leading white */ X continue; X X tp = user; /* remove trailing white */ X if( skipblack( &tp ) ) /* skip token. find EOS? */ X *tp = EOS; /* found white -- nuke it! */ X X tp = rindex(user, '@'); /* any ATs? (reverse -- for routing) */ X if( tp != NULL ) { /* oh goody! */ X *tp++ = EOS; /* blast at */ X add4n( user, tp ); /* add to list of aliens */ X continue; X } X X SavedSw = Sw; /* save flags */ X unswitch( user ); /* remove and process switches */ X addlocal( user ); /* process local user */ X Sw = SavedSw; /* per user switches */ X } /* for user */ X} /* adduser */ X XLOCAL void finger(prog, argc, argv) Xchar *prog; Xint argc; Xchar *argv[]; X{ X static char mytty[ 20 ]; X register char *cp, *tp; X X if( strcmp(prog, "whoj") == 0 ) X sw_jobs = TRUE; X X ini_select(); /* init selector tree etc.. */ X X# ifdef INQUIRE X useinquire = TRUE; X if( !Mapin( NULL ) ) { /* map in inquire database */ X useinquire = FALSE; X fprintf( stderr, "%s\n", inq_error ); X } /* Mapin failed */ X# endif /* INQUIRE defined */ X X tp = ttyname( 0 ); /* get device */ X if( tp != NULL ) { X if( strncmp( tp, "/dev/", 5 ) == 0 ) X tp += 5; X strcpy( mytty, tp ); X } X else X mytty[0] = EOS; X X# ifdef NETBERK X if( netfinger ) /* from network? */ X sw_berkeley = TRUE; /* be verbose if asked by name */ X /* I hate it, but it helps aliens */ X /* with lousy finger programs */ X# endif /* NETBERK defined */ X X if( strcmp(prog, "whois") == 0 ) /* invoked as whois? */ X sw_whois = TRUE; /* yes, set flag now */ X else if( strcmp(prog, "xf") == 0 ) /* xf? */ X sw_nosave = TRUE; /* be nice (don't write nm file) */ X X argv++; X argc--; X while( argc > 0 ) { /* while more args */ X struct switches SavedSw; X X switch( argv[0][0] ) { X case '-': X case '/': /* switch */ X doswitch( &argv[0][1] ); X break; X X case '+': /* tty */ X SavedSw = Sw; X unswitch( &argv[0][1] ); X addtty( &argv[0][1] ); X Sw = SavedSw; /* per user switches */ X break; X X case '.': /* just dot */ X SavedSw = Sw; X unswitch( &argv[0][1] ); X if( argv[0][1] != EOS ) X fprintf( stderr, "%%Garbage after DOT: %s\n", &argv[0][1] ); X X if( mytty[0] != EOS ) X addtty( mytty ); /* do us. */ X else X fprintf( stderr, "%%Could not get own terminal for '.'\n" ); X Sw = SavedSw; /* per user switches!! */ X break; X X case '\\': /* quoting against local switch */ X /* expansion? */ X adduser( argv[0]+1 ); X break; X X default: /* must be a user */ X adduser( argv[0] ); X break; X } /* switch */ X argv++; X argc--; X } /* while argc */ X X read_conf(); /* read finger.conf */ X /* after switches!! */ X X if( sw_jobs ) { X dowhoj(); X return; X } X X if( !have_locals() && host_chain == NULL ) /* no hard work */ X dofinger( NULL ); /* show logged in users */ X X if( have_locals() ) { /* /follow may have added locals! */ X struct switches SavedSw; X sw_t SavedWhois; X X SavedSw = Sw; /* save flags */ X SavedWhois = sw_whois; X if( sw_berkeley ) { /* in berkley emulation mode? */ X sw_whois = TRUE; /* yes, be verbose */ X Sw.sw_plan = !Sw.sw_noplan; X } X X# ifdef NETFOLLOW X if( netfinger ) /* only follow if network AND people */ X sw_follow = TRUE; X# endif /* NETFOLLOW defined */ X X select_go(); /* run locals */ X X Sw = SavedSw; /* restore flags */ X sw_whois = SavedWhois; /* before doing remote!! */ X } /* else */ X X if( host_chain != NULL ) X doremote( host_chain ); X X} /* finger */ X XLOCAL RHOST *mkrhost( name ) Xchar *name; X{ X register RHOST *rh; X if( (rh = (RHOST *)malloc( sizeof( RHOST ) )) == NULL ) { X perror("mkrhost malloc failed"); X exit( 1 ); X } /* malloc failed */ X X rh->rh_name = name; X rh->rh_next = NULL; X rh->rh_user = rh->rh_endu = NULL; X X return( rh ); X} /* mkrhost */ X XLOCAL RUSER *mkruser( name ) Xchar *name; X{ X register RUSER *ru; X if( (ru = (RUSER *)malloc( sizeof( RUSER ) )) == NULL ) { X perror("mkruser malloc failed"); X exit( 1 ); X } /* malloc failed */ X X ru->ru_name = name; X ru->ru_next = NULL; X return( ru ); X} /* mkruser */ X XGLOBAL void add4n( user, host ) Xchar *user, *host; X{ X if( *host == EOS ) { X fprintf(stderr, "?Empty hostname\n"); X } X else { /* has host */ X register RHOST *hp; /* host pointer */ X X for( hp = host_chain; hp != NULL; hp = hp->rh_next ) X if( strcmp(hp->rh_name, host) == 0 ) X break; X X if( hp == NULL ) { /* search failed */ X if( host_chain == NULL ) /* empty chain? */ X host_chain = end_host_chain = hp = mkrhost( host ); /* make1 */ X else { /* add new host */ X hp = mkrhost( host ); /* create node */ X end_host_chain->rh_next = hp; /* add after last */ X end_host_chain = hp; /* point end to me */ X } /* add new host */ X X hp->rh_user = hp->rh_endu = mkruser( user ); /* create usr chain */ X } /* search failed */ X else { /* search won */ X register RUSER *up; X X up = mkruser( user ); /* create user node */ X hp->rh_endu->ru_next = up; /* add after last for this host */ X hp->rh_endu = up; /* point end of list to us */ X } /* add to existing chain (search won) */ X } /* non-empty host */ X X# ifdef DEBUG X if( *user == EOS ) X printf(" @%s\n", host); X else X printf("%s@%s\n", user, host); X# endif /* DEBUG defined */ X} /* add 4n */ X XGLOBAL BOOL islocalhost( s ) X char *s; X{ X struct hostent *h; X char **a; X X if( strcmp( s, officialhostname ) == 0 || strcmp( s, localhost ) == 0 ) X return( TRUE ); X X a = aliases; X while( *a != NULL ) X if( strcmp( s, *a++ ) == 0 ) X return( TRUE ); X X if( (h = gethostbyname( s )) == NULL ) X return( FALSE ); X X if( strcmp( h->h_name, officialhostname ) == 0 ) X return( TRUE ); X X return( FALSE ); X} /* islocalhost */ X X/* X * Local variables: X * comment-column: 40 X * End: X */ END_OF_args.c if test 9817 -ne `wc -c autoconfig <<'END_OF_autoconfig' X#! /bin/sh X# X# Automatic configuration shell script for finger X# Not quite up to Larry Wall's level... X# X# Copyright (C) 1988, 1990 Philip L. Budne X# X# This file is part of "Phil's Finger Program". X# X# This program is free software; you can redistribute it and/or modify X# it under the terms of the GNU General Public License as published by X# the Free Software Foundation; either version 1, or (at your option) X# any later version. X# X X# $Id: autoconfig,v 3.0 90/07/06 13:10:22 budd Rel $ X X# X# XTMPDIR=/tmp X# XSYSTEM='' X# XE=/bin/echo X# X# blank line XB=$E X# X# should return status XCONTAINS=grep X# X# hope its on your path, or built in XT=test X# end test XET= X# X# test flags: X# X# existance XEXI=-f X# directory XDIR=-d X# negation XNOT=! X# XOR=-o XAND=-a XSTR= XLP='(' XRP=')' X# X# S5 XBLK=-b XCHR=-c X# also -f means regular file only! X# X# shorthand... XTEXI="$T $EXI" XTSTR="$T $STR" XTDIR="$T $DIR" X# Xif $TEXI /bin/hostname $ET; then X HOSTNAME=`/bin/hostname` Xelif $TEXI /bin/uname $ET; then X HOSTNAME=`/bin/uname -n` Xelse X HOSTNAME='idunno' Xfi X# X$E '/*' X$E ' * local.h for '$HOSTNAME X$E ' * created on '`date` by `./mywhoami` using autoconfig X$E ' *' X$E ' * do not edit this file. instead put #define and #undef lines' X$E ' * in the file local-flags which is inserted at the end of this file.' X$E ' */' X$B X################ Xif $TEXI /bin/sun $ET && /bin/sun; then X # check for /usr/lib/liblwp.a ? X if $TDIR /var $ET; then X if $TEXI /bin/uname $ET; then X SOS=`uname -r -v | sed -e 's/\.//g' -e 's/ //g'` X elif $TDIR /usr/kvm $ET; then X # consdev fixed/broken in 4.0.3 X SOS=403 X else X SOS=400 X fi X else X # 3.something X SOS=300 X fi X $E '# define SunOS '$SOS X $B Xelif $TEXI /Umax.image $ET; then X if $TDIR /var $ET; then X $E '# define Umax 43 /* Encore Umax 4.3 */' X else X $E '# define Umax 42 /* Encore Umax 4.2 */' X fi X $B Xelif $CONTAINS BSD4_3 /usr/include/sys/param.h > /dev/null; then X $E '# define bsd4_3' X $B Xfi X# accel, ultrix cpp have predefines X################ X# Sun, A/UX Xif $TEXI /etc/in.rlogind $OR $EXI /usr/etc/in.rlogind $ET; then X $E '# define IN_DOT_DAEMON /* internet daemon names prefixed with in. */' X $B Xfi X################ X# check for /usr/adm/lastlog as well? Xif $TEXI /usr/include/lastlog.h $ET; then X $E '# define LASTLOG /* BSD last login file */' X $B Xfi X################ X# check libc.a for wait3?? Xif $T $NOT $EXI /usr/include/sys/wait.h $ET; then X $E '# define NO_WAIT_H /* no BSD sys/wait.h */' X $B Xfi X################ X# BSD systems have drum X# use checkmode to avoid incompatabilities in test X# RT AIX and UmaxV lack /dev/swap Xif ./checkmode /dev/drum 0 >/dev/null 2>&1; then X $E '# define SWAP_DEVICE "/dev/drum" /* swap device */' X $B Xelif ./checkmode /dev/swap 0 >/dev/null 2>&1; then X $E '# define SWAP_DEVICE "/dev/swap" /* swap device */' X $B X USG=true Xelif $T $CHR /dev/ipldevice $ET; then X $E '# define AIX3 /* AIX release 3 (RS/6000) */' X USG=true Xelif $TEXI /bin/vrmfmt $ET; then X # AIX defined by cc command (what about PS/2 AIX?) X USG=true X UNDERSCORE=true X $E '# define AIX_RT /* IBM PC/RT AIX */' X $B Xelif $T $CHR /dev/bbram $ET; then X $E '# define UmaxV /* Encore Umax V */' X $B X USG=true X UNDERSCORE=true Xelif $TEXI /usr/include/sys/sysi86.h $ET; then X # Interactive SVR3.2 (others?) X USG=true X $E '# define SYSI86 /* 386/ix */' X $B Xfi X#### Xif $TSTR "$USG" $ET; then X $E '# define USG /* AT&T Unix */' X $B X if $T $CHR /dev/pts1 $ET; then X # AIX at least... X $E '# define PTYPATH "/dev/pts1"' X $B X $E '# define PTS_PTY_NAMES' X $B X elif $T $CHR /dev/ttyq1 $ET; then X # SGI at least... X $E '# define PTYPATH "/dev/ttyq1"' X $B X fi X if $TEXI /usr/include/sys/dir.h $ET; then X $E '# define DIR_H' X $B X fi X if $TEXI /usr/include/sys/i386/ps2mous.h $ET; then X $E '# define AIX_PS2' X $B X fi Xfi X################ Xif $TEXI /usr/include/filehdr.h $ET; then X $E '# define COFF /* Common Object File Fiasco */' X $B Xelse X UNDERSCORE=true Xfi X#### Xif $TSTR "$UNDERSCORE"; then X $E '# define UNDERSCORE_NLIST_NAMES' X $B Xfi X################ X# SOS3.4 has (empty) stream.h! Xif $TEXI /usr/include/sys/stropts.h $ET; then X $E '# define STREAMS' X $B Xfi X################ X# check for SVR3 state names Xif $CONTAINS SXBRK /usr/include/sys/proc.h >/dev/null; then X $E '# define SVR3_STATES' X $B Xfi X################ X# check for short *{u,p}_ttyp (streams tty driver) sgi and SOS4 Xif $CONTAINS 'short[ ]*\*[ ]*[ups]_ttyp' \ X /usr/include/sys/user.h /usr/include/sys/proc.h >/dev/null 2>&1 || X $TEXI /usr/include/sys/session.h $ET; then X $E '# define SHORT_TTYP' X $B Xfi X################ X# p_addr on AOS/ACIS 4.3 (RT) loses Xif $TDIR /usr/ibm $ET; then X $E '# define NEED_USRPT' X $B Xfi X################ X# USG uname(2) call (or simulation) X# perhaps grep nm of libc.a too? Xif $TEXI /usr/include/sys/utsname.h $ET; then X $E '# define UTSNAME /* USG uname(2) call */' X $B Xfi X################ Xif $T $NOT $EXI /usr/include/strings.h $ET; then X $E '# define NO_STRINGS_H /* No BSD strings */' X $B Xfi X################ XLIB=/lib/libc.a XLIBNM=/tmp/auto$$ Xif $TEXI /usr/include/netdb.h $ET && \ X $CONTAINS h_errno /usr/include/netdb.h >/dev/null; then X $E "netdb.h has h_errno. Checking libc.a..." 1>&2 X nm $LIB > $LIBNM X if $CONTAINS 'h_errlist' $LIBNM >/dev/null; then X $E "The world is safe! $LIB contains h_errlist" 1>&2 X $E '# define HAVE_H_ERRNO /* found h_errno */' X else X# SunOS 4.0 strikes again! X $E "$LIB lacks h_errlist!!" 1>&2 X fi X $B X rm -f $LIBNM Xfi X################ Xif $TEXI /bin/write $ET; then X if ./checkmode /bin/write gs >/dev/null; then X set foo `./getgroup /bin/write` X $E "# define TTY_GROUP_NUMBER $3" X $B X if $TSTR "$4" $ET; then X $E '# define TTY_GROUP "'$4'"' X $B X fi X fi Xfi X################ X# for Install.cpp -- shell orif to avoid confusing BSD test with -c X# check for protected swap device as well?? Xif $TEXI /dev/kmem $ET || $T $CHR /dev/kmem $ET; then X if ./checkmode /dev/kmem gr+o gr >/dev/null; then X $E '/* for Install.cpp */' X set foo `./getgroup /dev/kmem` X if $TSTR "$4" $ET; then X $E "# define KMEM_GROUP $4" X else X $E "# define KMEM_GROUP $3" X fi X $B X fi Xfi X################ Xif $TEXI /bin/domainname $ET; then X YPDOMAIN=`/bin/domainname` Xelif $TEXI /usr/bin/domainname $ET; then X YPDOMAIN=`/usr/bin/domainname` Xfi X################ Xif $TEXI /etc/ypbind $OR $EXI /usr/etc/ypbind $ET; then X if $TSTR "$YPDOMAIN" $ET; then X $E "IF YOU ARE NOT USING YP, YOU MAY NEED TO DEFINE 'GETPWNAM_SLOW'"\ X 1>&2 X $E '/* getpwnam(3) is fast (yellow pages) */' X else X $E "IF YOU ARE USING YP, YOU MAY WANT TO UNDEFINE 'GETPWNAM_SLOW'"\ X 1>&2 X $E '# define GETPWNAM_SLOW /* yp not enabled */' X fi Xelif $TEXI /etc/passwd.pag $OR $EXI /etc/passwd.dir $ET; then X $E '/* getpwnam(3) is fast (dbm passwd file) */' Xelse X $E '# define GETPWNAM_SLOW /* 4.2 getpwnam(3) is losing */' Xfi X$B X################ X# should check libc.a for yp_match.o Xif $TEXI /usr/include/rpcsvc/ypclnt.h $AND $STR "$YPDOMAIN" $ET; then X $E '# define HAVE_YP_MATCH /* have yp_match(3) */' X $B Xfi X################ Xif $TEXI /etc/aliases $ET; then X ALIASES=/etc/aliases Xelif $TEXI /usr/lib/aliases $ET; then X ALIASES=/usr/lib/aliases Xfi X# Xif $TSTR "$ALIASES" $ET; then X $E '# define ALIASES "'$ALIASES'" /* sendmail aliases file */' X $B Xfi X################ X# 4.3 and Ultrix X# note: use exists. let them see grep error! Xif $TEXI /usr/include/sys/tty.h $ET; then X if $CONTAINS t_winsize /usr/include/sys/tty.h >/dev/null; then X $E '# define TTY_REQUIRES_IOCTL /* struct winsize */' X $B X fi Xfi X################ X# 4.3 and Ultrix X# perhaps search libc.a too? Xif $TEXI /usr/include/ttyent.h $ET; then X $E '# define TTYENT /* use getttyent(3) */' X $B Xfi X################ X# 4.3, Ultrix and Sun Xif $TEXI /etc/inetd $OR $EXI /usr/etc/inetd $ET; then X $E '# define INETD /* use inetd for fingerd */' X $B Xfi X################ X# SunOS 4.x, Ultrix 3.x, SVR3? Xif $CONTAINS 'void.*signal' /usr/include/signal.h >/dev/null; then X $E '# define VOIDSIG /* signal() declared as void * */' X $B Xfi X################ X# Ultrix 3.x, A/UX Xif $CONTAINS p_ttyp /usr/include/sys/proc.h >/dev/null; then X $E '# define P_TTYP /* tty pointer in proc struct */' X $B Xfi X################ X# USG Xif $CONTAINS ut_host /usr/include/utmp.h >/dev/null; then X $E '/* utmp has ut_host field */' Xelse X $E '# define UTMP_NO_HOST /* utmp file lacks host field */' Xfi X$B X################ Xif $TEXI /vmunix $ET; then X $E '# define KERNEL_FILE "/vmunix"' Xelif $TEXI /unix $ET; then X $E '# define KERNEL_FILE "/unix"' Xelif $TEXI /dynix $ET; then X $E '# define KERNEL_FILE "/dynix"' Xelif $TEXI /Umax.image $ET; then X $E '# define KERNEL_FILE "/Umax.image"' Xelse X $E '/* no KERNEL_FILE found */' Xfi X$B X################ X# AIX has both? check /usr/mail first!! Xif $TDIR /usr/mail $ET; then X $E '# define MAIL_SPOOL "/usr/mail"' Xelif $TDIR /usr/spool/mail $ET; then X $E '# define MAIL_SPOOL "/usr/spool/mail"' Xelse X $E '/* no MAIL_SPOOL found */' Xfi X$B X################ Xif $TEXI /usr/include/syslog.h $ET; then X $E '# define SYSLOG /* fingerd does syslog-ing */' X $B Xfi X################ Xif $TEXI /usr/include/inquir.h $ET; then X $E '# define INQUIRE /* use inquire database */' X $B Xfi X X# Boilerplate... Xcat <getperson.c <<'END_OF_getperson.c' X/* X * getperson.c -- read person oriented data (December 1985) X * X * Copyright (C) 1986, 1990 Philip L. Budne X * X * This file is part of "Phil's Finger Program". X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X */ X X# ifndef lint Xstatic char *rcsid = "$Id: getperson.c,v 3.0 90/07/06 13:10:51 budd Rel $"; X# endif /* lint not defined */ X X# include X# include X# include X# include X# include /* getpwent defns */ X# ifdef INQUIRE X# include X# endif /* INQUIRE defined */ X# include "person.h" X# include "args.h" /* before luser.h */ X# include "luser.h" X# include "finger.h" X X# ifndef DEFSHELL X# define DEFSHELL "/bin/csh" /* dull shell */ X# endif /* DEFSHELL not defined */ X X# ifndef PRJLEN X# define PRJLEN 70 /* max lex for project */ X# endif /* PRJLEN not defined */ X Xextern char *strip(); /* from string.c */ Xextern BOOL useinquire; X XPERSON *makeperson(); /* forward... */ X XGLOBAL int treesize( t ) /* count entries in a tree */ Xregister LUSER *t; X{ X if( t == NULL ) X return( 0 ); X else X return( treesize( t->u_left ) + treesize( t->u_right ) + 1 ); X} X XGLOBAL LUSER *treefind(t, uname) /* find uname in tree */ Xregister LUSER *t; Xchar *uname; X{ X register int compare; X X while( t != NULL ) { X# ifdef DEBUG X printf(" tf '%s' ", uname ); X fflush(stdout); X printf(" '%s'", t->u_user ); X fflush(stdout); X# endif /* DEBUG defined */ X compare = strcmp(uname, t->u_user); /* do compare once */ X# ifdef DEBUG X printf(" %d\n", compare ); X# endif /* DEBUG defined */ X if( compare > 0 ) X t = t->u_right; X else if( compare < 0 ) X t = t->u_left; X else X return( t ); X } X return( NULL ); X} /* treefind */ X X# ifdef GETPWNAM_SLOW XGLOBAL int pwtree( t ) /* get pw entries for whole tree */ XLTREE *t; X{ X register struct passwd *pw; X int size, todo; /* number of tree entries */ X X size = todo = treesize( t ); /* get entries in tree */ X if( todo == 0 ) X return( 0 ); /* nothing to do! */ X X setpwent(); X while( todo > 0 && (pw = getpwent()) != NULL ) { /* for each pwentry */ X /* search in tree for this uname */ X /* if found, create a person struct */ X /* and look for multiple logins */ X X register LUSER *tp; X register PERSON *pp; X X# ifdef DEBUG X printf("pwtree(%d): %s\n", todo, pw->pw_name ); X# endif /* DEBUG defined */ X X tp = t; /* get root of tree */ X pp = NULL; /* no person entry created yet */ X X tp = treefind(tp, pw->pw_name); /* lookup user in tree */ X while( todo > 0 && tp != NULL ) { X if( tp->u_person != NULL ) /* already have person? */ X break; /* must be is passwd twice! (or yp) */ X X todo--; /* one less to do */ X# ifdef DEBUG X printf(" ** %s **\n", tp->u_user ); X# endif /* DEBUG defined */ X if( pp == NULL ) /* created a person yet? */ X pp = makeperson(tp,pw,NULL); /* do it now. */ X pp->p_count++; /* bump use count */ X tp->u_person = pp; /* point user to person */ X tp = treefind(tp->u_right, pw->pw_name); /* lookup again */ X /* assumes that dupes are added */ X /* to right side (.see insert)*/ X } /* while tp != NULL */ X } /* while getpwent */ X endpwent(); X return( size ); X} /* pwtree */ X# else /* GETPWNAM_SLOW not defined */ XLOCAL int pwtree2_count; /* ah for pascal */ XLOCAL void pwtree2(); /* forward */ X XGLOBAL int pwtree( t ) XLTREE *t; X{ X setpwent(); /* getpwnam does set/end */ X /* so this is a noop */ X pwtree2_count = 0; X pwtree2( t ); X endpwent(); X return( pwtree2_count ); X} /* pwtree */ X XLOCAL void pwtree2( t ) /* fill in person entries */ XLTREE *t; /* using getpwnam */ X{ X register struct passwd *pw; X register LUSER *tp; X register PERSON *pp; X X# ifdef DEBUG X printf("pwtree2(%d): %s\n", todo, pw->pw_name ); X# endif /* DEBUG defined */ X X tp = (LUSER *)t; /* get root of tree */ X pp = NULL; /* no person entry created yet */ X X if( tp == NULL ) X return; X X while( tp != NULL && tp->u_person == NULL ) { X if( pp == NULL ) { /* created a person yet? */ X if( (pw = getpwnam( tp->u_user )) == NULL ) X break; X pp = makeperson(tp,pw,NULL); /* do it now. */ X } X pp->p_count++; /* bump use count */ X pwtree2_count++; X tp->u_person = pp; /* point user to person */ X tp = treefind(tp->u_right, pw->pw_name); /* lookup again */ X /* assumes that dupes are added */ X /* to right side (.see insert)*/ X } /* while tp != NULL */ X X pwtree2( t->u_right ); X pwtree2( t->u_left ); X X} /* pwtree2 */ X# endif /* GETPWNAM_SLOW not defined */ X XGLOBAL PERSON *makeperson( up, pw, inq ) XLUSER *up; Xstruct passwd *pw; Xstruct info *inq; X{ X char fname[100], pbuf[ PLEN+1 ]; X register PERSON *pp; X register char *dp; X register int i; X char *sp; X int file; X X if( (pp = (PERSON *) malloc( sizeof( PERSON ) )) == NULL ) X return( NULL ); X X pp->p_count = 0; X pp->p_flags = 0; /* clear flags */ X pp->p_waddr = pp->p_wphone = pp->p_hphone = pp->p_haddr = NULL; X pp->p_birthday = pp->p_supervisor = pp->p_project = pp->p_nickname = NULL; X pp->p_maddr = pp->p_personal = pp->p_home = NULL; X pp->p_remarks = pp->p_shell = NULL; X pp->p_group = pp->p_relation = ' '; X X if( pw != NULL ) { /* !! */ X pp->p_uid = pw->pw_uid; /* copy user id */ X pp->p_gid = pw->pw_gid; /* copy group id */ X pp->p_home = savestr( pw->pw_dir ); /* home directory */ X X maddr( pp, pw->pw_name ); /* get mailing address */ X X sp = pw->pw_gecos; /* source pointer */ X if( strcmp(sp, "RC") == 0 ) { /* gecos == "RC" */ X pp->p_flags |= P_RC; /* flag it */ X return( pp ); X } /* RC */ X } X else X pp->p_flags |= P_NOPWENT; X X# ifdef INQUIRE X if( pw != NULL ) X name = pw->pw_name; X else /* seems unlikely, but */ X name = up->u_user; /* of use when yp kaput! */ X if( useinquire && doinquire( name, pp, inq ) ) /* check holmes database */ X pp->p_flags |= P_INQUIRE; /* flag it */ X# else /* INQUIRE not defined */ X acct_group( pp ); X# endif /* INQUIRE not defined */ X X if( pw != NULL && pp->p_personal == NULL ) { X dp = pbuf; /* pointer to dest */ X for( i = 0; i < PLEN; i++ ) { /* for max len of personal name */ X if( *sp == EOS || *sp == ',' ) X break; X if( *sp == '&' ) { /* sigh, handle ampersand crock */ X register char *unp; /* uname pointer */ X unp = pw->pw_name; /* get pointer to user name */ X if( islower( *unp ) && (i == 0 || isspace(sp[-1])) ) { X *dp++ = toupper( *unp ); X unp++; /* avoid side effect as macro arg */ X i++; X } /* first char is lower */ X X while( i < PLEN && *unp != NULL ) { /* copy it in */ X i++; X *dp++ = *unp++; X } /* while */ X sp++; X } /* & */ X else X *dp++ = *sp++; X } /* for i */ X *dp = EOS; X pp->p_personal = savestr( pbuf ); X } /* have pw entry, no personal name */ X X if( !sw_whois ) /* **** doing full? **** */ X return( pp ); /* no, quit now */ X X if( pw != NULL && X (pp->p_waddr == NULL || X pp->p_wphone == NULL || pp->p_hphone == NULL ) ) { X X /* BUG: handle USG format gecos data */ X sp = index(pw->pw_gecos, ','); /* anything after user? */ X while( sp != NULL ) { /* radioactive waste *BOGUS LOOP* */ X sp++; /* skip comma */ X X if( !skipwhite( &sp ) ) X break; /* break bogus loop */ X /* avoids harmful goto! */ X dp = index(sp, ','); X if( dp != NULL ) X *dp++ = EOS; X sp = strip( sp ); X if( pp->p_waddr == NULL && strlen( sp ) > 0 ) X pp->p_waddr = savestr( office( sp ) ); X if( dp == NULL ) X break; /* break bogus loop */ X X sp = dp; X if( !skipwhite( &sp ) ) X break; /* break bogus loop */ X X dp = index(sp, ','); X if( dp != NULL ) X *dp++ = EOS; X sp = strip( sp ); X if( *sp != EOS ) X if( pp->p_wphone == NULL ) X pp->p_wphone = savestr( sp ); X X if( dp == NULL ) X break; /* break bogus loop */ X X sp = dp; X if( !skipwhite( &sp ) ) X break; /* break bogus loop */ X X sp = strip( sp ); X if( *sp != EOS ) X if( pp->p_hphone == NULL ) X pp->p_hphone = savestr( sp ); X X break; /* break bogus loop */ X } /* process radioactive waste (gecos) */ X } /* pw entry & missing info from GECOS */ X X if( pw != NULL ) { X if( strcmp(pw->pw_shell, DEFSHELL) != 0 ) X pp->p_shell = savestr( pw->pw_shell ); X else X pp->p_shell = NULL; X X if( pp->p_project == NULL ) { X strcpy(fname, pp->p_home); X strcat(fname, "/.project"); X while( (file = open(fname, 0)) >= 0 ) { X char prjbuf[PRJLEN]; X char *cp; X int cc; X X cc = read(file, prjbuf, PRJLEN-1); X close(file); X if( cc < 1 ) X break; /* leave bogus loop */ X prjbuf[cc] = EOS; X X if( (cp = index(prjbuf, '\n')) != NULL ) X *cp = EOS; X X cp = strip( prjbuf ); X if( *cp != EOS ) X pp->p_project = savestr( cp ); X break; /* leave bogus loop */ X } /* found project */ X } /* look at .project file */ X } /* have pw entry */ X return( pp ); X} /* makeperson */ X X/* X * Local variables: X * comment-column: 40 X * End: X */ END_OF_getperson.c if test 9142 -ne `wc -c readpr.c <<'END_OF_readpr.c' X/* X * readpr.c -- read process table X * X * Copyright (C) 1986, 1990 Philip L. Budne X * X * This file is part of "Phil's Finger Program". X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X */ X X# ifndef lint Xstatic char *rcsid = "$Id: readpr.c,v 3.0 90/07/06 13:11:38 budd Rel $"; X# endif /* lint not defined */ X X# include "finger.h" X# include "waitstate.h" X# ifndef Umax X X# include X# include "ustruct.h" X X# ifdef USG X# include X# endif /* USG defined */ X X# ifndef SIGHUP X# include X# endif /* SIGHUP not defined */ X X# include "pr.h" X# include "kmem.h" X# include "info.h" /* after finger.h */ X# include "args.h" /* for debugsw */ X X/* # define DEBUG_READPR /* dump all pr's */ X X# ifndef UTMP_NO_HOST X# define MUST_HAVE_TTY /* run a bit faster */ X# endif /* UTMP_NO_HOST not defined */ X Xextern struct info I; /* namelist values from names.c */ Xextern struct user *ustruct(); /* from ustruct.c */ Xextern void u_cleanup(); /* from ustruct.c */ X Xextern FTYPE kmem; /* fd for /dev/kmem */ X /* (more under SunOS 4.0) */ X# if SunOS < 400 Xextern FTYPE mem; /* fd for /dev/mem */ Xextern FTYPE swap; /* fd for /dev/drum */ X /* from kmem.c */ X# endif /* SunOS < 400 */ X XFORWARD LOCAL enum sig istate(); X XLOCAL int nproc; /* kernel nproc */ XLOCAL struct proc *aproc; /* kernel virt addr of process table */ X X/* X * readpr finds and reads in the array pr, containing the interesting X * parts of the proc and user tables for each live process. X */ X X# ifdef AIX3 X# define MAXPROC 512 X XGLOBAL struct pr *readpr() { X int i, n; X struct pr *prvec; X struct procinfo pivec[MAXPROC]; X register struct pr *prp; X register struct procinfo *pip; X X n = getproc( pivec, MAXPROC, sizeof( struct procinfo ) ); X if( n < 1 ) { X /* Check errno, report of MAXPROC too small!!! */ X return( NULL ); X } X X prvec = (struct pr *) calloc( n+1, sizeof( struct pr ) ); X if( prvec == NULL ) X return( NULL ); X X prp = prvec; X for( i = 0, pip = pivec; i < n; i++, pip++ ) { X struct userinfo ui; X X if( pip->pi_stat == 0 ) X continue; X X if( getuser( pip, sizeof( struct procinfo ), X &ui, sizeof( struct userinfo ) ) < 0 ) X continue; X X prp->pr_uid = pip->pi_uid; X prp->pr_pid = pip->pi_pid; X prp->pr_ppid = pip->pi_ppid; X prp->pr_pgrp = pip->pi_pgrp; X prp->pr_stat = pip->pi_stat; X prp->pr_flag = pip->pi_flag; X prp->pr_wchan = pip->pi_wchan; X X prp->pr_ttyp = ui.ui_ttyp; X prp->pr_ttyd = ui.ui_ttyd + ui.ui_ttympx; X X strzcpy(prp->pr_cmd, ui.ui_comm, sizeof( ui.ui_comm ) ); X# ifdef DEBUG_READPR X dumppr( prp ); X# endif /* DEBUG_READPR defined */ X prp++; X } X prp->pr_stat = 0; /* mark end */ X X# ifdef DEBUGSW X if( sw_debug ) X printf("read %d processes\n", prp - prvec ); X# endif /* DEBUGSW defined */ X X /* realloc prvec to size? */ X return( prvec ); X} X X# else /* AIX3 not defined */ X XGLOBAL struct pr *readpr() { X register struct pr *prp; /* current pr entry */ X register int i; /* loop index */ X struct user *upp; /* pointer to upage(s) */ X struct proc *mpp; /* ptr to current process */ X struct pr *prvec; X struct proc *allproc; /* whole process table */ X# ifdef USG X struct var v; X# endif /* USG defined */ X# if SunOS >= 410 X struct sess sess; X# endif /* SunOS >= 410 */ X X if( !ini_kmem() ) /* initialize /dev/kmem etc. */ X return( NULL ); X X# ifdef USG X KMEMREAD(I.info_v, &v, sizeof( v ) ); /* var struct */ X nproc = v.v_proc; /* size of proc table */ X aproc = (struct proc *) I.info_proc; /* addr of proc table */ X# else /* USG not defined */ X KMEMREAD(I.info_nproc, &nproc, sizeof( nproc )); /* size of proc tbl */ X KMEMREAD(I.info_proc, &aproc, sizeof( aproc )); /* addr of proc tbl */ X# endif /* USG not defined */ X X# ifdef DEBUG_READPR X printf("nproc %d aproc %#x\n", nproc, aproc ); X# endif /* DEBUG_READPR defined */ X X prvec = (struct pr *)calloc(nproc+1, sizeof(struct pr));/* allocate tbl */ X if( prvec == NULL ) X return( NULL ); X X allproc = (struct proc *) calloc(nproc, sizeof( struct proc ) ); X KMEMREAD(aproc, allproc, nproc * sizeof( struct proc ) ); X mpp = allproc; X X prp = prvec; /* pointer to dest block */ X for( i = 0; i < nproc; i++, mpp++ ) { /* for all processes */ X if( mpp->p_stat == 0 || mpp->p_stat == SZOMB ) /* a zombie or worse? */ X continue; /* forget it */ X X# ifdef SSYS X if( mpp->p_flag & SSYS ) /* swapper or pager? */ X continue; /* flush */ X# endif /* SSYS defined */ X X# ifdef SWEXIT X if( mpp->p_flag & SWEXIT ) /* exiting? */ X continue; /* nevermind. */ X# endif /* SWEXIT defined */ X X# if defined(MUST_HAVE_TTY) && defined(P_TTYP) X /* avoid fetching ustruct needlessly */ X if( mpp->p_ttyp == NULL ) /* no terminal pointer? */ X continue; X# endif /* defined(MUST_HAVE_TTY) && defined(P_TTYP) */ X X# if SunOS >= 410 X if( mpp->p_sessp == NULL || X !KMEMREAD( (long)mpp->p_sessp, (char *)&sess, sizeof(sess) ) ) { X# ifdef MUST_HAVE_TTY X continue; X# else /* MUST_HAVE_TTY not defined */ X sess.s_ttyp = NULL; X# endif /* MUST_HAVE_TTY not defined */ X } /* no session or kmem read failed */ X# endif /* SunOS >= 410 */ X X if( (upp = ustruct( mpp )) == NULL ) /* get ustruct? */ X continue; /* no point. */ X X# ifdef DEBUGSW X if( sw_debug && ((unsigned)upp->u_procp) != ((unsigned)(aproc + i)) ) X printf("%%Funny u struct for pid %d u_procp %#x != %#x\n", X mpp->p_pid, upp->u_procp, (aproc + i) ); X# endif /* DEBUGSW defined */ X X /* X * WISH: X * check for master /etc/inetd /etc/rlogind etc??? (as a way to X * establish root of a process tree and avoid stray background X * processes on that tty) and keep only descendants thereof. X */ X X# if 0 /* since we already have ustruct, just keep it! */ X# if defined(MUST_HAVE_TTY) && !defined(P_TTYP) && SunOS < 410 X if( upp->u_ttyp == NULL ) /* no terminal pointer? */ X continue; X# endif /* defined(MUST_HAVE_TTY) && !defined(P_TTYP) && SunOS < 410 */ X# endif /* 0 */ X X /* save the interesting parts */ X prp->pr_uid = mpp->p_uid; /* user id */ X prp->pr_pid = mpp->p_pid; /* pid */ X prp->pr_ppid = mpp->p_ppid; /* parent pid */ X prp->pr_pgrp = mpp->p_pgrp; /* process group leader pid */ X prp->pr_stat = mpp->p_stat; /* state (1..6) */ X prp->pr_flag = mpp->p_flag; /* flags (esp swap) */ X prp->pr_wchan = mpp->p_wchan; /* wait address */ X X# if SunOS >= 410 X prp->pr_ttyp = sess.s_ttyp; X prp->pr_ttyd = sess.s_ttyd; X# else /* not SunOS >= 410 */ X# ifdef P_TTYP X prp->pr_ttyp = mpp->p_ttyp; /* pointer to tty structure */ X# else /* P_TTYP not defined */ X prp->pr_ttyp = upp->u_ttyp; /* pointer to tty structure or tpg */ X# endif /* P_TTYP not defined */ X prp->pr_ttyd = upp->u_ttyd; /* device number */ X# endif /* not SunOS >= 410 */ X prp->pr_hup = istate( upp->u_signal[SIGHUP] ); X prp->pr_intr = istate( upp->u_signal[SIGINT] ); X prp->pr_quit = istate( upp->u_signal[SIGQUIT]); X /* what you've all been waiting for... */ X strzcpy(prp->pr_cmd, upp->u_comm, sizeof( upp->u_comm ) ); X X# ifdef DEBUG_READPR X dumppr( prp ); X# endif /* DEBUG_READPR defined */ X prp++; X } /* for i */ X prp->pr_stat = 0; /* mark end */ X X /* WISH: realloc to shorten prvec? */ X X free( allproc ); /* free copy of process table */ X u_cleanup(); /* cleanup ustruct reader */ X X# ifdef DEBUGSW X if( sw_debug ) X printf("read %d processes\n", prp - prvec ); X# endif /* DEBUGSW defined */ X X return( prvec ); X} /* readpr */ X XLOCAL enum sig istate( x ) /* return signal handler state */ X# ifdef VOIDSIG X void (*x)(); X# else /* VOIDSIG not defined */ X int (*x)(); X# endif /* VOIDSIG not defined */ X{ X if( x == SIG_DFL ) X return( S_DEFAULT ); /* no handler */ X else if( x == SIG_IGN ) X return( S_IGNORE ); /* ignores interrupts */ X# ifdef SIG_HOLD X else if( x == SIG_HOLD ) X return( S_HOLD ); /* interrupt held? */ X# endif /* SIG_HOLD defined */ X else X return( S_CATCH ); /* has handler */ X} /* istate */ X X# endif /* AIX3 not defined */ X XGLOBAL waitstate_t waitstate( prp ) /* look at process wait states */ X struct pr *prp; X{ X# ifndef SHORT_TTYP /* non-streams tty drivers... */ X register struct tty *t; X# endif /* SHORT_TTYP not defined */ X register caddr_t w; X X w = prp->pr_wchan; /* get wait addr */ X if( w == (caddr_t) 0 ) /* no wait? */ X return( WS_RU ); /* runable */ X X# ifndef SHORT_TTYP /* non-streams tty drivers... */ X t = prp->pr_ttyp; /* get tty pointer */ X X if( w == (caddr_t) &t->t_rawq ) /* input wait */ X return( WS_TI ); X if( w == (caddr_t) &t->t_outq ) /* output wait */ X return( WS_TO ); X if( w >= (caddr_t) t && w < (caddr_t) (t+1) ) /* other terminal wait */ X return( WS_TW ); X# endif /* SHORT_TTYP not defined */ X X# ifdef USG X# ifdef STREAMS X if( w == (caddr_t) I.info_pollwait ) /* poll(2) */ X return( WS_SE ); X# endif /* STREAMS defined */ X# else /* USG not defined */ X if( w == (caddr_t) I.info_selwait ) /* select(2) */ X return( WS_SE ); X# endif /* USG not defined */ X# if SunOS < 410 X if( w == (caddr_t) I.info_u ) /* pause(2) */ X return( WS_PA ); X# endif /* SunOS < 410 */ X if( w >= (caddr_t) aproc && w <= (caddr_t) (aproc+nproc) ) /* wait(2)*/ X return( WS_WA ); X X return( WS_SL ); /* something else */ X} /* waitstate */ X# endif /* Umax not defined */ X X X/* X * Local variables: X * comment-column: 40 X * End: X */ END_OF_readpr.c if test 9509 -ne `wc -c ttyask.c <<'END_OF_ttyask.c' X/* X * ttyask.c -- front end for ttyloc -- ask about ttyplaces X * X * Copyright (C) 1986, 1990 Philip L. Budne X * X * This file is part of "Phil's Finger Program". X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X */ X X# ifndef lint Xstatic char *rcsid = "$Id: ttyask.c,v 3.0 90/07/06 13:11:57 budd Rel $"; X# endif /* lint not defined */ X X# include "finger.h" X# include X# include X# include X# include X# include X# ifdef USG X# include /* POSIX too! */ X# else /* USG not defined */ X# include X# endif /* USG not defined */ X X# include "ttylocfile.h" X Xextern char *getttytype(); /* from getttytype.c */ Xextern TTYLOC *findttyloc(); /* from readttylocfile.c */ X X# define TTYLOC_PROG "ttyloc" /* program to set ttylocs */ X# define TTYPLACES ".ttyplaces" /* file to read */ X# define MAXTTP 256 X X# ifndef DEFCYCLE X# define DEFCYCLE 120 /* default cycle sleep time */ X# endif /* DEFCYCLE not defined */ X X# ifndef MINCYCLE X# define MINCYCLE 60 /* minimum allowed cycle/random time */ X# endif /* MINCYCLE not defined */ X Xchar *pname; /* name we were invoked as */ X Xchar *non_hardwire_types[] = { /* if you are this in /etc/ttytype */ X /* (or /etc/ttys in 4.3) you are */ X /* probably NOT hardwired */ X "su", "stupid", X "du", "dialup", "sd", "D2", X "sa", "network", X "un", "unknown", X "se", "ethernet", X "sw", "switch", X "sp", "plugboard", "patch", X "sb", "arpanet", X "sc", "bussiplexer", X# ifdef Umax X "", /* CALL connections come in like this*/ X /* if tty type not set */ X# endif /* Umax defined */ X# ifdef NON_HARDWIRE_TYPES X NON_HARDWIRE_TYPES , X# endif /* NON_HARDWIRE_TYPES defined */ X NULL X }; X Xstruct ttp { X char *t_name; X char *t_string; X} ttp[MAXTTP]; Xint nttp; X X# ifdef USG Xstruct termio old, new; X# else /* USG not defined */ Xstruct sgttyb old, new; X# endif /* USG not defined */ X XFORWARD LOCAL BOOL check_hardwire(); XFORWARD LOCAL void X setup(), restore(), readttp(), do_ttyask(), do_ttyplace(), X do_ttyrandom(), do_ttycycle(), sayit(), setit(), terpri(), X whine(), catcher(), checkwho(); X Xint hardwire = 0; Xint cycletime = 0; Xchar mytty[ 512 ]; X Xint main(argc, argv) Xint argc; Xchar *argv[]; X{ X enum { F_NONE=0, F_TTYASK, F_TTYPLACE, F_TTYRANDOM, F_TTYCYCLE } function; X char *ttpfile; /* -f argument */ X int err, arg; X char *cp; /* temp char ptr */ X X extern int getopt(), optind; X extern char *optarg; X X err = 0; X pname = argv[0]; X function = F_NONE; X X if( (cp = rindex(pname, '/')) != NULL ) X pname = cp + 1; X ttpfile = NULL; X X while( (arg = getopt(argc, argv, "acf:hprt:")) != -1 ) { X switch( arg ) { X case 'f': X ttpfile = optarg; X break; X case 'h': X hardwire = 1; X break; X case 'c': X function = F_TTYCYCLE; X break; X case 'p': X function = F_TTYPLACE; X break; X case 'r': X function = F_TTYRANDOM; X break; X case 'a': X function = F_TTYASK; X break; X case 't': X cycletime = atoi( optarg ); X break; X X default: /* ? or other junk */ X err++; X } /* switch */ X } /* while */ X X if( err > 0 ) X whine("-a -c -r -h -t