home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / A / PS / PROCPS-0.000 / PROCPS-0 / procps-0.97 / w.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-25  |  9.8 KB  |  363 lines

  1. /* w - show users and their processes
  2.  *
  3.  * Copyright (c) 1993 Larry Greenfield
  4.  * Distributable under the terms of the copyleft, etc.
  5.  *
  6.  * greenfie@gauss.rutgers.edu: Initial version
  7.  *
  8.  * modifications by Michael K. Johnson, johnsonm@sunsite.unc.edu
  9.  *
  10.  * $Log: w.c,v $
  11.  * Revision 1.8  1994/01/29  17:31:52  johnsonm
  12.  * Fixed isnice(), and made the "from" field not shown by default, with
  13.  * the -f switch being a toggle.  Also possible to compile so that the
  14.  * "from" field is shown by default; just define W_SHOWFROM.  The Makefile
  15.  * contains a line to do this if you wish.
  16.  *
  17.  * Revision 1.7  1994/01/01  18:47:07  johnsonm
  18.  * Made only printable characters appear in the hostname field, since
  19.  * utmps apparantly get screwed up all over.  Wrote a terrible
  20.  * inline function called isnice(), which needs to be replaced
  21.  * with something better someday.  See the comment near it.
  22.  *
  23.  * Revision 1.6  1994/01/01  18:05:40  johnsonm
  24.  * Added from field, and fixed get_maxcmd() to work correctly with all
  25.  * possible combinations of options.
  26.  *
  27.  * Revision 1.5  1994/01/01  14:24:31  johnsonm
  28.  * JCPU and PCPU appear to work now.
  29.  *
  30.  * Revision 1.4  1994/01/01  12:47:29  johnsonm
  31.  * The tty and what fields now work.  JCPU and PCPU don't yet.
  32.  *
  33.  * Visible change log (for those great doc writers):
  34.  *  - Feb 11, 1993 (LG):  added "u" switch to ignore users while figuring
  35.  *                        process time and current processes.
  36.  *  - Mar 07, 1993 (LG):  changed the output to go to the next date form
  37.  *                        sooner
  38.  *  - Mar 07, 1993 (LG):  added help on bad command
  39.  *  - Mar 07, 1993 (LG):  added the option of supplying a user name
  40.  *  - Mar 15, 1993 (mkj): fixed formatting with diffs from Quowong P Liu
  41.  *  - Apr 13, 1993 (mkj): fixed Liu's formatting strings to not display
  42.  *              old bug with string length.
  43.  *
  44.  */
  45.  
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <sys/ioctl.h>
  50. #include <time.h>
  51. #include <utmp.h>
  52. #include <fcntl.h>
  53. #include <unistd.h>
  54. #include <sys/stat.h>
  55. #include <ctype.h>
  56.  
  57. #include "ps.h"
  58. #include "whattime.h"
  59.  
  60. struct ps_proc_head *ph; /* a global variable */
  61. int ignoreuser=0; /* another global, for use with -u */
  62.  
  63. static char rcsid[] = "$Id: w.c,v 1.8 1994/01/29 17:31:52 johnsonm Exp $";
  64. static char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  65. static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  66.                            "Aug", "Sep", "Oct", "Nov", "Dec" };
  67.  
  68. void showinfo(struct utmp *user, int formtype, int maxcmd, int from);
  69. char *stripblank(char *instr);
  70. int get_maxcmd(int longform, int from);
  71. char *logintime(struct utmp *user);
  72. char *idletime(struct utmp *user);
  73. void getproc(struct utmp *user, char *name, int *jcpu, int *pcpu, 
  74.          int maxcmd);
  75.  
  76. int main(int argc, char **argv)
  77. {
  78.   int header=1, longform=1; /* parameters */
  79. #ifdef W_SHOWFROM
  80.   int from=1;
  81. #else /* default case, from field not shown */
  82.   int from=0;
  83. #endif
  84.   int args=0; /* were there any args? */
  85.   char ch, *watchuser=NULL;
  86.   FILE *ut; /* /etc/utmp */
  87.   struct utmp *ut_rec; /* utmp record */
  88.   int maxcmd;
  89.  
  90. /* get options */
  91.   while ((ch = getopt(argc, argv, "hlusf")) != EOF)
  92.     switch (ch) {
  93.     case 'h':
  94.       header = 0; args++;
  95.       break;
  96.     case 'l':
  97.       longform=1; args++;
  98.       break;
  99.     case 's':
  100.       longform=0; args++;
  101.       break;
  102.     case 'u':
  103.       ignoreuser=1; args++;
  104.       break;
  105.     case 'f':
  106.       if(from)
  107.     from = 0;
  108.       else
  109.     from = 1;
  110.       args++;
  111.       break;
  112.     default:
  113.       printf("usage: w -hlsu [user]\n");
  114.       exit(1);
  115.       break;
  116.     }
  117.  
  118. /* was there any user to look for? */
  119.   if ((argv[args ? 2 : 1]) != NULL)
  120.     watchuser = (argv[args ? 2 : 1]);
  121.  
  122. /* get maximum command length */
  123.   maxcmd = get_maxcmd(longform, from);
  124.  
  125. /* get running processes -- want all processes, we want the username as well
  126.    as id, don't need processes without controlling
  127.    terminals, don't need memory stats, uid doesn't matter, and ctty is NULL
  128.    so that it doesn't get considered. */
  129.   ph = take_snapshot(1, 1, 0, 0, 0, 0, 0);
  130.  
  131. /* print uptime */
  132.   if (header) {
  133.     print_uptime();
  134.       printf("User     tty      ");
  135.     if(from)
  136.       printf("from            ");
  137.     if (longform)
  138.       printf(" login@  idle   JCPU   PCPU  what\n");
  139.     else
  140.       printf("  idle   what\n");
  141.   }
  142. /* open utmp */
  143.  
  144.   ut = fopen(UTMP_FILE, "r");
  145.   if (watchuser == NULL) {
  146.     while (ut_rec = getutent())
  147.       if ((ut_rec->ut_type == USER_PROCESS) &&
  148.       (ut_rec->ut_name[0] != '\000'))
  149.     showinfo(ut_rec, longform, maxcmd, from);
  150.   } else {
  151.     while (ut_rec = getutent())
  152.       if (!strcmp(ut_rec->ut_name, watchuser) &&
  153.       (ut_rec->ut_type == USER_PROCESS))
  154.     showinfo(ut_rec, longform, maxcmd, from);
  155.   }
  156.   fclose(ut);
  157.   return 0;
  158. }
  159.  
  160.  
  161. /* For showinfo.  The (c < 128) is because some terminals are being screwed
  162.  * up by high-order characters that some utmp-modifying programs are
  163.  * either putting or leaving in utmp.
  164.  */
  165. inline int isnice(char c)
  166. {
  167.   return (isprint(c) && ((unsigned char)c < 128));
  168. }
  169.  
  170. void showinfo(struct utmp *user, int formtype, int maxcmd, int from)
  171. {
  172.   char name[254], uname[UT_NAMESIZE + 1], *ltime, *itime;
  173.   int jcpu, pcpu;
  174.  
  175.   getproc(user, name, &jcpu, &pcpu, maxcmd);
  176.   ltime = logintime(user); 
  177.   itime = idletime(user);
  178.   strncpy(uname, user->ut_user, 8); uname[8] = 0;
  179.   if (formtype) {
  180.     printf("%-9.8s%-9.8s", user->ut_user, user->ut_line);
  181.     if (from) {
  182.       int i;
  183.       for (i=0;i<16;i++) {
  184.     if (!isnice(user->ut_host[i]))
  185.       user->ut_host[i] = ' ';
  186.       }
  187.       printf("%-16.16s", user->ut_host);
  188.     }
  189.     printf("%-7.7s%-7.7s", ltime, itime);
  190.     if (jcpu/60) printf ("%3d:%02d", jcpu/60, jcpu%60);
  191.     else if (jcpu) printf ("    %2d", jcpu);
  192.     else printf ("      ");
  193.     if (pcpu/60) printf (" %3d:%02d  %s\n", pcpu/60, pcpu%60, name);
  194.     else if (pcpu%60) printf ("     %2d  %s\n", pcpu, name);
  195.     else printf ("         %s\n", name);
  196.   }
  197.   else {
  198.     printf("%-9.8s%-9.8s", user->ut_user, user->ut_line);
  199.     if (from) {
  200.       int i;
  201.       for (i=0;i<16;i++) {
  202.     if (!isnice(user->ut_host[i]))
  203.       user->ut_host[i] = ' ';
  204.       }
  205.       printf("%-16.16s", user->ut_host);
  206.     }
  207.     printf("%-7.7s  %s\n", itime, name);
  208.  
  209.   }
  210. }
  211.  
  212. char *logintime(struct utmp *user)
  213.  
  214. /* get the login time in order */
  215.  
  216. {
  217.   time_t curtime;
  218.   struct tm *logintime, *curtm;
  219.   int hour, am, curday, logday;
  220.   static char give[20];
  221.  
  222.   curtime = time(NULL);
  223.   curtm = localtime(&curtime);
  224.   curday = curtm->tm_yday;
  225.   logintime = localtime(&user->ut_time);
  226.   hour = logintime->tm_hour;
  227.   logday = logintime->tm_yday;
  228.   am = (hour < 12);
  229.   if (!am)
  230.     hour -= 12;
  231.   if (hour == 0)
  232.     hour = 12;
  233. /* This is a newer behavior: it waits 12 hours and the next day, and then
  234.    goes to the 2nd time format. This should reduce confusion.
  235.    It then waits only 6 days (not till the last moment) to go the last
  236.    time format.
  237. */
  238.   if ((curtime > (user->ut_time + (60 * 60 * 12))) && (logday != curday))
  239.     if (curtime > (user->ut_time + (60 * 60 * 24 * 6)))
  240.       sprintf(give, "%2d%3s%2d", logintime->tm_mday, month[logintime->tm_mon],
  241.          (logintime->tm_year % 100));
  242.     else
  243.       sprintf(give, "%*s%2d%s", 3, weekday[logintime->tm_wday],
  244.          hour, am ? "am" : "pm");
  245.   else
  246.     sprintf(give, "%2d:%02d%s", hour, logintime->tm_min, am ? "am" : "pm");
  247.   return give;
  248. }
  249.  
  250. char *idletime(struct utmp *user)
  251.  
  252. /* find idle time */
  253.  
  254. {
  255.   struct stat terminfo;
  256.   unsigned long idle;
  257.   char ttytmp[40];
  258.   static char give[20];
  259.   time_t curtime;
  260.  
  261.   curtime = time(NULL);
  262.   sprintf(ttytmp, "/dev/%s", stripblank(user->ut_line));
  263.   stat(ttytmp, &terminfo);
  264.   idle = (unsigned long) curtime - (unsigned long) terminfo.st_atime;
  265.   if (idle >= (60 * 60)) /* more than an hour */
  266.     if (idle >= (60 * 60 * 48)) /* more than two days */
  267.       sprintf(give, "%2ludays", idle / (60 * 60 * 24));
  268.     else
  269.       sprintf(give, " %2lu:%02u", idle / (60 * 60), 
  270.           (unsigned) ((idle / 60) % 60));
  271.   else
  272.     if (idle / 60)
  273.       sprintf(give, "%6lu", idle / 60);
  274.     else
  275.       give[0]=0;
  276. /*      sprintf(give, "");*/
  277.   return give;
  278. }
  279.  
  280. void getproc(struct utmp *user, char *name, int *jcpu, int *pcpu, 
  281.          int maxcmd)
  282.  
  283. /* Find current commands */
  284.  
  285. {
  286.   struct ps_proc *finder, *best;
  287.   static char line[4];
  288.  
  289.   (*jcpu) = 0; (*pcpu) = 0;
  290.   best = NULL;
  291.   strncpy(line, dev3(user->ut_line), 3);
  292.   line[3] = '\0';
  293.   if (ignoreuser) {
  294.     for (finder = ph->head; finder != NULL; finder = finder->next) {
  295.       if (!strcmp(finder->ttyc, line)) {
  296.     (*jcpu) += finder->utime + finder->stime;
  297.     if ((finder->pid == finder->tpgid) &&
  298.         ((best == NULL) || (finder->pid > best->pid)))
  299.       best = finder;
  300.       }
  301.     }
  302.   } else { /* pay attention to users */
  303.     for (finder = ph->head; finder != NULL; finder = finder->next) {
  304.       if (!strcmp(finder->ttyc, line)) {
  305.     (*jcpu) += finder->utime + finder->stime;
  306.     if (!strncmp(finder->user, user->ut_user, 8)) {
  307.       if ((finder->pid == finder->tpgid) &&
  308.           ((best == NULL) ||(finder->pid > best->pid)))
  309.         best = finder;
  310.     }
  311.       }
  312.     }
  313.   }
  314.   (*jcpu) /= 100;
  315.   if (best != NULL) {
  316.     (*pcpu) = (best->utime + best->stime) / 100;
  317.     
  318. /* print the command line, but no more than will go off the edge of the
  319.    screen.  This is standard obfuscated c... ;-)  best->cmd is used if
  320.    the process is swapped out. */
  321.     sprintf(name, "%s", strlen(best->cmdline) ?
  322.        best->cmdline[maxcmd]=0,best->cmdline : best->cmd );
  323.   } else {
  324.     sprintf(name, "-");
  325.   }
  326. }
  327.  
  328.  
  329. char *stripblank(char *instr)
  330.  
  331. /* truncates the string at the site of a ' ' */
  332.  
  333. {
  334.   int c=0;
  335.  
  336.   while (instr[c] != ' ' && instr[c] != '\000')
  337.     c++;
  338.   instr[c] = '\000';
  339.   return instr;
  340. }
  341.  
  342.  
  343. int get_maxcmd(int longform, int from)
  344. {
  345.     struct winsize win;
  346.     int cols = 80;
  347.  
  348.     if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
  349.     cols = win.ws_col;
  350.  
  351.     cols -= 28;
  352.     if (from)
  353.       cols -= 16;
  354.     if (longform)
  355.       cols -= 20;
  356.     if (cols < 3) {
  357.       fprintf(stderr, "Screen size too small: %d", win.ws_col);
  358.       exit(1);
  359.     }
  360.     return cols;
  361. }
  362.  
  363.