4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * ptree -- print family tree of processes
28 */
29
30 #pragma ident "%Z%%M% %I% %E% SMI"
31
32 #include <assert.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/termios.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <dirent.h>
42 #include <pwd.h>
43 #include <libproc.h>
44 #include <libzonecfg.h>
45 #include <limits.h>
46 #include <libcontract.h>
47 #include <sys/contract.h>
48 #include <sys/ctfs.h>
49 #include <libcontract_priv.h>
50 #include <sys/stat.h>
51
52 #define FAKEDPID0(p) (p->pid == 0 && p->psargs[0] == '\0')
53
54 typedef struct ps {
55 int done;
56 uid_t uid;
57 uid_t gid;
58 pid_t pid; /* pid == -1 indicates this is a contract */
59 pid_t ppid;
60 pid_t pgrp;
61 pid_t sid;
62 zoneid_t zoneid;
63 ctid_t ctid;
64 timestruc_t start;
65 char psargs[PRARGSZ];
66 struct ps *pp; /* parent */
67 struct ps *sp; /* sibling */
68 struct ps *cp; /* child */
69 } ps_t;
70
86 static int columns = 80;
87
88 static void markprocs(ps_t *p);
89 static int printone(ps_t *p, int level);
90 static void insertchild(ps_t *, ps_t *);
91 static void prsort(ps_t *p);
92 static void printsubtree(ps_t *p, int level);
93 static zoneid_t getzone(char *arg);
94 static ps_t *fakepid0(void);
95
96 int
97 main(int argc, char **argv)
98 {
99 psinfo_t info; /* process information structure from /proc */
100 int opt;
101 int errflg = 0;
102 struct winsize winsize;
103 char *s;
104 int n;
105 int retc = 0;
106
107 DIR *dirp;
108 struct dirent *dentp;
109 char pname[100];
110 int pdlen;
111
112 ps_t *p;
113
114 if ((command = strrchr(argv[0], '/')) == NULL)
115 command = argv[0];
116 else
117 command++;
118
119 /* options */
120 while ((opt = getopt(argc, argv, "acz:")) != EOF) {
121 switch (opt) {
122 case 'a': /* include children of process 0 */
123 aflag = 1;
124 break;
125 case 'c': /* display contract ownership */
126 aflag = cflag = 1;
127 break;
128 case 'z': /* only processes in given zone */
129 zflag = 1;
152 " -c : show contract ownership\n");
153 (void) fprintf(stderr,
154 " -z : print only processes in given zone\n");
155 return (2);
156 }
157
158 /*
159 * Kind of a hack to determine the width of the output...
160 */
161 if ((s = getenv("COLUMNS")) != NULL && (n = atoi(s)) > 0)
162 columns = n;
163 else if (isatty(fileno(stdout)) &&
164 ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 &&
165 winsize.ws_col != 0)
166 columns = winsize.ws_col;
167
168 nps = 0;
169 psize = 0;
170 ps = NULL;
171
172 /*
173 * Search the /proc directory for all processes.
174 */
175 if ((dirp = opendir("/proc")) == NULL) {
176 (void) fprintf(stderr, "%s: cannot open /proc directory\n",
177 command);
178 return (1);
179 }
180
181 (void) strcpy(pname, "/proc");
182 pdlen = strlen(pname);
183 pname[pdlen++] = '/';
184
185 /* for each active process --- */
186 while (dentp = readdir(dirp)) {
187 int procfd; /* filedescriptor for /proc/nnnnn/psinfo */
188
189 if (dentp->d_name[0] == '.') /* skip . and .. */
190 continue;
191 (void) strcpy(pname + pdlen, dentp->d_name);
192 (void) strcpy(pname + strlen(pname), "/psinfo");
193 retry:
194 if ((procfd = open(pname, O_RDONLY)) == -1)
195 continue;
196
197 /*
198 * Get the info structure for the process and close quickly.
199 */
200 if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
201 int saverr = errno;
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
25 */
26
27 /*
28 * ptree -- print family tree of processes
29 */
30
31 #include <assert.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/termios.h>
38 #include <unistd.h>
39 #include <stdlib.h>
40 #include <dirent.h>
41 #include <pwd.h>
42 #include <libproc.h>
43 #include <libzonecfg.h>
44 #include <limits.h>
45 #include <libcontract.h>
46 #include <sys/contract.h>
47 #include <sys/ctfs.h>
48 #include <libcontract_priv.h>
49 #include <sys/stat.h>
50 #include "ptools_common.h"
51
52 #define FAKEDPID0(p) (p->pid == 0 && p->psargs[0] == '\0')
53
54 typedef struct ps {
55 int done;
56 uid_t uid;
57 uid_t gid;
58 pid_t pid; /* pid == -1 indicates this is a contract */
59 pid_t ppid;
60 pid_t pgrp;
61 pid_t sid;
62 zoneid_t zoneid;
63 ctid_t ctid;
64 timestruc_t start;
65 char psargs[PRARGSZ];
66 struct ps *pp; /* parent */
67 struct ps *sp; /* sibling */
68 struct ps *cp; /* child */
69 } ps_t;
70
86 static int columns = 80;
87
88 static void markprocs(ps_t *p);
89 static int printone(ps_t *p, int level);
90 static void insertchild(ps_t *, ps_t *);
91 static void prsort(ps_t *p);
92 static void printsubtree(ps_t *p, int level);
93 static zoneid_t getzone(char *arg);
94 static ps_t *fakepid0(void);
95
96 int
97 main(int argc, char **argv)
98 {
99 psinfo_t info; /* process information structure from /proc */
100 int opt;
101 int errflg = 0;
102 struct winsize winsize;
103 char *s;
104 int n;
105 int retc = 0;
106 char ppath[PATH_MAX];
107
108 DIR *dirp;
109 struct dirent *dentp;
110 char pname[PATH_MAX];
111 int pdlen;
112
113 ps_t *p;
114
115 if ((command = strrchr(argv[0], '/')) == NULL)
116 command = argv[0];
117 else
118 command++;
119
120 /* options */
121 while ((opt = getopt(argc, argv, "acz:")) != EOF) {
122 switch (opt) {
123 case 'a': /* include children of process 0 */
124 aflag = 1;
125 break;
126 case 'c': /* display contract ownership */
127 aflag = cflag = 1;
128 break;
129 case 'z': /* only processes in given zone */
130 zflag = 1;
153 " -c : show contract ownership\n");
154 (void) fprintf(stderr,
155 " -z : print only processes in given zone\n");
156 return (2);
157 }
158
159 /*
160 * Kind of a hack to determine the width of the output...
161 */
162 if ((s = getenv("COLUMNS")) != NULL && (n = atoi(s)) > 0)
163 columns = n;
164 else if (isatty(fileno(stdout)) &&
165 ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 &&
166 winsize.ws_col != 0)
167 columns = winsize.ws_col;
168
169 nps = 0;
170 psize = 0;
171 ps = NULL;
172
173 (void) proc_snprintf(ppath, sizeof (ppath), "/proc");
174
175 /*
176 * Search the /proc directory for all processes.
177 */
178 if ((dirp = opendir(ppath)) == NULL) {
179 (void) fprintf(stderr, "%s: cannot open %s directory\n",
180 command, ppath);
181 return (1);
182 }
183
184 (void) strcpy(pname, ppath);
185 pdlen = strlen(pname);
186 pname[pdlen++] = '/';
187
188 /* for each active process --- */
189 while (dentp = readdir(dirp)) {
190 int procfd; /* filedescriptor for /proc/nnnnn/psinfo */
191
192 if (dentp->d_name[0] == '.') /* skip . and .. */
193 continue;
194 (void) strcpy(pname + pdlen, dentp->d_name);
195 (void) strcpy(pname + strlen(pname), "/psinfo");
196 retry:
197 if ((procfd = open(pname, O_RDONLY)) == -1)
198 continue;
199
200 /*
201 * Get the info structure for the process and close quickly.
202 */
203 if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
204 int saverr = errno;
|