xref: /freebsd/usr.bin/fstat/fuser.c (revision 0daf62d9f5f7d2c15d00d71eb519b90516df016f)
1*0daf62d9SStanislav Sedov /*-
2*0daf62d9SStanislav Sedov  * Copyright (c) 2005-2009 Stanislav Sedov <stas@FreeBSD.org>
3*0daf62d9SStanislav Sedov  * All rights reserved.
4*0daf62d9SStanislav Sedov  *
5*0daf62d9SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
6*0daf62d9SStanislav Sedov  * modification, are permitted provided that the following conditions
7*0daf62d9SStanislav Sedov  * are met:
8*0daf62d9SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
9*0daf62d9SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
10*0daf62d9SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
11*0daf62d9SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
12*0daf62d9SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
13*0daf62d9SStanislav Sedov  *
14*0daf62d9SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*0daf62d9SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*0daf62d9SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*0daf62d9SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*0daf62d9SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*0daf62d9SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*0daf62d9SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*0daf62d9SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*0daf62d9SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*0daf62d9SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*0daf62d9SStanislav Sedov  * SUCH DAMAGE.
25*0daf62d9SStanislav Sedov  *
26*0daf62d9SStanislav Sedov  */
27*0daf62d9SStanislav Sedov #include <sys/cdefs.h>
28*0daf62d9SStanislav Sedov __FBSDID("$FreeBSD$");
29*0daf62d9SStanislav Sedov 
30*0daf62d9SStanislav Sedov #include <sys/queue.h>
31*0daf62d9SStanislav Sedov #include <sys/stat.h>
32*0daf62d9SStanislav Sedov #include <sys/sysctl.h>
33*0daf62d9SStanislav Sedov #include <sys/user.h>
34*0daf62d9SStanislav Sedov 
35*0daf62d9SStanislav Sedov #include <assert.h>
36*0daf62d9SStanislav Sedov #include <ctype.h>
37*0daf62d9SStanislav Sedov #include <err.h>
38*0daf62d9SStanislav Sedov #include <fcntl.h>
39*0daf62d9SStanislav Sedov #include <libprocstat.h>
40*0daf62d9SStanislav Sedov #include <limits.h>
41*0daf62d9SStanislav Sedov #include <paths.h>
42*0daf62d9SStanislav Sedov #include <pwd.h>
43*0daf62d9SStanislav Sedov #include <signal.h>
44*0daf62d9SStanislav Sedov #include <stdio.h>
45*0daf62d9SStanislav Sedov #include <stdlib.h>
46*0daf62d9SStanislav Sedov #include <string.h>
47*0daf62d9SStanislav Sedov #include <sysexits.h>
48*0daf62d9SStanislav Sedov #include <unistd.h>
49*0daf62d9SStanislav Sedov 
50*0daf62d9SStanislav Sedov #include "functions.h"
51*0daf62d9SStanislav Sedov 
52*0daf62d9SStanislav Sedov /*
53*0daf62d9SStanislav Sedov  * File access mode flags table.
54*0daf62d9SStanislav Sedov  */
55*0daf62d9SStanislav Sedov struct {
56*0daf62d9SStanislav Sedov 	int	flag;
57*0daf62d9SStanislav Sedov 	char	ch;
58*0daf62d9SStanislav Sedov } fflags[] = {
59*0daf62d9SStanislav Sedov 	{PS_FST_FFLAG_WRITE,	'w'},
60*0daf62d9SStanislav Sedov 	{PS_FST_FFLAG_APPEND,	'a'},
61*0daf62d9SStanislav Sedov 	{PS_FST_FFLAG_DIRECT,	'd'},
62*0daf62d9SStanislav Sedov 	{PS_FST_FFLAG_SHLOCK,	's'},
63*0daf62d9SStanislav Sedov 	{PS_FST_FFLAG_EXLOCK,	'e'}
64*0daf62d9SStanislav Sedov };
65*0daf62d9SStanislav Sedov #define	NFFLAGS	(sizeof(fflags) / sizeof(*fflags))
66*0daf62d9SStanislav Sedov 
67*0daf62d9SStanislav Sedov /*
68*0daf62d9SStanislav Sedov  * Usage flags translation table.
69*0daf62d9SStanislav Sedov  */
70*0daf62d9SStanislav Sedov struct {
71*0daf62d9SStanislav Sedov 	int	flag;
72*0daf62d9SStanislav Sedov 	char	ch;
73*0daf62d9SStanislav Sedov } uflags[] = {
74*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_RDIR,	'r'},
75*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_CDIR,	'c'},
76*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_JAIL,	'j'},
77*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_TRACE,	't'},
78*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_TEXT,	'x'},
79*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_MMAP,	'm'},
80*0daf62d9SStanislav Sedov 	{PS_FST_UFLAG_CTTY,	'y'}
81*0daf62d9SStanislav Sedov };
82*0daf62d9SStanislav Sedov #define	NUFLAGS	(sizeof(uflags) / sizeof(*uflags))
83*0daf62d9SStanislav Sedov 
84*0daf62d9SStanislav Sedov struct consumer {
85*0daf62d9SStanislav Sedov 	pid_t	pid;
86*0daf62d9SStanislav Sedov 	uid_t	uid;
87*0daf62d9SStanislav Sedov 	int	fd;
88*0daf62d9SStanislav Sedov 	int	flags;
89*0daf62d9SStanislav Sedov 	int	uflags;
90*0daf62d9SStanislav Sedov 	STAILQ_ENTRY(consumer)	next;
91*0daf62d9SStanislav Sedov };
92*0daf62d9SStanislav Sedov struct reqfile {
93*0daf62d9SStanislav Sedov 	uint32_t	fsid;
94*0daf62d9SStanislav Sedov 	uint64_t	fileid;
95*0daf62d9SStanislav Sedov 	const char	*name;
96*0daf62d9SStanislav Sedov 	STAILQ_HEAD(, consumer) consumers;
97*0daf62d9SStanislav Sedov };
98*0daf62d9SStanislav Sedov 
99*0daf62d9SStanislav Sedov /*
100*0daf62d9SStanislav Sedov  * Option flags.
101*0daf62d9SStanislav Sedov  */
102*0daf62d9SStanislav Sedov #define	UFLAG	0x01	/* -u flag: show users				*/
103*0daf62d9SStanislav Sedov #define	FFLAG	0x02	/* -f flag: specified files only		*/
104*0daf62d9SStanislav Sedov #define	CFLAG	0x04	/* -c flag: treat as mpoints			*/
105*0daf62d9SStanislav Sedov #define	MFLAG	0x10	/* -m flag: mmapped files too			*/
106*0daf62d9SStanislav Sedov #define	KFLAG	0x20	/* -k flag: send signal (SIGKILL by default)	*/
107*0daf62d9SStanislav Sedov 
108*0daf62d9SStanislav Sedov static int flags = 0;	/* Option flags. */
109*0daf62d9SStanislav Sedov 
110*0daf62d9SStanislav Sedov static void	printflags(struct consumer *consumer);
111*0daf62d9SStanislav Sedov static int	str2sig(const char *str);
112*0daf62d9SStanislav Sedov static void	usage(void) __dead2;
113*0daf62d9SStanislav Sedov static int	addfile(const char *path, struct reqfile *reqfile);
114*0daf62d9SStanislav Sedov static void	dofiles(struct procstat *procstat, struct kinfo_proc *kp,
115*0daf62d9SStanislav Sedov     struct reqfile *reqfiles, size_t nfiles);
116*0daf62d9SStanislav Sedov 
117*0daf62d9SStanislav Sedov static void
118*0daf62d9SStanislav Sedov usage(void)
119*0daf62d9SStanislav Sedov {
120*0daf62d9SStanislav Sedov 
121*0daf62d9SStanislav Sedov 	fprintf(stderr,
122*0daf62d9SStanislav Sedov "usage: fuser [-cfhkmu] [-M core] [-N system] [-s signal] file ...\n");
123*0daf62d9SStanislav Sedov 	exit(EX_USAGE);
124*0daf62d9SStanislav Sedov }
125*0daf62d9SStanislav Sedov 
126*0daf62d9SStanislav Sedov static void
127*0daf62d9SStanislav Sedov printflags(struct consumer *cons)
128*0daf62d9SStanislav Sedov {
129*0daf62d9SStanislav Sedov 	unsigned int i;
130*0daf62d9SStanislav Sedov 
131*0daf62d9SStanislav Sedov 	assert(cons);
132*0daf62d9SStanislav Sedov 	for (i = 0; i < NUFLAGS; i++)
133*0daf62d9SStanislav Sedov 		if ((cons->uflags & uflags[i].flag) != 0)
134*0daf62d9SStanislav Sedov 			fputc(uflags[i].ch, stderr);
135*0daf62d9SStanislav Sedov 	for (i = 0; i < NFFLAGS; i++)
136*0daf62d9SStanislav Sedov 		if ((cons->flags & fflags[i].flag) != 0)
137*0daf62d9SStanislav Sedov 			fputc(fflags[i].ch, stderr);
138*0daf62d9SStanislav Sedov }
139*0daf62d9SStanislav Sedov 
140*0daf62d9SStanislav Sedov /*
141*0daf62d9SStanislav Sedov  * Add file to the list.
142*0daf62d9SStanislav Sedov  */
143*0daf62d9SStanislav Sedov static int
144*0daf62d9SStanislav Sedov addfile(const char *path, struct reqfile *reqfile)
145*0daf62d9SStanislav Sedov {
146*0daf62d9SStanislav Sedov 	struct stat sb;
147*0daf62d9SStanislav Sedov 
148*0daf62d9SStanislav Sedov 	assert(path);
149*0daf62d9SStanislav Sedov 	if (stat(path, &sb) != 0) {
150*0daf62d9SStanislav Sedov 		warn("%s", path);
151*0daf62d9SStanislav Sedov 		return (1);
152*0daf62d9SStanislav Sedov 	}
153*0daf62d9SStanislav Sedov 	reqfile->fileid = sb.st_ino;
154*0daf62d9SStanislav Sedov 	reqfile->fsid = sb.st_dev;
155*0daf62d9SStanislav Sedov 	reqfile->name = path;
156*0daf62d9SStanislav Sedov 	STAILQ_INIT(&reqfile->consumers);
157*0daf62d9SStanislav Sedov 	return (0);
158*0daf62d9SStanislav Sedov }
159*0daf62d9SStanislav Sedov 
160*0daf62d9SStanislav Sedov int
161*0daf62d9SStanislav Sedov do_fuser(int argc, char *argv[])
162*0daf62d9SStanislav Sedov {
163*0daf62d9SStanislav Sedov 	struct consumer *consumer;
164*0daf62d9SStanislav Sedov 	struct kinfo_proc *p, *procs;
165*0daf62d9SStanislav Sedov 	struct procstat *procstat;
166*0daf62d9SStanislav Sedov 	struct reqfile *reqfiles;
167*0daf62d9SStanislav Sedov 	char *ep, *nlistf, *memf;
168*0daf62d9SStanislav Sedov 	int ch, cnt, sig;
169*0daf62d9SStanislav Sedov 	unsigned int i, nfiles;
170*0daf62d9SStanislav Sedov 
171*0daf62d9SStanislav Sedov 	sig = SIGKILL;	/* Default to kill. */
172*0daf62d9SStanislav Sedov 	nlistf = NULL;
173*0daf62d9SStanislav Sedov 	memf = NULL;
174*0daf62d9SStanislav Sedov 	while ((ch = getopt(argc, argv, "M:N:cfhkms:u")) != -1)
175*0daf62d9SStanislav Sedov 		switch(ch) {
176*0daf62d9SStanislav Sedov 		case 'f':
177*0daf62d9SStanislav Sedov 			if ((flags & CFLAG) != 0)
178*0daf62d9SStanislav Sedov 				usage();
179*0daf62d9SStanislav Sedov 			flags |= FFLAG;
180*0daf62d9SStanislav Sedov 			break;
181*0daf62d9SStanislav Sedov 		case 'c':
182*0daf62d9SStanislav Sedov 			if ((flags & FFLAG) != 0)
183*0daf62d9SStanislav Sedov 				usage();
184*0daf62d9SStanislav Sedov 			flags |= CFLAG;
185*0daf62d9SStanislav Sedov 			break;
186*0daf62d9SStanislav Sedov 		case 'N':
187*0daf62d9SStanislav Sedov 			nlistf = optarg;
188*0daf62d9SStanislav Sedov 			break;
189*0daf62d9SStanislav Sedov 		case 'M':
190*0daf62d9SStanislav Sedov 			memf = optarg;
191*0daf62d9SStanislav Sedov 			break;
192*0daf62d9SStanislav Sedov 		case 'u':
193*0daf62d9SStanislav Sedov 			flags |= UFLAG;
194*0daf62d9SStanislav Sedov 			break;
195*0daf62d9SStanislav Sedov 		case 'm':
196*0daf62d9SStanislav Sedov 			flags |= MFLAG;
197*0daf62d9SStanislav Sedov 			break;
198*0daf62d9SStanislav Sedov 		case 'k':
199*0daf62d9SStanislav Sedov 			flags |= KFLAG;
200*0daf62d9SStanislav Sedov 			break;
201*0daf62d9SStanislav Sedov 		case 's':
202*0daf62d9SStanislav Sedov 			if (isdigit(*optarg)) {
203*0daf62d9SStanislav Sedov 				sig = strtol(optarg, &ep, 10);
204*0daf62d9SStanislav Sedov 				if (*ep != '\0' || sig < 0 || sig >= sys_nsig)
205*0daf62d9SStanislav Sedov 					errx(EX_USAGE, "illegal signal number" ": %s",
206*0daf62d9SStanislav Sedov 					    optarg);
207*0daf62d9SStanislav Sedov 			} else {
208*0daf62d9SStanislav Sedov 				sig = str2sig(optarg);
209*0daf62d9SStanislav Sedov 				if (sig < 0)
210*0daf62d9SStanislav Sedov 					errx(EX_USAGE, "illegal signal name: "
211*0daf62d9SStanislav Sedov 					    "%s", optarg);
212*0daf62d9SStanislav Sedov 			}
213*0daf62d9SStanislav Sedov 			break;
214*0daf62d9SStanislav Sedov 		case 'h':
215*0daf62d9SStanislav Sedov 			/* PASSTHROUGH */
216*0daf62d9SStanislav Sedov 		default:
217*0daf62d9SStanislav Sedov 			usage();
218*0daf62d9SStanislav Sedov 			/* NORETURN */
219*0daf62d9SStanislav Sedov 		}
220*0daf62d9SStanislav Sedov 	argv += optind;
221*0daf62d9SStanislav Sedov 	argc -= optind;
222*0daf62d9SStanislav Sedov 
223*0daf62d9SStanislav Sedov 	assert(argc >= 0);
224*0daf62d9SStanislav Sedov 	if (argc == 0)
225*0daf62d9SStanislav Sedov 		usage();
226*0daf62d9SStanislav Sedov 		/* NORETURN */
227*0daf62d9SStanislav Sedov 
228*0daf62d9SStanislav Sedov 	/*
229*0daf62d9SStanislav Sedov 	 * Process named files.
230*0daf62d9SStanislav Sedov 	 */
231*0daf62d9SStanislav Sedov 	reqfiles = malloc(argc * sizeof(struct reqfile));
232*0daf62d9SStanislav Sedov 	if (reqfiles == NULL)
233*0daf62d9SStanislav Sedov 		err(EX_OSERR, "malloc()");
234*0daf62d9SStanislav Sedov 	nfiles = 0;
235*0daf62d9SStanislav Sedov 	while (argc--)
236*0daf62d9SStanislav Sedov 		if (!addfile(*(argv++), &reqfiles[nfiles]))
237*0daf62d9SStanislav Sedov 			nfiles++;
238*0daf62d9SStanislav Sedov 	if (nfiles == 0)
239*0daf62d9SStanislav Sedov 		errx(EX_IOERR, "files not accessible");
240*0daf62d9SStanislav Sedov 
241*0daf62d9SStanislav Sedov 	if (memf != NULL)
242*0daf62d9SStanislav Sedov 		procstat = procstat_open_kvm(nlistf, memf);
243*0daf62d9SStanislav Sedov 	else
244*0daf62d9SStanislav Sedov 		procstat = procstat_open_sysctl();
245*0daf62d9SStanislav Sedov 	if (procstat == NULL)
246*0daf62d9SStanislav Sedov 		errx(1, "procstat_open()");
247*0daf62d9SStanislav Sedov 	procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &cnt);
248*0daf62d9SStanislav Sedov 	if (procs == NULL)
249*0daf62d9SStanislav Sedov 		 errx(1, "procstat_getprocs()");
250*0daf62d9SStanislav Sedov 
251*0daf62d9SStanislav Sedov 	/*
252*0daf62d9SStanislav Sedov 	 * Walk through process table and look for matching files.
253*0daf62d9SStanislav Sedov 	 */
254*0daf62d9SStanislav Sedov 	p = procs;
255*0daf62d9SStanislav Sedov 	while(cnt--)
256*0daf62d9SStanislav Sedov 		if (p->ki_stat != SZOMB)
257*0daf62d9SStanislav Sedov 			dofiles(procstat, p++, reqfiles, nfiles);
258*0daf62d9SStanislav Sedov 
259*0daf62d9SStanislav Sedov 	for (i = 0; i < nfiles; i++) {
260*0daf62d9SStanislav Sedov 		fprintf(stderr, "%s:", reqfiles[i].name);
261*0daf62d9SStanislav Sedov 		fflush(stderr);
262*0daf62d9SStanislav Sedov 		STAILQ_FOREACH(consumer, &reqfiles[i].consumers, next) {
263*0daf62d9SStanislav Sedov 			if (consumer->flags != 0) {
264*0daf62d9SStanislav Sedov 				fprintf(stdout, "%6d", consumer->pid);
265*0daf62d9SStanislav Sedov 				fflush(stdout);
266*0daf62d9SStanislav Sedov 				printflags(consumer);
267*0daf62d9SStanislav Sedov 				if ((flags & UFLAG) != 0)
268*0daf62d9SStanislav Sedov 					fprintf(stderr, "(%s)",
269*0daf62d9SStanislav Sedov 					    user_from_uid(consumer->uid, 0));
270*0daf62d9SStanislav Sedov 				if ((flags & KFLAG) != 0)
271*0daf62d9SStanislav Sedov 					kill(consumer->pid, sig);
272*0daf62d9SStanislav Sedov 				fflush(stderr);
273*0daf62d9SStanislav Sedov 			}
274*0daf62d9SStanislav Sedov 		}
275*0daf62d9SStanislav Sedov 		(void)fprintf(stderr, "\n");
276*0daf62d9SStanislav Sedov 	}
277*0daf62d9SStanislav Sedov 	procstat_freeprocs(procstat, procs);
278*0daf62d9SStanislav Sedov 	procstat_close(procstat);
279*0daf62d9SStanislav Sedov 	free(reqfiles);
280*0daf62d9SStanislav Sedov 	return (0);
281*0daf62d9SStanislav Sedov }
282*0daf62d9SStanislav Sedov 
283*0daf62d9SStanislav Sedov static void
284*0daf62d9SStanislav Sedov dofiles(struct procstat *procstat, struct kinfo_proc *kp,
285*0daf62d9SStanislav Sedov     struct reqfile *reqfiles, size_t nfiles)
286*0daf62d9SStanislav Sedov {
287*0daf62d9SStanislav Sedov 	struct vnstat vn;
288*0daf62d9SStanislav Sedov 	struct consumer *cons;
289*0daf62d9SStanislav Sedov 	struct filestat *fst;
290*0daf62d9SStanislav Sedov 	struct filestat_list *head;
291*0daf62d9SStanislav Sedov 	int error, match;
292*0daf62d9SStanislav Sedov 	unsigned int i;
293*0daf62d9SStanislav Sedov 	char errbuf[_POSIX2_LINE_MAX];
294*0daf62d9SStanislav Sedov 
295*0daf62d9SStanislav Sedov 	head = procstat_getfiles(procstat, kp, flags & MFLAG);
296*0daf62d9SStanislav Sedov 	if (head == NULL)
297*0daf62d9SStanislav Sedov 		return;
298*0daf62d9SStanislav Sedov 	STAILQ_FOREACH(fst, head, next) {
299*0daf62d9SStanislav Sedov 		if (fst->fs_type != PS_FST_TYPE_VNODE)
300*0daf62d9SStanislav Sedov 			continue;
301*0daf62d9SStanislav Sedov 		error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
302*0daf62d9SStanislav Sedov 		if (error != 0)
303*0daf62d9SStanislav Sedov 			continue;
304*0daf62d9SStanislav Sedov 		for (i = 0; i < nfiles; i++) {
305*0daf62d9SStanislav Sedov 			if (flags & CFLAG && reqfiles[i].fsid == vn.vn_fsid) {
306*0daf62d9SStanislav Sedov 				break;
307*0daf62d9SStanislav Sedov 			}
308*0daf62d9SStanislav Sedov 			else if (reqfiles[i].fsid == vn.vn_fsid &&
309*0daf62d9SStanislav Sedov 			    reqfiles[i].fileid == vn.vn_fileid) {
310*0daf62d9SStanislav Sedov 				break;
311*0daf62d9SStanislav Sedov 			}
312*0daf62d9SStanislav Sedov 			else if (!(flags & FFLAG) &&
313*0daf62d9SStanislav Sedov 			    (vn.vn_type == PS_FST_VTYPE_VCHR ||
314*0daf62d9SStanislav Sedov 			    vn.vn_type == PS_FST_VTYPE_VBLK) &&
315*0daf62d9SStanislav Sedov 			    vn.vn_fsid == reqfiles[i].fileid) {
316*0daf62d9SStanislav Sedov 				break;
317*0daf62d9SStanislav Sedov 			}
318*0daf62d9SStanislav Sedov 		}
319*0daf62d9SStanislav Sedov 		if (i == nfiles)
320*0daf62d9SStanislav Sedov 			continue;	/* No match. */
321*0daf62d9SStanislav Sedov 
322*0daf62d9SStanislav Sedov 		/*
323*0daf62d9SStanislav Sedov 		 * Look for existing entries.
324*0daf62d9SStanislav Sedov 		 */
325*0daf62d9SStanislav Sedov 		match = 0;
326*0daf62d9SStanislav Sedov 		STAILQ_FOREACH(cons, &reqfiles[i].consumers, next)
327*0daf62d9SStanislav Sedov 			if (cons->pid == kp->ki_pid) {
328*0daf62d9SStanislav Sedov 				match = 1;
329*0daf62d9SStanislav Sedov 				break;
330*0daf62d9SStanislav Sedov 			}
331*0daf62d9SStanislav Sedov 		if (match == 1) {	/* Use old entry. */
332*0daf62d9SStanislav Sedov 			cons->flags |= fst->fs_fflags;
333*0daf62d9SStanislav Sedov 			cons->uflags |= fst->fs_uflags;
334*0daf62d9SStanislav Sedov 		} else {
335*0daf62d9SStanislav Sedov 			/*
336*0daf62d9SStanislav Sedov 			 * Create new entry in the consumer chain.
337*0daf62d9SStanislav Sedov 			 */
338*0daf62d9SStanislav Sedov 			cons = calloc(1, sizeof(struct consumer));
339*0daf62d9SStanislav Sedov 			if (cons == NULL) {
340*0daf62d9SStanislav Sedov 				warn("malloc()");
341*0daf62d9SStanislav Sedov 				continue;
342*0daf62d9SStanislav Sedov 			}
343*0daf62d9SStanislav Sedov 			cons->uid = kp->ki_uid;
344*0daf62d9SStanislav Sedov 			cons->pid = kp->ki_pid;
345*0daf62d9SStanislav Sedov 			cons->uflags = fst->fs_uflags;
346*0daf62d9SStanislav Sedov 			cons->flags = fst->fs_fflags;
347*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(&reqfiles[i].consumers, cons, next);
348*0daf62d9SStanislav Sedov 		}
349*0daf62d9SStanislav Sedov 	}
350*0daf62d9SStanislav Sedov 	procstat_freefiles(procstat, head);
351*0daf62d9SStanislav Sedov }
352*0daf62d9SStanislav Sedov 
353*0daf62d9SStanislav Sedov /*
354*0daf62d9SStanislav Sedov  * Returns signal number for it's string representation.
355*0daf62d9SStanislav Sedov  */
356*0daf62d9SStanislav Sedov static int
357*0daf62d9SStanislav Sedov str2sig(const char *str)
358*0daf62d9SStanislav Sedov {
359*0daf62d9SStanislav Sedov 	int i;
360*0daf62d9SStanislav Sedov 
361*0daf62d9SStanislav Sedov #define	SIGPREFIX	"sig"
362*0daf62d9SStanislav Sedov 	if (!strncasecmp(str, SIGPREFIX, sizeof(SIGPREFIX)))
363*0daf62d9SStanislav Sedov 		str += sizeof(SIGPREFIX);
364*0daf62d9SStanislav Sedov 	for (i = 1; i < sys_nsig; i++) {
365*0daf62d9SStanislav Sedov                 if (!strcasecmp(sys_signame[i], str))
366*0daf62d9SStanislav Sedov                         return (i);
367*0daf62d9SStanislav Sedov         }
368*0daf62d9SStanislav Sedov         return (-1);
369*0daf62d9SStanislav Sedov }
370