home *** CD-ROM | disk | FTP | other *** search
- /* w - show users and their processes
- *
- * Copyright (c) 1993 Larry Greenfield
- * Distributable under the terms of the copyleft, etc.
- *
- * greenfie@gauss.rutgers.edu: Initial version
- *
- * modifications by Michael K. Johnson, johnsonm@sunsite.unc.edu
- *
- * $Log: w.c,v $
- * Revision 1.8 1994/01/29 17:31:52 johnsonm
- * Fixed isnice(), and made the "from" field not shown by default, with
- * the -f switch being a toggle. Also possible to compile so that the
- * "from" field is shown by default; just define W_SHOWFROM. The Makefile
- * contains a line to do this if you wish.
- *
- * Revision 1.7 1994/01/01 18:47:07 johnsonm
- * Made only printable characters appear in the hostname field, since
- * utmps apparantly get screwed up all over. Wrote a terrible
- * inline function called isnice(), which needs to be replaced
- * with something better someday. See the comment near it.
- *
- * Revision 1.6 1994/01/01 18:05:40 johnsonm
- * Added from field, and fixed get_maxcmd() to work correctly with all
- * possible combinations of options.
- *
- * Revision 1.5 1994/01/01 14:24:31 johnsonm
- * JCPU and PCPU appear to work now.
- *
- * Revision 1.4 1994/01/01 12:47:29 johnsonm
- * The tty and what fields now work. JCPU and PCPU don't yet.
- *
- * Visible change log (for those great doc writers):
- * - Feb 11, 1993 (LG): added "u" switch to ignore users while figuring
- * process time and current processes.
- * - Mar 07, 1993 (LG): changed the output to go to the next date form
- * sooner
- * - Mar 07, 1993 (LG): added help on bad command
- * - Mar 07, 1993 (LG): added the option of supplying a user name
- * - Mar 15, 1993 (mkj): fixed formatting with diffs from Quowong P Liu
- * - Apr 13, 1993 (mkj): fixed Liu's formatting strings to not display
- * old bug with string length.
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <time.h>
- #include <utmp.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <ctype.h>
-
- #include "ps.h"
- #include "whattime.h"
-
- struct ps_proc_head *ph; /* a global variable */
- int ignoreuser=0; /* another global, for use with -u */
-
- static char rcsid[] = "$Id: w.c,v 1.8 1994/01/29 17:31:52 johnsonm Exp $";
- static char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
- static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
- "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- void showinfo(struct utmp *user, int formtype, int maxcmd, int from);
- char *stripblank(char *instr);
- int get_maxcmd(int longform, int from);
- char *logintime(struct utmp *user);
- char *idletime(struct utmp *user);
- void getproc(struct utmp *user, char *name, int *jcpu, int *pcpu,
- int maxcmd);
-
- int main(int argc, char **argv)
- {
- int header=1, longform=1; /* parameters */
- #ifdef W_SHOWFROM
- int from=1;
- #else /* default case, from field not shown */
- int from=0;
- #endif
- int args=0; /* were there any args? */
- char ch, *watchuser=NULL;
- FILE *ut; /* /etc/utmp */
- struct utmp *ut_rec; /* utmp record */
- int maxcmd;
-
- /* get options */
- while ((ch = getopt(argc, argv, "hlusf")) != EOF)
- switch (ch) {
- case 'h':
- header = 0; args++;
- break;
- case 'l':
- longform=1; args++;
- break;
- case 's':
- longform=0; args++;
- break;
- case 'u':
- ignoreuser=1; args++;
- break;
- case 'f':
- if(from)
- from = 0;
- else
- from = 1;
- args++;
- break;
- default:
- printf("usage: w -hlsu [user]\n");
- exit(1);
- break;
- }
-
- /* was there any user to look for? */
- if ((argv[args ? 2 : 1]) != NULL)
- watchuser = (argv[args ? 2 : 1]);
-
- /* get maximum command length */
- maxcmd = get_maxcmd(longform, from);
-
- /* get running processes -- want all processes, we want the username as well
- as id, don't need processes without controlling
- terminals, don't need memory stats, uid doesn't matter, and ctty is NULL
- so that it doesn't get considered. */
- ph = take_snapshot(1, 1, 0, 0, 0, 0, 0);
-
- /* print uptime */
- if (header) {
- print_uptime();
- printf("User tty ");
- if(from)
- printf("from ");
- if (longform)
- printf(" login@ idle JCPU PCPU what\n");
- else
- printf(" idle what\n");
- }
- /* open utmp */
-
- ut = fopen(UTMP_FILE, "r");
- if (watchuser == NULL) {
- while (ut_rec = getutent())
- if ((ut_rec->ut_type == USER_PROCESS) &&
- (ut_rec->ut_name[0] != '\000'))
- showinfo(ut_rec, longform, maxcmd, from);
- } else {
- while (ut_rec = getutent())
- if (!strcmp(ut_rec->ut_name, watchuser) &&
- (ut_rec->ut_type == USER_PROCESS))
- showinfo(ut_rec, longform, maxcmd, from);
- }
- fclose(ut);
- return 0;
- }
-
-
- /* For showinfo. The (c < 128) is because some terminals are being screwed
- * up by high-order characters that some utmp-modifying programs are
- * either putting or leaving in utmp.
- */
- inline int isnice(char c)
- {
- return (isprint(c) && ((unsigned char)c < 128));
- }
-
- void showinfo(struct utmp *user, int formtype, int maxcmd, int from)
- {
- char name[254], uname[UT_NAMESIZE + 1], *ltime, *itime;
- int jcpu, pcpu;
-
- getproc(user, name, &jcpu, &pcpu, maxcmd);
- ltime = logintime(user);
- itime = idletime(user);
- strncpy(uname, user->ut_user, 8); uname[8] = 0;
- if (formtype) {
- printf("%-9.8s%-9.8s", user->ut_user, user->ut_line);
- if (from) {
- int i;
- for (i=0;i<16;i++) {
- if (!isnice(user->ut_host[i]))
- user->ut_host[i] = ' ';
- }
- printf("%-16.16s", user->ut_host);
- }
- printf("%-7.7s%-7.7s", ltime, itime);
- if (jcpu/60) printf ("%3d:%02d", jcpu/60, jcpu%60);
- else if (jcpu) printf (" %2d", jcpu);
- else printf (" ");
- if (pcpu/60) printf (" %3d:%02d %s\n", pcpu/60, pcpu%60, name);
- else if (pcpu%60) printf (" %2d %s\n", pcpu, name);
- else printf (" %s\n", name);
- }
- else {
- printf("%-9.8s%-9.8s", user->ut_user, user->ut_line);
- if (from) {
- int i;
- for (i=0;i<16;i++) {
- if (!isnice(user->ut_host[i]))
- user->ut_host[i] = ' ';
- }
- printf("%-16.16s", user->ut_host);
- }
- printf("%-7.7s %s\n", itime, name);
-
- }
- }
-
- char *logintime(struct utmp *user)
-
- /* get the login time in order */
-
- {
- time_t curtime;
- struct tm *logintime, *curtm;
- int hour, am, curday, logday;
- static char give[20];
-
- curtime = time(NULL);
- curtm = localtime(&curtime);
- curday = curtm->tm_yday;
- logintime = localtime(&user->ut_time);
- hour = logintime->tm_hour;
- logday = logintime->tm_yday;
- am = (hour < 12);
- if (!am)
- hour -= 12;
- if (hour == 0)
- hour = 12;
- /* This is a newer behavior: it waits 12 hours and the next day, and then
- goes to the 2nd time format. This should reduce confusion.
- It then waits only 6 days (not till the last moment) to go the last
- time format.
- */
- if ((curtime > (user->ut_time + (60 * 60 * 12))) && (logday != curday))
- if (curtime > (user->ut_time + (60 * 60 * 24 * 6)))
- sprintf(give, "%2d%3s%2d", logintime->tm_mday, month[logintime->tm_mon],
- (logintime->tm_year % 100));
- else
- sprintf(give, "%*s%2d%s", 3, weekday[logintime->tm_wday],
- hour, am ? "am" : "pm");
- else
- sprintf(give, "%2d:%02d%s", hour, logintime->tm_min, am ? "am" : "pm");
- return give;
- }
-
- char *idletime(struct utmp *user)
-
- /* find idle time */
-
- {
- struct stat terminfo;
- unsigned long idle;
- char ttytmp[40];
- static char give[20];
- time_t curtime;
-
- curtime = time(NULL);
- sprintf(ttytmp, "/dev/%s", stripblank(user->ut_line));
- stat(ttytmp, &terminfo);
- idle = (unsigned long) curtime - (unsigned long) terminfo.st_atime;
- if (idle >= (60 * 60)) /* more than an hour */
- if (idle >= (60 * 60 * 48)) /* more than two days */
- sprintf(give, "%2ludays", idle / (60 * 60 * 24));
- else
- sprintf(give, " %2lu:%02u", idle / (60 * 60),
- (unsigned) ((idle / 60) % 60));
- else
- if (idle / 60)
- sprintf(give, "%6lu", idle / 60);
- else
- give[0]=0;
- /* sprintf(give, "");*/
- return give;
- }
-
- void getproc(struct utmp *user, char *name, int *jcpu, int *pcpu,
- int maxcmd)
-
- /* Find current commands */
-
- {
- struct ps_proc *finder, *best;
- static char line[4];
-
- (*jcpu) = 0; (*pcpu) = 0;
- best = NULL;
- strncpy(line, dev3(user->ut_line), 3);
- line[3] = '\0';
- if (ignoreuser) {
- for (finder = ph->head; finder != NULL; finder = finder->next) {
- if (!strcmp(finder->ttyc, line)) {
- (*jcpu) += finder->utime + finder->stime;
- if ((finder->pid == finder->tpgid) &&
- ((best == NULL) || (finder->pid > best->pid)))
- best = finder;
- }
- }
- } else { /* pay attention to users */
- for (finder = ph->head; finder != NULL; finder = finder->next) {
- if (!strcmp(finder->ttyc, line)) {
- (*jcpu) += finder->utime + finder->stime;
- if (!strncmp(finder->user, user->ut_user, 8)) {
- if ((finder->pid == finder->tpgid) &&
- ((best == NULL) ||(finder->pid > best->pid)))
- best = finder;
- }
- }
- }
- }
- (*jcpu) /= 100;
- if (best != NULL) {
- (*pcpu) = (best->utime + best->stime) / 100;
-
- /* print the command line, but no more than will go off the edge of the
- screen. This is standard obfuscated c... ;-) best->cmd is used if
- the process is swapped out. */
- sprintf(name, "%s", strlen(best->cmdline) ?
- best->cmdline[maxcmd]=0,best->cmdline : best->cmd );
- } else {
- sprintf(name, "-");
- }
- }
-
-
- char *stripblank(char *instr)
-
- /* truncates the string at the site of a ' ' */
-
- {
- int c=0;
-
- while (instr[c] != ' ' && instr[c] != '\000')
- c++;
- instr[c] = '\000';
- return instr;
- }
-
-
- int get_maxcmd(int longform, int from)
- {
- struct winsize win;
- int cols = 80;
-
- if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
- cols = win.ws_col;
-
- cols -= 28;
- if (from)
- cols -= 16;
- if (longform)
- cols -= 20;
- if (cols < 3) {
- fprintf(stderr, "Screen size too small: %d", win.ws_col);
- exit(1);
- }
- return cols;
- }
-
-