Print this page
    
OS-3280 need a way to specify the root of a native system in the lx brand
OS-3279 lx brand should allow delegated datasets
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/prstat/prstat.c
          +++ new/usr/src/cmd/prstat/prstat.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2013 Gary Mills
  24   24   *
  25   25   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26   26   * Use is subject to license terms.
  27   27   *
  28   28   * Portions Copyright 2009 Chad Mynhier
  29   29   */
  30   30  
  31   31  #include <sys/types.h>
  32   32  #include <sys/resource.h>
  33   33  #include <sys/loadavg.h>
  34   34  #include <sys/time.h>
  35   35  #include <sys/pset.h>
  36   36  #include <sys/vm_usage.h>
  37   37  #include <zone.h>
  38   38  #include <libzonecfg.h>
  39   39  
  40   40  #include <stdio.h>
  41   41  #include <stdlib.h>
  42   42  #include <unistd.h>
  43   43  #include <dirent.h>
  44   44  #include <string.h>
  45   45  #include <errno.h>
  46   46  #include <poll.h>
  47   47  #include <ctype.h>
  48   48  #include <fcntl.h>
  49   49  #include <limits.h>
  50   50  #include <signal.h>
  51   51  #include <time.h>
  52   52  #include <project.h>
  53   53  
  54   54  #include <langinfo.h>
  55   55  #include <libintl.h>
  56   56  #include <locale.h>
  57   57  
  58   58  #include "prstat.h"
  59   59  #include "prutil.h"
  60   60  #include "prtable.h"
  61   61  #include "prsort.h"
  62   62  #include "prfile.h"
  63   63  
  64   64  /*
  65   65   * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR.  For the purposes
  66   66   * of this file, we care about the curses.h ERR so include that last.
  67   67   */
  68   68  
  69   69  #if     defined(ERR)
  70   70  #undef  ERR
  71   71  #endif
  72   72  
  73   73  #ifndef TEXT_DOMAIN                     /* should be defined by cc -D */
  74   74  #define TEXT_DOMAIN     "SYS_TEST"      /* use this only if it wasn't */
  75   75  #endif
  76   76  
  77   77  #include <curses.h>
  78   78  #include <term.h>
  79   79  
  80   80  #define LOGIN_WIDTH     8
  81   81  #define ZONE_WIDTH      28
  82   82  #define PROJECT_WIDTH   28
  83   83  
  84   84  #define PSINFO_HEADER_PROC \
  85   85  "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP       "
  86   86  #define PSINFO_HEADER_PROC_LGRP \
  87   87  "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU LGRP PROCESS/NLWP  "
  88   88  #define PSINFO_HEADER_LWP \
  89   89  "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/LWPID      "
  90   90  #define PSINFO_HEADER_LWP_LGRP \
  91   91  "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU LGRP PROCESS/LWPID "
  92   92  #define USAGE_HEADER_PROC \
  93   93  "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP  "
  94   94  #define USAGE_HEADER_LWP \
  95   95  "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
  96   96  #define USER_HEADER_PROC \
  97   97  " NPROC USERNAME  SWAP   RSS MEMORY      TIME  CPU                             "
  98   98  #define USER_HEADER_LWP \
  99   99  "  NLWP USERNAME  SWAP   RSS MEMORY      TIME  CPU                             "
 100  100  #define TASK_HEADER_PROC \
 101  101  "TASKID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
 102  102  #define TASK_HEADER_LWP \
 103  103  "TASKID     NLWP  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
 104  104  #define PROJECT_HEADER_PROC \
 105  105  "PROJID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
 106  106  #define PROJECT_HEADER_LWP \
 107  107  "PROJID     NLWP  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
 108  108  #define ZONE_HEADER_PROC \
 109  109  "ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE                        "
 110  110  #define ZONE_HEADER_LWP \
 111  111  "ZONEID     NLWP  SWAP   RSS MEMORY      TIME  CPU ZONE                        "
 112  112  #define PSINFO_LINE \
 113  113  "%6d %-8s %5s %5s %-6s %3s  %3s %9s %3.3s%% %-.16s/%d"
 114  114  #define PSINFO_LINE_LGRP \
 115  115  "%6d %-8s %5s %5s %-6s %3s  %3s %9s %3.3s%% %4d %-.16s/%d"
 116  116  #define USAGE_LINE \
 117  117  "%6d %-8s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s "\
 118  118  "%3.3s %3.3s %-.12s/%d"
 119  119  #define USER_LINE \
 120  120  "%6d %-8s %5.5s %5.5s   %3.3s%% %9s %3.3s%%"
 121  121  #define TASK_LINE \
 122  122  "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
 123  123  #define PROJECT_LINE \
 124  124  "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
 125  125  #define ZONE_LINE \
 126  126  "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
 127  127  
 128  128  #define TOTAL_LINE \
 129  129  "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
 130  130  
 131  131  /* global variables */
 132  132  
 133  133  static char     *t_ulon;                        /* termcap: start underline */
 134  134  static char     *t_uloff;                       /* termcap: end underline */
 135  135  static char     *t_up;                          /* termcap: cursor 1 line up */
 136  136  static char     *t_eol;                         /* termcap: clear end of line */
 137  137  static char     *t_smcup;                       /* termcap: cursor mvcap on */
 138  138  static char     *t_rmcup;                       /* termcap: cursor mvcap off */
 139  139  static char     *t_home;                        /* termcap: move cursor home */
 140  140  static char     *movecur = NULL;                /* termcap: move up string */
 141  141  static char     *empty_string = "\0";           /* termcap: empty string */
 142  142  static uint_t   print_movecur = FALSE;          /* print movecur or not */
 143  143  static int      is_curses_on = FALSE;           /* current curses state */
 144  144  
 145  145  static table_t  pid_tbl = {0, 0, NULL};         /* selected processes */
 146  146  static table_t  cpu_tbl = {0, 0, NULL};         /* selected processors */
 147  147  static table_t  set_tbl = {0, 0, NULL};         /* selected processor sets */
 148  148  static table_t  prj_tbl = {0, 0, NULL};         /* selected projects */
 149  149  static table_t  tsk_tbl = {0, 0, NULL};         /* selected tasks */
 150  150  static table_t  lgr_tbl = {0, 0, NULL};         /* selected lgroups */
 151  151  static zonetbl_t zone_tbl = {0, 0, NULL};       /* selected zones */
 152  152  static uidtbl_t euid_tbl = {0, 0, NULL};        /* selected effective users */
 153  153  static uidtbl_t ruid_tbl = {0, 0, NULL};        /* selected real users */
 154  154  
 155  155  static uint_t   total_procs;                    /* total number of procs */
 156  156  static uint_t   total_lwps;                     /* total number of lwps */
 157  157  static float    total_cpu;                      /* total cpu usage */
 158  158  static float    total_mem;                      /* total memory usage */
 159  159  
 160  160  static list_t   lwps;                           /* list of lwps/processes */
 161  161  static list_t   users;                          /* list of users */
 162  162  static list_t   tasks;                          /* list of tasks */
 163  163  static list_t   projects;                       /* list of projects */
 164  164  static list_t   zones;                          /* list of zones */
 165  165  static list_t   lgroups;                        /* list of lgroups */
 166  166  
 167  167  static volatile uint_t sigwinch = 0;
 168  168  static volatile uint_t sigtstp = 0;
 169  169  static volatile uint_t sigterm = 0;
 170  170  
 171  171  static long pagesize;
 172  172  
 173  173  /* default settings */
  
    | 
      ↓ open down ↓ | 
    173 lines elided | 
    
      ↑ open up ↑ | 
  
 174  174  
 175  175  static optdesc_t opts = {
 176  176          5,                      /* interval between updates, seconds */
 177  177          15,                     /* number of lines in top part */
 178  178          5,                      /* number of lines in bottom part */
 179  179          -1,                     /* number of iterations; infinitely */
 180  180          OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP,
 181  181          -1                      /* sort in decreasing order */
 182  182  };
 183  183  
      184 +
      185 +static int
      186 +proc_snprintf(char *_RESTRICT_KYWD s, size_t n,
      187 +    const char *_RESTRICT_KYWD fmt, ...)
      188 +{
      189 +        static boolean_t ptools_zroot_valid = B_FALSE;
      190 +        static const char *ptools_zroot = NULL;
      191 +        va_list args;
      192 +        int ret, nret = 0;
      193 +
      194 +        if (ptools_zroot_valid == B_FALSE) {
      195 +                ptools_zroot_valid = B_TRUE;
      196 +                ptools_zroot = zone_get_nroot();
      197 +        }
      198 +
      199 +        if (ptools_zroot != NULL) {
      200 +                nret = snprintf(s, n, "%s", ptools_zroot);
      201 +                if (nret > n)
      202 +                        return (nret);
      203 +        }
      204 +        va_start(args, fmt);
      205 +        ret = vsnprintf(s + nret, n - nret, fmt, args);
      206 +        va_end(args);
      207 +
      208 +        return (ret + nret);
      209 +}
      210 +
 184  211  /*
 185  212   * Print timestamp as decimal reprentation of time_t value (-d u was specified)
 186  213   * or the standard date format (-d d was specified).
 187  214   */
 188  215  static void
 189  216  print_timestamp(void)
 190  217  {
 191  218          time_t t = time(NULL);
 192  219          static char *fmt = NULL;
 193  220  
 194  221          /* We only need to retrieve this once per invocation */
 195  222          if (fmt == NULL)
 196  223                  fmt = nl_langinfo(_DATE_FMT);
 197  224  
 198  225          if (opts.o_outpmode & OPT_UDATE) {
 199  226                  (void) printf("%ld", t);
 200  227          } else if (opts.o_outpmode & OPT_DDATE) {
 201  228                  char dstr[64];
 202  229                  int len;
 203  230  
 204  231                  len = strftime(dstr, sizeof (dstr), fmt, localtime(&t));
 205  232                  if (len > 0)
 206  233                          (void) printf("%s", dstr);
 207  234          }
 208  235          (void) putp(t_eol);
 209  236          (void) putchar('\n');
 210  237  }
 211  238  
 212  239  static void
 213  240  psetloadavg(long psetid, void *ptr)
 214  241  {
 215  242          double psetloadavg[3];
 216  243          double *loadavg = ptr;
 217  244  
 218  245          if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) {
 219  246                  *loadavg++ += psetloadavg[0];
 220  247                  *loadavg++ += psetloadavg[1];
 221  248                  *loadavg += psetloadavg[2];
 222  249          }
 223  250  }
 224  251  
 225  252  /*
 226  253   * Queries the memory virtual and rss size for each member of a list.
 227  254   * This will override the values computed by /proc aggregation.
 228  255   */
 229  256  static void
 230  257  list_getsize(list_t *list)
 231  258  {
 232  259          id_info_t *id;
 233  260          vmusage_t *results, *next;
 234  261          vmusage_t *match;
 235  262          size_t nres = 0;
 236  263          size_t i;
 237  264          uint_t flags = 0;
 238  265          int ret;
 239  266          size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize;
 240  267  
 241  268          /*
 242  269           * Determine what swap/rss results to calculate.  getvmusage() will
 243  270           * prune results returned to non-global zones automatically, so
 244  271           * there is no need to pass different flags when calling from a
 245  272           * non-global zone.
 246  273           *
 247  274           * Currently list_getsize() is only called with a single flag.  This
 248  275           * is because -Z, -J, -T, and -a are mutually exclusive.  Regardless
 249  276           * of this, we handle multiple flags.
 250  277           */
 251  278          if (opts.o_outpmode & OPT_USERS) {
 252  279                  /*
 253  280                   * Gather rss for all users in all zones.  Treat the same
 254  281                   * uid in different zones as the same user.
 255  282                   */
 256  283                  flags |= VMUSAGE_COL_RUSERS;
 257  284  
 258  285          } else if (opts.o_outpmode & OPT_TASKS) {
 259  286                  /* Gather rss for all tasks in all zones */
 260  287                  flags |= VMUSAGE_ALL_TASKS;
 261  288  
 262  289          } else if (opts.o_outpmode & OPT_PROJECTS) {
 263  290                  /*
 264  291                   * Gather rss for all projects in all zones.  Treat the same
 265  292                   * projid in diffrent zones as the same project.
 266  293                   */
 267  294                  flags |= VMUSAGE_COL_PROJECTS;
 268  295  
 269  296          } else if (opts.o_outpmode & OPT_ZONES) {
 270  297                  /* Gather rss for all zones */
 271  298                  flags |= VMUSAGE_ALL_ZONES;
 272  299  
 273  300          } else {
 274  301                  Die(gettext(
 275  302                      "Cannot determine rss flags for output options %x\n"),
 276  303                      opts.o_outpmode);
 277  304          }
 278  305  
 279  306          /*
 280  307           * getvmusage() returns an array of result structures.  One for
 281  308           * each zone, project, task, or user on the system, depending on
 282  309           * flags.
 283  310           *
 284  311           * If getvmusage() fails, prstat will use the size already gathered
 285  312           * from psinfo
 286  313           */
 287  314          if (getvmusage(flags, opts.o_interval, NULL, &nres) != 0)
 288  315                  return;
 289  316  
 290  317          results = (vmusage_t *)Malloc(sizeof (vmusage_t) * nres);
 291  318          for (;;) {
 292  319                  ret = getvmusage(flags, opts.o_interval, results, &nres);
 293  320                  if (ret == 0)
 294  321                          break;
 295  322                  if (errno == EOVERFLOW) {
 296  323                          results = (vmusage_t *)Realloc(results,
 297  324                              sizeof (vmusage_t) * nres);
 298  325                          continue;
 299  326                  }
 300  327                  /*
 301  328                   * Failure for some other reason.  Prstat will use the size
 302  329                   * already gathered from psinfo.
 303  330                   */
 304  331                  free(results);
 305  332                  return;
 306  333          }
 307  334          for (id = list->l_head; id != NULL; id = id->id_next) {
 308  335  
 309  336                  match = NULL;
 310  337                  next = results;
 311  338                  for (i = 0; i < nres; i++, next++) {
 312  339                          switch (flags) {
 313  340                          case VMUSAGE_COL_RUSERS:
 314  341                                  if (next->vmu_id == id->id_uid)
 315  342                                          match = next;
 316  343                                  break;
 317  344                          case VMUSAGE_ALL_TASKS:
 318  345                                  if (next->vmu_id == id->id_taskid)
 319  346                                          match = next;
 320  347                                  break;
 321  348                          case VMUSAGE_COL_PROJECTS:
 322  349                                  if (next->vmu_id == id->id_projid)
 323  350                                          match = next;
 324  351                                  break;
 325  352                          case VMUSAGE_ALL_ZONES:
 326  353                                  if (next->vmu_id == id->id_zoneid)
 327  354                                          match = next;
 328  355                                  break;
 329  356                          default:
 330  357                                  Die(gettext(
 331  358                                      "Unknown vmusage flags %d\n"), flags);
 332  359                          }
 333  360                  }
 334  361                  if (match != NULL) {
 335  362                          id->id_size = match->vmu_swap_all / 1024;
 336  363                          id->id_rssize = match->vmu_rss_all / 1024;
 337  364                          id->id_pctmem = (100.0 * (float)match->vmu_rss_all) /
 338  365                              (float)physmem;
 339  366                          /* Output using data from getvmusage() */
 340  367                          id->id_sizematch = B_TRUE;
 341  368                  }
 342  369                  /*
 343  370                   * If no match is found, prstat will use the size already
 344  371                   * gathered from psinfo.
 345  372                   */
 346  373          }
 347  374          free(results);
 348  375  }
 349  376  
 350  377  /*
 351  378   * A routine to display the contents of the list on the screen
 352  379   */
 353  380  static void
 354  381  list_print(list_t *list)
 355  382  {
 356  383          lwp_info_t *lwp;
 357  384          id_info_t *id;
 358  385          char usr[4], sys[4], trp[4], tfl[4];
 359  386          char dfl[4], lck[4], slp[4], lat[4];
 360  387          char vcx[4], icx[4], scl[4], sig[4];
 361  388          char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
 362  389          char pstate[7], pnice[4], ppri[4];
 363  390          char pname[LOGNAME_MAX+1];
 364  391          char projname[PROJNAME_MAX+1];
 365  392          char zonename[ZONENAME_MAX+1];
 366  393          float cpu, mem;
 367  394          double loadavg[3] = {0, 0, 0};
 368  395          int i, lwpid;
 369  396  
 370  397          if (list->l_size == 0)
 371  398                  return;
 372  399  
 373  400          if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) {
 374  401                  /*
 375  402                   * If processor sets aren't specified, we display system-wide
 376  403                   * load averages.
 377  404                   */
 378  405                  (void) getloadavg(loadavg, 3);
 379  406          }
 380  407  
 381  408          if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)) &&
 382  409              ((list->l_type == LT_LWPS) || !(opts.o_outpmode & OPT_SPLIT)))
 383  410                  print_timestamp();
 384  411          if (opts.o_outpmode & OPT_TTY)
 385  412                  (void) putchar('\r');
 386  413          (void) putp(t_ulon);
 387  414  
 388  415          switch (list->l_type) {
 389  416          case LT_PROJECTS:
 390  417                  if (opts.o_outpmode & OPT_LWPS)
 391  418                          (void) printf(PROJECT_HEADER_LWP);
 392  419                  else
 393  420                          (void) printf(PROJECT_HEADER_PROC);
 394  421                  break;
 395  422          case LT_TASKS:
 396  423                  if (opts.o_outpmode & OPT_LWPS)
 397  424                          (void) printf(TASK_HEADER_LWP);
 398  425                  else
 399  426                          (void) printf(TASK_HEADER_PROC);
 400  427                  break;
 401  428          case LT_ZONES:
 402  429                  if (opts.o_outpmode & OPT_LWPS)
 403  430                          (void) printf(ZONE_HEADER_LWP);
 404  431                  else
 405  432                          (void) printf(ZONE_HEADER_PROC);
 406  433                  break;
 407  434          case LT_USERS:
 408  435                  if (opts.o_outpmode & OPT_LWPS)
 409  436                          (void) printf(USER_HEADER_LWP);
 410  437                  else
 411  438                          (void) printf(USER_HEADER_PROC);
 412  439                  break;
 413  440          case LT_LWPS:
 414  441                  if (opts.o_outpmode & OPT_LWPS) {
 415  442                          if (opts.o_outpmode & OPT_PSINFO) {
 416  443                                  if (opts.o_outpmode & OPT_LGRP)
 417  444                                          (void) printf(PSINFO_HEADER_LWP_LGRP);
 418  445                                  else
 419  446                                          (void) printf(PSINFO_HEADER_LWP);
 420  447                          }
 421  448                          if (opts.o_outpmode & OPT_MSACCT)
 422  449                                  (void) printf(USAGE_HEADER_LWP);
 423  450                  } else {
 424  451                          if (opts.o_outpmode & OPT_PSINFO) {
 425  452                                  if (opts.o_outpmode & OPT_LGRP)
 426  453                                          (void) printf(PSINFO_HEADER_PROC_LGRP);
 427  454                                  else
 428  455                                          (void) printf(PSINFO_HEADER_PROC);
 429  456                          }
 430  457                          if (opts.o_outpmode & OPT_MSACCT)
 431  458                                  (void) printf(USAGE_HEADER_PROC);
 432  459                  }
 433  460                  break;
 434  461          }
 435  462  
 436  463          (void) putp(t_uloff);
 437  464          (void) putp(t_eol);
 438  465          (void) putchar('\n');
 439  466  
 440  467          for (i = 0; i < list->l_used; i++) {
 441  468                  switch (list->l_type) {
 442  469                  case LT_PROJECTS:
 443  470                  case LT_TASKS:
 444  471                  case LT_USERS:
 445  472                  case LT_ZONES:
 446  473                          id = list->l_ptrs[i];
 447  474                          /*
 448  475                           * CPU usage and memory usage normalization
 449  476                           */
 450  477                          if (total_cpu >= 100)
 451  478                                  cpu = (100 * id->id_pctcpu) / total_cpu;
 452  479                          else
 453  480                                  cpu = id->id_pctcpu;
 454  481                          if (id->id_sizematch == B_FALSE && total_mem >= 100)
 455  482                                  mem = (100 * id->id_pctmem) / total_mem;
 456  483                          else
 457  484                                  mem = id->id_pctmem;
 458  485                          if (list->l_type == LT_USERS) {
 459  486                                  pwd_getname(id->id_uid, pname, sizeof (pname),
 460  487                                      opts.o_outpmode & OPT_NORESOLVE,
 461  488                                      opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
 462  489                                      LOGIN_WIDTH);
 463  490                          } else if (list->l_type == LT_ZONES) {
 464  491                                  getzonename(id->id_zoneid, zonename,
 465  492                                      sizeof (zonename),
 466  493                                      opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
 467  494                                      ZONE_WIDTH);
 468  495                          } else {
 469  496                                  getprojname(id->id_projid, projname,
 470  497                                      sizeof (projname),
 471  498                                      opts.o_outpmode & OPT_NORESOLVE,
 472  499                                      opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
 473  500                                      PROJECT_WIDTH);
 474  501                          }
 475  502                          Format_size(psize, id->id_size, 6);
 476  503                          Format_size(prssize, id->id_rssize, 6);
 477  504                          Format_pct(pmem, mem, 4);
 478  505                          Format_pct(pcpu, cpu, 4);
 479  506                          Format_time(ptime, id->id_time, 10);
 480  507                          if (opts.o_outpmode & OPT_TTY)
 481  508                                  (void) putchar('\r');
 482  509                          if (list->l_type == LT_PROJECTS)
 483  510                                  (void) printf(PROJECT_LINE, (int)id->id_projid,
 484  511                                      id->id_nproc, psize, prssize, pmem, ptime,
 485  512                                      pcpu, projname);
 486  513                          else if (list->l_type == LT_TASKS)
 487  514                                  (void) printf(TASK_LINE, (int)id->id_taskid,
 488  515                                      id->id_nproc, psize, prssize, pmem, ptime,
 489  516                                      pcpu, projname);
 490  517                          else if (list->l_type == LT_ZONES)
 491  518                                  (void) printf(ZONE_LINE, (int)id->id_zoneid,
 492  519                                      id->id_nproc, psize, prssize, pmem, ptime,
 493  520                                      pcpu, zonename);
 494  521                          else
 495  522                                  (void) printf(USER_LINE, id->id_nproc, pname,
 496  523                                      psize, prssize, pmem, ptime, pcpu);
 497  524                          (void) putp(t_eol);
 498  525                          (void) putchar('\n');
 499  526                          break;
 500  527                  case LT_LWPS:
 501  528                          lwp = list->l_ptrs[i];
 502  529                          if (opts.o_outpmode & OPT_LWPS)
 503  530                                  lwpid = lwp->li_info.pr_lwp.pr_lwpid;
 504  531                          else
 505  532                                  lwpid = lwp->li_info.pr_nlwp +
 506  533                                      lwp->li_info.pr_nzomb;
 507  534                          pwd_getname(lwp->li_info.pr_uid, pname, sizeof (pname),
 508  535                              opts.o_outpmode & OPT_NORESOLVE,
 509  536                              opts.o_outpmode & (OPT_TERMCAP|OPT_TRUNC),
 510  537                              LOGIN_WIDTH);
 511  538                          if (opts.o_outpmode & OPT_PSINFO) {
 512  539                                  Format_size(psize, lwp->li_info.pr_size, 6);
 513  540                                  Format_size(prssize, lwp->li_info.pr_rssize, 6);
 514  541                                  Format_state(pstate,
 515  542                                      lwp->li_info.pr_lwp.pr_sname,
 516  543                                      lwp->li_info.pr_lwp.pr_onpro, 7);
 517  544                                  if (strcmp(lwp->li_info.pr_lwp.pr_clname,
 518  545                                      "RT") == 0 ||
 519  546                                      strcmp(lwp->li_info.pr_lwp.pr_clname,
 520  547                                      "SYS") == 0 ||
 521  548                                      lwp->li_info.pr_lwp.pr_sname == 'Z')
 522  549                                          (void) strcpy(pnice, "  -");
 523  550                                  else
 524  551                                          Format_num(pnice,
 525  552                                              lwp->li_info.pr_lwp.pr_nice - NZERO,
 526  553                                              4);
 527  554                                  Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4);
 528  555                                  Format_pct(pcpu,
 529  556                                      FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4);
 530  557                                  if (opts.o_outpmode & OPT_LWPS)
 531  558                                          Format_time(ptime,
 532  559                                              lwp->li_info.pr_lwp.pr_time.tv_sec,
 533  560                                              10);
 534  561                                  else
 535  562                                          Format_time(ptime,
 536  563                                              lwp->li_info.pr_time.tv_sec, 10);
 537  564                                  if (opts.o_outpmode & OPT_TTY)
 538  565                                          (void) putchar('\r');
 539  566                                  stripfname(lwp->li_info.pr_fname);
 540  567                                  if (opts.o_outpmode & OPT_LGRP) {
 541  568                                          (void) printf(PSINFO_LINE_LGRP,
 542  569                                              (int)lwp->li_info.pr_pid, pname,
 543  570                                              psize, prssize, pstate,
 544  571                                              ppri, pnice, ptime, pcpu,
 545  572                                              (int)lwp->li_info.pr_lwp.pr_lgrp,
 546  573                                              lwp->li_info.pr_fname, lwpid);
 547  574                                  } else {
 548  575                                          (void) printf(PSINFO_LINE,
 549  576                                              (int)lwp->li_info.pr_pid, pname,
 550  577                                              psize, prssize,
 551  578                                              pstate, ppri, pnice,
 552  579                                              ptime, pcpu,
 553  580                                              lwp->li_info.pr_fname, lwpid);
 554  581                                  }
 555  582                                  (void) putp(t_eol);
 556  583                                  (void) putchar('\n');
 557  584                          }
 558  585                          if (opts.o_outpmode & OPT_MSACCT) {
 559  586                                  Format_pct(usr, lwp->li_usr, 4);
 560  587                                  Format_pct(sys, lwp->li_sys, 4);
 561  588                                  Format_pct(slp, lwp->li_slp, 4);
 562  589                                  Format_num(vcx, lwp->li_vcx, 4);
 563  590                                  Format_num(icx, lwp->li_icx, 4);
 564  591                                  Format_num(scl, lwp->li_scl, 4);
 565  592                                  Format_num(sig, lwp->li_sig, 4);
 566  593                                  Format_pct(trp, lwp->li_trp, 4);
 567  594                                  Format_pct(tfl, lwp->li_tfl, 4);
 568  595                                  Format_pct(dfl, lwp->li_dfl, 4);
 569  596                                  Format_pct(lck, lwp->li_lck, 4);
 570  597                                  Format_pct(lat, lwp->li_lat, 4);
 571  598                                  if (opts.o_outpmode & OPT_TTY)
 572  599                                          (void) putchar('\r');
 573  600                                  stripfname(lwp->li_info.pr_fname);
 574  601                                  (void) printf(USAGE_LINE,
 575  602                                      (int)lwp->li_info.pr_pid, pname,
 576  603                                      usr, sys, trp, tfl, dfl, lck,
 577  604                                      slp, lat, vcx, icx, scl, sig,
 578  605                                      lwp->li_info.pr_fname, lwpid);
 579  606                                  (void) putp(t_eol);
 580  607                                  (void) putchar('\n');
 581  608                          }
 582  609                          break;
 583  610                  }
 584  611          }
 585  612  
 586  613          if (opts.o_outpmode & OPT_TTY)
 587  614                  (void) putchar('\r');
 588  615          if (opts.o_outpmode & OPT_TERMCAP) {
 589  616                  switch (list->l_type) {
 590  617                  case LT_PROJECTS:
 591  618                  case LT_USERS:
 592  619                  case LT_TASKS:
 593  620                  case LT_ZONES:
 594  621                          while (i++ < opts.o_nbottom) {
 595  622                                  (void) putp(t_eol);
 596  623                                  (void) putchar('\n');
 597  624                          }
 598  625                          break;
 599  626                  case LT_LWPS:
 600  627                          while (i++ < opts.o_ntop) {
 601  628                                  (void) putp(t_eol);
 602  629                                  (void) putchar('\n');
 603  630                          }
 604  631                  }
 605  632          }
 606  633  
 607  634          if (opts.o_outpmode & OPT_TTY)
 608  635                  (void) putchar('\r');
 609  636  
 610  637          if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS)
 611  638                  return;
 612  639  
 613  640          (void) printf(TOTAL_LINE, total_procs, total_lwps,
 614  641              loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
 615  642              loadavg[LOADAVG_15MIN]);
 616  643          (void) putp(t_eol);
 617  644          (void) putchar('\n');
 618  645          if (opts.o_outpmode & OPT_TTY)
 619  646                  (void) putchar('\r');
 620  647          (void) putp(t_eol);
 621  648          (void) fflush(stdout);
 622  649  }
 623  650  
 624  651  static lwp_info_t *
 625  652  list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
 626  653  {
 627  654          lwp_info_t *lwp;
 628  655  
 629  656          if (list->l_head == NULL) {
 630  657                  list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
 631  658          } else {
 632  659                  lwp = Zalloc(sizeof (lwp_info_t));
 633  660                  lwp->li_prev = list->l_tail;
 634  661                  ((lwp_info_t *)list->l_tail)->li_next = lwp;
 635  662                  list->l_tail = lwp;
 636  663          }
 637  664          lwp->li_info.pr_pid = pid;
 638  665          lwp->li_info.pr_lwp.pr_lwpid = lwpid;
 639  666          lwpid_add(lwp, pid, lwpid);
 640  667          list->l_count++;
 641  668          return (lwp);
 642  669  }
 643  670  
 644  671  static void
 645  672  list_remove_lwp(list_t *list, lwp_info_t *lwp)
 646  673  {
 647  674          if (lwp->li_prev)
 648  675                  lwp->li_prev->li_next = lwp->li_next;
 649  676          else
 650  677                  list->l_head = lwp->li_next;    /* removing the head */
 651  678          if (lwp->li_next)
 652  679                  lwp->li_next->li_prev = lwp->li_prev;
 653  680          else
 654  681                  list->l_tail = lwp->li_prev;    /* removing the tail */
 655  682          lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid);
 656  683          if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0)
 657  684                  fds_rm(lwp->li_info.pr_pid);
 658  685          list->l_count--;
 659  686          free(lwp);
 660  687  }
 661  688  
 662  689  static void
 663  690  list_clear(list_t *list)
 664  691  {
 665  692          if (list->l_type == LT_LWPS) {
 666  693                  lwp_info_t      *lwp = list->l_tail;
 667  694                  lwp_info_t      *lwp_tmp;
 668  695  
 669  696                  fd_closeall();
 670  697                  while (lwp) {
 671  698                          lwp_tmp = lwp;
 672  699                          lwp = lwp->li_prev;
 673  700                          list_remove_lwp(&lwps, lwp_tmp);
 674  701                  }
 675  702          } else {
 676  703                  id_info_t *id = list->l_head;
 677  704                  id_info_t *nextid;
 678  705  
 679  706                  while (id) {
 680  707                          nextid = id->id_next;
 681  708                          free(id);
 682  709                          id = nextid;
 683  710                  }
 684  711                  list->l_count = 0;
 685  712                  list->l_head = list->l_tail = NULL;
 686  713          }
 687  714  }
 688  715  
 689  716  static void
 690  717  list_update(list_t *list, lwp_info_t *lwp)
 691  718  {
 692  719          id_info_t *id;
 693  720  
 694  721          if (list->l_head == NULL) {                     /* first element */
 695  722                  list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
 696  723                  goto update;
 697  724          }
 698  725  
 699  726          for (id = list->l_head; id; id = id->id_next) {
 700  727                  if ((list->l_type == LT_USERS) &&
 701  728                      (id->id_uid != lwp->li_info.pr_uid))
 702  729                          continue;
 703  730                  if ((list->l_type == LT_TASKS) &&
 704  731                      (id->id_taskid != lwp->li_info.pr_taskid))
 705  732                          continue;
 706  733                  if ((list->l_type == LT_PROJECTS) &&
 707  734                      (id->id_projid != lwp->li_info.pr_projid))
 708  735                          continue;
 709  736                  if ((list->l_type == LT_ZONES) &&
 710  737                      (id->id_zoneid != lwp->li_info.pr_zoneid))
 711  738                          continue;
 712  739                  if ((list->l_type == LT_LGRPS) &&
 713  740                      (id->id_lgroup != lwp->li_info.pr_lwp.pr_lgrp))
 714  741                          continue;
 715  742                  id->id_nproc++;
 716  743                  id->id_taskid   = lwp->li_info.pr_taskid;
 717  744                  id->id_projid   = lwp->li_info.pr_projid;
 718  745                  id->id_zoneid   = lwp->li_info.pr_zoneid;
 719  746                  id->id_lgroup   = lwp->li_info.pr_lwp.pr_lgrp;
 720  747  
 721  748                  if (lwp->li_flags & LWP_REPRESENT) {
 722  749                          id->id_size     += lwp->li_info.pr_size;
 723  750                          id->id_rssize   += lwp->li_info.pr_rssize;
 724  751                  }
 725  752                  id->id_pctcpu   += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
 726  753                  if (opts.o_outpmode & OPT_LWPS)
 727  754                          id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
 728  755                  else
 729  756                          id->id_time += TIME2SEC(lwp->li_info.pr_time);
 730  757                  id->id_pctmem   += FRC2PCT(lwp->li_info.pr_pctmem);
 731  758                  id->id_key      += lwp->li_key;
 732  759                  total_cpu       += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
 733  760                  total_mem       += FRC2PCT(lwp->li_info.pr_pctmem);
 734  761                  return;
 735  762          }
 736  763  
 737  764          id = list->l_tail;
 738  765          id->id_next = Zalloc(sizeof (id_info_t));
 739  766          id->id_next->id_prev = list->l_tail;
 740  767          id->id_next->id_next = NULL;
 741  768          list->l_tail = id->id_next;
 742  769          id = list->l_tail;
 743  770  update:
 744  771          id->id_uid      = lwp->li_info.pr_uid;
 745  772          id->id_projid   = lwp->li_info.pr_projid;
 746  773          id->id_taskid   = lwp->li_info.pr_taskid;
 747  774          id->id_zoneid   = lwp->li_info.pr_zoneid;
 748  775          id->id_lgroup   = lwp->li_info.pr_lwp.pr_lgrp;
 749  776          id->id_nproc++;
 750  777          id->id_sizematch = B_FALSE;
 751  778          if (lwp->li_flags & LWP_REPRESENT) {
 752  779                  id->id_size     = lwp->li_info.pr_size;
 753  780                  id->id_rssize   = lwp->li_info.pr_rssize;
 754  781          }
 755  782          id->id_pctcpu   = FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
 756  783          if (opts.o_outpmode & OPT_LWPS)
 757  784                  id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
 758  785          else
 759  786                  id->id_time = TIME2SEC(lwp->li_info.pr_time);
 760  787          id->id_pctmem   = FRC2PCT(lwp->li_info.pr_pctmem);
 761  788          id->id_key      = lwp->li_key;
 762  789          total_cpu       += id->id_pctcpu;
 763  790          total_mem       += id->id_pctmem;
 764  791          list->l_count++;
 765  792  }
 766  793  
 767  794  static void
 768  795  lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage)
 769  796  {
 770  797          float period;
 771  798  
 772  799          if (!lwpid_is_active(pid, lwpid)) {
 773  800                  /*
 774  801                   * If we are reading cpu times for the first time then
 775  802                   * calculate average cpu times based on whole process
 776  803                   * execution time.
 777  804                   */
 778  805                  (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
 779  806                  period = TIME2NSEC(usage->pr_rtime);
 780  807                  period = period/(float)100;
 781  808  
 782  809                  if (period == 0) { /* zombie */
 783  810                          period = 1;
 784  811                          lwp->li_usr = 0;
 785  812                          lwp->li_sys = 0;
 786  813                          lwp->li_slp = 0;
 787  814                  } else {
 788  815                          lwp->li_usr = TIME2NSEC(usage->pr_utime)/period;
 789  816                          lwp->li_sys = TIME2NSEC(usage->pr_stime)/period;
 790  817                          lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period;
 791  818                  }
 792  819                  lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period;
 793  820                  lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period;
 794  821                  lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period;
 795  822                  lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period;
 796  823                  lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period;
 797  824                  period = (period / NANOSEC)*(float)100; /* now in seconds */
 798  825                  lwp->li_vcx = (ulong_t)
 799  826                      (opts.o_interval * (usage->pr_vctx/period));
 800  827                  lwp->li_icx = (ulong_t)
 801  828                      (opts.o_interval * (usage->pr_ictx/period));
 802  829                  lwp->li_scl = (ulong_t)
 803  830                      (opts.o_interval * (usage->pr_sysc/period));
 804  831                  lwp->li_sig = (ulong_t)
 805  832                      (opts.o_interval * (usage->pr_sigs/period));
 806  833                  (void) lwpid_set_active(pid, lwpid);
 807  834          } else {
 808  835                  /*
 809  836                   * If this is not a first time we are reading a process's
 810  837                   * CPU times then recalculate CPU times based on fresh data
 811  838                   * obtained from procfs and previous CPU time usage values.
 812  839                   */
 813  840                  period = TIME2NSEC(usage->pr_rtime)-
 814  841                      TIME2NSEC(lwp->li_usage.pr_rtime);
 815  842                  period = period/(float)100;
 816  843  
 817  844                  if (period == 0) { /* zombie */
 818  845                          period = 1;
 819  846                          lwp->li_usr = 0;
 820  847                          lwp->li_sys = 0;
 821  848                          lwp->li_slp = 0;
 822  849                  } else {
 823  850                          lwp->li_usr = (TIME2NSEC(usage->pr_utime)-
 824  851                              TIME2NSEC(lwp->li_usage.pr_utime))/period;
 825  852                          lwp->li_sys = (TIME2NSEC(usage->pr_stime) -
 826  853                              TIME2NSEC(lwp->li_usage.pr_stime))/period;
 827  854                          lwp->li_slp = (TIME2NSEC(usage->pr_slptime) -
 828  855                              TIME2NSEC(lwp->li_usage.pr_slptime))/period;
 829  856                  }
 830  857                  lwp->li_trp = (TIME2NSEC(usage->pr_ttime) -
 831  858                      TIME2NSEC(lwp->li_usage.pr_ttime))/period;
 832  859                  lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) -
 833  860                      TIME2NSEC(lwp->li_usage.pr_tftime))/period;
 834  861                  lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) -
 835  862                      TIME2NSEC(lwp->li_usage.pr_dftime))/period;
 836  863                  lwp->li_lck = (TIME2NSEC(usage->pr_ltime) -
 837  864                      TIME2NSEC(lwp->li_usage.pr_ltime))/period;
 838  865                  lwp->li_lat = (TIME2NSEC(usage->pr_wtime) -
 839  866                      TIME2NSEC(lwp->li_usage.pr_wtime))/period;
 840  867                  lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx;
  
    | 
      ↓ open down ↓ | 
    647 lines elided | 
    
      ↑ open up ↑ | 
  
 841  868                  lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx;
 842  869                  lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc;
 843  870                  lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
 844  871                  (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
 845  872          }
 846  873  }
 847  874  
 848  875  static int
 849  876  read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
 850  877  {
 851      -        char procfile[MAX_PROCFS_PATH];
      878 +        char procfile[PATH_MAX];
 852  879  
 853      -        (void) snprintf(procfile, MAX_PROCFS_PATH,
      880 +        (void) proc_snprintf(procfile, PATH_MAX,
 854  881              "/proc/%s/%s", pidstr, file);
 855  882          if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL)
 856  883                  return (1);
 857  884          if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) {
 858  885                  fd_close(*fd);
 859  886                  return (1);
 860  887          }
 861  888          return (0);
 862  889  }
 863  890  
 864  891  static void
 865  892  add_proc(psinfo_t *psinfo)
 866  893  {
 867  894          lwp_info_t *lwp;
 868  895          id_t lwpid;
 869  896          pid_t pid = psinfo->pr_pid;
 870  897  
 871  898          lwpid = psinfo->pr_lwp.pr_lwpid;
 872  899          if ((lwp = lwpid_get(pid, lwpid)) == NULL)
 873  900                  lwp = list_add_lwp(&lwps, pid, lwpid);
 874  901          lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT;
 875  902          (void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t));
 876  903          lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu;
 877  904  }
 878  905  
 879  906  static void
 880  907  add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
 881  908  {
 882  909          lwp_info_t *lwp;
 883  910          pid_t pid = psinfo->pr_pid;
 884  911          id_t lwpid = lwpsinfo->pr_lwpid;
 885  912  
 886  913          if ((lwp = lwpid_get(pid, lwpid)) == NULL)
 887  914                  lwp = list_add_lwp(&lwps, pid, lwpid);
 888  915          lwp->li_flags &= ~LWP_REPRESENT;
 889  916          lwp->li_flags |= LWP_ALIVE;
 890  917          lwp->li_flags |= flags;
 891  918          (void) memcpy(&lwp->li_info, psinfo,
 892  919              sizeof (psinfo_t) - sizeof (lwpsinfo_t));
 893  920          (void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
 894  921  }
 895  922  
 896  923  static void
 897  924  prstat_scandir(DIR *procdir)
 898  925  {
 899  926          char *pidstr;
 900  927          pid_t pid;
 901  928          id_t lwpid;
 902  929          size_t entsz;
 903  930          long nlwps, nent, i;
 904  931          char *buf, *ptr;
 905  932  
 906  933          fds_t *fds;
 907  934          lwp_info_t *lwp;
 908  935          dirent_t *direntp;
 909  936  
 910  937          prheader_t      header;
 911  938          psinfo_t        psinfo;
 912  939          prusage_t       usage;
 913  940          lwpsinfo_t      *lwpsinfo;
 914  941          prusage_t       *lwpusage;
 915  942  
 916  943          total_procs = 0;
 917  944          total_lwps = 0;
 918  945          total_cpu = 0;
 919  946          total_mem = 0;
 920  947  
 921  948          convert_zone(&zone_tbl);
 922  949          for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
 923  950                  pidstr = direntp->d_name;
 924  951                  if (pidstr[0] == '.')   /* skip "." and ".."  */
 925  952                          continue;
 926  953                  pid = atoi(pidstr);
 927  954                  if (pid == 0 || pid == 2 || pid == 3)
 928  955                          continue;       /* skip sched, pageout and fsflush */
 929  956                  if (has_element(&pid_tbl, pid) == 0)
 930  957                          continue;       /* check if we really want this pid */
 931  958                  fds = fds_get(pid);     /* get ptr to file descriptors */
 932  959  
 933  960                  if (read_procfile(&fds->fds_psinfo, pidstr,
 934  961                      "psinfo", &psinfo, sizeof (psinfo_t)) != 0)
 935  962                          continue;
 936  963                  if (!has_uid(&ruid_tbl, psinfo.pr_uid) ||
 937  964                      !has_uid(&euid_tbl, psinfo.pr_euid) ||
 938  965                      !has_element(&prj_tbl, psinfo.pr_projid) ||
 939  966                      !has_element(&tsk_tbl, psinfo.pr_taskid) ||
 940  967                      !has_zone(&zone_tbl, psinfo.pr_zoneid)) {
 941  968                          fd_close(fds->fds_psinfo);
 942  969                          continue;
 943  970                  }
 944  971                  nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb;
 945  972  
 946  973                  if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) {
 947  974                          int rep_lwp = 0;
 948  975  
 949  976                          if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo",
 950  977                              &header, sizeof (prheader_t)) != 0) {
 951  978                                  fd_close(fds->fds_psinfo);
 952  979                                  continue;
 953  980                          }
 954  981  
 955  982                          nent = header.pr_nent;
 956  983                          entsz = header.pr_entsize * nent;
 957  984                          ptr = buf = Malloc(entsz);
 958  985                          if (pread(fd_getfd(fds->fds_lpsinfo), buf,
 959  986                              entsz, sizeof (struct prheader)) != entsz) {
 960  987                                  fd_close(fds->fds_lpsinfo);
 961  988                                  fd_close(fds->fds_psinfo);
 962  989                                  free(buf);
 963  990                                  continue;
 964  991                          }
 965  992  
 966  993                          nlwps = 0;
 967  994                          for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
 968  995                                  /*LINTED ALIGNMENT*/
 969  996                                  lwpsinfo = (lwpsinfo_t *)ptr;
 970  997                                  if (!has_element(&cpu_tbl,
 971  998                                      lwpsinfo->pr_onpro) ||
 972  999                                      !has_element(&set_tbl,
 973 1000                                      lwpsinfo->pr_bindpset) ||
 974 1001                                      !has_element(&lgr_tbl, lwpsinfo->pr_lgrp))
 975 1002                                          continue;
 976 1003                                  nlwps++;
 977 1004                                  if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS))
 978 1005                                      == OPT_PSETS) {
 979 1006                                          /*
 980 1007                                           * If one of process's LWPs is bound
 981 1008                                           * to a given processor set, report the
 982 1009                                           * whole process.  We may be doing this
 983 1010                                           * a few times but we'll get an accurate
 984 1011                                           * lwp count in return.
 985 1012                                           */
 986 1013                                          add_proc(&psinfo);
 987 1014                                  } else {
 988 1015                                          if (rep_lwp == 0) {
 989 1016                                                  rep_lwp = 1;
 990 1017                                                  add_lwp(&psinfo, lwpsinfo,
 991 1018                                                      LWP_REPRESENT);
 992 1019                                          } else {
 993 1020                                                  add_lwp(&psinfo, lwpsinfo, 0);
 994 1021                                          }
 995 1022                                  }
 996 1023                          }
 997 1024                          free(buf);
 998 1025                          if (nlwps == 0) {
 999 1026                                  fd_close(fds->fds_lpsinfo);
1000 1027                                  fd_close(fds->fds_psinfo);
1001 1028                                  continue;
1002 1029                          }
1003 1030                  } else {
1004 1031                          if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) ||
1005 1032                              !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset) ||
1006 1033                              !has_element(&lgr_tbl, psinfo.pr_lwp.pr_lgrp)) {
1007 1034                                  fd_close(fds->fds_psinfo);
1008 1035                                  continue;
1009 1036                          }
1010 1037                          add_proc(&psinfo);
1011 1038                  }
1012 1039                  if (!(opts.o_outpmode & OPT_MSACCT)) {
1013 1040                          total_procs++;
1014 1041                          total_lwps += nlwps;
1015 1042                          continue;
1016 1043                  }
1017 1044                  /*
1018 1045                   * Get more information about processes from /proc/pid/usage.
1019 1046                   * If process has more than one lwp, then we may have to
1020 1047                   * also look at the /proc/pid/lusage file.
1021 1048                   */
1022 1049                  if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) {
1023 1050                          if (read_procfile(&fds->fds_lusage, pidstr, "lusage",
1024 1051                              &header, sizeof (prheader_t)) != 0) {
1025 1052                                  fd_close(fds->fds_lpsinfo);
1026 1053                                  fd_close(fds->fds_psinfo);
1027 1054                                  continue;
1028 1055                          }
1029 1056                          nent = header.pr_nent;
1030 1057                          entsz = header.pr_entsize * nent;
1031 1058                          buf = Malloc(entsz);
1032 1059                          if (pread(fd_getfd(fds->fds_lusage), buf,
1033 1060                              entsz, sizeof (struct prheader)) != entsz) {
1034 1061                                  fd_close(fds->fds_lusage);
1035 1062                                  fd_close(fds->fds_lpsinfo);
1036 1063                                  fd_close(fds->fds_psinfo);
1037 1064                                  free(buf);
1038 1065                                  continue;
1039 1066                          }
1040 1067                          for (i = 1, ptr = buf + header.pr_entsize; i < nent;
1041 1068                              i++, ptr += header.pr_entsize) {
1042 1069                                  /*LINTED ALIGNMENT*/
1043 1070                                  lwpusage = (prusage_t *)ptr;
1044 1071                                  lwpid = lwpusage->pr_lwpid;
1045 1072                                  /*
1046 1073                                   * New LWPs created after we read lpsinfo
1047 1074                                   * will be ignored.  Don't want to do
1048 1075                                   * everything all over again.
1049 1076                                   */
1050 1077                                  if ((lwp = lwpid_get(pid, lwpid)) == NULL)
1051 1078                                          continue;
1052 1079                                  lwp_update(lwp, pid, lwpid, lwpusage);
1053 1080                          }
1054 1081                          free(buf);
1055 1082                  } else {
1056 1083                          if (read_procfile(&fds->fds_usage, pidstr, "usage",
1057 1084                              &usage, sizeof (prusage_t)) != 0) {
1058 1085                                  fd_close(fds->fds_lpsinfo);
1059 1086                                  fd_close(fds->fds_psinfo);
1060 1087                                  continue;
1061 1088                          }
1062 1089                          lwpid = psinfo.pr_lwp.pr_lwpid;
1063 1090                          if ((lwp = lwpid_get(pid, lwpid)) == NULL)
1064 1091                                  continue;
1065 1092                          lwp_update(lwp, pid, lwpid, &usage);
1066 1093                  }
1067 1094                  total_procs++;
1068 1095                  total_lwps += nlwps;
1069 1096          }
1070 1097          fd_update();
1071 1098  }
1072 1099  
1073 1100  /*
1074 1101   * This procedure removes all dead lwps from the linked list of all lwps.
1075 1102   * It also creates linked list of ids if necessary.
1076 1103   */
1077 1104  static void
1078 1105  list_refresh(list_t *list)
1079 1106  {
1080 1107          lwp_info_t *lwp, *lwp_next;
1081 1108  
1082 1109          if (!(list->l_type & LT_LWPS))
1083 1110                  return;
1084 1111  
1085 1112          for (lwp = list->l_head; lwp != NULL; ) {
1086 1113                  if (lwp->li_flags & LWP_ALIVE) {
1087 1114                          /*
1088 1115                           * Process all live LWPs.
1089 1116                           * When we're done, mark them as dead.
1090 1117                           * They will be marked "alive" on the next
1091 1118                           * /proc scan if they still exist.
1092 1119                           */
1093 1120                          lwp->li_key = list_getkeyval(list, lwp);
1094 1121                          if (opts.o_outpmode & OPT_USERS)
1095 1122                                  list_update(&users, lwp);
1096 1123                          if (opts.o_outpmode & OPT_TASKS)
1097 1124                                  list_update(&tasks, lwp);
1098 1125                          if (opts.o_outpmode & OPT_PROJECTS)
1099 1126                                  list_update(&projects, lwp);
1100 1127                          if (opts.o_outpmode & OPT_ZONES)
1101 1128                                  list_update(&zones, lwp);
1102 1129                          if (opts.o_outpmode & OPT_LGRP)
1103 1130                                  list_update(&lgroups, lwp);
1104 1131                          lwp->li_flags &= ~LWP_ALIVE;
1105 1132                          lwp = lwp->li_next;
1106 1133  
1107 1134                  } else {
1108 1135                          lwp_next = lwp->li_next;
1109 1136                          list_remove_lwp(&lwps, lwp);
1110 1137                          lwp = lwp_next;
1111 1138                  }
1112 1139          }
1113 1140  }
1114 1141  
1115 1142  static void
1116 1143  curses_on()
1117 1144  {
1118 1145          if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
1119 1146                  (void) initscr();
1120 1147                  (void) nonl();
1121 1148                  (void) putp(t_smcup);
1122 1149                  is_curses_on = TRUE;
1123 1150          }
1124 1151  }
1125 1152  
1126 1153  static void
1127 1154  curses_off()
1128 1155  {
1129 1156          if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
1130 1157                  (void) putp(t_rmcup);
1131 1158                  (void) endwin();
1132 1159                  is_curses_on = FALSE;
1133 1160          }
1134 1161          (void) fflush(stdout);
1135 1162  }
1136 1163  
1137 1164  static int
1138 1165  nlines()
1139 1166  {
1140 1167          struct winsize ws;
1141 1168          char *envp;
1142 1169          int n;
1143 1170          if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
1144 1171                  if (ws.ws_row > 0)
1145 1172                          return (ws.ws_row);
1146 1173          }
1147 1174          if (envp = getenv("LINES")) {
1148 1175                  if ((n = Atoi(envp)) > 0) {
1149 1176                          opts.o_outpmode &= ~OPT_USEHOME;
1150 1177                          return (n);
1151 1178                  }
1152 1179          }
1153 1180          return (-1);
1154 1181  }
1155 1182  
1156 1183  static void
1157 1184  setmovecur()
1158 1185  {
1159 1186          int i, n;
1160 1187          if ((opts.o_outpmode & OPT_FULLSCREEN) &&
1161 1188              (opts.o_outpmode & OPT_USEHOME)) {
1162 1189                  movecur = t_home;
1163 1190                  return;
1164 1191          }
1165 1192          if (opts.o_outpmode & OPT_SPLIT) {
1166 1193                  if (opts.o_ntop == 0)
1167 1194                          n = opts.o_nbottom + 1;
1168 1195                  else
1169 1196                          n = opts.o_ntop + opts.o_nbottom + 2;
1170 1197          } else {
1171 1198                  if (opts.o_outpmode & OPT_USERS)
1172 1199                          n = opts.o_nbottom + 1;
1173 1200                  else
1174 1201                          n = opts.o_ntop + 1;
1175 1202          }
1176 1203          if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)))
1177 1204                  n++;
1178 1205  
1179 1206          if (movecur != NULL && movecur != empty_string && movecur != t_home)
1180 1207                  free(movecur);
1181 1208          movecur = Zalloc(strlen(t_up) * (n + 5));
1182 1209          for (i = 0; i <= n; i++)
1183 1210                  (void) strcat(movecur, t_up);
1184 1211  }
1185 1212  
1186 1213  static int
1187 1214  setsize()
1188 1215  {
1189 1216          static int oldn = 0;
1190 1217          int n;
1191 1218  
1192 1219          if (opts.o_outpmode & OPT_FULLSCREEN) {
1193 1220                  n = nlines();
1194 1221                  if (n == oldn)
1195 1222                          return (0);
1196 1223                  oldn = n;
1197 1224                  if (n == -1) {
1198 1225                          opts.o_outpmode &= ~OPT_USEHOME;
1199 1226                          setmovecur();           /* set default window size */
1200 1227                          return (1);
1201 1228                  }
1202 1229                  n = n - 3;      /* minus header, total and cursor lines */
1203 1230                  if ((opts.o_outpmode & OPT_UDATE) ||
1204 1231                      (opts.o_outpmode & OPT_DDATE))
1205 1232                          n--;    /* minus timestamp */
1206 1233                  if (n < 1)
1207 1234                          Die(gettext("window is too small (try -n)\n"));
1208 1235                  if (opts.o_outpmode & OPT_SPLIT) {
1209 1236                          if (n < 8) {
1210 1237                                  Die(gettext("window is too small (try -n)\n"));
1211 1238                          } else {
1212 1239                                  opts.o_ntop = (n / 4) * 3;
1213 1240                                  opts.o_nbottom = n - 1 - opts.o_ntop;
1214 1241                          }
1215 1242                  } else {
1216 1243                          if (opts.o_outpmode & OPT_USERS)
1217 1244                                  opts.o_nbottom = n;
1218 1245                          else
1219 1246                                  opts.o_ntop = n;
1220 1247                  }
1221 1248          }
1222 1249          setmovecur();
1223 1250          return (1);
1224 1251  }
1225 1252  
1226 1253  static void
1227 1254  ldtermcap()
1228 1255  {
1229 1256          int err;
1230 1257          if (setupterm(NULL, STDIN_FILENO, &err) == ERR) {
1231 1258                  switch (err) {
1232 1259                  case 0:
1233 1260                          Warn(gettext("failed to load terminal info, "
1234 1261                              "defaulting to -c option\n"));
1235 1262                          break;
1236 1263                  case -1:
1237 1264                          Warn(gettext("terminfo database not found, "
1238 1265                              "defaulting to -c option\n"));
1239 1266                          break;
1240 1267                  default:
1241 1268                          Warn(gettext("failed to initialize terminal, "
1242 1269                              "defaulting to -c option\n"));
1243 1270                  }
1244 1271                  opts.o_outpmode &= ~OPT_TERMCAP;
1245 1272                  t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1246 1273                  t_ulon = t_uloff = empty_string;
1247 1274                  return;
1248 1275          }
1249 1276          t_ulon  = tigetstr("smul");
1250 1277          t_uloff = tigetstr("rmul");
1251 1278          t_up    = tigetstr("cuu1");
1252 1279          t_eol   = tigetstr("el");
1253 1280          t_smcup = tigetstr("smcup");
1254 1281          t_rmcup = tigetstr("rmcup");
1255 1282          t_home  = tigetstr("home");
1256 1283          if ((t_up == (char *)-1) || (t_eol == (char *)-1) ||
1257 1284              (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) {
1258 1285                  opts.o_outpmode &= ~OPT_TERMCAP;
1259 1286                  t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1260 1287                  return;
1261 1288          }
1262 1289          if (t_up == NULL || t_eol == NULL) {
1263 1290                  opts.o_outpmode &= ~OPT_TERMCAP;
1264 1291                  t_eol = t_up = movecur = empty_string;
1265 1292                  return;
1266 1293          }
1267 1294          if (t_ulon == (char *)-1 || t_uloff == (char *)-1 ||
1268 1295              t_ulon == NULL || t_uloff == NULL) {
1269 1296                  t_ulon = t_uloff = empty_string;  /* can live without it */
1270 1297          }
1271 1298          if (t_smcup == NULL || t_rmcup == NULL)
1272 1299                  t_smcup = t_rmcup = empty_string;
1273 1300          if (t_home == (char *)-1 || t_home == NULL) {
1274 1301                  opts.o_outpmode &= ~OPT_USEHOME;
1275 1302                  t_home = empty_string;
1276 1303          }
1277 1304  }
1278 1305  
1279 1306  static void
1280 1307  sig_handler(int sig)
1281 1308  {
1282 1309          switch (sig) {
1283 1310          case SIGTSTP:   sigtstp = 1;
1284 1311                          break;
1285 1312          case SIGWINCH:  sigwinch = 1;
1286 1313                          break;
1287 1314          case SIGINT:
1288 1315          case SIGTERM:   sigterm = 1;
1289 1316                          break;
1290 1317          }
1291 1318  }
1292 1319  
1293 1320  static void
1294 1321  set_signals()
1295 1322  {
1296 1323          (void) signal(SIGTSTP, sig_handler);
1297 1324          (void) signal(SIGINT, sig_handler);
1298 1325          (void) signal(SIGTERM, sig_handler);
1299 1326          if (opts.o_outpmode & OPT_FULLSCREEN)
1300 1327                  (void) signal(SIGWINCH, sig_handler);
1301 1328  }
1302 1329  
1303 1330  static void
1304 1331  fill_table(table_t *table, char *arg, char option)
1305 1332  {
1306 1333          char *p = strtok(arg, ", ");
1307 1334  
1308 1335          if (p == NULL)
1309 1336                  Die(gettext("invalid argument for -%c\n"), option);
1310 1337  
1311 1338          add_element(table, (long)Atoi(p));
1312 1339          while (p = strtok(NULL, ", "))
1313 1340                  add_element(table, (long)Atoi(p));
1314 1341  }
1315 1342  
1316 1343  static void
1317 1344  fill_prj_table(char *arg)
1318 1345  {
1319 1346          projid_t projid;
1320 1347          char *p = strtok(arg, ", ");
1321 1348  
1322 1349          if (p == NULL)
1323 1350                  Die(gettext("invalid argument for -j\n"));
1324 1351  
1325 1352          if ((projid = getprojidbyname(p)) == -1)
1326 1353                  projid = Atoi(p);
1327 1354          add_element(&prj_tbl, (long)projid);
1328 1355  
1329 1356          while (p = strtok(NULL, ", ")) {
1330 1357                  if ((projid = getprojidbyname(p)) == -1)
1331 1358                          projid = Atoi(p);
1332 1359                  add_element(&prj_tbl, (long)projid);
1333 1360          }
1334 1361  }
1335 1362  
1336 1363  static void
1337 1364  fill_set_table(char *arg)
1338 1365  {
1339 1366          char *p = strtok(arg, ", ");
1340 1367          psetid_t id;
1341 1368  
1342 1369          if (p == NULL)
1343 1370                  Die(gettext("invalid argument for -C\n"));
1344 1371  
1345 1372          if ((id = Atoi(p)) == 0)
1346 1373                  id = PS_NONE;
1347 1374          add_element(&set_tbl, id);
1348 1375          while (p = strtok(NULL, ", ")) {
1349 1376                  if ((id = Atoi(p)) == 0)
1350 1377                          id = PS_NONE;
1351 1378                  if (!has_element(&set_tbl, id))
1352 1379                          add_element(&set_tbl, id);
1353 1380          }
1354 1381  }
1355 1382  
1356 1383  static void
1357 1384  Exit()
1358 1385  {
1359 1386          curses_off();
1360 1387          list_clear(&lwps);
1361 1388          list_clear(&users);
1362 1389          list_clear(&tasks);
1363 1390          list_clear(&projects);
1364 1391          list_clear(&zones);
1365 1392          fd_exit();
1366 1393  }
1367 1394  
1368 1395  
  
    | 
      ↓ open down ↓ | 
    505 lines elided | 
    
      ↑ open up ↑ | 
  
1369 1396  int
1370 1397  main(int argc, char **argv)
1371 1398  {
1372 1399          DIR *procdir;
1373 1400          char *p;
1374 1401          char *sortk = "cpu";    /* default sort key */
1375 1402          int opt;
1376 1403          int timeout;
1377 1404          struct pollfd pollset;
1378 1405          char key;
     1406 +        char procpath[PATH_MAX];
1379 1407  
1380 1408          (void) setlocale(LC_ALL, "");
1381 1409          (void) textdomain(TEXT_DOMAIN);
1382 1410          Progname(argv[0]);
1383 1411          lwpid_init();
1384 1412          fd_init(Setrlimit());
1385 1413  
1386 1414          pagesize = sysconf(_SC_PAGESIZE);
1387 1415  
1388 1416          while ((opt = getopt(argc, argv,
1389 1417              "vcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJWz:Z")) != (int)EOF) {
1390 1418                  switch (opt) {
1391 1419                  case 'r':
1392 1420                          opts.o_outpmode |= OPT_NORESOLVE;
1393 1421                          break;
1394 1422                  case 'R':
1395 1423                          opts.o_outpmode |= OPT_REALTIME;
1396 1424                          break;
1397 1425                  case 'c':
1398 1426                          opts.o_outpmode &= ~OPT_TERMCAP;
1399 1427                          opts.o_outpmode &= ~OPT_FULLSCREEN;
1400 1428                          break;
1401 1429                  case 'd':
1402 1430                          if (optarg) {
1403 1431                                  if (*optarg == 'u')
1404 1432                                          opts.o_outpmode |= OPT_UDATE;
1405 1433                                  else if (*optarg == 'd')
1406 1434                                          opts.o_outpmode |= OPT_DDATE;
1407 1435                                  else
1408 1436                                          Usage();
1409 1437                          } else {
1410 1438                                  Usage();
1411 1439                          }
1412 1440                          break;
1413 1441                  case 'h':
1414 1442                          fill_table(&lgr_tbl, optarg, 'h');
1415 1443                          break;
1416 1444                  case 'H':
1417 1445                          opts.o_outpmode |= OPT_LGRP;
1418 1446                          break;
1419 1447                  case 'm':
1420 1448                  case 'v':
1421 1449                          opts.o_outpmode &= ~OPT_PSINFO;
1422 1450                          opts.o_outpmode |=  OPT_MSACCT;
1423 1451                          break;
1424 1452                  case 't':
1425 1453                          opts.o_outpmode &= ~OPT_PSINFO;
1426 1454                          opts.o_outpmode |= OPT_USERS;
1427 1455                          break;
1428 1456                  case 'a':
1429 1457                          opts.o_outpmode |= OPT_SPLIT | OPT_USERS;
1430 1458                          break;
1431 1459                  case 'T':
1432 1460                          opts.o_outpmode |= OPT_SPLIT | OPT_TASKS;
1433 1461                          break;
1434 1462                  case 'J':
1435 1463                          opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS;
1436 1464                          break;
1437 1465                  case 'n':
1438 1466                          if ((p = strtok(optarg, ",")) == NULL)
1439 1467                                  Die(gettext("invalid argument for -n\n"));
1440 1468                          opts.o_ntop = Atoi(p);
1441 1469                          if (p = strtok(NULL, ","))
1442 1470                                  opts.o_nbottom = Atoi(p);
1443 1471                          else if (opts.o_ntop == 0)
1444 1472                                  opts.o_nbottom = 5;
1445 1473                          opts.o_outpmode &= ~OPT_FULLSCREEN;
1446 1474                          break;
1447 1475                  case 's':
1448 1476                          opts.o_sortorder = -1;
1449 1477                          sortk = optarg;
1450 1478                          break;
1451 1479                  case 'S':
1452 1480                          opts.o_sortorder = 1;
1453 1481                          sortk = optarg;
1454 1482                          break;
1455 1483                  case 'u':
1456 1484                          if ((p = strtok(optarg, ", ")) == NULL)
1457 1485                                  Die(gettext("invalid argument for -u\n"));
1458 1486                          add_uid(&euid_tbl, p);
1459 1487                          while (p = strtok(NULL, ", "))
1460 1488                                  add_uid(&euid_tbl, p);
1461 1489                          break;
1462 1490                  case 'U':
1463 1491                          if ((p = strtok(optarg, ", ")) == NULL)
1464 1492                                  Die(gettext("invalid argument for -U\n"));
1465 1493                          add_uid(&ruid_tbl, p);
1466 1494                          while (p = strtok(NULL, ", "))
1467 1495                                  add_uid(&ruid_tbl, p);
1468 1496                          break;
1469 1497                  case 'p':
1470 1498                          fill_table(&pid_tbl, optarg, 'p');
1471 1499                          break;
1472 1500                  case 'C':
1473 1501                          fill_set_table(optarg);
1474 1502                          opts.o_outpmode |= OPT_PSETS;
1475 1503                          break;
1476 1504                  case 'P':
1477 1505                          fill_table(&cpu_tbl, optarg, 'P');
1478 1506                          break;
1479 1507                  case 'k':
1480 1508                          fill_table(&tsk_tbl, optarg, 'k');
1481 1509                          break;
1482 1510                  case 'j':
1483 1511                          fill_prj_table(optarg);
1484 1512                          break;
1485 1513                  case 'L':
1486 1514                          opts.o_outpmode |= OPT_LWPS;
1487 1515                          break;
1488 1516                  case 'W':
1489 1517                          opts.o_outpmode |= OPT_TRUNC;
1490 1518                          break;
1491 1519                  case 'z':
1492 1520                          if ((p = strtok(optarg, ", ")) == NULL)
1493 1521                                  Die(gettext("invalid argument for -z\n"));
1494 1522                          add_zone(&zone_tbl, p);
1495 1523                          while (p = strtok(NULL, ", "))
1496 1524                                  add_zone(&zone_tbl, p);
1497 1525                          break;
1498 1526                  case 'Z':
1499 1527                          opts.o_outpmode |= OPT_SPLIT | OPT_ZONES;
1500 1528                          break;
1501 1529                  default:
1502 1530                          Usage();
1503 1531                  }
1504 1532          }
1505 1533  
1506 1534          (void) atexit(Exit);
1507 1535          if ((opts.o_outpmode & OPT_USERS) &&
1508 1536              !(opts.o_outpmode & OPT_SPLIT))
1509 1537                  opts.o_nbottom = opts.o_ntop;
1510 1538          if (!(opts.o_outpmode & OPT_SPLIT) && opts.o_ntop == 0)
1511 1539                  Die(gettext("invalid argument for -n\n"));
1512 1540          if (opts.o_nbottom == 0)
1513 1541                  Die(gettext("invalid argument for -n\n"));
1514 1542          if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
1515 1543              ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1516 1544                  Die(gettext("-t option cannot be used with -v or -m\n"));
1517 1545  
1518 1546          if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
1519 1547              !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1520 1548                  Die(gettext("-t option cannot be used with "
1521 1549                      "-a, -J, -T or -Z\n"));
1522 1550  
1523 1551          if ((opts.o_outpmode & OPT_USERS) &&
1524 1552              (opts.o_outpmode & (OPT_TASKS | OPT_PROJECTS | OPT_ZONES)))
1525 1553                  Die(gettext("-a option cannot be used with "
1526 1554                      "-t, -J, -T or -Z\n"));
1527 1555  
1528 1556          if (((opts.o_outpmode & OPT_TASKS) &&
1529 1557              (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) ||
1530 1558              ((opts.o_outpmode & OPT_PROJECTS) &&
1531 1559              (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) {
1532 1560                  Die(gettext(
1533 1561                      "-J, -T and -Z options are mutually exclusive\n"));
1534 1562          }
1535 1563  
1536 1564          /*
1537 1565           * There is not enough space to combine microstate information and
1538 1566           * lgroup information and still fit in 80-column output.
1539 1567           */
1540 1568          if ((opts.o_outpmode & OPT_LGRP) && (opts.o_outpmode & OPT_MSACCT)) {
1541 1569                  Die(gettext("-H and -m options are mutually exclusive\n"));
1542 1570          }
1543 1571  
1544 1572          if (argc > optind)
1545 1573                  opts.o_interval = Atoi(argv[optind++]);
1546 1574          if (argc > optind)
1547 1575                  opts.o_count = Atoi(argv[optind++]);
1548 1576          if (opts.o_count == 0)
1549 1577                  Die(gettext("invalid counter value\n"));
1550 1578          if (argc > optind)
1551 1579                  Usage();
1552 1580          if (opts.o_outpmode & OPT_REALTIME)
1553 1581                  Priocntl("RT");
1554 1582          if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO))
1555 1583                  opts.o_outpmode |= OPT_TTY;     /* interactive */
1556 1584          if (!(opts.o_outpmode & OPT_TTY)) {
1557 1585                  opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */
1558 1586                  opts.o_outpmode &= ~OPT_FULLSCREEN;
1559 1587          }
1560 1588          if (opts.o_outpmode & OPT_TERMCAP)
1561 1589                  ldtermcap();            /* can turn OPT_TERMCAP off */
1562 1590          if (opts.o_outpmode & OPT_TERMCAP)
1563 1591                  (void) setsize();
1564 1592          list_alloc(&lwps, opts.o_ntop);
1565 1593          list_alloc(&users, opts.o_nbottom);
1566 1594          list_alloc(&tasks, opts.o_nbottom);
1567 1595          list_alloc(&projects, opts.o_nbottom);
  
    | 
      ↓ open down ↓ | 
    179 lines elided | 
    
      ↑ open up ↑ | 
  
1568 1596          list_alloc(&zones, opts.o_nbottom);
1569 1597          list_alloc(&lgroups, opts.o_nbottom);
1570 1598          list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS);
1571 1599          list_setkeyfunc(NULL, &opts, &users, LT_USERS);
1572 1600          list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS);
1573 1601          list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS);
1574 1602          list_setkeyfunc(NULL, &opts, &zones, LT_ZONES);
1575 1603          list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS);
1576 1604          if (opts.o_outpmode & OPT_TERMCAP)
1577 1605                  curses_on();
1578      -        if ((procdir = opendir("/proc")) == NULL)
     1606 +        (void) proc_snprintf(procpath, sizeof (procpath), "/proc");
     1607 +        if ((procdir = opendir(procpath)) == NULL)
1579 1608                  Die(gettext("cannot open /proc directory\n"));
1580 1609          if (opts.o_outpmode & OPT_TTY) {
1581 1610                  (void) printf(gettext("Please wait...\r"));
1582 1611                  if (!(opts.o_outpmode & OPT_TERMCAP))
1583 1612                          (void) putchar('\n');
1584 1613                  (void) fflush(stdout);
1585 1614          }
1586 1615          set_signals();
1587 1616          pollset.fd = STDIN_FILENO;
1588 1617          pollset.events = POLLIN;
1589 1618          timeout = opts.o_interval * MILLISEC;
1590 1619  
1591 1620          /*
1592 1621           * main program loop
1593 1622           */
1594 1623          do {
1595 1624                  if (sigterm == 1)
1596 1625                          break;
1597 1626                  if (sigtstp == 1) {
1598 1627                          curses_off();
1599 1628                          (void) signal(SIGTSTP, SIG_DFL);
1600 1629                          (void) kill(0, SIGTSTP);
1601 1630                          /*
1602 1631                           * prstat stops here until it receives SIGCONT signal.
1603 1632                           */
1604 1633                          sigtstp = 0;
1605 1634                          (void) signal(SIGTSTP, sig_handler);
1606 1635                          curses_on();
1607 1636                          print_movecur = FALSE;
1608 1637                          if (opts.o_outpmode & OPT_FULLSCREEN)
1609 1638                                  sigwinch = 1;
1610 1639                  }
1611 1640                  if (sigwinch == 1) {
1612 1641                          if (setsize() == 1) {
1613 1642                                  list_free(&lwps);
1614 1643                                  list_free(&users);
1615 1644                                  list_free(&tasks);
1616 1645                                  list_free(&projects);
1617 1646                                  list_free(&zones);
1618 1647                                  list_alloc(&lwps, opts.o_ntop);
1619 1648                                  list_alloc(&users, opts.o_nbottom);
1620 1649                                  list_alloc(&tasks, opts.o_nbottom);
1621 1650                                  list_alloc(&projects, opts.o_nbottom);
1622 1651                                  list_alloc(&zones, opts.o_nbottom);
1623 1652                          }
1624 1653                          sigwinch = 0;
1625 1654                          (void) signal(SIGWINCH, sig_handler);
1626 1655                  }
1627 1656                  prstat_scandir(procdir);
1628 1657                  list_refresh(&lwps);
1629 1658                  if (print_movecur)
1630 1659                          (void) putp(movecur);
1631 1660                  print_movecur = TRUE;
1632 1661                  if ((opts.o_outpmode & OPT_PSINFO) ||
1633 1662                      (opts.o_outpmode & OPT_MSACCT)) {
1634 1663                          list_sort(&lwps);
1635 1664                          list_print(&lwps);
1636 1665                  }
1637 1666                  if (opts.o_outpmode & OPT_USERS) {
1638 1667                          list_getsize(&users);
1639 1668                          list_sort(&users);
1640 1669                          list_print(&users);
1641 1670                          list_clear(&users);
1642 1671                  }
1643 1672                  if (opts.o_outpmode & OPT_TASKS) {
1644 1673                          list_getsize(&tasks);
1645 1674                          list_sort(&tasks);
1646 1675                          list_print(&tasks);
1647 1676                          list_clear(&tasks);
1648 1677                  }
1649 1678                  if (opts.o_outpmode & OPT_PROJECTS) {
1650 1679                          list_getsize(&projects);
1651 1680                          list_sort(&projects);
1652 1681                          list_print(&projects);
1653 1682                          list_clear(&projects);
1654 1683                  }
1655 1684                  if (opts.o_outpmode & OPT_ZONES) {
1656 1685                          list_getsize(&zones);
1657 1686                          list_sort(&zones);
1658 1687                          list_print(&zones);
1659 1688                          list_clear(&zones);
1660 1689                  }
1661 1690                  if (opts.o_count == 1)
1662 1691                          break;
1663 1692                  /*
1664 1693                   * If poll() returns -1 and sets errno to EINTR here because
1665 1694                   * the process received a signal, it is Ok to abort this
1666 1695                   * timeout and loop around because we check the signals at the
1667 1696                   * top of the loop.
1668 1697                   */
1669 1698                  if (opts.o_outpmode & OPT_TTY) {
1670 1699                          if (poll(&pollset, (nfds_t)1, timeout) > 0) {
1671 1700                                  if (read(STDIN_FILENO, &key, 1) == 1) {
1672 1701                                          if (tolower(key) == 'q')
1673 1702                                                  break;
1674 1703                                  }
1675 1704                          }
1676 1705                  } else {
1677 1706                          (void) sleep(opts.o_interval);
1678 1707                  }
1679 1708          } while (opts.o_count == (-1) || --opts.o_count);
1680 1709  
1681 1710          if (opts.o_outpmode & OPT_TTY)
1682 1711                  (void) putchar('\r');
1683 1712          return (0);
1684 1713  }
  
    | 
      ↓ open down ↓ | 
    96 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX