Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section


  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2013 Gary Mills
  24  *
  25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  31  */
  32 
  33 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  34 /*        All Rights Reserved   */
  35 
  36 /*
  37  * ps -- print things about processes.
  38  */
  39 #include <stdio.h>
  40 #include <ctype.h>
  41 #include <string.h>
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <pwd.h>
  45 #include <grp.h>
  46 #include <sys/types.h>
  47 #include <sys/stat.h>
  48 #include <sys/mkdev.h>
  49 #include <unistd.h>
  50 #include <stdlib.h>


  91         size_t  size;           /* number of ugdata structs allocated */
  92         size_t  nent;           /* number of active entries */
  93         struct ugdata *ent;     /* pointer to array of actual entries */
  94 };
  95 
  96 enum fname {    /* enumeration of field names */
  97         F_USER,         /* effective user of the process */
  98         F_RUSER,        /* real user of the process */
  99         F_GROUP,        /* effective group of the process */
 100         F_RGROUP,       /* real group of the process */
 101         F_UID,          /* numeric effective uid of the process */
 102         F_RUID,         /* numeric real uid of the process */
 103         F_GID,          /* numeric effective gid of the process */
 104         F_RGID,         /* numeric real gid of the process */
 105         F_PID,          /* process id */
 106         F_PPID,         /* parent process id */
 107         F_PGID,         /* process group id */
 108         F_SID,          /* session id */
 109         F_PSR,          /* bound processor */
 110         F_LWP,          /* lwp-id */

 111         F_NLWP,         /* number of lwps */
 112         F_OPRI,         /* old priority (obsolete) */
 113         F_PRI,          /* new priority */
 114         F_F,            /* process flags */
 115         F_S,            /* letter indicating the state */
 116         F_C,            /* processor utilization (obsolete) */
 117         F_PCPU,         /* percent of recently used cpu time */
 118         F_PMEM,         /* percent of physical memory used (rss) */
 119         F_OSZ,          /* virtual size of the process in pages */
 120         F_VSZ,          /* virtual size of the process in kilobytes */
 121         F_RSS,          /* resident set size of the process in kilobytes */
 122         F_NICE,         /* "nice" value of the process */
 123         F_CLASS,        /* scheduler class */
 124         F_STIME,        /* start time of the process, hh:mm:ss or Month Day */
 125         F_ETIME,        /* elapsed time of the process, [[dd-]hh:]mm:ss */
 126         F_TIME,         /* cpu time of the process, [[dd-]hh:]mm:ss */
 127         F_TTY,          /* name of the controlling terminal */
 128         F_ADDR,         /* address of the process (obsolete) */
 129         F_WCHAN,        /* wait channel (sleep condition variable) */
 130         F_FNAME,        /* file name of command */


 160         int width;
 161         int minwidth;
 162 };
 163 
 164 static struct def_field fname[] = {
 165         /* fname        header          width   minwidth */
 166         { "user",       "USER",         8,      8       },
 167         { "ruser",      "RUSER",        8,      8       },
 168         { "group",      "GROUP",        8,      8       },
 169         { "rgroup",     "RGROUP",       8,      8       },
 170         { "uid",        "UID",          5,      5       },
 171         { "ruid",       "RUID",         5,      5       },
 172         { "gid",        "GID",          5,      5       },
 173         { "rgid",       "RGID",         5,      5       },
 174         { "pid",        "PID",          5,      5       },
 175         { "ppid",       "PPID",         5,      5       },
 176         { "pgid",       "PGID",         5,      5       },
 177         { "sid",        "SID",          5,      5       },
 178         { "psr",        "PSR",          3,      2       },
 179         { "lwp",        "LWP",          6,      2       },

 180         { "nlwp",       "NLWP",         4,      2       },
 181         { "opri",       "PRI",          3,      2       },
 182         { "pri",        "PRI",          3,      2       },
 183         { "f",          "F",            2,      2       },
 184         { "s",          "S",            1,      1       },
 185         { "c",          "C",            2,      2       },
 186         { "pcpu",       "%CPU",         4,      4       },
 187         { "pmem",       "%MEM",         4,      4       },
 188         { "osz",        "SZ",           4,      4       },
 189         { "vsz",        "VSZ",          4,      4       },
 190         { "rss",        "RSS",          4,      4       },
 191         { "nice",       "NI",           2,      2       },
 192         { "class",      "CLS",          4,      2       },
 193         { "stime",      "STIME",        8,      8       },
 194         { "etime",      "ELAPSED",      11,     7       },
 195         { "time",       "TIME",         11,     5       },
 196         { "tty",        "TT",           7,      7       },
 197 #ifdef _LP64
 198         { "addr",       "ADDR",         16,     8       },
 199         { "wchan",      "WCHAN",        16,     8       },


 786         /* allocate a buffer for lwpsinfo structures */
 787         lpbufsize = 4096;
 788         if (Lflg && (lpsinfobuf = malloc(lpbufsize)) == NULL) {
 789                 (void) fprintf(stderr,
 790                     gettext("ps: no memory\n"));
 791                 exit(1);
 792         }
 793 
 794         if (fields) {   /* print user-specified header */
 795                 if (do_header) {
 796                         struct field *f;
 797 
 798                         for (f = fields; f != NULL; f = f->next) {
 799                                 if (f != fields)
 800                                         (void) printf(" ");
 801                                 switch (f->fname) {
 802                                 case F_TTY:
 803                                         (void) printf("%-*s",
 804                                             f->width, f->header);
 805                                         break;

 806                                 case F_FNAME:
 807                                 case F_COMM:
 808                                 case F_ARGS:
 809                                         /*
 810                                          * Print these headers full width
 811                                          * unless they appear at the end.
 812                                          */
 813                                         if (f->next != NULL) {
 814                                                 (void) printf("%-*s",
 815                                                     f->width, f->header);
 816                                         } else {
 817                                                 (void) printf("%s",
 818                                                     f->header);
 819                                         }
 820                                         break;
 821                                 default:
 822                                         (void) printf("%*s",
 823                                             f->width, f->header);
 824                                         break;
 825                                 }


1161         name = arg;
1162         arg = strpbrk(arg, " \t\r\v\f\n,=");
1163         if (arg != NULL) {
1164                 c = *arg;
1165                 *arg++ = '\0';
1166                 if (c == '=') {
1167                         char *s;
1168 
1169                         header = arg;
1170                         arg = NULL;
1171                         width = strlen(header);
1172                         s = header + width;
1173                         while (s > header && isspace(*--s))
1174                                 *s = '\0';
1175                         while (isspace(*header))
1176                                 header++;
1177                 }
1178         }
1179         for (df = &fname[0]; df < &fname[NFIELDS]; df++)
1180                 if (strcmp(name, df->fname) == 0) {
1181                         if (strcmp(name, "lwp") == 0)

1182                                 Lflg++;
1183                         break;
1184                 }
1185         if (df >= &fname[NFIELDS]) {
1186                 (void) fprintf(stderr,
1187                     gettext("ps: unknown output format: -o %s\n"),
1188                     name);
1189                 errflg++;
1190                 return (arg);
1191         }
1192         if ((f = malloc(sizeof (*f))) == NULL) {
1193                 (void) fprintf(stderr,
1194                     gettext("ps: malloc() for output format failed, %s\n"),
1195                     err_string(errno));
1196                 exit(1);
1197         }
1198         f->next = NULL;
1199         f->fname = df - &fname[0];
1200         f->header = header? header : df->header;
1201         if (width == 0)


1737                 (void) printf("%*d", width, (int)psinfo->pr_pid);
1738                 break;
1739         case F_PPID:
1740                 (void) printf("%*d", width, (int)psinfo->pr_ppid);
1741                 break;
1742         case F_PGID:
1743                 (void) printf("%*d", width, (int)psinfo->pr_pgid);
1744                 break;
1745         case F_SID:
1746                 (void) printf("%*d", width, (int)psinfo->pr_sid);
1747                 break;
1748         case F_PSR:
1749                 if (zombie_lwp || psinfo->pr_lwp.pr_bindpro == PBIND_NONE)
1750                         (void) printf("%*s", width, "-");
1751                 else
1752                         (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpro);
1753                 break;
1754         case F_LWP:
1755                 (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid);
1756                 break;





















1757         case F_NLWP:
1758                 (void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb);
1759                 break;
1760         case F_OPRI:
1761                 if (zombie_lwp)
1762                         (void) printf("%*s", width, "-");
1763                 else
1764                         (void) printf("%*d", width, psinfo->pr_lwp.pr_oldpri);
1765                 break;
1766         case F_PRI:
1767                 if (zombie_lwp)
1768                         (void) printf("%*s", width, "-");
1769                 else
1770                         (void) printf("%*d", width, psinfo->pr_lwp.pr_pri);
1771                 break;
1772         case F_F:
1773                 mask = 0xffffffffUL;
1774                 if (width < 8)
1775                         mask >>= (8 - width) * 4;
1776                 (void) printf("%*lx", width, psinfo->pr_flag & mask);




  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2013 Gary Mills
  24  *
  25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2018, Joyent, Inc.
  31  */
  32 
  33 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  34 /*        All Rights Reserved   */
  35 
  36 /*
  37  * ps -- print things about processes.
  38  */
  39 #include <stdio.h>
  40 #include <ctype.h>
  41 #include <string.h>
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <pwd.h>
  45 #include <grp.h>
  46 #include <sys/types.h>
  47 #include <sys/stat.h>
  48 #include <sys/mkdev.h>
  49 #include <unistd.h>
  50 #include <stdlib.h>


  91         size_t  size;           /* number of ugdata structs allocated */
  92         size_t  nent;           /* number of active entries */
  93         struct ugdata *ent;     /* pointer to array of actual entries */
  94 };
  95 
  96 enum fname {    /* enumeration of field names */
  97         F_USER,         /* effective user of the process */
  98         F_RUSER,        /* real user of the process */
  99         F_GROUP,        /* effective group of the process */
 100         F_RGROUP,       /* real group of the process */
 101         F_UID,          /* numeric effective uid of the process */
 102         F_RUID,         /* numeric real uid of the process */
 103         F_GID,          /* numeric effective gid of the process */
 104         F_RGID,         /* numeric real gid of the process */
 105         F_PID,          /* process id */
 106         F_PPID,         /* parent process id */
 107         F_PGID,         /* process group id */
 108         F_SID,          /* session id */
 109         F_PSR,          /* bound processor */
 110         F_LWP,          /* lwp-id */
 111         F_LWPNAME,      /* lwp name */
 112         F_NLWP,         /* number of lwps */
 113         F_OPRI,         /* old priority (obsolete) */
 114         F_PRI,          /* new priority */
 115         F_F,            /* process flags */
 116         F_S,            /* letter indicating the state */
 117         F_C,            /* processor utilization (obsolete) */
 118         F_PCPU,         /* percent of recently used cpu time */
 119         F_PMEM,         /* percent of physical memory used (rss) */
 120         F_OSZ,          /* virtual size of the process in pages */
 121         F_VSZ,          /* virtual size of the process in kilobytes */
 122         F_RSS,          /* resident set size of the process in kilobytes */
 123         F_NICE,         /* "nice" value of the process */
 124         F_CLASS,        /* scheduler class */
 125         F_STIME,        /* start time of the process, hh:mm:ss or Month Day */
 126         F_ETIME,        /* elapsed time of the process, [[dd-]hh:]mm:ss */
 127         F_TIME,         /* cpu time of the process, [[dd-]hh:]mm:ss */
 128         F_TTY,          /* name of the controlling terminal */
 129         F_ADDR,         /* address of the process (obsolete) */
 130         F_WCHAN,        /* wait channel (sleep condition variable) */
 131         F_FNAME,        /* file name of command */


 161         int width;
 162         int minwidth;
 163 };
 164 
 165 static struct def_field fname[] = {
 166         /* fname        header          width   minwidth */
 167         { "user",       "USER",         8,      8       },
 168         { "ruser",      "RUSER",        8,      8       },
 169         { "group",      "GROUP",        8,      8       },
 170         { "rgroup",     "RGROUP",       8,      8       },
 171         { "uid",        "UID",          5,      5       },
 172         { "ruid",       "RUID",         5,      5       },
 173         { "gid",        "GID",          5,      5       },
 174         { "rgid",       "RGID",         5,      5       },
 175         { "pid",        "PID",          5,      5       },
 176         { "ppid",       "PPID",         5,      5       },
 177         { "pgid",       "PGID",         5,      5       },
 178         { "sid",        "SID",          5,      5       },
 179         { "psr",        "PSR",          3,      2       },
 180         { "lwp",        "LWP",          6,      2       },
 181         { "lwpname",    "LWPNAME",      32,     8       },
 182         { "nlwp",       "NLWP",         4,      2       },
 183         { "opri",       "PRI",          3,      2       },
 184         { "pri",        "PRI",          3,      2       },
 185         { "f",          "F",            2,      2       },
 186         { "s",          "S",            1,      1       },
 187         { "c",          "C",            2,      2       },
 188         { "pcpu",       "%CPU",         4,      4       },
 189         { "pmem",       "%MEM",         4,      4       },
 190         { "osz",        "SZ",           4,      4       },
 191         { "vsz",        "VSZ",          4,      4       },
 192         { "rss",        "RSS",          4,      4       },
 193         { "nice",       "NI",           2,      2       },
 194         { "class",      "CLS",          4,      2       },
 195         { "stime",      "STIME",        8,      8       },
 196         { "etime",      "ELAPSED",      11,     7       },
 197         { "time",       "TIME",         11,     5       },
 198         { "tty",        "TT",           7,      7       },
 199 #ifdef _LP64
 200         { "addr",       "ADDR",         16,     8       },
 201         { "wchan",      "WCHAN",        16,     8       },


 788         /* allocate a buffer for lwpsinfo structures */
 789         lpbufsize = 4096;
 790         if (Lflg && (lpsinfobuf = malloc(lpbufsize)) == NULL) {
 791                 (void) fprintf(stderr,
 792                     gettext("ps: no memory\n"));
 793                 exit(1);
 794         }
 795 
 796         if (fields) {   /* print user-specified header */
 797                 if (do_header) {
 798                         struct field *f;
 799 
 800                         for (f = fields; f != NULL; f = f->next) {
 801                                 if (f != fields)
 802                                         (void) printf(" ");
 803                                 switch (f->fname) {
 804                                 case F_TTY:
 805                                         (void) printf("%-*s",
 806                                             f->width, f->header);
 807                                         break;
 808                                 case F_LWPNAME:
 809                                 case F_FNAME:
 810                                 case F_COMM:
 811                                 case F_ARGS:
 812                                         /*
 813                                          * Print these headers full width
 814                                          * unless they appear at the end.
 815                                          */
 816                                         if (f->next != NULL) {
 817                                                 (void) printf("%-*s",
 818                                                     f->width, f->header);
 819                                         } else {
 820                                                 (void) printf("%s",
 821                                                     f->header);
 822                                         }
 823                                         break;
 824                                 default:
 825                                         (void) printf("%*s",
 826                                             f->width, f->header);
 827                                         break;
 828                                 }


1164         name = arg;
1165         arg = strpbrk(arg, " \t\r\v\f\n,=");
1166         if (arg != NULL) {
1167                 c = *arg;
1168                 *arg++ = '\0';
1169                 if (c == '=') {
1170                         char *s;
1171 
1172                         header = arg;
1173                         arg = NULL;
1174                         width = strlen(header);
1175                         s = header + width;
1176                         while (s > header && isspace(*--s))
1177                                 *s = '\0';
1178                         while (isspace(*header))
1179                                 header++;
1180                 }
1181         }
1182         for (df = &fname[0]; df < &fname[NFIELDS]; df++)
1183                 if (strcmp(name, df->fname) == 0) {
1184                         if (strcmp(name, "lwp") == 0 ||
1185                             strcmp(name, "lwpname") == 0)
1186                                 Lflg++;
1187                         break;
1188                 }
1189         if (df >= &fname[NFIELDS]) {
1190                 (void) fprintf(stderr,
1191                     gettext("ps: unknown output format: -o %s\n"),
1192                     name);
1193                 errflg++;
1194                 return (arg);
1195         }
1196         if ((f = malloc(sizeof (*f))) == NULL) {
1197                 (void) fprintf(stderr,
1198                     gettext("ps: malloc() for output format failed, %s\n"),
1199                     err_string(errno));
1200                 exit(1);
1201         }
1202         f->next = NULL;
1203         f->fname = df - &fname[0];
1204         f->header = header? header : df->header;
1205         if (width == 0)


1741                 (void) printf("%*d", width, (int)psinfo->pr_pid);
1742                 break;
1743         case F_PPID:
1744                 (void) printf("%*d", width, (int)psinfo->pr_ppid);
1745                 break;
1746         case F_PGID:
1747                 (void) printf("%*d", width, (int)psinfo->pr_pgid);
1748                 break;
1749         case F_SID:
1750                 (void) printf("%*d", width, (int)psinfo->pr_sid);
1751                 break;
1752         case F_PSR:
1753                 if (zombie_lwp || psinfo->pr_lwp.pr_bindpro == PBIND_NONE)
1754                         (void) printf("%*s", width, "-");
1755                 else
1756                         (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpro);
1757                 break;
1758         case F_LWP:
1759                 (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid);
1760                 break;
1761         case F_LWPNAME: {
1762                 char lwpname[THREAD_NAME_MAX] = "";
1763                 char *path = NULL;
1764                 int fd;
1765 
1766                 if (asprintf(&path, "%s/%d/lwp/%d/lwpname", procdir,
1767                     (int)psinfo->pr_pid, (int)psinfo->pr_lwp.pr_lwpid) != -1 &&
1768                     (fd = open(path, O_RDONLY)) != -1) {
1769                         (void) read(fd, lwpname, sizeof (lwpname));
1770                         lwpname[THREAD_NAME_MAX - 1] = '\0';
1771                         (void) close(fd);
1772                 }
1773 
1774                 free(path);
1775 
1776                 if (f->next != NULL)
1777                         (void) printf("%-*s", width, lwpname);
1778                 else
1779                         (void) printf("%s", lwpname);
1780                 break;
1781         }
1782         case F_NLWP:
1783                 (void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb);
1784                 break;
1785         case F_OPRI:
1786                 if (zombie_lwp)
1787                         (void) printf("%*s", width, "-");
1788                 else
1789                         (void) printf("%*d", width, psinfo->pr_lwp.pr_oldpri);
1790                 break;
1791         case F_PRI:
1792                 if (zombie_lwp)
1793                         (void) printf("%*s", width, "-");
1794                 else
1795                         (void) printf("%*d", width, psinfo->pr_lwp.pr_pri);
1796                 break;
1797         case F_F:
1798                 mask = 0xffffffffUL;
1799                 if (width < 8)
1800                         mask >>= (8 - width) * 4;
1801                 (void) printf("%*lx", width, psinfo->pr_flag & mask);