hans@let.vu.nl (Hans Varkevisser) (01/13/89)
I have changed the w.c program (BSD 4.3 w.c version 5.3) to a programm with the following options: I have renamed w.c to autologout.c. autologout -k kill all users with only one proces and 30 min idle Kill all users who are 120 minutes idle without looking to the proces autologout The same as w I don't send the complete file, I only send the diff file because of the copywrite of w.c. You can change the program to an other idle time etc. I have added some explanation in the file, because I needed the program very badly there is a bug in it. This bug must be solved but I don't have the time for it. The bug is: if the idle time > 120 the user is logout, but not always by killing the shell with the hangup signal. Sometimes child processes are killed with hangup instead and finaly the shell is killed. This is because I look at the lowest proces-id and not to the number of the shell pid. the diff file follows. cut here -------------------- cut here ---------------- cut here 7,14c7,11 < /* This programm is adapted from the programm w.c. < * There some changes and some features are deleted < * I add the autologout feature, the programm looks at the < * idle time and the number of processes. If the idle time is > 30 < * and the number of processes = 1 the the user is logout by kill signal < * Hans Varkevisser, Fac of Literature Free University the Netherlands < * let.vu.nl!hans or hans@let.vu.nl (UUCP) < */ --- > #ifndef lint > char copyright[] = > "@(#) Copyright (c) 1980 Regents of the University of California.\n\ > All rights reserved.\n"; > #endif not lint 17c14 < static char sccsid[] = "@(#)autologout.c 1.0 (Free University) 1/11/89"; --- > static char sccsid[] = "@(#)w.c 5.3 (Berkeley) 2/23/86"; 19a17,22 > /* > * w - print system status (who and what) > * > * This program is similar to the systat command on Tenex/Tops 10/20 > * It needs read permission on /dev/mem, /dev/kmem, and /dev/drum. > */ 104,119d106 < /* new variables for autologout */ < < #define KILL_SIGNAL "-1" /* use this for kill, -1 = hangup */ < < int tmp_pid = 0; /* temporary proces id */ < int tmp_uid = 0; /* temporary user id */ < int max_idle = 30; /* max idle time in minutes */ < int max_limit = 120; /* max limit time in minutes */ < int kill_on = 0; /* true if -k flag, kill idle process */ < int tot_proc = 0; /* total of processes */ < char tmp_itoa[10]; /* tmp var to convert int to string */ < char command[512]; /* command string for systemcall */ < int min_number = 100; /* user number less than min_number < * won't be affected < */ < 159,162d145 < case 'k': < kill_on++; < break; < 213a197,199 > if (header) { > /* Print time of day */ > prtat(&now); 214a201,206 > /* > * Print how long system has been up. > * (Found by looking for "boottime" in kernel) > */ > lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0); > read(kmem, &boottime, sizeof (boottime)); 215a208,260 > uptime = now - boottime.tv_sec; > uptime += 30; > days = uptime / (60*60*24); > uptime %= (60*60*24); > hrs = uptime / (60*60); > uptime %= (60*60); > mins = uptime / 60; > > printf(" up"); > if (days > 0) > printf(" %d day%s,", days, days>1?"s":""); > if (hrs > 0 && mins > 0) { > printf(" %2d:%02d,", hrs, mins); > } else { > if (hrs > 0) > printf(" %d hr%s,", hrs, hrs>1?"s":""); > if (mins > 0) > printf(" %d min%s,", mins, mins>1?"s":""); > } > > /* Print number of users logged in to system */ > while (fread(&utmp, sizeof(utmp), 1, ut)) { > if (utmp.ut_name[0] != '\0') > nusers++; > } > rewind(ut); > printf(" %d user%s", nusers, nusers>1?"s":""); > > /* > * Print 1, 5, and 15 minute load averages. > * (Found by looking in kernel for avenrun). > */ > printf(", load average:"); > lseek(kmem, (long)nl[X_AVENRUN].n_value, 0); > read(kmem, avenrun, sizeof(avenrun)); > for (i = 0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) { > if (i > 0) > printf(","); > printf(" %.2f", avenrun[i]); > } > printf("\n"); > if (firstchar == 'u') > exit(0); > > /* Headers for rest of output */ > if (lflag) > printf("User tty login@ idle JCPU PCPU what\n"); > else > printf("User tty idle what\n"); > fflush(stdout); > } > > 233d277 < tot_proc=0; 239,244c283,299 < tot_proc++; < < if (tmp_pid == 0) < tmp_pid=pr[i].w_pid; < tmp_uid=pr[i].w_uid; < --- > /* > * Meaning of debug fields following proc name is: > * & by itself: ignoring both SIGINT and QUIT. > * (==> this proc is not a candidate.) > * & <i> <q>: i is SIGINT status, q is quit. > * 0 == DFL, 1 == IGN, 2 == caught. > * *: proc pgrp == tty pgrp. > */ > if (debug) { > printf("\t\t%d\t%s", pr[i].w_pid, pr[i].w_args); > if ((j=pr[i].w_igintr) > 0) > if (j==IGINT) > printf(" &"); > else > printf(" & %d %d", j%3, j/3); > printf("\n"); > } 248a304,314 > if(pr[i].w_pid>curpid && (pr[i].w_igintr!=IGINT || empty)){ > curpid = pr[i].w_pid; > strcpy(doing, lflag ? pr[i].w_args : pr[i].w_comm); > #ifdef notdef > if (doing[0]==0 || doing[0]=='-' && doing[1]<=' ' || doing[0] == '?') { > strcat(doing, " ("); > strcat(doing, pr[i].w_comm); > strcat(doing, ")"); > } > #endif > } 250,275d315 < < /* -k flag log users out who are idle > 30 minutes */ < if (kill_on == 1) { < < /* convert int pid to string */ < itoa(tmp_pid,tmp_itoa); < < /* put command in command string */ < strcpy(command,"kill "); < strcat(command, KILL_SIGNAL); < strcat(command, " "); < < /* append pid to commandstring */ < strcat(command,tmp_itoa); < /* kill user for idle > 120 minutes don't look at processes*/ < < if ((tmp_uid > min_number) && ( idle >= max_limit)){ < /* execute a kill -1 on pid */ < system(command); < } < /* kill user for idle > 30 minutes and only one process running */ < if ((tmp_uid > min_number) && ( idle >= max_idle) && (tot_proc == 1)){ < /* execute a kill -1 on pid */ < system( command); < } < } else { 277,278d316 < } < tmp_pid=0; 302c340 < --- > 304,305c342 < printf("%d\t%d\t%-*.*s ", tmp_uid, tmp_pid, NMAX, NMAX, utmp.ut_name); < printf("%3d idle \n", idle ); --- > printf("%-*.*s ", NMAX, NMAX, utmp.ut_name); 306a344,374 > /* print tty user is on */ > if (lflag) > /* long form: all (up to) LMAX chars */ > printf("%-*.*s", LMAX, LMAX, utmp.ut_line); > else { > /* short form: 2 chars, skipping 'tty' if there */ > if (utmp.ut_line[0]=='t' && utmp.ut_line[1]=='t' && utmp.ut_line[2]=='y') > printf("%-2.2s", &utmp.ut_line[3]); > else > printf("%-2.2s", utmp.ut_line); > } > > if (lflag) > /* print when the user logged in */ > prtat(&utmp.ut_time); > > /* print idle time */ > if (idle >= 36 * 60) > printf("%2ddays ", (idle + 12 * 60) / (24 * 60)); > else > prttime(idle," "); > > if (lflag) { > /* print CPU time for all processes & children */ > prttime(jobtime," "); > /* print cpu time for interesting process */ > prttime(proctime," "); > } > > /* what user is doing, either command tail or args */ > printf(" %-.32s\n",doing); 606,633d673 < } < itoa(n,s) < char s[]; < int n; < { < int i, sign; < < if ((sign = n) < 0) < n = -n; < i = 0; < do { < s[i++] = n % 10 + '0'; < } while (( n /= 10 ) > 0 ); < if (sign < 0) < s[i++] = '-'; < s[i] = '\0'; < reverse(s); < } < reverse (s) < char s[]; < { < int c, i, j; < < for (i = 0, j = strlen(s)-1; i < j; i++, j--) { < c = s[i]; < s[i] = s[j]; < s[j] = c; < }
hans@let.vu.nl (Hans Varkevisser) (01/18/89)
This only is for users of BSD 4.3 with w.c version 5.3 I have made changes to the program w.c and changed the name to autologout.c. I use the program autologout to logout users who are idle for a given time You set the time in the source file. There are two var for time, max_idle and max_limit. max_idle is used to logout a user who is idle for > max_idle and who only has the shellproces running (number of processes =1). max_limit is used to logout a user who is idle for > max_limit and can have more processes running, only the shellproces is killed. I use the kill -1, pid because -1 is the hangup signal . I find this the best way to do, of course you can use other signals. I use the var min_number to test for uid > given number, this is used by us to leave staff users logged in. I put an entry in crontab that start every 5 minutes autologout -k. Because of the copyright I only have send the diff between w.c and autologout.c. The next vars I used for the program, see the diff file at the end. #define KILL_SIGNAL "-1" /* use this for kill, -1 = hangup */ int tmp_pid = 0; /* temporary proces id */ int tmp_uid = 0; /* temporary user id */ int max_idle = 30; /* max idle time in minutes */ int max_limit = 60; /* max limit time in minutes */ int kill_on = 0; /* true if -k flag, kill idle process */ int tot_proc = 0; /* total of processes */ char tmp_itoa[10]; /* tmp var to convert int to string */ char command[512]; /* command string for systemcall */ int min_number = 100; /* user number less than min_number The text is the result of diff -e w.c autologout.c -------- cut here ------------- cut here ---------------- 673a } itoa(n,s) char s[]; int n; { int i, sign; if ((sign = n) < 0) n = -n; i = 0; do { s[i++] = n % 10 + '0'; } while (( n /= 10 ) > 0 ); if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } reverse (s) char s[]; { int c, i, j; for (i = 0, j = strlen(s)-1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } } kill_shell() { /* convert int pid to string */ itoa(tmp_pid,tmp_itoa); /* put command in command string */ strcpy(command,"kill "); /* KILL_SIGNAL can be user defined */ strcat(command, KILL_SIGNAL); strcat(command, " "); /* append pid to commandstring */ strcat(command,tmp_itoa); /* kill user for idle > 60 minutes don't look at number of processes*/ if ((tmp_uid > min_number) && ( idle >= max_limit)){ /* execute a kill -1 on pid */ system(command); } /* kill user for idle > 30 minutes and only one process running */ if ((tmp_uid > min_number) && ( idle >= max_idle) && (tot_proc == 1)){ /* execute a kill -1 on pid */ system(command); } . 535a pr[np].w_pgrp = mproc.p_pgrp; . 344,374d 342c printf("pid %5d\t%-*.*s ", tmp_pid, NMAX, NMAX, utmp.ut_name); printf("%3d idle \t%-.32s\n", idle,doing ); . 340c . 318a } . 317a strcpy(tmp_doing, lflag ? pr[i].w_args : pr[i].w_comm); if ((doing[0] == '-' || doing[0] == 0) && (tmp_pid == 0)) tmp_pid=pr[i].w_pid; if ((tmp_doing[0] == '-' || tmp_doing[0] == 0) && (tmp_pid == 0)) tmp_pid=pr[i].w_pid; } /* -k flag log users out who are idle > 30 minutes */ if ((kill_on == 1) && ( tmp_pid >= 10)) kill_shell(); else putline(); . 304,316c if(pr[i].w_pid>curpid && (pr[i].w_igintr!=IGINT || empty)){ curpid = pr[i].w_pid; strcpy(doing, lflag ? pr[i].w_args : pr[i].w_comm); . 283,297c tot_proc++; tmp_uid=pr[i].w_uid; if (debug) { printf("\t%5d\t%s",pr[i].w_pid,pr[i].w_args); . 277a tot_proc=0; tmp_pid=0; . 208,260d 201,206d 197,199d 163c case 'a': . 145a case 'k': kill_on++; break; . 106a /* new variables for autologout */ #define KILL_SIGNAL "-1" /* use this for kill, -1 = hangup */ int tmp_pid = 0; /* temporary proces id */ int tmp_uid = 0; /* temporary user id */ int max_idle = 30; /* max idle time in minutes */ int max_limit = 60; /* max limit time in minutes */ int kill_on = 0; /* true if -k flag, kill idle process */ int tot_proc = 0; /* total of processes */ char tmp_itoa[10]; /* tmp var to convert int to string */ char command[512]; /* command string for systemcall */ int min_number = 100; /* user number less than min_number * won't be affected */ char tmp_doing[520]; /* process attached to terminal */ . 41a short w_pgrp; /* proc.p_pgrp */ . 17,22d 14c static char sccsid[] = "@(#)autologout.c 1.0 (Free University) 1/11/89"; . 7,11c /* This programm is adapted from the programm w.c. * There some changes and some features are deleted * I add the autologout feature, the programm looks at the * idle time and the number of processes. If the idle time is > 30 * and the number of processes = 1 the the user is logout by kill signal * For safety there is a check on the uid, on our computer we only kill * the user if the uid > 100. * Hans Varkevisser, Fac of Literature Free University the Netherlands * let.vu.nl!hans or hans@let.vu.nl (UUCP) */ . ----------- end ----------------- -- Organisation: Free University, Faculty of Literature Amsterdam, the Netherlands Name: Hans Varkevisser (system administrator) hans@let.vu.nl or let.vu.nl!hans UUCP