|
|
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 - metrics - 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);
}