DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T i

⟦0b8409076⟧ TextFile

    Length: 5448 (0x1548)
    Types: TextFile
    Names: »idle.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/idle/idle.c« 

TextFile

/* idles deamon - kills off users who have not used their terminals for
 * a specified time.
 * Tested and run for 6 month on 4.2 BSD at site Erix.
 * Change LMESSAGE, WMESSAGE, DAYOUY, NIGHTO, EVENING, MORNING and SLEEP
 * to what you want locally (see comments in code) compile and run (as root).
 * preferably started in /etc/rc.local by lines something like this:
 *	if [ -f /usr/local/lib/id ]; then
 *		/usr/local/lib/id & echo -n ' idle'	>/dev/console
 *	fi
 * when starting local daemons.
 * The daemon wakes up every SLEEP minutes, reads UTMP and stats the terminals
 * to see if when they were last used. A warning (WMESSAGE) is sent if the 
 * time elapsed excedes time WARN minutes. The user is logged out and a message
 * (LMESSAGE) is sent if the user has been idle for more than DAYOUT minutes
 * between the hours MORNING to EVENING or else NIGHTO minutes. Error messages
 * are sent to syslog LOG_CRIT. A log of users logged out is sent to syslog
 * LOG_INFO. Useful for defending system managers from irate users who do 
 * something stupid and log themselves out and then blame the daemon!
 */
#include <utmp.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sgtty.h>
#include <syslog.h>
#include <setjmp.h>
#include <signal.h>
#include <strings.h>
#define UTMP "/etc/utmp"
#define LMESSAGE "\007\007\rAuto logout - too long idle time\r\n"
#define WMESSAGE "\007\007\rThe idle deamon has spotted you\r\n"
#define DAYOUT 480 /* logout after this number of idle minutes - daytime*/
#define NIGHTO 120 /* logout after this number of idle minutes - nightime */
#define MORNING 7 /* start of daytime */
#define EVENING 18 /* start of evening time */
#define WARN 90 /* start sending warnings after this time */
#define SLEEP 10 /* time (minutes) between each check */

jmp_buf env;
struct utmp ut;
struct stat sbuf;
struct timeval tv;
struct timezone tz;
struct tm *ltime;
struct stat sbuf;
main()
{
	int fd, minutes, logout;
	char fname[12];
#ifndef DEBUG
	if (fork() != 0) exit(0); /* kill off parent */
	/* close all files */
	fd = getdtablesize();
	for ( fd--; fd>=0; fd--){
		(void) close(fd);
	}
	/* create files for std{in,out,err} if they are used by syslog or some 
	   such stupidity */
	if ((fd = open("/dev/null", O_RDWR)) < 0 ) exit(1);
	if ((fd = open("/dev/null", O_RDWR)) < 0 ) exit(1);
	if ((fd = open("/dev/null", O_RDWR)) < 0 ) exit(1);
	/* now remove the controling tty (if there is one) */
	if ( (fd = open("/dev/tty", O_RDWR)) >= 0 ) {
		(void) ioctl(fd, TIOCNOTTY, 0);
		(void) close(fd);
	}
#endif
	
	while (1) {
		/* open the utmp file */
		if ((fd = open(UTMP, O_RDONLY, 0)) < 0) {
			syslog(LOG_CRIT, "Idles can't open utmp");
			exit(1);
		}
		/* get the time */
		if (gettimeofday(&tv, &tz) != 0) {
			syslog(LOG_CRIT, "Idles can't get timeofday");
			exit(1);
		}
		ltime = localtime(&tv.tv_sec);
		/* work out the logout time limit */
		if ((ltime->tm_hour > MORNING) && (ltime->tm_hour < EVENING)) {
			logout = DAYOUT;
		}
		else logout = NIGHTO;
		
		/* read the utmp file, record by record until finished */
		while (read(fd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) {
			if (ut.ut_line[0] != '\0' && ut.ut_name[0] != '\0') {
				/* get the last time of use of the terminal by
				   stat-ing the terminal */
				strcpy(fname, "/dev/");
				strcat(fname, ut.ut_line);
				if (stat(fname, &sbuf) != 0) {
					perror("idles: stat: ");
					continue;
				}
				/* calculate the number of minutes since the terminal was last
				   acessed */
				minutes = (tv.tv_sec - sbuf.st_atime ) / 60;
				/* kill him off or warn him if he hasn't used his terminal */
				if (minutes >= logout) {
					zap(fname, LMESSAGE, 0);
					syslog(LOG_INFO, "Auto logout %s %s ",
					  ut.ut_name, ut.ut_line);
				}
				else if (minutes >= WARN) {
					zap(fname, WMESSAGE, 1);
				}
			}
		}
		(void) close(fd);
		/* sleep until its time to start again */
		sleep(SLEEP * 60);
	}
}
/* kill or warn a user */
zap(fname, message, warn)
char *fname, *message;
{
	int allarmed();
	struct sgttyb ttyb;
	int tfd;
	if (fork() == 0) {
		/* child kills the offender */
		/* close all files */
		tfd = getdtablesize();
		for ( tfd--; tfd>=0; tfd--){
			(void) close(tfd);
		}
		/* now remove the controling tty (if there is one) */
		if ( (tfd = open("/dev/tty", O_RDWR)) >= 0 ) {
			(void) ioctl(tfd, TIOCNOTTY, 0);
			(void) close(tfd);
		}
		/* this open will also set a new controling terminal */
		tfd = open(fname, O_RDWR, 0600) ;
		if (tfd < 0) exit(1);
		/* setup a timeout if against all odds we get hung */
		signal(SIGALRM,allarmed);
		alarm(2);
		if (setjmp(env) == 0) {
			/* do this to prevent ^S from hanging the process */
			(void) ioctl(tfd, TIOCSTART, (char *)0);
			/* toggle cbreak to disrupt any terminal paging */
			(void) ioctl(tfd, TIOCGETP, &ttyb);
			ttyb.sg_flags ^= CBREAK;
			(void) ioctl(tfd, TIOCSETP, &ttyb);
			ttyb.sg_flags ^= CBREAK;
			(void) ioctl(tfd, TIOCSETP, &ttyb);
			
			/* write out the logout message */
			write(tfd, message, strlen(message));
		
			/* flush it out for safety's sake */
			(void) ioctl(tfd, TIOCFLUSH, (char *)0);
		}
		alarm(0);
		(void) close(tfd);
		/* kill off the offender's login and exit */
		if (!warn) vhangup();
		exit(0);
	}
	/*parent: wait for the forked process*/
	while (wait(0) == 0);
}

/* just longjmp out if timed out (SIGALRM received) */
allarmed(sig)
int sig;
{
longjmp(env,1);
}