home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-09-11 | 42.5 KB | 1,853 lines |
- Subject: v07i079: Log out idle users (untamo revised)
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Wombat <rsk@j.cc.purdue.edu>
- Mod.sources: Volume 7, Issue 79
- Archive-name: untamo3
-
-
- Hopefully, this one will be easier for the net at large to deal with.
-
- ---Rsk
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- #----cut here-----cut here-----cut here-----cut here----#
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README
- # Makefile
- # untamo.cf
- # doc
- # untamo.8l
- # untamo.cf.5l
- # insque.c
- # list.c
- # untamo.c
- # warn.c
- # zap.c
- # parse.y
- # scan.l
- # ttydev.h
- # untamo.h
- cat << \SHAR_EOF > README
- Untamo is a locally developed daemon which periodically wakes up and
- logs off idle terminals; it also can deal with multiply-logged in
- users. It is configurable without recompilation, and features tunable
- parameters such as maximum allowed idle time, maximum allowable
- multiple logins, exemption lists, and so on. (Note: session limits
- do not work at the moment.)
-
- We use this program to ensure availability of one of our scarcer
- resources: terminals. Others may find it useful for different reasons;
- preventing users from leaving a terminal logged-in and unattended
- for hours is probably a reasonable security measure.
-
- The original posting caused a deluge of mail, as the sources contained
- references to local include files. This has been fixed by #ifdef'ing
- the code which applies only locally. This version has been successfully
- compiled on a Sequent Balance 21000 running Dynix v2.0.6, a CCI 6/32
- running 4.3bsd, a DEC VAX-8600 running 4.3bsd, a Gould PowerNode 9080
- Running UTX-32 Release 1.3, and and a VAX-11/780 running 4.2bsd.
-
- Please address correspondence concerning untamo to "doc" on this machine;
- the original author has left Purdue, but Craig Norborg (aka "doc") is
- reasonably familiar with the program.
- --
- Rich Kulawiec, pucc-j!rsk, rsk@j.cc.purdue.edu, rsk@purdue-asc.arpa
- SHAR_EOF
- cat << \SHAR_EOF > Makefile
- # Makefile for /usr/src/new/untamo
- #
- # Author : Craig Norborg, Purdue University Computing Center
- # To configure this for your system, be sure to check out untamo.h
- # Also, if compiling on generic 4.2BSD system, be sure to make dependancies
- # or remove all occurances of "rld" stuff from dependancies lines. -doc
-
- # C compiler flags for PUCC.
- # Note, when the DEBUG flag is set, the RLD_FILE is changed to /tmp/rlds.
- #INCLUDE =
- #DEFS = -DPUCC -DBSD4_2
- #CFLAGS = -O ${DEFS} ${INCLUDE}
- #LIBS = -lacct
-
- # C compiler flags for generic BSD4_2
- INCLUDE =
- DEFS = -DBSD4_2
- CFLAGS = -O ${DEFS} ${INCLUDE}
- LIBS =
-
- #install flags
- DEST = /usr/new/etc
- FDEST = /usr/local/lib
- OWNER = doc
- GROUP = system
- MODE = 751
- SHMODE = 755
- FMODE = 644
-
- # Source files to be mkdepended
- SRC = insque.c list.c untamo.c warn.c zap.c
- SRCl = parse.y scan.l
- SRCg = parse.c scan.c
- HDR = ttydev.h untamo.h
- OBJ = insque.o list.o parse.o scan.o untamo.o warn.o zap.o
-
- # programs that need explicit make lines, plain files
- NSTD = untamo
- FILE = untamo.cf doc
- MAN = untamo.8l untamo.cf.5l
-
- all: ${NSTD} ${FILE}
-
- clean:
- rm -f a.out ${OBJ} core errs lint.errs Makefile.bak *.s tags \
- ${SRCg} ${NSTD} y.tab.* lex.yy.c
-
- depend: ${SRC} ${SRCg} ${HDR}
- maketd -a ${DEFS} ${INCLUDE} ${SRC} ${SRCg}
-
- install: all
- -for p in ${NSTD}; do \
- install -c -m ${MODE} -o ${OWNER} -g ${GROUP} -s $$p ${DEST}; \
- done
- for p in ${FILE}; do \
- install -c -m ${FMODE} -o ${OWNER} -g ${GROUP} -s $$p ${FDEST};\
- done
-
- lint: ${SRC} ${SRCg}
- lint -hxn ${DEFS} ${SRC} ${SRCg}
-
- print:
- lpr -p -Pstaff -J"Untamo Source" Makefile ${SRCl} ${SRC} ${HDR}
-
- shar:
- shar README Makefile ${FILE} ${MAN} ${SRC} ${SRCl} ${HDR} > untamo.shar
-
- source: ${SRC} ${SRCl} ${HDR} ${MAN} ${FILE}
-
- spotless:
- rm -f a.out ${OBJ} core errs lint.errs Makefile.bak y.tab.* yacc.act\
- yacc.tmp *.s ${NSTD} tags parse.c scan.c
- rcsclean ${SRC} ${SRCl} ${HDR} ${FILE} ${MAN}
-
- tags: ${SRCS} ${SRCg} tags
- ctags ${SRC} ${SRCg}
-
- ${SRC} ${SRCl} ${HDR} ${FILE} ${MAN}:
- co $@
-
- # rules for everybody in ${NSTD} go here
- untamo: parse.o scan.o insque.o list.o untamo.o warn.o zap.o
- cc ${CFLAGS} -o untamo insque.o list.o parse.o scan.o untamo.o \
- warn.o zap.o ${LIBS}
- y.tab.h: parse.c
-
- parse.c:
- yacc -d parse.y
- mv y.tab.c parse.c
-
- scan.c:
- lex scan.l
- mv lex.yy.c scan.c
-
- # DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
- I=/usr/include
- S=/usr/include/sys
-
- insque.o: insque.c
-
- list.o: $I/setjmp.h $I/stdio.h $S/file.h $S/types.h list.c untamo.h y.tab.h
-
- untamo.o: $I/pwd.h $I/setjmp.h $I/signal.h $I/stdio.h $S/file.h $S/ioctl.h \
- $S/jioctl.h $S/stat.h $S/ttychars.h $S/ttydev.h $S/types.h $I/utmp.h \
- untamo.c untamo.h y.tab.h
-
- untamo.o: $I/setjmp.h $I/stdio.h $S/types.h untamo.h
-
- warn.o: $I/setjmp.h $I/signal.h $I/stdio.h $S/ioctl.h $S/jioctl.h \
- $S/ttychars.h $S/ttydev.h $S/types.h untamo.h warn.c y.tab.h
-
- zap.o: $I/setjmp.h $I/stdio.h $S/file.h $S/ioctl.h $S/jioctl.h $S/ttychars.h \
- $S/ttydev.h $S/types.h $S/wait.h $I/utmp.h untamo.h zap.c
-
- parse.o: $I/grp.h $I/setjmp.h $I/stdio.h $S/types.h parse.c untamo.h
-
- scan.o: $I/stdio.h scan.c y.tab.h
-
- # *** Do not add anything here - It will go away. ***
- SHAR_EOF
- cat << \SHAR_EOF > untamo.cf
- *
- * how long to sleep between checks
- *
- sleep 5
- *
- *
- *
- threshold multiple 30
- threshold session 43
- *
- * now list the timeout rules
- *
- timeout cluster public 45
- timeout default 60
- *
- * "necessary" exemptions
- *
- exempt tty console all
- exempt group staff multiple
- exempt group system multiple
- exempt login kdr all
- SHAR_EOF
- cat << \SHAR_EOF > doc
- .nr PS 12
- .TL
- The 'Untamo' Project
- .AU
- Andy Wilcox
- .AI
- Purdue University Computing Center
- .PP
- The Purdue University Computing Center needs more machines and
- terminals to provide better services to our users. The purchase
- of more machines and terminals will come in time. However, ways are needed
- now to more evenly distribute our present resources.
- The Untamo project is an attempt to solve these and related problems.
- .PP
- There is always a problem at the beginning of the semester with naive
- users who turn their terminals off without logging out. Many of these
- unfortunate souls will soon be in the consultants office explaining
- how their account was booby trapped by a malicious user. Untamo will
- decide that a terminal is idle if the keyboard has not been touched
- for thirty minutes (this choice of time is under investigation). Untamo
- will then log out idle terminals after a warning message has been sent to them.
- This will help combat this serious security problem, and save large
- amounts of work on the user's part if his or her files were deleted.
- .PP
- Sometimes it is advantageous to have idle terminals, for example, a
- Vaxen console. Untamo also provides an 'exemption' feature that allows
- such cases.
- .PP
- Late in the semester when final projects are due, there are inevitably
- waiting lines for the terminals, and ideally we would prefer one user to
- be logged on only once. With job control in c-shell, there is no
- need to be logged in more than once. Untamo looks for these multiple logins,
- warns each one of them, and then will log out all but the first terminal
- to be logged on.
- .PP
- Once again, there are exceptions to the case of multiple logins.
- Many times the consultants can log a person in again and fix a hung terminal
- by killing a runaway process without having to call the console room.
- Untamo allows a few minutes of multiple login time, which is enough time
- to locate and kill a runaway process.
- .PP
- It is important to note that Untamo will primarily affect our public
- terminals. Most other terminals will be 'exempt'.
- .PP
- Untamo is a dynamically reconfigurable program, so if there is a
- problem with someone needing more idle time, or a multiple login,
- it can be added without killing Untamo, recompiling, reinstalling,
- and restarting. These changes take effect in a few minutes, so the
- wait is not long.
- .PP
- The amount of time Untamo 'sleeps' between checking logins and idle times
- is also redefinable, it can be made larger by the operator on a
- heavily loaded machine to allow more time for a multiple login. This
- necessary human interaction with Untamo is questionable, and
- ways of making the sleep time a function of the
- load are being investigated. In any case, the operator always has
- final control of Untamo.
- SHAR_EOF
- cat << \SHAR_EOF > untamo.8l
- .TH UNTAMO 8L PUCC
- .SH NAME
- untamo \- Idle terminal and multiple login monitor daemon.
- .SH SYNOPSIS
- .B /usr/local/etc/untamo
- .SH DESCRIPTION
- .PP
- .I Untamo
- wakes up at regular intervals and scans /etc/utmp to see
- which users are currently logged in, how long they have been idle,
- whether they are logged in more than once, etc.
- .I Untamo
- then warns and logs out users based on a set of rules in its
- configuration file.
- .I Untamo
- is usually started from /etc/rc.local.
- .PP
- .I Untamo
- uses a configuration file,
- .IR untamo.cf ,
- to find out how long a terminal must be unused to be considered
- \*(lqidle\*(rq, and which users, groups, terminals, or clusters of
- terminals are exempt from being logged out.
- .PP
- .I Untamo
- gets its name from the Finnish god of sleep and dreams.
- .SH FILES
- .TP
- .B /usr/local/lib/untamo.cf
- Configuration file which specifies how often untamo is to wake up, and
- exemptions to rules, etc.
- .TP
- .B /usr/adm/untamo.log
- Log of when untamo is started, killed, who it logs off and why, and any
- errors it encounters.
- .SH DIAGNOSTICS
- Various \*(lqcouldn't open ...\*(rq error messages. Since untamo
- dissacociates itself from the invoking terminal, most of the errors
- get put in the log file.
- .SH SEE ALSO
- untamo.cf(5L), utmp(5)
- .SH BUGS
- If a user logs off and then on again fast enough and manages to get a
- different tty, he may be warned about a multiple login.
- SHAR_EOF
- cat << \SHAR_EOF > untamo.cf.5l
- .TH UNTAMO.CF 5L "PUCC
- .SH NAME
- /usr/local/lib/untamo.cf \- untamo configuration file format
- .SH DESCRIPTION
- .IR Untamo,
- the login monitor daemon, decides how it should act based on the file
- untamo.cf.
- .PP
- The file untamo.cf consists of a series of specifications which each
- describe an aspect of untamo's actions. There are four types of commands:
- .IP 1.
- .B Exemption
- commands
- specify login ids that are exempt from untamo's actions.
- .IP 2.
- .B Timeout
- commands
- define how long a terminal must be idle before it is logged out.
- .IP 3.
- .B Sleep
- commands
- set the number of minutes untamo should sleep between checks,
- as well as the amount of time between warnings and logouts.
- .IP 4.
- .B Threshold
- commands
- set the threshold number of users who must be logged in before multiple
- login control takes effect. If the number of users on the system exceeds
- the threshold, then warnings and logouts for multiple logins will be issued.
- .PP
- Lines beginning with an asterisk in column one are comments.
- Other lines may be indented for readability.
- .SH EXEMPTIONS
-
- .PP
- Exemptions have the form:
-
- .IP
- .B exempt
- .I who
- .I from
-
- .PP
- .I Who
- must be one of:
- .IP
- .B cluster
- .I name
- .IP
- .B login
- .I id
- .IP
- .B group
- .I groupname
- .IP
- .B tty
- .I ttyname
- .IP
- .B rld
- .I num
- .PP
- where
- .I name
- must be a terminal cluster name such as \*(lqpublic\*(rq or \*(lqstaff\*(rq.
- (See the PUCC in-house document Z0-TERMFIL for more information about clusters.)
- .I Id
- must be a valid login id as in /etc/passwd.
- .I Groupname
- must be a valid group name as in /etc/groups.
- .I Ttyname
- is a terminal name as in /etc/utmp (e.g., \*(lqtty\fIXX\fP\*(rq).
- .I Num
- must be an rld (terminal) number.
-
- .I From
- must be one of:
- .IP
- .B multiple
- .IP
- .B idle
- .IP
- .B session
- .IP
- .B all
- .PP
- which specify that
- .I who
- is exempt from being logged off for maintaining multiple logins,
- remaining idle longer than the idle timeout period, exceeding a login
- session limit, or all three.
-
- .SH TIMEOUTS
- .PP
- Timeouts are of the form:
- .IP
- .B timeout
- .I who
- .I minutes
- .br
- .B timeout default
- .I minutes
- .PP
- In the first form,
- .I who
- must be a valid login id and
- .I minutes
- a decimal number.
- This form indicates that
- .I who
- will be logged off after remaining idle for
- .I minutes
- minutes. The second form sets a default idle timeout that affects
- anyone not otherwise exempted from timeouts or mentioned by login id
- in an explicit timeout rule.
-
- .SH SLEEP
- .PP
- Sleep commands are of the form:
- .IP
- .B sleep
- .I minutes
- .PP
- and specify that untamo will sleep
- .I minutes
- minutes between its checks.
- If there is more than one sleep specification, only the last one is used.
- .PP
- .SH THRESHOLD
- Threshold commands are of the form:
- .IP
- .B threshold
- .I number
- .PP
- This specifies that at least
- .I number
- ttys must be active before untamo will check for multiple logins.
- If there is more than one
- .I threshold
- command, only the last one is used.
- .SH EXAMPLE
- .PP
- A sample untamo configuration file follows:
- .br
- .nf
- *
- * sleep 5 minutes between checks
- *
- sleep 5
-
- *
- * 30 users must be logged on before
- * multiple login checks will begin
- *
- threshold 30
- *
- * Set the default idle timeout to 60 mintes. For the
- * public cluster, set the idle timeout to 45 minutes.
- *
- timeout cluster public 45
- timeout default 60
- *
- * Necessary exemptions to make sure the console doesn't
- * get logged off and staff members can log in more than once.
- *
- exempt tty console all
- exempt group staff multiple
-
- .fi
- .SH "SEE ALSO"
- untamo(8L), utmp(5), rld(1L)
- SHAR_EOF
- cat << \SHAR_EOF > insque.c
- /* Queue insertion and deletion routines for non-Vaxen */
- struct qelem {
- struct qelem *q_forw , *q_back;
- #ifdef LINT
- char q_data[];
- #endif LINT
- };
-
- #ifndef VAX
- insque( elem , pred )
- register struct qelem *elem , *pred;
- {
- elem->q_forw = pred->q_forw;
- pred->q_forw = elem;
- elem->q_forw->q_back = elem;
- elem->q_back = pred;
- }
-
- #endif VAX
- SHAR_EOF
- cat << \SHAR_EOF > list.c
- #ifdef PUCC
- #include <sys/types.h>
- #include <rld.h>
- #endif PUCC
- #include <sys/file.h>
- #include "untamo.h"
- #include "y.tab.h"
-
- extern char *malloc(), *strcpy(), *ctime();
- extern strlen();
- time_t time();
- long lseek();
-
- /*
- * addlist -- adds a record to the list "list". Uses the
- * insque(3) call for speed.
- * list -- which list to add the rule to (rules or exempt)
- * type -- what kind of rule (LOGIN, GROUP, etc)
- * name -- who it applies to (ajw, console, etc)
- * num -- who it applies to (1505 (rld), 5 (group staff) )
- * flag -- idle time for a "rule" rule, or exemption type
- * for "exempt" rule: IDLE, MULTIPLE, etc.
- */
- addlist(list, type, name, num, flag)
- struct qelem *list;
- char *name;
- int type, flag, num;
- {
- struct qelem *new_node;
- struct qelem *ptr;
- struct item *new_data;
-
- /*
- * make all the new structures
- */
- new_node = (struct qelem *) malloc( sizeof(struct qelem) );
- new_data = (struct item *) malloc( sizeof(struct item ) );
- new_data->name_t = type;
- new_data->name = name;
- new_data->num = num;
- new_data->flag = flag;
- new_node->q_item = new_data;
- /*
- * find where to insert it in the list
- */
- ptr = list->q_forw;
- while (ptr != list) {
- if (ptr->q_item->name_t <= new_data->name_t)
- break;
- ptr = ptr->q_forw;
- }
- /*
- * and insert it
- */
- (void) insque(new_node,ptr->q_back);
- }
-
-
- /*
- * freelist -- frees up the space in the list pointed to
- * by ptr. Uses free.
- */
- freelist(ptr)
- struct qelem *ptr;
- {
- struct qelem *dead;
- struct qelem *start;
-
- start = ptr;
- ptr = ptr->q_forw;
- while ( ptr != start ) {
- dead = ptr;
- ptr = ptr->q_forw;
- (void) free( (char *) dead->q_item); /* kill the data */
- (void) free( (char *) dead ); /* now get the node */
- }
- start->q_forw = start; /* reset pointers for a null list */
- start->q_back = start;
- }
-
-
- /*
- * setlimits -- looks through the rules list and uses the most
- * specific rule for users[i], then looks through
- * the exceptions and uses the (again) most specific
- * exemption for the user.
- */
-
- setlimits(i)
- int i;
- {
- struct qelem *ptr;
- int rule;
- time_t tempus;
-
- /*
- * look down the rules list and set the
- * most specific rule that applies to
- * this user
- */
- rule = 0;
- (void) time(&tempus);
- ptr = rules->q_back; /* start at the end of the list */
- users[i].warned = 0; /* clear his warning and exempt flag */
- users[i].exempt = 0; /* to avoid granularity problems */
-
- users[i].next = tempus; /* next time is set to now, so */
- /* the new rules (or exemptions) */
- /* take affect immediately */
- /*
- * while we haven't looked through the whole list,
- * and we haven't found a rule...
- */
- while ( (ptr != rules) && (!rule) ) {
- if ( (rule = find(ptr, i)) ) {
- users[i].idle = (ptr->q_item)->flag * 60;
- users[i].exempt &= ~IS_IDLE;
- } else
- ptr = ptr->q_back; /* move back one */
- }
-
- rule = 0;
- ptr = session->q_back;
- while ( (ptr != session) && (!rule) ){
- if ( (rule = find(ptr, i)) ) {
- users[i].session = (ptr->q_item)->flag * 60;
- users[i].exempt &= ~IS_LIMIT;
- } else
- ptr = ptr->q_back; /* move back one */
- }
- /*
- * now look down the exemptions list and
- * set the first exemptions for this user.
- */
- rule = 0;
- ptr = exmpt->q_back; /* start at the end of the list */
- while ( (ptr != exmpt) && (!rule) ) {
- if ( (rule = find(ptr, i)) ) {
- if ( (ptr->q_item)->flag == ALL)
- users[i].exempt |= IS_IDLE|IS_MULT|IS_LIMIT;
- else if ( (ptr->q_item)->flag == IDLE)
- users[i].exempt |= IS_IDLE;
- else if ( (ptr->q_item)->flag == MULTIPLE)
- users[i].exempt |= IS_MULT;
- else if ( (ptr->q_item)->flag == SESSION)
- users[i].exempt |= IS_LIMIT;
- } else
- ptr = ptr->q_back; /* move back one */
- }
- }
-
-
- /*
- * find -- given a rule (or exemption) and a users, see if it applies.
- * Example: If the rule is a LOGIN type rule, compare the name with that
- * of the user to see if it applies. If we find a match, return 1,
- * else return 0.
- */
- find(ptr,i)
- int i;
- struct qelem *ptr;
- {
- switch ( (ptr->q_item)->name_t ) {
- case LOGIN:
- if (!strcmp( (ptr->q_item)->name, users[i].uid) )
- return(1);
- break;
- case TTY:
- if (!strcmp( (ptr->q_item)->name, (users[i].line+5) ) )
- return(1);
- break;
- case GROUP:
- if ( (ptr->q_item)->num == users[i].ugroup )
- return(1);
- break;
- #ifdef PUCC
- case CLUSTER:
- if (!strcmp( (ptr->q_item)->name, users[i].clust) )
- return(1);
- break;
- case RLD:
- if ( (ptr->q_item)->num == users[i].rld )
- return(1);
- break;
- #endif PUCC
- case DEFAULT:
- return(1);
- break;
- }
- return(0);
- }
-
- #ifdef PUCC
-
- #define makestr(Z) (strcpy(malloc( (unsigned) strlen(Z)+1),Z))
-
- /*
- * findcluster -- passes an rld number, it returns a char *
- * to the name of the cluster associated with it
- */
- char *
- findcluster(rld)
- int rld;
- {
- int fd;
- static struct rld_data data;
-
- #ifdef BSD2_9
- if ( (fd = open(RLD_FILE,O_RDONLY) ) < 0 ) {
- #else BSD2_9
- if ( (fd = open(RLD_FILE,O_RDONLY,0) ) < 0 ) {
- #endif BSD2_9
- (void) error("Can't open rld file.");
- exit(1);
- }
-
- /*
- * seek to the proper rld and read it.
- */
- (void) lseek(fd, rld*sizeof(data), 0);
-
- (void) read(fd, (char *) &data, sizeof(data) );
-
- (void) close(fd);
-
- /*
- * return the cluster name, if null, return "public"
- */
- if (data.rld_cluster)
- return(makestr(data.rld_cluster));
- else
- return(makestr("public"));
- }
- #endif PUCC
- SHAR_EOF
- cat << \SHAR_EOF > untamo.c
- #ifdef PUCC
- #include <sys/types.h>
- #include <rld.h>
- #endif PUCC
- #include <utmp.h>
- #include <signal.h>
- #include <sys/file.h>
- #ifndef F_OK
- # define F_OK 0
- #endif F_OK
- #include <sys/ioctl.h>
- #include "untamo.h"
- #include <sys/stat.h>
-
- #ifdef PUCC
- #define PWIDLE 6 /*accounting bit for no idle time logout */
- #define PWMULT 7 /*accounting bit for multiple logins allowed */
- #include <passwd.h>
- struct usrpwd *getupnam();
- #else PUCC
- #include <pwd.h>
- #endif PUCC
-
- #include "y.tab.h"
-
- struct user users[MAXUSERS];
- struct user *pusers[MAXUSERS];
-
- extern char *malloc(), *strcpy(), *ctime() , *strcat();
- extern unsigned strlen();
- extern time_t time();
-
- struct qelem *rules,
- *session,
- *exmpt; /* lists for timeouts, session limits, and exemptions */
-
- jmp_buf env_buf;
- int sleeptime; /* time to sleep between checks */
- FILE *logfd; /* log file file descriptor pointer */
- int m_threshold; /* number of users before multiple limits */
- int s_threshold; /* number of users for session limits */
- int warn_flags = IS_IDLE | IS_MULT | IS_LIMIT;
- /* what sorts of warnings should be accepted */
-
- main(n_args, ppch_args)
- int n_args;
- char **ppch_args;
- {
- struct utmp utmpbuf;
- struct stat statbuf;
- #ifdef PUCC
- struct usrpwd *pswd;
- #else PUCC
- struct passwd *pswd;
- #endif PUCC
- struct user *user;
- char pathbuf[20];
- int utmptr, utmpfd;
- time_t conf_oldstamp;
- int userptr;
- int res, td;
- int new; /* if the configuration file is new */
- time_t tempus;
- int finish(), wakeup();
- FILE *conffd, *freopen(), *fopen();
- /* command line flags */
- int fl_multiple = 1, fl_session = 1, fl_idle = 1;
-
- while( --n_args && *++ppch_args && **ppch_args == '-' ) {
- while( *++(*ppch_args) ){
- switch( **ppch_args ){
- case 'm': /* don't even think about multiple logins */
- fl_multiple = 0;
- break;
- case 'i': /* don't even think about idle timeouts */
- fl_idle = 0;
- break;
- case 's': /* don't even think about session limits */
- fl_session = 0;
- break;
- default:
- fprintf( stderr,
- "untamo: bad flag -%c\n", **ppch_args );
- break;
- }
- }
- }
-
- if( !fl_multiple && !fl_idle && !fl_session ){
- /* do absolutely nothing!! */
- exit(0);
- }
-
- #ifdef PUCC
- if ( access( "/flags/testsys" , F_OK ) == 0 )
- exit(0); /* dont run in test mode */
- #endif PUCC
- (void) signal(SIGHUP, SIG_IGN);
- (void) signal(SIGQUIT, SIG_IGN);
- (void) signal(SIGINT, SIG_IGN);
- #ifdef BSD4_2
- (void) signal(SIGTTOU, SIG_IGN);
- (void) signal(SIGTSTP, SIG_IGN);
- #endif BSD4_2
-
- (void) signal(SIGTERM, finish);
- (void) signal(SIGALRM, wakeup);
- conf_oldstamp = 1; /* a very old stamp */
- /*
- * set up new header nodes for each of the lists.
- * The forw and back pointers must point to them
- * selves so the system insque routine can be used
- */
- rules = (struct qelem *) malloc( sizeof(struct qelem) );
- exmpt = (struct qelem *) malloc( sizeof(struct qelem) );
- session = (struct qelem *) malloc( sizeof(struct qelem) );
- rules->q_forw = rules->q_back = rules;
- exmpt->q_forw = exmpt->q_back = exmpt;
- session->q_forw = session->q_back = session;
- rules->q_item = session->q_item = exmpt->q_item = NULL;
-
- if ( (logfd = fopen(LOGFILE,"a")) > 0) {
- (void) time(&tempus);
- (void) fprintf(logfd,"%24.24s Untamo started\n",ctime(&tempus) );
- (void) fclose(logfd);
- } else {
- (void) fprintf( stderr , "Untamo: couldn't open log file: %s\n", LOGFILE );
- exit(1);
- }
-
- if ( (res = fork()) < 0) {
- (void) fprintf(stderr,"Untamo: couldn't start\n");
- }
- if (res){ /* if the parent */
- #ifdef DEBUG
- exit(res);
- #else
- exit(0);
- #endif DEBUG
- }
-
- /*
- * lose our controlling terminal
- */
- #ifdef BSD2_9
- td = open("/dev/tty", O_RDWR);
- #else BSD2_9
- td = open("/dev/tty", O_RDWR, 0600);
- #endif BSD2_9
- if (td >= 0){
- (void) ioctl(td, TIOCNOTTY, (char *)0);
- (void) close( td );
- }
-
- /*
- * now sit in an infinite loop and work
- */
-
- while (1){
- if ( stat(CONFIG,&statbuf) < 0) {
- (void) error("Untamo: couldn't stat conf file");
- exit(1);
- }
-
- if ( statbuf.st_mtime > conf_oldstamp ) {
- conf_oldstamp = statbuf.st_mtime;
-
- if ( (conffd = freopen(CONFIG, "r", stdin)) < 0) {
- (void) error("Untamo: can't open configuration file");
- exit(1);
- }
-
- /*
- * get rid of the old rules and exempt lists
- */
- (void) freelist(rules);
- (void) freelist(exmpt);
- (void) freelist(session);
- m_threshold = 0;
- s_threshold = 0;
- /*
- * now read the configuration file and set up the
- * rules and exemption lists
- */
- (void) yyparse();
- new = 1;
- } else
- new = 0;
- #ifdef BSD2_9
- if ( (utmpfd = open(UTMP, O_RDONLY)) < 0) {
- #else BSD2_9
- if ( (utmpfd = open(UTMP, O_RDONLY, 0)) < 0) {
- #endif BSD2_9
- (void) error("Untamo: can't open /etc/utmp");
- exit(1);
- } /* } <-- to match ifdefed open... */
-
- utmptr = 0;
- userptr = 0;
- /*
- * look through the utmp file, compare each entry to the users
- * array to see if an entry has changed. If it has, build a new
- * record for that person, if it hasn't, see if it is time to
- * examine him again.
- */
- while ( (res = read(utmpfd, (char *)&utmpbuf, sizeof(struct utmp)) ) > 0 ) {
-
- if (res != sizeof(struct utmp)) {
- (void) error("Untamo: error reading utmp file, continuing");
- continue;
- }
- (void) time(&tempus);
- if (utmpbuf.ut_name[0] != '\0') {
- user = &users[utmptr];
- if ( !(strcmp(user->uid,utmpbuf.ut_name)) &&
- (user->time_on == utmpbuf.ut_time) ) {
- if (new)
- (void) setlimits(utmptr);
- if (fl_idle && tempus > user->next) {
- (void) checkidle(utmptr);
- }
- } else {
- /*
- * build a new record
- */
- user->warned = 0;
- (void) strcpy(pathbuf,DEV);
- (void) strcat(pathbuf,utmpbuf.ut_line);
- #ifdef PUCC
- user->rld = findrld(pathbuf);
- (void) strcpy(user->clust, findcluster(user->rld));
- #endif PUCC
-
- (void) strcpy(user->line, pathbuf);
- (void) stat(pathbuf,&statbuf);
- (void) strcpy(user->uid, utmpbuf.ut_name);
-
- #ifdef PUCC
- pswd = getupnam(utmpbuf.ut_name);
- user->ugroup = pswd->up_gid;
- #else PUCC
- pswd = getpwnam(utmpbuf.ut_name);
- user->ugroup = pswd->pw_gid;
- #endif PUCC
-
- user->time_on = utmpbuf.ut_time;
- (void) setlimits(utmptr);
-
- #ifdef PUCC
- if( pswd->up_flags & (1l << PWMULT ))
- user->exempt |= IS_MULT;
- if( pswd->up_flags & (1l << PWIDLE ))
- user->exempt |= IS_IDLE;
- #endif PUCC
- user->next = tempus;
- }
- pusers[userptr++] = user;
- }
- utmptr++;
- }
-
- (void) close(utmpfd);
- (void) fclose(conffd);
-
- #ifdef PUCC
- /*
- ** check session limits
- */
-
- if( fl_session ){
- (void) chk_session(userptr);
- }
- #endif PUCC
-
- /*
- ** check for and warn multiple logins
- */
-
- if( fl_multiple ){
- (void) chk_multiple(userptr);
- }
-
- /*
- ** wait sleeptime minutes
- */
-
- (void) sleep( (unsigned) sleeptime * 60);
- }
- }
-
- #ifdef PUCC
- /*
- * chk_session( users )
- * find out how many people are on sds ports,
- * and try to warn enough people to get below the threshold
- */
-
- chk_session( n_users )
- register int n_users;
- {
- register int which_user;
- time_t tempus;
- register int n_sds_ports = 0;
- static int fl_sessionlimits = 0;
-
- (void) time(&tempus);
- for( which_user = 0; which_user < n_users ; which_user++ ){
- if( pusers[which_user]->warned & IS_LIMIT ){
- (void) warn(which_user,IS_LIMIT);
- } else if( is_sds_port( pusers[which_user]->rld ) ){
- n_sds_ports++;
- }
- }
-
- if( n_sds_ports > s_threshold && !fl_sessionlimits ){
- (void) close( creat( "/flags/sessionlimits", 0600 ));
- fl_sessionlimits = 1;
- }
-
- if( n_sds_ports < s_threshold && fl_sessionlimits ){
- unlink( "/flags/sessionlimits" );
- fl_sessionlimits = 0;
- }
-
- while( n_sds_ports>s_threshold && s_threshold>0 && which_user>0 ){
- which_user--;
- if( tempus-pusers[which_user]->time_on > pusers[which_user]->session
- && pusers[which_user]->session > 2*60
- && !(pusers[which_user]->warned & IS_LIMIT) ){
-
- (void) warn(which_user,IS_LIMIT);
- n_sds_ports--;
- }
- }
- }
-
-
- int
- is_sds_port( rld_number )
- int rld_number;
- {
- int fd, res;
- struct rld_data rdat;
-
- /*
- * Get to the right place in /etc/rlds
- * Complements of Jeff Smith...
- */
- if( fd = open (RLD_FILE, O_RDONLY, 0) >= 0 ) {
- lseek (fd, (long) rld_number * sizeof (struct rld_data), L_SET);
- res = read (fd, (char *) &rdat, sizeof (struct rld_data));
- (void) close(fd);
- if (res == sizeof(struct rld_data) && rdat.rld_tio != -1) {
- return 1;
- }
- }
- return 0;
- }
- #endif PUCC
-
- /*
- * chk_multiple -- given the number of users (i), warn any of
- * them that have multiple logins. Calls qsort(3)
- * to sort them by id.
- */
- chk_multiple(i)
- int i;
- {
- int j, comp();
- int match, skip = -1;
- int wait = 0;
-
- if( i < m_threshold && m_threshold > 0 ) { /* below threshold...*/
- return;
- }
- (void) qsort( (char *) pusers, i, sizeof(struct user *), comp);
- for (j=0; j<i-1; j++) {
- /*
- * if not all the multiple logins logged out,
- * decide on one not to kill, clear his warned
- * bit, and continue. But don't look again until
- * we have passed all the guys with the same login.
- */
- if ( wait == 0 ) {
- match = 0;
- skip = decide(j, i, &wait);
- } else
- wait--;
-
- if ( ( (*pusers[j]).exempt & IS_MULT) || (j == skip) ) {
- continue; /* he's exempt ! */
- }
-
- if ( !strcmp( (*pusers[j]).uid, (*pusers[j+1]).uid) ) {
- match = 1;
- (void) warn(j,IS_MULT);
- } else {
- if ( match )
- (void) warn(j,IS_MULT);
- match = 0;
- }
- }
- }
-
-
- /*
- * decide -- given a bunch of multiply logged on terminals that did
- * not heed the warning, decide returns the index into the
- * *pusers array of the user NOT to log off. Wait is the
- * number of ids that chk_multiple must skip before calling
- * decide again. Admittedly this is gross, but it works.
- */
- decide(j, num, wait)
- int j, num, *wait;
- {
- int i;
- int count = 1;
- int warned = 1;
- int skip;
-
- /*
- * look through the users and find how many
- * of login (*pusers[i]).uid are logged on
- * and whether or not they have been warned
- */
- for ( i=j; i<num; i++) {
- if ( !((*pusers[i]).warned & IS_MULT) )
- warned = 0;
-
- if ( !strcmp( (*pusers[i]).uid, (*pusers[i+1]).uid) )
- count++;
- else
- break;
- }
- /*
- * now, if there is a need to skip someone, do it
- */
- *wait = count-1;
- if ( (warned) && (count > 1) ) {
- skip = j;
- /*
- * set skip to the alpha-numerical least tty
- */
- for(i=j+1; i<j+count; i++)
- if (strcmp((*pusers[skip]).line,(*pusers[i]).line)>0)
- skip = i;
- (*pusers[skip]).warned &= ~IS_MULT;
- return(skip);
- }
- return(-1);
- }
-
-
- /*
- * finish -- end Untamo
- */
- finish()
- {
- time_t tempus;
- FILE *logfd;
-
- (void) signal(SIGTERM, SIG_IGN);
- (void) time(&tempus);
- (void) unlink( "/flags/sessionlimits");
- if ( (logfd = fopen(LOGFILE,"a")) > 0) {
- (void) time(&tempus);
- (void) fprintf(logfd,"%24.24s Untamo killed.\n",ctime(&tempus) );
- (void) fclose(logfd);
- }
- exit(0);
- }
-
-
- /*
- * comp -- used by qsort to sort by id
- */
- comp(h1, h2)
- struct user **h1, **h2;
- {
- return( strcmp((**h1).uid, (**h2).uid) );
- }
-
-
- /*
- * checkidle -- given a user, see if we want to warn him about idle time.
- * first check the exempt vector to see if he is exempt.
- */
- #define min(a,b) ( (a)<(b)?(a):(b) )
-
- checkidle(i)
- int i;
- {
- struct stat statbuf;
- time_t tempus;
-
- (void) time(&tempus);
- (void) stat(users[i].line,&statbuf);
- #ifdef DEBUG
- { static char debugprint[80];
- sprintf(debugprint,"**debug: checkidle(%d); %d %d %x\n",
- i, users[i].session, users[i].idle, users[i].exempt);
- error(debugprint);
- sprintf(debugprint," *debug: %s %s\n", users[i].line, users[i].uid);
- error(debugprint);
- }
- #endif DEBUG
- if (( tempus - statbuf.st_atime) < users[i].idle ) {
- users[i].warned &= ~IS_IDLE;
- } else {
- if (users[i].idle > 2*60 && !(users[i].exempt & IS_IDLE)) {
- (void) warn(i,IS_IDLE);
- }
- }
- users[i].next = min( statbuf.st_atime + users[i].idle,
- users[i].time_on + users[i].session );
- }
- SHAR_EOF
- cat << \SHAR_EOF > warn.c
- #include <signal.h>
- #include <sys/ioctl.h>
- #include "untamo.h"
- #include "y.tab.h"
-
- extern char *malloc() , *strcpy() , *ctime();
- extern unsigned strlen();
-
- /*
- * warn -- warn a user that he is logged in multiply, or has
- * been idle past his limit. Uses the magic of setjmp
- * and longjmp to avoid a timeout on a terminal write.
- */
- warn(i,type)
- int i, type;
- {
- int res;
- int opened;
- struct user *him;
- FILE *termf;
-
- if( !(type & warn_flags )) { /* we are not doing this warning now.. */
- return 0;
- }
-
- if (type == IS_IDLE )
- him = &users[i];
- else /* type == IS_MULT || type == IS_LIMIT */
- him = pusers[i];
-
- if ( (res=vfork()) < 0) {
- (void) error("couldn't fork in warn");
- exit(0);
- }
- /*
- * the parent returns after it
- * has modified the global data structures
- * that the child obviously can't
- */
- if (res) {
- if ( (type == IS_MULT) && !(him->warned & IS_MULT) )
- him->warned |= IS_MULT;
- if ( (type == IS_IDLE) && !(him->warned & IS_IDLE) )
- him->warned |= IS_IDLE;
- #ifdef PUCC
- if ( (type == IS_LIMIT) && !(him->warned & IS_LIMIT) )
- him->warned |= IS_LIMIT;
- #endif PUCC
- return( wait(0) );
- }
-
- /*
- * child continues here
- */
- if (setjmp(env_buf) == 0) {
- opened = 0;
- (void) alarm(5);
- if ((termf = fopen( him->line, "w")) != NULL) {
- opened = 1;
- /*
- * start the terminal if stopped
- */
- (void) ioctl(fileno(termf),TIOCSTART,(char *) 0);
- if (type == IS_MULT) {
- if (him->warned & IS_MULT) {
- (void) zap( him );
- } else {
- (void)fprintf(termf,"\007\r\n\r\nThis user id is ");
- (void)fprintf(termf,"logged on more than ");
- (void)fprintf(termf,"once, please end\r\n");
- (void)fprintf(termf,"all but one of your ");
- (void)fprintf(termf,"logins in the next");
- (void)fprintf(termf," %1d minutes\r\n",
- sleeptime);
- (void)fprintf(termf,"or you will be logged ");
- (void)fprintf(termf,"out by the system.\r\n\r\n\007");
- }
- }
- else if (type == IS_IDLE) {
- if( him->warned & IS_IDLE ) {
- (void) zap( him );
- } else {
- (void)fprintf(termf,
- "\007\r\n\r\nThis terminal has been idle %2d ",
- him->idle/60);
-
- (void)fprintf(termf,
- "minutes. If it remains\r\nidle for %1d ",
- sleeptime);
-
- (void)fprintf(termf,
- "minutes it will be logged out by the system.");
- (void)fprintf(termf,"\r\n\r\n\007");
- }
- }
- else if (type == IS_LIMIT) {
- if( him->warned & IS_LIMIT ) {
- (void) zap( him );
- } else {
- (void)fprintf(termf,
- "\007\r\n\r\nThis terminal has been in use %2d",
- him->session/60);
-
- (void)fprintf(termf, " minutes.\nIn %1d ",
- sleeptime);
-
- (void)fprintf(termf,
- "minutes it will be logged out by the system.");
- (void)fprintf(termf,"\r\n\r\n\007");
- }
- }
- (void) fclose(termf);
- opened = 0;
- }
- (void) alarm(0);
- } else {
- /* we timed out */
-
- if ( opened ) {
- /* free FILE without write() */
- termf->_ptr = termf->_base;
- (void) fclose(termf);
- }
- }
- exit(0); /* child exits here */
- return(0); /* lint doesnt believe in exit()... */
- }
-
-
- /*
- * wakeup -- signal handler for SIGALRM
- */
- wakeup()
- {
- (void) longjmp(env_buf, 1);
- }
- SHAR_EOF
- cat << \SHAR_EOF > zap.c
- #ifdef PUCC
- #include <sys/types.h>
- #endif PUCC
- #include <utmp.h>
-
- #ifdef BSD2_9
- #include <wait.h>
- #else BSD2_9
- #include <sys/wait.h>
- #endif BSD2_9
-
- #include <sys/ioctl.h>
- #include <sys/file.h>
- #include "untamo.h"
-
- #ifdef BSD2_9
- #include <sys/param.h>
- #define getdtablesize() NOFILE
- #endif BSD2_9
-
- extern char *malloc() , *ctime() , *strcpy();
- time_t time();
-
- /*
- * zap -- disconnect the person logged on to tty "dev".
- * makes use of ioctl(2) to get a new controlling
- * terminal and the infinitely clever vhangup(2)
- * to disconnect it.
- */
- zap(him)
- struct user *him;
- {
- static char message[] = "\n\n\007Logged out by the system.\n";
- int dts, td;
- time_t tempus;
-
- /*
- * close all the child's descriptors
- */
- dts = getdtablesize();
- for ( dts--; dts>=0; dts--){
- (void) close(dts);
- }
- /*
- * now tell him it's over, and disconnect.
- */
- #ifdef BSD2_9
- td = open(him->line, O_RDWR);
- #else BSD2_9
- td = open(him->line, O_RDWR, 0600);
- #endif BSD2_9
- (void) ioctl(td, TIOCSTART, (char *)0);
- if (td >= 0) {
- (void) write(td, message, sizeof(message) );
- (void) fsync(td);
- (void) ioctl(td, TIOCFLUSH, (char *)0);
- td = vhangup();
- (void) time(&tempus);
- if ( (logfd = fopen(LOGFILE,"a")) != NULL) {
- (void)fprintf(logfd,
- "%19.19s : %s on %s because %s, vhangup returned %d\n",
- ctime(&tempus), him->uid, him->line,
- ( (him->warned & IS_MULT) ? "multiple" : (him->warned & IS_IDLE ? "idle" : "session" )), td );
- (void)fclose(logfd);
- }
- } else {
- (void) time(&tempus);
- if ( (logfd = fopen(LOGFILE,"a")) != NULL) {
- (void)fprintf(logfd,
- "%19.19s : couldn't open %s on %s\n",
- ctime(&tempus), him->line, him->uid );
- (void)fclose(logfd);
- }
- }
- }
-
-
- error(sb)
- char *sb;
- {
- if ( (logfd = fopen(LOGFILE,"a")) != NULL) {
- (void)fprintf(logfd,"%s",sb);
- (void)fclose(logfd);
- }
- }
- SHAR_EOF
- cat << \SHAR_EOF > parse.y
- %{
- #include <stdio.h>
- #include <grp.h>
- #include "untamo.h"
- struct group *grp;
- char oct[5]; /* rld kludge */
- char *name;
- int num;
- extern char *yytext;
-
- /*
- * vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- * >>>>>>>>> IMPORTANT <<<<<<<<<
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * The order of the tokens in the *first line* is significant.
- *
- * They dictate which rules and exemptions have precence. This order
- * states that RLD is the most significant, and Untamo will use an
- * rld rule first if it has a choice. The second two %token lines may
- * be ordered anyway. DEFAULT is the least specific, but will always
- * match. It must always remain in the last position.
- */
- %}
-
- %token RLD TTY LOGIN GROUP CLUSTER DEFAULT
-
- %token EXEMPT TIMEOUT SLEEP SESSION
- %token NUM IDLE MULTIPLE NAME ALL
- %token THRESHOLD NL
-
- %union {
- char *sb;
- int nb;
- }
-
- %type <sb> NAME
- %type <nb> NUM LOGIN GROUP TTY RLD ALL IDLE MULTIPLE
- %type <nb> who exempt_type name_type
-
- %start cmd_cmd
-
- %%
-
- cmd_cmd : /*EMPTY*/
- | cmd_cmd exempt_cmd
- | cmd_cmd idle_cmd
- | cmd_cmd sleep_cmd
- | cmd_cmd session_cmd
- | cmd_cmd thresh_cmd
- | cmd_cmd error NL
- | cmd_cmd NL
- ;
-
- thresh_cmd : THRESHOLD MULTIPLE NUM NL
- {
- m_threshold = $3;
- }
- | THRESHOLD SESSION NUM NL
- {
- s_threshold = $3;
- }
- | THRESHOLD error NL
- {
- yyerror("Malformed threshold command.");
- }
- ;
-
-
- exempt_cmd : EXEMPT who exempt_type NL
- {
- addlist(exmpt,$2,name,num,$3);
- }
- | EXEMPT error NL
- {
- yyerror("Malformed exempt command.");
- }
- ;
-
- session_cmd : SESSION who NUM NL
- {
- addlist(session,$2,name,num,$3);
- }
- | SESSION error NL
- {
- yyerror("Malformed session command.");
- }
- ;
-
- idle_cmd : TIMEOUT who NUM NL
- {
- addlist(rules,$2,name,num,$3);
- }
- | TIMEOUT DEFAULT NUM NL
- {
- addlist(rules, DEFAULT, NULL, 0, $3);
- }
- | TIMEOUT error NL
- {
- yyerror("Malformed timeout command.");
- }
- ;
-
- sleep_cmd : SLEEP NUM NL
- {
- sleeptime = $2;
- }
- | SLEEP error NL
- {
- yyerror("Malformed sleep command.");
- }
- ;
-
- who : name_type NAME
- {
- $$ = $1;
- name = $2;
- if ($1 == GROUP) {
- grp = getgrnam(name);
- num = grp->gr_gid;
- }
- }
- | name_type NUM
- {
- $$ = $1;
- /*
- * Kludge alert: here we must convert the
- * rld number, which was read as decimal
- * (lex doesn't know any better...) to an
- * octal so that it will jive with what
- * findrld (in libacct) returns.
- */
- if ($1 == RLD) {
- sprintf(oct,"%d",$2);
- sscanf(oct,"%o",&num);
- } else
- num = $2;
- }
- ;
-
- name_type : CLUSTER { $$ = CLUSTER; }
- | LOGIN { $$ = LOGIN; }
- | GROUP { $$ = GROUP; }
- | TTY { $$ = TTY; }
- | RLD { $$ = RLD; }
- ;
-
- exempt_type : ALL { $$ = ALL; }
- | IDLE { $$ = IDLE; }
- | MULTIPLE { $$ = MULTIPLE; }
- | SESSION { $$ = SESSION; }
- ;
-
- %%
- static int errorcnt = 0;
-
- yyerror(sb)
- char *sb;
- {
- extern int linenum;
- char buf[128];
-
- sprintf(buf, "%s: line %d: %s\n", CONFIG, linenum, sb);
- error( buf );
- errorcnt++;
- }
-
- yywrap()
- {
- extern int linenum;
-
- if( errorcnt > 0 ){
- error( "Aborting due to config file syntax errors.\n");
- exit( 1 );
- }
- linenum = 1;
- return 1;
- }
- SHAR_EOF
- cat << \SHAR_EOF > scan.l
-
- %{
- /*
- * Lex grammer to scan input file for untamo
- */
- #include <stdio.h>
- #include "y.tab.h"
- #define makestr(Z) ((char *)strcpy(malloc(strlen(Z)+1),Z))
- int linenum = 1; /* current line number for error messages */
- %}
-
- %%
- exempt return EXEMPT;
- timeout return TIMEOUT;
- sleep return SLEEP;
- login return LOGIN;
- group return GROUP;
- tty return TTY;
- rld return RLD;
- cluster return CLUSTER;
- default return DEFAULT;
- idle return IDLE;
- multiple return MULTIPLE;
- session return SESSION;
- threshold return THRESHOLD;
- all return ALL;
-
- [/A-Za-z][/A-Za-z0-9_]* {
- yylval.sb = makestr(yytext);
- return NAME;
- }
-
- [0-9]+ {
- yylval.nb = atoi(yytext);
- return NUM;
- }
-
- "*".* ;
- "\n" {
- linenum++;
- return NL;
- }
- [ \t]* ;
- . {
- static char *errormsg ="Illegal character ' '.";
-
- errormsg[19] = yytext[0];
- yyerror( errormsg );
- }
- SHAR_EOF
- cat << \SHAR_EOF > ttydev.h
- /* ttydev.h 6.1 83/07/29 */
-
- /*
- * Terminal definitions related to underlying hardware.
- */
- #ifndef _TTYDEV_
- #define _TTYDEV_
-
- /*
- * Speeds
- */
- #define B0 0
- #define B50 1
- #define B75 2
- #define B110 3
- #define B134 4
- #define B150 5
- #define B200 6
- #define B300 7
- #define B600 8
- #define B1200 9
- #define B1800 10
- #define B2400 11
- #define B4800 12
- #define B9600 13
- #define EXTA 14
- #define EXTB 15
-
- #ifdef KERNEL
- /*
- * Hardware bits.
- * SHOULD NOT BE HERE.
- */
- #define DONE 0200
- #define IENABLE 0100
-
- /*
- * Modem control commands.
- */
- #define DMSET 0
- #define DMBIS 1
- #define DMBIC 2
- #define DMGET 3
- #endif
- #endif
- SHAR_EOF
- cat << \SHAR_EOF > untamo.h
- #include <sys/types.h>
- #include <stdio.h>
- #include <setjmp.h>
-
- #define UTMP "/etc/utmp" /* name of utmp file */
- #define TERMFILE "/etc/termfile" /* name of termfile */
-
- #ifdef DEBUG
- #define CONFIG "/userf/doc/untamo/untamo.cf"
- #define LOGFILE "/userf/doc/untamo/untamo.log"
- #else DEBUG
- #define CONFIG "/usr/local/lib/untamo.cf"
- #define LOGFILE "/usr/adm/untamo.log"
- #endif DEBUG
-
- #define DEV "/dev/\0"
-
- #define MAXUSERS 100 /* max people expected */
- #define NAMELEN 8 /* length of login name */
- #define IS_IDLE 01
- #define IS_MULT 02
- #define IS_LIMIT 04
-
- struct user {
- #ifdef PUCC
- int rld; /* rld number last logged in to */
- char clust[7]; /* cluster */
- #endif PUCC
- int idle; /* max idle limit for this user */
- int ugroup; /* gid obtained from getgrent call */
- int session; /* session limit for this user */
- int warned; /* if he has been warned before */
- int exempt; /* what is this guy exempt from? */
- time_t next; /* next time to examine this structure */
- time_t time_on; /* loggin time (express terminals?) */
- char uid[NAMELEN]; /* who is this is? */
- char line[14]; /* his tty in the form "/dev/ttyxx"*/
- char site[10]; /* where */
- };
-
- /*
- next will be cur_time+limit-idle do all we have to do is check
- the current time against the action field when the daemon comes
- around. if >= then it's time to check the idle time again, else
- just skip him.
- */
-
- extern struct user users[];
- extern struct user *pusers[];
-
- /*
- * records that the nodes of the linked list
- * will have pointers too
- */
- struct item {
- int name_t; /* is it a login, group, etc... */
- char *name; /* which login, etc */
- int num; /* which rld (special case, rld is a #)*/
- /* or group -doc*/
- int flag; /* what is the timeout/exemption ? */
- };
-
- /*
- * necessary structures to use the system
- * linked list stuff. q_item will be a pointer
- * to stuct items.
- */
- struct qelem {
- struct qelem *q_forw;
- struct qelem *q_back;
- struct item *q_item;
- };
-
- extern jmp_buf env_buf; /* where to jump on timeouts */
- extern FILE *logfd; /* log file file descriptor */
- #ifdef PUCC
- extern char *findcluster();
- #endif PUCC
-
- /* These items are gleaned from the configuration file... */
-
- extern struct qelem *rules, /* list of idle timeout rules */
- *exmpt, /* list of exemptions */
- *session; /* list of session limit rules */
- extern int sleeptime; /* how long to sleep between scans of utmp */
- extern int m_threshold; /* number of users for multiple login warnings */
- extern int s_threshold; /* number of users (sds-ports) fork session limits */
- extern int warn_flags; /* what warnings to make */
- SHAR_EOF
- # End of shell archive
- exit 0
-
-