|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T i ┃
Length: 5448 (0x1548) Types: TextFile Names: »idle.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/idle/idle.c«
/* 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); }