xref: /onnv-gate/usr/src/cmd/truss/listopts.c (revision 12789:82cffaae72d5)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53235Sraf  * Common Development and Distribution License (the "License").
63235Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
213235Sraf 
220Sstevel@tonic-gate /*
23*12789SRoger.Faulkner@Oracle.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <ctype.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <memory.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <signal.h>
370Sstevel@tonic-gate #include <libproc.h>
380Sstevel@tonic-gate #include "ramdata.h"
390Sstevel@tonic-gate #include "systable.h"
400Sstevel@tonic-gate #include "proto.h"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /* XXX A bug in the <string.h> header file requires this */
430Sstevel@tonic-gate extern char *strtok_r(char *s1, const char *s2, char **lasts);
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * option procesing ---
470Sstevel@tonic-gate  * Routines for scanning syscall, signal, fault
480Sstevel@tonic-gate  * and file descriptor lists.
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * Function prototypes for static routines in this module.
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate void	upcase(char *);
550Sstevel@tonic-gate 
560Sstevel@tonic-gate const char white[] = " \t\n";	/* white space characters */
570Sstevel@tonic-gate const char sepr[] = " ,\t\n";	/* list separator characters */
580Sstevel@tonic-gate const char csepr[] = " :,\t\n";	/* same, with ':' added */
590Sstevel@tonic-gate 
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate  * Scan list of syscall names.
620Sstevel@tonic-gate  * Return 0 on success, != 0 on any failure.
630Sstevel@tonic-gate  */
640Sstevel@tonic-gate int
syslist(char * str,sysset_t * setp,int * fp)650Sstevel@tonic-gate syslist(char *str,			/* string of syscall names */
660Sstevel@tonic-gate 	sysset_t *setp,			/* syscall set */
670Sstevel@tonic-gate 	int *fp)			/* first-time flag */
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	char *name;
700Sstevel@tonic-gate 	int exclude = FALSE;
710Sstevel@tonic-gate 	int rc = 0;
720Sstevel@tonic-gate 	char *lasts;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	name = strtok_r(str, sepr, &lasts);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (name != NULL && *name == '!') {	/* exclude from set */
770Sstevel@tonic-gate 		exclude = TRUE;
780Sstevel@tonic-gate 		if (*++name == '\0')
790Sstevel@tonic-gate 			name = strtok_r(NULL, sepr, &lasts);
800Sstevel@tonic-gate 	} else if (!*fp) {	/* first time, clear the set */
810Sstevel@tonic-gate 		premptyset(setp);
820Sstevel@tonic-gate 		*fp = TRUE;
830Sstevel@tonic-gate 	}
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
860Sstevel@tonic-gate 		int sys;
870Sstevel@tonic-gate 		int sysx;
883235Sraf 		int sysxx;
890Sstevel@tonic-gate 		int sys64;
900Sstevel@tonic-gate 		char *next;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 		if (*name == '!') {	/* exclude remainder from set */
930Sstevel@tonic-gate 			exclude = TRUE;
940Sstevel@tonic-gate 			while (*++name == '!')
950Sstevel@tonic-gate 				/* empty */;
960Sstevel@tonic-gate 			if (*name == '\0')
970Sstevel@tonic-gate 				continue;
980Sstevel@tonic-gate 		}
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 		sys = strtol(name, &next, 0);
1013235Sraf 		sysx = sysxx = sys64 = 0;
1020Sstevel@tonic-gate 		if (sys < 0 || sys > PRMAXSYS || *next != '\0')
1030Sstevel@tonic-gate 			sys = 0;
1040Sstevel@tonic-gate 		if (sys == 0) {
1050Sstevel@tonic-gate 			const struct systable *stp = systable;
1060Sstevel@tonic-gate 			for (; sys == 0 && stp->nargs >= 0; stp++)
1070Sstevel@tonic-gate 				if (stp->name && strcmp(stp->name, name) == 0)
1080Sstevel@tonic-gate 					sys = stp-systable;
1090Sstevel@tonic-gate 		}
1100Sstevel@tonic-gate 		if (sys == 0) {
1110Sstevel@tonic-gate 			const struct sysalias *sap = sysalias;
1120Sstevel@tonic-gate 			for (; sys == 0 && sap->name; sap++)
1130Sstevel@tonic-gate 				if (strcmp(sap->name, name) == 0)
1140Sstevel@tonic-gate 					sys = sap->number;
1150Sstevel@tonic-gate 		}
1160Sstevel@tonic-gate 		if (sys > 0 && sys <= PRMAXSYS) {
1170Sstevel@tonic-gate 			switch (sys) {
11811798SRoger.Faulkner@Sun.COM 			case SYS_fstatat:	/* set both if either */
11911798SRoger.Faulkner@Sun.COM 			case SYS_fstatat64:
12011798SRoger.Faulkner@Sun.COM 				sys = SYS_fstatat;
12111798SRoger.Faulkner@Sun.COM 				sys64 = SYS_fstatat64;
12211798SRoger.Faulkner@Sun.COM 				goto def;
12311798SRoger.Faulkner@Sun.COM 
12411798SRoger.Faulkner@Sun.COM 			case SYS_stat:		/* set all if either */
1250Sstevel@tonic-gate 			case SYS_stat64:
1260Sstevel@tonic-gate 				sys = SYS_stat;
1270Sstevel@tonic-gate 				sys64 = SYS_stat64;
12811798SRoger.Faulkner@Sun.COM 				sysx = SYS_fstatat;
12911798SRoger.Faulkner@Sun.COM 				sysxx = SYS_fstatat64;
1300Sstevel@tonic-gate 				goto def;
1310Sstevel@tonic-gate 
13211798SRoger.Faulkner@Sun.COM 			case SYS_lstat:		/* set all if either */
1330Sstevel@tonic-gate 			case SYS_lstat64:
1340Sstevel@tonic-gate 				sys = SYS_lstat;
1350Sstevel@tonic-gate 				sys64 = SYS_lstat64;
13611798SRoger.Faulkner@Sun.COM 				sysx = SYS_fstatat;
13711798SRoger.Faulkner@Sun.COM 				sysxx = SYS_fstatat64;
1380Sstevel@tonic-gate 				goto def;
1390Sstevel@tonic-gate 
14011798SRoger.Faulkner@Sun.COM 			case SYS_fstat:		/* set all if either */
1410Sstevel@tonic-gate 			case SYS_fstat64:
1420Sstevel@tonic-gate 				sys = SYS_fstat;
1430Sstevel@tonic-gate 				sys64 = SYS_fstat64;
14411798SRoger.Faulkner@Sun.COM 				sysx = SYS_fstatat;
14511798SRoger.Faulkner@Sun.COM 				sysxx = SYS_fstatat64;
1460Sstevel@tonic-gate 				goto def;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 			case SYS_getdents:	/* set both if either */
1490Sstevel@tonic-gate 			case SYS_getdents64:
1500Sstevel@tonic-gate 				sys = SYS_getdents;
1510Sstevel@tonic-gate 				sys64 = SYS_getdents64;
1520Sstevel@tonic-gate 				goto def;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 			case SYS_mmap:		/* set both if either */
1550Sstevel@tonic-gate 			case SYS_mmap64:
1560Sstevel@tonic-gate 				sys = SYS_mmap;
1570Sstevel@tonic-gate 				sys64 = SYS_mmap64;
1580Sstevel@tonic-gate 				goto def;
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 			case SYS_statvfs:	/* set both if either */
1610Sstevel@tonic-gate 			case SYS_statvfs64:
1620Sstevel@tonic-gate 				sys = SYS_statvfs;
1630Sstevel@tonic-gate 				sys64 = SYS_statvfs64;
1640Sstevel@tonic-gate 				goto def;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 			case SYS_fstatvfs:	/* set both if either */
1670Sstevel@tonic-gate 			case SYS_fstatvfs64:
1680Sstevel@tonic-gate 				sys = SYS_fstatvfs;
1690Sstevel@tonic-gate 				sys64 = SYS_fstatvfs64;
1700Sstevel@tonic-gate 				goto def;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 			case SYS_setrlimit:	/* set both if either */
1730Sstevel@tonic-gate 			case SYS_setrlimit64:
1740Sstevel@tonic-gate 				sys = SYS_setrlimit;
1750Sstevel@tonic-gate 				sys64 = SYS_setrlimit64;
1760Sstevel@tonic-gate 				goto def;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 			case SYS_getrlimit:	/* set both if either */
1790Sstevel@tonic-gate 			case SYS_getrlimit64:
1800Sstevel@tonic-gate 				sys = SYS_getrlimit;
1810Sstevel@tonic-gate 				sys64 = SYS_getrlimit64;
1820Sstevel@tonic-gate 				goto def;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 			case SYS_pread:		/* set both if either */
1850Sstevel@tonic-gate 			case SYS_pread64:
1860Sstevel@tonic-gate 				sys = SYS_pread;
1870Sstevel@tonic-gate 				sys64 = SYS_pread64;
1880Sstevel@tonic-gate 				goto def;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 			case SYS_pwrite:	/* set both if either */
1910Sstevel@tonic-gate 			case SYS_pwrite64:
1920Sstevel@tonic-gate 				sys = SYS_pwrite;
1930Sstevel@tonic-gate 				sys64 = SYS_pwrite64;
1940Sstevel@tonic-gate 				goto def;
1950Sstevel@tonic-gate 
19611798SRoger.Faulkner@Sun.COM 			case SYS_openat:	/* set all if any */
19711798SRoger.Faulkner@Sun.COM 			case SYS_openat64:
19811798SRoger.Faulkner@Sun.COM 			case SYS_open:
1990Sstevel@tonic-gate 			case SYS_open64:
20011798SRoger.Faulkner@Sun.COM 				sys = SYS_openat;
20111798SRoger.Faulkner@Sun.COM 				sys64 = SYS_openat64;
20211798SRoger.Faulkner@Sun.COM 				sysx = SYS_open;
20311798SRoger.Faulkner@Sun.COM 				sysxx = SYS_open64;
2040Sstevel@tonic-gate 				goto def;
2050Sstevel@tonic-gate 
20611798SRoger.Faulkner@Sun.COM 			case SYS_forksys:	/* set both if either */
2070Sstevel@tonic-gate 			case SYS_vfork:
20811798SRoger.Faulkner@Sun.COM 				sysx = SYS_forksys;
20911798SRoger.Faulkner@Sun.COM 				sys = SYS_vfork;
2100Sstevel@tonic-gate 				goto def;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 			case SYS_sigprocmask:	/* set both if either */
2130Sstevel@tonic-gate 			case SYS_lwp_sigmask:
2140Sstevel@tonic-gate 				sysx = SYS_sigprocmask;
2150Sstevel@tonic-gate 				sys = SYS_lwp_sigmask;
2160Sstevel@tonic-gate 				goto def;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 			case SYS_lseek:		/* set both if either */
2190Sstevel@tonic-gate 			case SYS_llseek:
2200Sstevel@tonic-gate 				sysx = SYS_lseek;
2210Sstevel@tonic-gate 				sys = SYS_llseek;
2220Sstevel@tonic-gate 				goto def;
2230Sstevel@tonic-gate 
22411798SRoger.Faulkner@Sun.COM 			case SYS_rename:	/* set both */
22511798SRoger.Faulkner@Sun.COM 				sysx = SYS_renameat;
22611798SRoger.Faulkner@Sun.COM 				goto def;
22711798SRoger.Faulkner@Sun.COM 
228*12789SRoger.Faulkner@Oracle.COM 			case SYS_link:		/* set both */
229*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_linkat;
23011798SRoger.Faulkner@Sun.COM 				goto def;
23111798SRoger.Faulkner@Sun.COM 
232*12789SRoger.Faulkner@Oracle.COM 			case SYS_unlink:	/* set both */
23311798SRoger.Faulkner@Sun.COM 			case SYS_rmdir:		/* set both */
23411798SRoger.Faulkner@Sun.COM 				sysx = SYS_unlinkat;
2350Sstevel@tonic-gate 				goto def;
2360Sstevel@tonic-gate 
237*12789SRoger.Faulkner@Oracle.COM 			case SYS_symlink:	/* set both */
238*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_symlinkat;
239*12789SRoger.Faulkner@Oracle.COM 				goto def;
240*12789SRoger.Faulkner@Oracle.COM 
241*12789SRoger.Faulkner@Oracle.COM 			case SYS_readlink:	/* set both */
242*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_readlinkat;
243*12789SRoger.Faulkner@Oracle.COM 				goto def;
244*12789SRoger.Faulkner@Oracle.COM 
245*12789SRoger.Faulkner@Oracle.COM 			case SYS_chmod:		/* set both */
246*12789SRoger.Faulkner@Oracle.COM 			case SYS_fchmod:	/* set both */
247*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_fchmodat;
248*12789SRoger.Faulkner@Oracle.COM 				goto def;
249*12789SRoger.Faulkner@Oracle.COM 
25011798SRoger.Faulkner@Sun.COM 			case SYS_chown:		/* set both */
251*12789SRoger.Faulkner@Oracle.COM 			case SYS_lchown:	/* set both */
252*12789SRoger.Faulkner@Oracle.COM 			case SYS_fchown:	/* set both */
25311798SRoger.Faulkner@Sun.COM 				sysx = SYS_fchownat;
25411798SRoger.Faulkner@Sun.COM 				goto def;
25511798SRoger.Faulkner@Sun.COM 
256*12789SRoger.Faulkner@Oracle.COM 			case SYS_mkdir:		/* set both */
257*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_mkdirat;
25811798SRoger.Faulkner@Sun.COM 				goto def;
25911798SRoger.Faulkner@Sun.COM 
260*12789SRoger.Faulkner@Oracle.COM 			case SYS_mknod:		/* set both */
261*12789SRoger.Faulkner@Oracle.COM 				sysx = SYS_mknodat;
26211798SRoger.Faulkner@Sun.COM 				goto def;
26311798SRoger.Faulkner@Sun.COM 
26411798SRoger.Faulkner@Sun.COM 			case SYS_access:	/* set both */
26511798SRoger.Faulkner@Sun.COM 				sysx = SYS_faccessat;
2660Sstevel@tonic-gate 				goto def;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 			default:
2690Sstevel@tonic-gate 			def:
2700Sstevel@tonic-gate 				if (exclude) {
2710Sstevel@tonic-gate 					prdelset(setp, sys);
2720Sstevel@tonic-gate 					if (sysx)
2730Sstevel@tonic-gate 						prdelset(setp, sysx);
2743235Sraf 					if (sysxx)
2753235Sraf 						prdelset(setp, sysxx);
2760Sstevel@tonic-gate 					if (sys64)
2770Sstevel@tonic-gate 						prdelset(setp, sys64);
2780Sstevel@tonic-gate 				} else {
2790Sstevel@tonic-gate 					praddset(setp, sys);
2800Sstevel@tonic-gate 					if (sysx)
2810Sstevel@tonic-gate 						praddset(setp, sysx);
2823235Sraf 					if (sysxx)
2833235Sraf 						praddset(setp, sysxx);
2840Sstevel@tonic-gate 					if (sys64)
2850Sstevel@tonic-gate 						praddset(setp, sys64);
2860Sstevel@tonic-gate 				}
2870Sstevel@tonic-gate 				break;
2880Sstevel@tonic-gate 			}
2890Sstevel@tonic-gate 		} else if (strcmp(name, "all") == 0 ||
2900Sstevel@tonic-gate 		    strcmp(name, "ALL") == 0) {
2910Sstevel@tonic-gate 			if (exclude) {
2920Sstevel@tonic-gate 				premptyset(setp);
2930Sstevel@tonic-gate 			} else {
2940Sstevel@tonic-gate 				prfillset(setp);
2950Sstevel@tonic-gate 			}
2960Sstevel@tonic-gate 		} else {
2970Sstevel@tonic-gate 			(void) fprintf(stderr,
2985891Sraf 			    "%s: unrecognized syscall: %s\n",
2995891Sraf 			    command, name);
3000Sstevel@tonic-gate 			rc = -1;
3010Sstevel@tonic-gate 		}
3020Sstevel@tonic-gate 	}
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	return (rc);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate  * List of signals to trace.
3090Sstevel@tonic-gate  * Return 0 on success, != 0 on any failure.
3100Sstevel@tonic-gate  */
3110Sstevel@tonic-gate int
siglist(private_t * pri,char * str,sigset_t * setp,int * fp)3120Sstevel@tonic-gate siglist(private_t *pri,
3130Sstevel@tonic-gate 	char *str,			/* string of signal names */
3140Sstevel@tonic-gate 	sigset_t *setp,			/* signal set */
3150Sstevel@tonic-gate 	int *fp)			/* first-time flag */
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate 	char *name;
3180Sstevel@tonic-gate 	int exclude = FALSE;
3190Sstevel@tonic-gate 	int rc = 0;
3200Sstevel@tonic-gate 	char *lasts;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	upcase(str);
3230Sstevel@tonic-gate 	name = strtok_r(str, sepr, &lasts);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	if (name != NULL && *name == '!') {	/* exclude from set */
3260Sstevel@tonic-gate 		exclude = TRUE;
3270Sstevel@tonic-gate 		if (*++name == '\0')
3280Sstevel@tonic-gate 			name = strtok_r(NULL, sepr, &lasts);
3290Sstevel@tonic-gate 	} else if (!*fp) {	/* first time, clear the set */
3300Sstevel@tonic-gate 		premptyset(setp);
3310Sstevel@tonic-gate 		*fp = TRUE;
3320Sstevel@tonic-gate 	}
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
3350Sstevel@tonic-gate 		int sig;
3360Sstevel@tonic-gate 		char *next;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 		if (*name == '!') {	/* exclude remainder from set */
3390Sstevel@tonic-gate 			exclude = TRUE;
3400Sstevel@tonic-gate 			while (*++name == '!')
3410Sstevel@tonic-gate 				/* empty */;
3420Sstevel@tonic-gate 			if (*name == '\0')
3430Sstevel@tonic-gate 				continue;
3440Sstevel@tonic-gate 		}
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 		sig = strtol(name, &next, 0);
3470Sstevel@tonic-gate 		if (sig <= 0 || sig > PRMAXSIG || *next != '\0') {
3480Sstevel@tonic-gate 			for (sig = 1; sig <= PRMAXSIG; sig++) {
3490Sstevel@tonic-gate 				const char *sname = rawsigname(pri, sig);
3500Sstevel@tonic-gate 				if (sname == NULL)
3510Sstevel@tonic-gate 					continue;
3520Sstevel@tonic-gate 				if (strcmp(sname, name) == 0 ||
3530Sstevel@tonic-gate 				    strcmp(sname+3, name) == 0)
3540Sstevel@tonic-gate 					break;
3550Sstevel@tonic-gate 			}
3560Sstevel@tonic-gate 			if (sig > PRMAXSIG)
3570Sstevel@tonic-gate 				sig = 0;
3580Sstevel@tonic-gate 		}
3590Sstevel@tonic-gate 		if (sig > 0 && sig <= PRMAXSIG) {
3600Sstevel@tonic-gate 			if (exclude) {
3610Sstevel@tonic-gate 				prdelset(setp, sig);
3620Sstevel@tonic-gate 			} else {
3630Sstevel@tonic-gate 				praddset(setp, sig);
3640Sstevel@tonic-gate 			}
3650Sstevel@tonic-gate 		} else if (strcmp(name, "ALL") == 0) {
3660Sstevel@tonic-gate 			if (exclude) {
3670Sstevel@tonic-gate 				premptyset(setp);
3680Sstevel@tonic-gate 			} else {
3690Sstevel@tonic-gate 				prfillset(setp);
3700Sstevel@tonic-gate 			}
3710Sstevel@tonic-gate 		} else {
3720Sstevel@tonic-gate 			(void) fprintf(stderr,
3735891Sraf 			    "%s: unrecognized signal name/number: %s\n",
3745891Sraf 			    command, name);
3750Sstevel@tonic-gate 			rc = -1;
3760Sstevel@tonic-gate 		}
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	return (rc);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate /*
3830Sstevel@tonic-gate  * List of faults to trace.
3840Sstevel@tonic-gate  * return 0 on success, != 0 on any failure.
3850Sstevel@tonic-gate  */
3860Sstevel@tonic-gate int
fltlist(char * str,fltset_t * setp,int * fp)3870Sstevel@tonic-gate fltlist(char *str,			/* string of fault names */
3880Sstevel@tonic-gate 	fltset_t *setp,			/* fault set */
3890Sstevel@tonic-gate 	int *fp)			/* first-time flag */
3900Sstevel@tonic-gate {
3910Sstevel@tonic-gate 	char *name;
3920Sstevel@tonic-gate 	int exclude = FALSE;
3930Sstevel@tonic-gate 	int rc = 0;
3940Sstevel@tonic-gate 	char *lasts;
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	upcase(str);
3970Sstevel@tonic-gate 	name = strtok_r(str, sepr, &lasts);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	if (name != NULL && *name == '!') {	/* exclude from set */
4000Sstevel@tonic-gate 		exclude = TRUE;
4010Sstevel@tonic-gate 		if (*++name == '\0')
4020Sstevel@tonic-gate 			name = strtok_r(NULL, sepr, &lasts);
4030Sstevel@tonic-gate 	} else if (!*fp) {	/* first time, clear the set */
4040Sstevel@tonic-gate 		premptyset(setp);
4050Sstevel@tonic-gate 		*fp = TRUE;
4060Sstevel@tonic-gate 	}
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
4090Sstevel@tonic-gate 		int flt;
4100Sstevel@tonic-gate 		char *next;
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		if (*name == '!') {	/* exclude remainder from set */
4130Sstevel@tonic-gate 			exclude = TRUE;
4140Sstevel@tonic-gate 			while (*++name == '!')
4150Sstevel@tonic-gate 				/* empty */;
4160Sstevel@tonic-gate 			if (*name == '\0')
4170Sstevel@tonic-gate 				continue;
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 		flt = strtol(name, &next, 0);
4210Sstevel@tonic-gate 		if (flt <= 0 || flt > PRMAXFAULT || *next != '\0') {
4220Sstevel@tonic-gate 			for (flt = 1; flt <= PRMAXFAULT; flt++) {
4230Sstevel@tonic-gate 				char fname[32];
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 				if (proc_fltname(flt, fname,
4260Sstevel@tonic-gate 				    sizeof (fname)) == NULL)
4270Sstevel@tonic-gate 					continue;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 				if (strcmp(fname, name) == 0 ||
4300Sstevel@tonic-gate 				    strcmp(fname+3, name) == 0)
4310Sstevel@tonic-gate 					break;
4320Sstevel@tonic-gate 			}
4330Sstevel@tonic-gate 			if (flt > PRMAXFAULT)
4340Sstevel@tonic-gate 				flt = 0;
4350Sstevel@tonic-gate 		}
4360Sstevel@tonic-gate 		if (flt > 0 && flt <= PRMAXFAULT) {
4370Sstevel@tonic-gate 			if (exclude) {
4380Sstevel@tonic-gate 				prdelset(setp, flt);
4390Sstevel@tonic-gate 			} else {
4400Sstevel@tonic-gate 				praddset(setp, flt);
4410Sstevel@tonic-gate 			}
4420Sstevel@tonic-gate 		} else if (strcmp(name, "ALL") == 0) {
4430Sstevel@tonic-gate 			if (exclude) {
4440Sstevel@tonic-gate 				premptyset(setp);
4450Sstevel@tonic-gate 			} else {
4460Sstevel@tonic-gate 				prfillset(setp);
4470Sstevel@tonic-gate 			}
4480Sstevel@tonic-gate 		} else {
4490Sstevel@tonic-gate 			(void) fprintf(stderr,
4505891Sraf 			    "%s: unrecognized fault name/number: %s\n",
4515891Sraf 			    command, name);
4520Sstevel@tonic-gate 			rc = -1;
4530Sstevel@tonic-gate 		}
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	return (rc);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate /*
4600Sstevel@tonic-gate  * Gather file descriptors to dump.
4610Sstevel@tonic-gate  * Return 0 on success, != 0 on any failure.
4620Sstevel@tonic-gate  */
4630Sstevel@tonic-gate int
fdlist(char * str,fileset_t * setp)4640Sstevel@tonic-gate fdlist(char *str,		/* string of filedescriptors */
4650Sstevel@tonic-gate 	fileset_t *setp)	/* set of boolean flags */
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate 	char *name;
4680Sstevel@tonic-gate 	int exclude = FALSE;
4690Sstevel@tonic-gate 	int rc = 0;
4700Sstevel@tonic-gate 	char *lasts;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	upcase(str);
4730Sstevel@tonic-gate 	name = strtok_r(str, sepr, &lasts);
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	if (name != NULL && *name == '!') {	/* exclude from set */
4760Sstevel@tonic-gate 		exclude = TRUE;
4770Sstevel@tonic-gate 		if (*++name == '\0')
4780Sstevel@tonic-gate 			name = strtok_r(NULL, sepr, &lasts);
4790Sstevel@tonic-gate 	}
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
4820Sstevel@tonic-gate 		int fd;
4830Sstevel@tonic-gate 		char *next;
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 		if (*name == '!') {	/* exclude remainder from set */
4860Sstevel@tonic-gate 			exclude = TRUE;
4870Sstevel@tonic-gate 			while (*++name == '!')
4880Sstevel@tonic-gate 				/* empty */;
4890Sstevel@tonic-gate 			if (*name == '\0')
4900Sstevel@tonic-gate 				continue;
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 		fd = strtol(name, &next, 0);
4940Sstevel@tonic-gate 		if (fd >= 0 && fd < NOFILES_MAX && *next == '\0') {
4950Sstevel@tonic-gate 			fd++;
4960Sstevel@tonic-gate 			if (exclude) {
4970Sstevel@tonic-gate 				prdelset(setp, fd);
4980Sstevel@tonic-gate 			} else {
4990Sstevel@tonic-gate 				praddset(setp, fd);
5000Sstevel@tonic-gate 			}
5010Sstevel@tonic-gate 		} else if (strcmp(name, "ALL") == 0) {
5020Sstevel@tonic-gate 			if (exclude) {
5030Sstevel@tonic-gate 				premptyset(setp);
5040Sstevel@tonic-gate 			} else {
5050Sstevel@tonic-gate 				prfillset(setp);
5060Sstevel@tonic-gate 			}
5070Sstevel@tonic-gate 		} else {
5080Sstevel@tonic-gate 			(void) fprintf(stderr,
5095891Sraf 			    "%s: filedescriptor not in range[0..%d]: %s\n",
5105891Sraf 			    command, NOFILES_MAX-1, name);
5110Sstevel@tonic-gate 			rc = -1;
5120Sstevel@tonic-gate 		}
5130Sstevel@tonic-gate 	}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	return (rc);
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate void
upcase(char * str)5190Sstevel@tonic-gate upcase(char *str)
5200Sstevel@tonic-gate {
5210Sstevel@tonic-gate 	int c;
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	while ((c = *str) != '\0')
5240Sstevel@tonic-gate 		*str++ = toupper(c);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate /*
5280Sstevel@tonic-gate  * 'arg' points to a string like:
5290Sstevel@tonic-gate  *	libc,libnsl,... : printf,read,write,...
5300Sstevel@tonic-gate  * or
5310Sstevel@tonic-gate  *	libc,libnsl,... :: printf,read,write,...
5320Sstevel@tonic-gate  * with possible filename pattern-matching metacharacters.
5330Sstevel@tonic-gate  *
5340Sstevel@tonic-gate  * Assumption:  No library or function name can contain ',' or ':'.
5350Sstevel@tonic-gate  */
5360Sstevel@tonic-gate int
liblist(char * arg,int hang)5370Sstevel@tonic-gate liblist(char *arg, int hang)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 	const char *star = "*";
5400Sstevel@tonic-gate 	struct dynpat *Dyp;
5410Sstevel@tonic-gate 	char *pat;
5420Sstevel@tonic-gate 	char *fpat;
5430Sstevel@tonic-gate 	char *lasts;
5440Sstevel@tonic-gate 	uint_t maxpat;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	/* append a new dynpat structure to the end of the Dynpat list */
5470Sstevel@tonic-gate 	Dyp = my_malloc(sizeof (struct dynpat), NULL);
5480Sstevel@tonic-gate 	Dyp->next = NULL;
5490Sstevel@tonic-gate 	if (Lastpat == NULL)
5500Sstevel@tonic-gate 		Dynpat = Lastpat = Dyp;
5510Sstevel@tonic-gate 	else {
5520Sstevel@tonic-gate 		Lastpat->next = Dyp;
5530Sstevel@tonic-gate 		Lastpat = Dyp;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 	Dyp->flag = hang? BPT_HANG : 0;
5560Sstevel@tonic-gate 	Dyp->exclude_lib = 0;
5570Sstevel@tonic-gate 	Dyp->exclude = 0;
5580Sstevel@tonic-gate 	Dyp->internal = 0;
5590Sstevel@tonic-gate 	Dyp->Dp = NULL;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	/*
5620Sstevel@tonic-gate 	 * Find the beginning of the filename patterns
5630Sstevel@tonic-gate 	 * and null-terminate the library name patterns.
5640Sstevel@tonic-gate 	 */
5650Sstevel@tonic-gate 	if ((fpat = strchr(arg, ':')) != NULL)
5660Sstevel@tonic-gate 		*fpat++ = '\0';
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/*
5690Sstevel@tonic-gate 	 * Library name patterns.
5700Sstevel@tonic-gate 	 */
5710Sstevel@tonic-gate 	pat = strtok_r(arg, sepr, &lasts);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	/* '!' introduces an exclusion list */
5740Sstevel@tonic-gate 	if (pat != NULL && *pat == '!') {
5750Sstevel@tonic-gate 		Dyp->exclude_lib = 1;
5760Sstevel@tonic-gate 		pat += strspn(pat, "!");
5770Sstevel@tonic-gate 		if (*pat == '\0')
5780Sstevel@tonic-gate 			pat = strtok_r(NULL, sepr, &lasts);
5790Sstevel@tonic-gate 		/* force exclusion of all functions as well */
5800Sstevel@tonic-gate 		Dyp->exclude = 1;
5810Sstevel@tonic-gate 		Dyp->internal = 1;
5820Sstevel@tonic-gate 		fpat = NULL;
5830Sstevel@tonic-gate 	}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	if (pat == NULL) {
5860Sstevel@tonic-gate 		/* empty list means all libraries */
5870Sstevel@tonic-gate 		Dyp->libpat = my_malloc(sizeof (char *), NULL);
5880Sstevel@tonic-gate 		Dyp->libpat[0] = star;
5890Sstevel@tonic-gate 		Dyp->nlibpat = 1;
5900Sstevel@tonic-gate 	} else {
5910Sstevel@tonic-gate 		/*
5920Sstevel@tonic-gate 		 * We are now at the library list.
5930Sstevel@tonic-gate 		 * Generate the list and count the library name patterns.
5940Sstevel@tonic-gate 		 */
5950Sstevel@tonic-gate 		maxpat = 1;
5960Sstevel@tonic-gate 		Dyp->libpat = my_malloc(maxpat * sizeof (char *), NULL);
5970Sstevel@tonic-gate 		Dyp->nlibpat = 0;
5980Sstevel@tonic-gate 		Dyp->libpat[Dyp->nlibpat++] = pat;
5990Sstevel@tonic-gate 		while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
6000Sstevel@tonic-gate 			if (Dyp->nlibpat == maxpat) {
6010Sstevel@tonic-gate 				maxpat *= 2;
6020Sstevel@tonic-gate 				Dyp->libpat = my_realloc(Dyp->libpat,
6035891Sraf 				    maxpat * sizeof (char *), NULL);
6040Sstevel@tonic-gate 			}
6050Sstevel@tonic-gate 			Dyp->libpat[Dyp->nlibpat++] = pat;
6060Sstevel@tonic-gate 		}
6070Sstevel@tonic-gate 	}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	/*
6100Sstevel@tonic-gate 	 * Function name patterns.
6110Sstevel@tonic-gate 	 */
6120Sstevel@tonic-gate 	if (fpat == NULL)
6130Sstevel@tonic-gate 		pat = NULL;
6140Sstevel@tonic-gate 	else {
6150Sstevel@tonic-gate 		/*
6160Sstevel@tonic-gate 		 * We have already seen a ':'.  Look for another.
6170Sstevel@tonic-gate 		 * Double ':' means trace internal calls.
6180Sstevel@tonic-gate 		 */
6190Sstevel@tonic-gate 		fpat += strspn(fpat, white);
6200Sstevel@tonic-gate 		if (*fpat == ':') {
6210Sstevel@tonic-gate 			Dyp->internal = 1;
6220Sstevel@tonic-gate 			*fpat++ = '\0';
6230Sstevel@tonic-gate 		}
6240Sstevel@tonic-gate 		pat = strtok_r(fpat, csepr, &lasts);
6250Sstevel@tonic-gate 	}
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	/* '!' introduces an exclusion list */
6280Sstevel@tonic-gate 	if (pat != NULL && *pat == '!') {
6290Sstevel@tonic-gate 		Dyp->exclude = 1;
6300Sstevel@tonic-gate 		Dyp->internal = 1;
6310Sstevel@tonic-gate 		pat += strspn(pat, "!");
6320Sstevel@tonic-gate 		if (*pat == '\0')
6330Sstevel@tonic-gate 			pat = strtok_r(NULL, sepr, &lasts);
6340Sstevel@tonic-gate 	}
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	if (pat == NULL) {
6370Sstevel@tonic-gate 		/* empty function list means exclude all functions */
6380Sstevel@tonic-gate 		Dyp->sympat = my_malloc(sizeof (char *), NULL);
6390Sstevel@tonic-gate 		Dyp->sympat[0] = star;
6400Sstevel@tonic-gate 		Dyp->nsympat = 1;
6410Sstevel@tonic-gate 	} else {
6420Sstevel@tonic-gate 		/*
6430Sstevel@tonic-gate 		 * We are now at the function list.
6440Sstevel@tonic-gate 		 * Generate the list and count the symbol name patterns.
6450Sstevel@tonic-gate 		 */
6460Sstevel@tonic-gate 		maxpat = 1;
6470Sstevel@tonic-gate 		Dyp->sympat = my_malloc(maxpat * sizeof (char *), NULL);
6480Sstevel@tonic-gate 		Dyp->nsympat = 0;
6490Sstevel@tonic-gate 		Dyp->sympat[Dyp->nsympat++] = pat;
6500Sstevel@tonic-gate 		while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
6510Sstevel@tonic-gate 			if (Dyp->nsympat == maxpat) {
6520Sstevel@tonic-gate 				maxpat *= 2;
6530Sstevel@tonic-gate 				Dyp->sympat = my_realloc(Dyp->sympat,
6545891Sraf 				    maxpat * sizeof (char *), NULL);
6550Sstevel@tonic-gate 			}
6560Sstevel@tonic-gate 			Dyp->sympat[Dyp->nsympat++] = pat;
6570Sstevel@tonic-gate 		}
6580Sstevel@tonic-gate 	}
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	return (0);
6610Sstevel@tonic-gate }
662