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);
|