xref: /illumos-gate/usr/src/cmd/pgrep/pgrep.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/task.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/contract.h>
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <signal.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <dirent.h>
38*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include <libintl.h>
42*7c478bd9Sstevel@tonic-gate #include <locale.h>
43*7c478bd9Sstevel@tonic-gate #include <stdio.h>
44*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
45*7c478bd9Sstevel@tonic-gate #include <ctype.h>
46*7c478bd9Sstevel@tonic-gate #include <wchar.h>
47*7c478bd9Sstevel@tonic-gate #include <limits.h>
48*7c478bd9Sstevel@tonic-gate #include <libuutil.h>
49*7c478bd9Sstevel@tonic-gate #include <libcontract_priv.h>
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate #include <procfs.h>
52*7c478bd9Sstevel@tonic-gate #include <project.h>
53*7c478bd9Sstevel@tonic-gate #include <pwd.h>
54*7c478bd9Sstevel@tonic-gate #include <grp.h>
55*7c478bd9Sstevel@tonic-gate #include <zone.h>
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #include "psexp.h"
58*7c478bd9Sstevel@tonic-gate #include "pgrep.h"
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN
61*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
62*7c478bd9Sstevel@tonic-gate #endif
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate #define	OPT_SETB 	0x0001	/* Set the bits specified by o_bits */
65*7c478bd9Sstevel@tonic-gate #define	OPT_CLRB 	0x0002	/* Clear the bits specified by o_bits */
66*7c478bd9Sstevel@tonic-gate #define	OPT_FUNC 	0x0004	/* Call the function specified by o_func */
67*7c478bd9Sstevel@tonic-gate #define	OPT_STR  	0x0008	/* Set the string specified by o_ptr */
68*7c478bd9Sstevel@tonic-gate #define	OPT_CRIT 	0x0010	/* Option is part of selection criteria */
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate #define	F_LONG_FMT	0x0001	/* Match against long format cmd */
71*7c478bd9Sstevel@tonic-gate #define	F_NEWEST	0x0002	/* Match only newest pid */
72*7c478bd9Sstevel@tonic-gate #define	F_REVERSE	0x0004	/* Reverse matching criteria */
73*7c478bd9Sstevel@tonic-gate #define	F_EXACT_MATCH	0x0008	/* Require exact match */
74*7c478bd9Sstevel@tonic-gate #define	F_HAVE_CRIT	0x0010	/* Criteria specified */
75*7c478bd9Sstevel@tonic-gate #define	F_OUTPUT	0x0020	/* Some output has been printed */
76*7c478bd9Sstevel@tonic-gate #define	F_KILL		0x0040	/* Pkill semantics active (vs pgrep) */
77*7c478bd9Sstevel@tonic-gate #define	F_LONG_OUT	0x0080	/* Long output format (pgrep -l) */
78*7c478bd9Sstevel@tonic-gate #define	F_OLDEST	0x0100	/* Match only oldest pid */
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate static int opt_euid(char, char *);
81*7c478bd9Sstevel@tonic-gate static int opt_uid(char, char *);
82*7c478bd9Sstevel@tonic-gate static int opt_gid(char, char *);
83*7c478bd9Sstevel@tonic-gate static int opt_ppid(char, char *);
84*7c478bd9Sstevel@tonic-gate static int opt_pgrp(char, char *);
85*7c478bd9Sstevel@tonic-gate static int opt_sid(char, char *);
86*7c478bd9Sstevel@tonic-gate static int opt_term(char, char *);
87*7c478bd9Sstevel@tonic-gate static int opt_projid(char, char *);
88*7c478bd9Sstevel@tonic-gate static int opt_taskid(char, char *);
89*7c478bd9Sstevel@tonic-gate static int opt_zoneid(char, char *);
90*7c478bd9Sstevel@tonic-gate static int opt_ctid(char, char *);
91*7c478bd9Sstevel@tonic-gate static int opt_V(char, char *);
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate static const char *g_procdir = "/proc";	/* Default procfs mount point */
94*7c478bd9Sstevel@tonic-gate static const char *g_delim = "\n";	/* Default output delimiter */
95*7c478bd9Sstevel@tonic-gate static const char *g_pname;		/* Program name for error messages */
96*7c478bd9Sstevel@tonic-gate static ushort_t g_flags;		/* Miscellaneous flags */
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate static optdesc_t g_optdtab[] = {
99*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'A' */
100*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'B' */
101*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'C' */
102*7c478bd9Sstevel@tonic-gate 	{ OPT_STR, 0, 0, &g_procdir },			/* -D procfsdir */
103*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'E' */
104*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'F' */
105*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_gid, 0 },		/* -G gid */
106*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'H' */
107*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'I' */
108*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_projid, 0 },	/* -J projid */
109*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'K' */
110*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'L' */
111*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'M' */
112*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'N' */
113*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'O' */
114*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_ppid, 0 },	/* -P ppid */
115*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'Q' */
116*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'R' */
117*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'S' */
118*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_taskid, 0 },	/* -T taskid */
119*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_uid, 0 },		/* -U uid */
120*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_V, 0 },		/* -V */
121*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'W' */
122*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'X' */
123*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'Y' */
124*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'Z' */
125*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* '[' */
126*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* '\\' */
127*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* ']' */
128*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* '^' */
129*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* '_' */
130*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* '`' */
131*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'a' */
132*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'b' */
133*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_ctid, 0 },	/* -c ctid */
134*7c478bd9Sstevel@tonic-gate 	{ OPT_STR, 0, 0, &g_delim },			/* -d delim */
135*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'e' */
136*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_LONG_FMT, 0, &g_flags },		/* -f */
137*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_pgrp, 0 },	/* -g pgrp */
138*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'h' */
139*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'i' */
140*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'j' */
141*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'k' */
142*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_LONG_OUT, 0, &g_flags },		/* 'l' */
143*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'm' */
144*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_NEWEST, 0, &g_flags },    	/* -n */
145*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_OLDEST, 0, &g_flags },		/* -o */
146*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'p' */
147*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'q' */
148*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'r' */
149*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_sid, 0 },		/* -s sid */
150*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_term, 0 },	/* -t term */
151*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_euid, 0 },	/* -u euid */
152*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_REVERSE, 0, &g_flags },		/* -v */
153*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'w' */
154*7c478bd9Sstevel@tonic-gate 	{ OPT_SETB, F_EXACT_MATCH, 0, &g_flags },	/* -x */
155*7c478bd9Sstevel@tonic-gate 	{ 0, 0, 0, 0 },					/* 'y' */
156*7c478bd9Sstevel@tonic-gate 	{ OPT_FUNC | OPT_CRIT, 0, opt_zoneid, 0 }	/* -z zoneid */
157*7c478bd9Sstevel@tonic-gate };
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate static const char PGREP_USAGE[] = "\
160*7c478bd9Sstevel@tonic-gate Usage: %s [-flnovx] [-d delim] [-P ppidlist] [-g pgrplist] [-s sidlist]\n\
161*7c478bd9Sstevel@tonic-gate 	[-u euidlist] [-U uidlist] [-G gidlist] [-J projidlist]\n\
162*7c478bd9Sstevel@tonic-gate 	[-T taskidlist] [-t termlist] [-z zonelist] [-c ctidlist] [pattern]\n";
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate static const char PKILL_USAGE[] = "\
165*7c478bd9Sstevel@tonic-gate Usage: %s [-signal] [-fnovx] [-P ppidlist] [-g pgrplist] [-s sidlist]\n\
166*7c478bd9Sstevel@tonic-gate 	[-u euidlist] [-U uidlist] [-G gidlist] [-J projidlist]\n\
167*7c478bd9Sstevel@tonic-gate 	[-T taskidlist] [-t termlist] [-z zonelist] [-c ctidlist] [pattern]\n";
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate static const char PGREP_OPTS[] = "flnovVxc:d:D:u:U:G:P:g:s:t:z:J:T:";
170*7c478bd9Sstevel@tonic-gate static const char PKILL_OPTS[] = "fnovVxc:D:u:U:G:P:g:s:t:z:J:T:";
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate static const char LSEP[] = ",\t ";	/* Argument list delimiter chars */
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate static psexp_t g_psexp;			/* Process matching expression */
175*7c478bd9Sstevel@tonic-gate static pid_t g_pid;			/* Current pid */
176*7c478bd9Sstevel@tonic-gate static int g_signal = SIGTERM;		/* Signal to send */
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate static void
179*7c478bd9Sstevel@tonic-gate print_proc(psinfo_t *psinfo)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_OUTPUT)
182*7c478bd9Sstevel@tonic-gate 		(void) printf("%s%d", g_delim, (int)psinfo->pr_pid);
183*7c478bd9Sstevel@tonic-gate 	else {
184*7c478bd9Sstevel@tonic-gate 		(void) printf("%d", (int)psinfo->pr_pid);
185*7c478bd9Sstevel@tonic-gate 		g_flags |= F_OUTPUT;
186*7c478bd9Sstevel@tonic-gate 	}
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate static char *
190*7c478bd9Sstevel@tonic-gate mbstrip(char *buf, size_t nbytes)
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	wchar_t wc;
193*7c478bd9Sstevel@tonic-gate 	char *p;
194*7c478bd9Sstevel@tonic-gate 	int n;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	buf[nbytes - 1] = '\0';
197*7c478bd9Sstevel@tonic-gate 	p = buf;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	while (*p != '\0') {
200*7c478bd9Sstevel@tonic-gate 		n = mbtowc(&wc, p, MB_LEN_MAX);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 		if (n < 0 || !iswprint(wc)) {
203*7c478bd9Sstevel@tonic-gate 			if (n < 0)
204*7c478bd9Sstevel@tonic-gate 				n = sizeof (char);
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 			if (nbytes <= n) {
207*7c478bd9Sstevel@tonic-gate 				*p = '\0';
208*7c478bd9Sstevel@tonic-gate 				break;
209*7c478bd9Sstevel@tonic-gate 			}
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 			(void) memmove(p, p + n, nbytes - n);
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		} else {
214*7c478bd9Sstevel@tonic-gate 			nbytes -= n;
215*7c478bd9Sstevel@tonic-gate 			p += n;
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	return (buf);
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate static void
223*7c478bd9Sstevel@tonic-gate print_proc_long(psinfo_t *psinfo)
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	char *name;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_LONG_FMT)
228*7c478bd9Sstevel@tonic-gate 		name = mbstrip(psinfo->pr_psargs, PRARGSZ);
229*7c478bd9Sstevel@tonic-gate 	else
230*7c478bd9Sstevel@tonic-gate 		name = psinfo->pr_fname;
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_OUTPUT)
233*7c478bd9Sstevel@tonic-gate 		(void) printf("%s%5d %s", g_delim, (int)psinfo->pr_pid, name);
234*7c478bd9Sstevel@tonic-gate 	else {
235*7c478bd9Sstevel@tonic-gate 		(void) printf("%5d %s", (int)psinfo->pr_pid, name);
236*7c478bd9Sstevel@tonic-gate 		g_flags |= F_OUTPUT;
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate static void
241*7c478bd9Sstevel@tonic-gate kill_proc(psinfo_t *psinfo)
242*7c478bd9Sstevel@tonic-gate {
243*7c478bd9Sstevel@tonic-gate 	if (psinfo->pr_pid > 0 && kill(psinfo->pr_pid, g_signal) == -1)
244*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("Failed to signal pid %d"),
245*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_pid);
246*7c478bd9Sstevel@tonic-gate }
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate static DIR *
249*7c478bd9Sstevel@tonic-gate open_proc_dir(const char *dirpath)
250*7c478bd9Sstevel@tonic-gate {
251*7c478bd9Sstevel@tonic-gate 	struct stat buf;
252*7c478bd9Sstevel@tonic-gate 	DIR *dirp;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	if ((dirp = opendir(dirpath)) == NULL) {
255*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("Failed to open %s"), dirpath);
256*7c478bd9Sstevel@tonic-gate 		return (NULL);
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	if (fstat(dirp->dd_fd, &buf) == -1) {
260*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("Failed to stat %s"), dirpath);
261*7c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
262*7c478bd9Sstevel@tonic-gate 		return (NULL);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	if (strcmp(buf.st_fstype, "proc") != 0) {
266*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("%s is not a procfs mount point\n"), dirpath);
267*7c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
268*7c478bd9Sstevel@tonic-gate 		return (NULL);
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	return (dirp);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate #define	NEWER(ps1, ps2) \
275*7c478bd9Sstevel@tonic-gate 	((ps1.pr_start.tv_sec > ps2.pr_start.tv_sec) || \
276*7c478bd9Sstevel@tonic-gate 	    (ps1.pr_start.tv_sec == ps2.pr_start.tv_sec && \
277*7c478bd9Sstevel@tonic-gate 	    ps1.pr_start.tv_nsec > ps2.pr_start.tv_nsec))
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate static int
280*7c478bd9Sstevel@tonic-gate scan_proc_dir(const char *dirpath, DIR *dirp, psexp_t *psexp,
281*7c478bd9Sstevel@tonic-gate 	void (*funcp)(psinfo_t *))
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate 	char procpath[MAXPATHLEN];
284*7c478bd9Sstevel@tonic-gate 	psinfo_t ps, ops;
285*7c478bd9Sstevel@tonic-gate 	dirent_t *dent;
286*7c478bd9Sstevel@tonic-gate 	int procfd;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	int reverse = (g_flags & F_REVERSE) ? 1 : 0;
289*7c478bd9Sstevel@tonic-gate 	int ovalid = 0, nmatches = 0, flags = 0;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_LONG_FMT)
292*7c478bd9Sstevel@tonic-gate 		flags |= PSEXP_PSARGS;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_EXACT_MATCH)
295*7c478bd9Sstevel@tonic-gate 		flags |= PSEXP_EXACT;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	while ((dent = readdir(dirp)) != NULL) {
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		if (dent->d_name[0] == '.')
300*7c478bd9Sstevel@tonic-gate 			continue;
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 		(void) snprintf(procpath, sizeof (procpath), "%s/%s/psinfo",
303*7c478bd9Sstevel@tonic-gate 		    dirpath, dent->d_name);
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 		if ((procfd = open(procpath, O_RDONLY)) == -1)
306*7c478bd9Sstevel@tonic-gate 			continue;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 		if ((read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) &&
309*7c478bd9Sstevel@tonic-gate 		    (ps.pr_nlwp != 0) && (ps.pr_pid != g_pid) &&
310*7c478bd9Sstevel@tonic-gate 		    (psexp_match(psexp, &ps, flags) ^ reverse)) {
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 			if (g_flags & F_NEWEST) {
313*7c478bd9Sstevel@tonic-gate 				/* LINTED - opsinfo use ok */
314*7c478bd9Sstevel@tonic-gate 				if (!ovalid || NEWER(ps, ops)) {
315*7c478bd9Sstevel@tonic-gate 					(void) memcpy(&ops, &ps,
316*7c478bd9Sstevel@tonic-gate 					    sizeof (psinfo_t));
317*7c478bd9Sstevel@tonic-gate 					ovalid = 1;
318*7c478bd9Sstevel@tonic-gate 				}
319*7c478bd9Sstevel@tonic-gate 			} else if (g_flags & F_OLDEST) {
320*7c478bd9Sstevel@tonic-gate 				if (!ovalid || NEWER(ops, ps)) {
321*7c478bd9Sstevel@tonic-gate 					(void) memcpy(&ops, &ps,
322*7c478bd9Sstevel@tonic-gate 					    sizeof (psinfo_t));
323*7c478bd9Sstevel@tonic-gate 					ovalid = 1;
324*7c478bd9Sstevel@tonic-gate 				}
325*7c478bd9Sstevel@tonic-gate 			} else {
326*7c478bd9Sstevel@tonic-gate 				(*funcp)(&ps);
327*7c478bd9Sstevel@tonic-gate 				nmatches++;
328*7c478bd9Sstevel@tonic-gate 			}
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 		(void) close(procfd);
332*7c478bd9Sstevel@tonic-gate 	}
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	if ((g_flags & (F_NEWEST | F_OLDEST)) && ovalid) {
335*7c478bd9Sstevel@tonic-gate 		(*funcp)(&ops);
336*7c478bd9Sstevel@tonic-gate 		nmatches++;
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	return (nmatches);
340*7c478bd9Sstevel@tonic-gate }
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate static int
343*7c478bd9Sstevel@tonic-gate parse_ids(idtab_t *idt, char *arg, int base, int opt, idkey_t zero)
344*7c478bd9Sstevel@tonic-gate {
345*7c478bd9Sstevel@tonic-gate 	char *ptr, *next;
346*7c478bd9Sstevel@tonic-gate 	idkey_t id;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
349*7c478bd9Sstevel@tonic-gate 		if ((id = (idkey_t)strtoul(ptr, &next, base)) != 0)
350*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, id);
351*7c478bd9Sstevel@tonic-gate 		else
352*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, zero);
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 		if (next == ptr || *next != 0) {
355*7c478bd9Sstevel@tonic-gate 			uu_warn("invalid argument for option '%c' -- %s\n",
356*7c478bd9Sstevel@tonic-gate 			    opt, ptr);
357*7c478bd9Sstevel@tonic-gate 			return (-1);
358*7c478bd9Sstevel@tonic-gate 		}
359*7c478bd9Sstevel@tonic-gate 	}
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	return (0);
362*7c478bd9Sstevel@tonic-gate }
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate static int
365*7c478bd9Sstevel@tonic-gate parse_uids(idtab_t *idt, char *arg)
366*7c478bd9Sstevel@tonic-gate {
367*7c478bd9Sstevel@tonic-gate 	char *ptr, *next;
368*7c478bd9Sstevel@tonic-gate 	struct passwd *pwent;
369*7c478bd9Sstevel@tonic-gate 	idkey_t id;
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
372*7c478bd9Sstevel@tonic-gate 		if (isdigit(ptr[0])) {
373*7c478bd9Sstevel@tonic-gate 			id = strtol(ptr, &next, 10);
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 			if (next != ptr && *next == '\0') {
376*7c478bd9Sstevel@tonic-gate 				idtab_append(idt, id);
377*7c478bd9Sstevel@tonic-gate 				continue;
378*7c478bd9Sstevel@tonic-gate 			}
379*7c478bd9Sstevel@tonic-gate 		}
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 		if ((pwent = getpwnam(ptr)) != NULL)
382*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, pwent->pw_uid);
383*7c478bd9Sstevel@tonic-gate 		else
384*7c478bd9Sstevel@tonic-gate 			goto err;
385*7c478bd9Sstevel@tonic-gate 	}
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	return (0);
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate err:
390*7c478bd9Sstevel@tonic-gate 	uu_warn(gettext("invalid user name -- %s\n"), ptr);
391*7c478bd9Sstevel@tonic-gate 	return (-1);
392*7c478bd9Sstevel@tonic-gate }
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate static int
395*7c478bd9Sstevel@tonic-gate parse_gids(idtab_t *idt, char *arg)
396*7c478bd9Sstevel@tonic-gate {
397*7c478bd9Sstevel@tonic-gate 	char *ptr, *next;
398*7c478bd9Sstevel@tonic-gate 	struct group *grent;
399*7c478bd9Sstevel@tonic-gate 	idkey_t id;
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
402*7c478bd9Sstevel@tonic-gate 		if (isdigit(ptr[0])) {
403*7c478bd9Sstevel@tonic-gate 			id = strtol(ptr, &next, 10);
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 			if (next != ptr && *next == '\0') {
406*7c478bd9Sstevel@tonic-gate 				idtab_append(idt, id);
407*7c478bd9Sstevel@tonic-gate 				continue;
408*7c478bd9Sstevel@tonic-gate 			}
409*7c478bd9Sstevel@tonic-gate 		}
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 		if ((grent = getgrnam(ptr)) != NULL)
412*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, grent->gr_gid);
413*7c478bd9Sstevel@tonic-gate 		else
414*7c478bd9Sstevel@tonic-gate 			goto err;
415*7c478bd9Sstevel@tonic-gate 	}
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	return (0);
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate err:
420*7c478bd9Sstevel@tonic-gate 	uu_warn(gettext("invalid group name -- %s\n"), ptr);
421*7c478bd9Sstevel@tonic-gate 	return (-1);
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate static int
425*7c478bd9Sstevel@tonic-gate parse_ttys(idtab_t *idt, char *arg)
426*7c478bd9Sstevel@tonic-gate {
427*7c478bd9Sstevel@tonic-gate 	char devpath[MAXPATHLEN];
428*7c478bd9Sstevel@tonic-gate 	struct stat buf;
429*7c478bd9Sstevel@tonic-gate 	char *ptr;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	int seen_console = 0; /* Flag so we only stat syscon and systty once */
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
434*7c478bd9Sstevel@tonic-gate 		if (strcmp(ptr, "none") == 0) {
435*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, (idkey_t)PRNODEV);
436*7c478bd9Sstevel@tonic-gate 			continue;
437*7c478bd9Sstevel@tonic-gate 		}
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 		if (strcmp(ptr, "console") == 0) {
440*7c478bd9Sstevel@tonic-gate 			if (seen_console)
441*7c478bd9Sstevel@tonic-gate 				continue;
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 			if (stat("/dev/syscon", &buf) == 0)
444*7c478bd9Sstevel@tonic-gate 				idtab_append(idt, (idkey_t)buf.st_rdev);
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 			if (stat("/dev/systty", &buf) == 0)
447*7c478bd9Sstevel@tonic-gate 				idtab_append(idt, (idkey_t)buf.st_rdev);
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 			seen_console++;
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 		(void) snprintf(devpath, MAXPATHLEN - 1, "/dev/%s", ptr);
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 		if (stat(devpath, &buf) == -1)
455*7c478bd9Sstevel@tonic-gate 			goto err;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 		idtab_append(idt, (idkey_t)buf.st_rdev);
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	return (0);
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate err:
463*7c478bd9Sstevel@tonic-gate 	uu_warn(gettext("unknown terminal name -- %s\n"), ptr);
464*7c478bd9Sstevel@tonic-gate 	return (-1);
465*7c478bd9Sstevel@tonic-gate }
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate static int
468*7c478bd9Sstevel@tonic-gate parse_projects(idtab_t *idt, char *arg)
469*7c478bd9Sstevel@tonic-gate {
470*7c478bd9Sstevel@tonic-gate 	char *ptr, *next;
471*7c478bd9Sstevel@tonic-gate 	projid_t projid;
472*7c478bd9Sstevel@tonic-gate 	idkey_t id;
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
475*7c478bd9Sstevel@tonic-gate 		if (isdigit(ptr[0])) {
476*7c478bd9Sstevel@tonic-gate 			id = strtol(ptr, &next, 10);
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 			if (next != ptr && *next == '\0') {
479*7c478bd9Sstevel@tonic-gate 				idtab_append(idt, id);
480*7c478bd9Sstevel@tonic-gate 				continue;
481*7c478bd9Sstevel@tonic-gate 			}
482*7c478bd9Sstevel@tonic-gate 		}
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 		if ((projid = getprojidbyname(ptr)) != -1)
485*7c478bd9Sstevel@tonic-gate 			idtab_append(idt, projid);
486*7c478bd9Sstevel@tonic-gate 		else
487*7c478bd9Sstevel@tonic-gate 			goto err;
488*7c478bd9Sstevel@tonic-gate 	}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	return (0);
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate err:
493*7c478bd9Sstevel@tonic-gate 	uu_warn(gettext("invalid project name -- %s\n"), ptr);
494*7c478bd9Sstevel@tonic-gate 	return (-1);
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate static int
498*7c478bd9Sstevel@tonic-gate parse_zones(idtab_t *idt, char *arg)
499*7c478bd9Sstevel@tonic-gate {
500*7c478bd9Sstevel@tonic-gate 	char *ptr;
501*7c478bd9Sstevel@tonic-gate 	zoneid_t id;
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	for (ptr = strtok(arg, LSEP); ptr != NULL; ptr = strtok(NULL, LSEP)) {
504*7c478bd9Sstevel@tonic-gate 		if (zone_get_id(ptr, &id) != 0) {
505*7c478bd9Sstevel@tonic-gate 			uu_warn(gettext("invalid zone name -- %s\n"), ptr);
506*7c478bd9Sstevel@tonic-gate 			return (-1);
507*7c478bd9Sstevel@tonic-gate 		}
508*7c478bd9Sstevel@tonic-gate 		idtab_append(idt, id);
509*7c478bd9Sstevel@tonic-gate 	}
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	return (0);
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
515*7c478bd9Sstevel@tonic-gate static int
516*7c478bd9Sstevel@tonic-gate opt_euid(char c, char *arg)
517*7c478bd9Sstevel@tonic-gate {
518*7c478bd9Sstevel@tonic-gate 	return (parse_uids(&g_psexp.ps_euids, arg));
519*7c478bd9Sstevel@tonic-gate }
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
522*7c478bd9Sstevel@tonic-gate static int
523*7c478bd9Sstevel@tonic-gate opt_uid(char c, char *arg)
524*7c478bd9Sstevel@tonic-gate {
525*7c478bd9Sstevel@tonic-gate 	return (parse_uids(&g_psexp.ps_ruids, arg));
526*7c478bd9Sstevel@tonic-gate }
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
529*7c478bd9Sstevel@tonic-gate static int
530*7c478bd9Sstevel@tonic-gate opt_gid(char c, char *arg)
531*7c478bd9Sstevel@tonic-gate {
532*7c478bd9Sstevel@tonic-gate 	return (parse_gids(&g_psexp.ps_rgids, arg));
533*7c478bd9Sstevel@tonic-gate }
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate static int
536*7c478bd9Sstevel@tonic-gate opt_ppid(char c, char *arg)
537*7c478bd9Sstevel@tonic-gate {
538*7c478bd9Sstevel@tonic-gate 	return (parse_ids(&g_psexp.ps_ppids, arg, 10, c, 0));
539*7c478bd9Sstevel@tonic-gate }
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate static int
542*7c478bd9Sstevel@tonic-gate opt_pgrp(char c, char *arg)
543*7c478bd9Sstevel@tonic-gate {
544*7c478bd9Sstevel@tonic-gate 	return (parse_ids(&g_psexp.ps_pgids, arg, 10, c, getpgrp()));
545*7c478bd9Sstevel@tonic-gate }
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate static int
548*7c478bd9Sstevel@tonic-gate opt_sid(char c, char *arg)
549*7c478bd9Sstevel@tonic-gate {
550*7c478bd9Sstevel@tonic-gate 	return (parse_ids(&g_psexp.ps_sids, arg, 10, c, getsid(0)));
551*7c478bd9Sstevel@tonic-gate }
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
554*7c478bd9Sstevel@tonic-gate static int
555*7c478bd9Sstevel@tonic-gate opt_term(char c, char *arg)
556*7c478bd9Sstevel@tonic-gate {
557*7c478bd9Sstevel@tonic-gate 	return (parse_ttys(&g_psexp.ps_ttys, arg));
558*7c478bd9Sstevel@tonic-gate }
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
561*7c478bd9Sstevel@tonic-gate static int
562*7c478bd9Sstevel@tonic-gate opt_projid(char c, char *arg)
563*7c478bd9Sstevel@tonic-gate {
564*7c478bd9Sstevel@tonic-gate 	return (parse_projects(&g_psexp.ps_projids, arg));
565*7c478bd9Sstevel@tonic-gate }
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate static int
568*7c478bd9Sstevel@tonic-gate opt_taskid(char c, char *arg)
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	return (parse_ids(&g_psexp.ps_taskids, arg, 10, c, gettaskid()));
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
574*7c478bd9Sstevel@tonic-gate static int
575*7c478bd9Sstevel@tonic-gate opt_zoneid(char c, char *arg)
576*7c478bd9Sstevel@tonic-gate {
577*7c478bd9Sstevel@tonic-gate 	return (parse_zones(&g_psexp.ps_zoneids, arg));
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate static int
581*7c478bd9Sstevel@tonic-gate opt_ctid(char c, char *arg)
582*7c478bd9Sstevel@tonic-gate {
583*7c478bd9Sstevel@tonic-gate 	return (parse_ids(&g_psexp.ps_ctids, arg, 10, c, getctid()));
584*7c478bd9Sstevel@tonic-gate }
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
587*7c478bd9Sstevel@tonic-gate static int
588*7c478bd9Sstevel@tonic-gate opt_V(char c, char *arg)
589*7c478bd9Sstevel@tonic-gate {
590*7c478bd9Sstevel@tonic-gate 	idtab_append(&g_psexp.ps_ruids, 0);
591*7c478bd9Sstevel@tonic-gate 	g_flags |= F_EXACT_MATCH;
592*7c478bd9Sstevel@tonic-gate 	g_psexp.ps_pat = "vold";
593*7c478bd9Sstevel@tonic-gate 	return (0);
594*7c478bd9Sstevel@tonic-gate }
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate static void
597*7c478bd9Sstevel@tonic-gate print_usage(FILE *stream)
598*7c478bd9Sstevel@tonic-gate {
599*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_KILL)
600*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stream, gettext(PKILL_USAGE), g_pname);
601*7c478bd9Sstevel@tonic-gate 	else
602*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stream, gettext(PGREP_USAGE), g_pname);
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate int
606*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
607*7c478bd9Sstevel@tonic-gate {
608*7c478bd9Sstevel@tonic-gate 	void (*funcp)(psinfo_t *);
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	const char *optstr;
611*7c478bd9Sstevel@tonic-gate 	optdesc_t *optd;
612*7c478bd9Sstevel@tonic-gate 	int nmatches, c;
613*7c478bd9Sstevel@tonic-gate 
614*7c478bd9Sstevel@tonic-gate 	DIR *dirp;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
617*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	UU_EXIT_FATAL = E_ERROR;
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	g_pname = uu_setpname(argv[0]);
622*7c478bd9Sstevel@tonic-gate 	g_pid = getpid();
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	psexp_create(&g_psexp);
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	if (strcmp(g_pname, "pkill") == 0) {
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 		if (argc > 1 && argv[1][0] == '-' &&
629*7c478bd9Sstevel@tonic-gate 		    str2sig(&argv[1][1], &g_signal) == 0) {
630*7c478bd9Sstevel@tonic-gate 			argv[1] = argv[0];
631*7c478bd9Sstevel@tonic-gate 			argv++;
632*7c478bd9Sstevel@tonic-gate 			argc--;
633*7c478bd9Sstevel@tonic-gate 		}
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 		optstr = PKILL_OPTS;
636*7c478bd9Sstevel@tonic-gate 		g_flags |= F_KILL;
637*7c478bd9Sstevel@tonic-gate 	} else
638*7c478bd9Sstevel@tonic-gate 		optstr = PGREP_OPTS;
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 	opterr = 0;
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 	while (optind < argc) {
643*7c478bd9Sstevel@tonic-gate 		while ((c = getopt(argc, argv, optstr)) != (int)EOF) {
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 			if (c == '?' || g_optdtab[c - 'A'].o_opts == 0) {
646*7c478bd9Sstevel@tonic-gate 				if (optopt != '?') {
647*7c478bd9Sstevel@tonic-gate 					uu_warn(
648*7c478bd9Sstevel@tonic-gate 					    gettext("illegal option -- %c\n"),
649*7c478bd9Sstevel@tonic-gate 					    optopt);
650*7c478bd9Sstevel@tonic-gate 				}
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 				print_usage(stderr);
653*7c478bd9Sstevel@tonic-gate 				return (E_USAGE);
654*7c478bd9Sstevel@tonic-gate 			}
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 			optd = &g_optdtab[c - 'A'];
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 			if (optd->o_opts & OPT_SETB)
659*7c478bd9Sstevel@tonic-gate 				*((ushort_t *)optd->o_ptr) |= optd->o_bits;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 			if (optd->o_opts & OPT_CLRB)
662*7c478bd9Sstevel@tonic-gate 				*((ushort_t *)optd->o_ptr) &= ~optd->o_bits;
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 			if (optd->o_opts & OPT_STR)
665*7c478bd9Sstevel@tonic-gate 				*((char **)optd->o_ptr) = optarg;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 			if (optd->o_opts & OPT_CRIT)
668*7c478bd9Sstevel@tonic-gate 				g_flags |= F_HAVE_CRIT;
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate 			if (optd->o_opts & OPT_FUNC) {
671*7c478bd9Sstevel@tonic-gate 				if (optd->o_func(c, optarg) == -1)
672*7c478bd9Sstevel@tonic-gate 					return (E_USAGE);
673*7c478bd9Sstevel@tonic-gate 			}
674*7c478bd9Sstevel@tonic-gate 		}
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 		if (optind < argc) {
677*7c478bd9Sstevel@tonic-gate 			if (g_psexp.ps_pat != NULL) {
678*7c478bd9Sstevel@tonic-gate 				uu_warn(gettext("illegal argument -- %s\n"),
679*7c478bd9Sstevel@tonic-gate 				    argv[optind]);
680*7c478bd9Sstevel@tonic-gate 				print_usage(stderr);
681*7c478bd9Sstevel@tonic-gate 				return (E_USAGE);
682*7c478bd9Sstevel@tonic-gate 			}
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 			g_psexp.ps_pat = argv[optind++];
685*7c478bd9Sstevel@tonic-gate 			g_flags |= F_HAVE_CRIT;
686*7c478bd9Sstevel@tonic-gate 		}
687*7c478bd9Sstevel@tonic-gate 	}
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	if ((g_flags & F_NEWEST) && (g_flags & F_OLDEST)) {
690*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("-n and -o are mutually exclusive\n"));
691*7c478bd9Sstevel@tonic-gate 		print_usage(stderr);
692*7c478bd9Sstevel@tonic-gate 		return (E_USAGE);
693*7c478bd9Sstevel@tonic-gate 	}
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate 	if ((g_flags & F_HAVE_CRIT) == 0) {
696*7c478bd9Sstevel@tonic-gate 		uu_warn(gettext("No matching criteria specified\n"));
697*7c478bd9Sstevel@tonic-gate 		print_usage(stderr);
698*7c478bd9Sstevel@tonic-gate 		return (E_USAGE);
699*7c478bd9Sstevel@tonic-gate 	}
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	if (psexp_compile(&g_psexp) == -1) {
702*7c478bd9Sstevel@tonic-gate 		psexp_destroy(&g_psexp);
703*7c478bd9Sstevel@tonic-gate 		return (E_USAGE);
704*7c478bd9Sstevel@tonic-gate 	}
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	if ((dirp = open_proc_dir(g_procdir)) == NULL)
707*7c478bd9Sstevel@tonic-gate 		return (E_ERROR);
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_KILL)
710*7c478bd9Sstevel@tonic-gate 		funcp = kill_proc;
711*7c478bd9Sstevel@tonic-gate 	else if (g_flags & F_LONG_OUT)
712*7c478bd9Sstevel@tonic-gate 		funcp = print_proc_long;
713*7c478bd9Sstevel@tonic-gate 	else
714*7c478bd9Sstevel@tonic-gate 		funcp = print_proc;
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	nmatches = scan_proc_dir(g_procdir, dirp, &g_psexp, funcp);
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 	if (g_flags & F_OUTPUT)
719*7c478bd9Sstevel@tonic-gate 		(void) fputc('\n', stdout);
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	psexp_destroy(&g_psexp);
722*7c478bd9Sstevel@tonic-gate 	return (nmatches ? E_MATCH : E_NOMATCH);
723*7c478bd9Sstevel@tonic-gate }
724