Home | History | Annotate | Download | only in truss
      1     0  stevel /*
      2     0  stevel  * CDDL HEADER START
      3     0  stevel  *
      4     0  stevel  * The contents of this file are subject to the terms of the
      5  3235     raf  * Common Development and Distribution License (the "License").
      6  3235     raf  * You may not use this file except in compliance with the License.
      7     0  stevel  *
      8     0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0  stevel  * or http://www.opensolaris.org/os/licensing.
     10     0  stevel  * See the License for the specific language governing permissions
     11     0  stevel  * and limitations under the License.
     12     0  stevel  *
     13     0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0  stevel  *
     19     0  stevel  * CDDL HEADER END
     20     0  stevel  */
     21  3235     raf 
     22     0  stevel /*
     23  5891     raf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24     0  stevel  * Use is subject to license terms.
     25     0  stevel  */
     26     0  stevel 
     27     0  stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28     0  stevel /*	  All Rights Reserved  	*/
     29     0  stevel 
     30     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2	*/
     31     0  stevel 
     32     0  stevel #include <stdio.h>
     33     0  stevel #include <stdlib.h>
     34     0  stevel #include <unistd.h>
     35     0  stevel #include <ctype.h>
     36     0  stevel #include <string.h>
     37     0  stevel #include <memory.h>
     38     0  stevel #include <sys/types.h>
     39     0  stevel #include <signal.h>
     40     0  stevel #include <libproc.h>
     41     0  stevel #include "ramdata.h"
     42     0  stevel #include "systable.h"
     43     0  stevel #include "proto.h"
     44     0  stevel 
     45     0  stevel /* XXX A bug in the <string.h> header file requires this */
     46     0  stevel extern char *strtok_r(char *s1, const char *s2, char **lasts);
     47     0  stevel 
     48     0  stevel /*
     49     0  stevel  * option procesing ---
     50     0  stevel  * Routines for scanning syscall, signal, fault
     51     0  stevel  * and file descriptor lists.
     52     0  stevel  */
     53     0  stevel 
     54     0  stevel /*
     55     0  stevel  * Function prototypes for static routines in this module.
     56     0  stevel  */
     57     0  stevel void	upcase(char *);
     58     0  stevel 
     59     0  stevel const char white[] = " \t\n";	/* white space characters */
     60     0  stevel const char sepr[] = " ,\t\n";	/* list separator characters */
     61     0  stevel const char csepr[] = " :,\t\n";	/* same, with ':' added */
     62     0  stevel 
     63     0  stevel /*
     64     0  stevel  * Scan list of syscall names.
     65     0  stevel  * Return 0 on success, != 0 on any failure.
     66     0  stevel  */
     67     0  stevel int
     68     0  stevel syslist(char *str,			/* string of syscall names */
     69     0  stevel 	sysset_t *setp,			/* syscall set */
     70     0  stevel 	int *fp)			/* first-time flag */
     71     0  stevel {
     72     0  stevel 	char *name;
     73     0  stevel 	int exclude = FALSE;
     74     0  stevel 	int rc = 0;
     75     0  stevel 	char *lasts;
     76     0  stevel 
     77     0  stevel 	name = strtok_r(str, sepr, &lasts);
     78     0  stevel 
     79     0  stevel 	if (name != NULL && *name == '!') {	/* exclude from set */
     80     0  stevel 		exclude = TRUE;
     81     0  stevel 		if (*++name == '\0')
     82     0  stevel 			name = strtok_r(NULL, sepr, &lasts);
     83     0  stevel 	} else if (!*fp) {	/* first time, clear the set */
     84     0  stevel 		premptyset(setp);
     85     0  stevel 		*fp = TRUE;
     86     0  stevel 	}
     87     0  stevel 
     88     0  stevel 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
     89     0  stevel 		int sys;
     90     0  stevel 		int sysx;
     91  3235     raf 		int sysxx;
     92     0  stevel 		int sys64;
     93     0  stevel 		char *next;
     94     0  stevel 
     95     0  stevel 		if (*name == '!') {	/* exclude remainder from set */
     96     0  stevel 			exclude = TRUE;
     97     0  stevel 			while (*++name == '!')
     98     0  stevel 				/* empty */;
     99     0  stevel 			if (*name == '\0')
    100     0  stevel 				continue;
    101     0  stevel 		}
    102     0  stevel 
    103     0  stevel 		sys = strtol(name, &next, 0);
    104  3235     raf 		sysx = sysxx = sys64 = 0;
    105     0  stevel 		if (sys < 0 || sys > PRMAXSYS || *next != '\0')
    106     0  stevel 			sys = 0;
    107     0  stevel 		if (sys == 0) {
    108     0  stevel 			const struct systable *stp = systable;
    109     0  stevel 			for (; sys == 0 && stp->nargs >= 0; stp++)
    110     0  stevel 				if (stp->name && strcmp(stp->name, name) == 0)
    111     0  stevel 					sys = stp-systable;
    112     0  stevel 		}
    113     0  stevel 		if (sys == 0) {
    114     0  stevel 			const struct sysalias *sap = sysalias;
    115     0  stevel 			for (; sys == 0 && sap->name; sap++)
    116     0  stevel 				if (strcmp(sap->name, name) == 0)
    117     0  stevel 					sys = sap->number;
    118     0  stevel 		}
    119     0  stevel 		if (sys > 0 && sys <= PRMAXSYS) {
    120     0  stevel 			switch (sys) {
    121     0  stevel 			case SYS_xstat:		/* set all if any */
    122     0  stevel 			case SYS_stat:
    123     0  stevel 			case SYS_stat64:
    124     0  stevel 				sys = SYS_stat;
    125     0  stevel 				sysx = SYS_xstat;
    126     0  stevel 				sys64 = SYS_stat64;
    127     0  stevel 				goto def;
    128     0  stevel 
    129     0  stevel 			case SYS_lxstat:	/* set all if any */
    130     0  stevel 			case SYS_lstat:
    131     0  stevel 			case SYS_lstat64:
    132     0  stevel 				sys = SYS_lstat;
    133     0  stevel 				sysx = SYS_lxstat;
    134     0  stevel 				sys64 = SYS_lstat64;
    135     0  stevel 				goto def;
    136     0  stevel 
    137     0  stevel 			case SYS_fxstat:	/* set all if any */
    138     0  stevel 			case SYS_fstat:
    139     0  stevel 			case SYS_fstat64:
    140     0  stevel 				sys = SYS_fstat;
    141     0  stevel 				sysx = SYS_fxstat;
    142     0  stevel 				sys64 = SYS_fstat64;
    143     0  stevel 				goto def;
    144     0  stevel 
    145     0  stevel 			case SYS_getdents:	/* set both if either */
    146     0  stevel 			case SYS_getdents64:
    147     0  stevel 				sys = SYS_getdents;
    148     0  stevel 				sys64 = SYS_getdents64;
    149     0  stevel 				goto def;
    150     0  stevel 
    151     0  stevel 			case SYS_mmap:		/* set both if either */
    152     0  stevel 			case SYS_mmap64:
    153     0  stevel 				sys = SYS_mmap;
    154     0  stevel 				sys64 = SYS_mmap64;
    155     0  stevel 				goto def;
    156     0  stevel 
    157     0  stevel 			case SYS_statvfs:	/* set both if either */
    158     0  stevel 			case SYS_statvfs64:
    159     0  stevel 				sys = SYS_statvfs;
    160     0  stevel 				sys64 = SYS_statvfs64;
    161     0  stevel 				goto def;
    162     0  stevel 
    163     0  stevel 			case SYS_fstatvfs:	/* set both if either */
    164     0  stevel 			case SYS_fstatvfs64:
    165     0  stevel 				sys = SYS_fstatvfs;
    166     0  stevel 				sys64 = SYS_fstatvfs64;
    167     0  stevel 				goto def;
    168     0  stevel 
    169     0  stevel 			case SYS_setrlimit:	/* set both if either */
    170     0  stevel 			case SYS_setrlimit64:
    171     0  stevel 				sys = SYS_setrlimit;
    172     0  stevel 				sys64 = SYS_setrlimit64;
    173     0  stevel 				goto def;
    174     0  stevel 
    175     0  stevel 			case SYS_getrlimit:	/* set both if either */
    176     0  stevel 			case SYS_getrlimit64:
    177     0  stevel 				sys = SYS_getrlimit;
    178     0  stevel 				sys64 = SYS_getrlimit64;
    179     0  stevel 				goto def;
    180     0  stevel 
    181     0  stevel 			case SYS_pread:		/* set both if either */
    182     0  stevel 			case SYS_pread64:
    183     0  stevel 				sys = SYS_pread;
    184     0  stevel 				sys64 = SYS_pread64;
    185     0  stevel 				goto def;
    186     0  stevel 
    187     0  stevel 			case SYS_pwrite:	/* set both if either */
    188     0  stevel 			case SYS_pwrite64:
    189     0  stevel 				sys = SYS_pwrite;
    190     0  stevel 				sys64 = SYS_pwrite64;
    191     0  stevel 				goto def;
    192     0  stevel 
    193     0  stevel 			case SYS_creat:		/* set both if either */
    194     0  stevel 			case SYS_creat64:
    195     0  stevel 				sys = SYS_creat;
    196     0  stevel 				sys64 = SYS_creat64;
    197     0  stevel 				goto def;
    198     0  stevel 
    199     0  stevel 			case SYS_open:		/* set both if either */
    200     0  stevel 			case SYS_open64:
    201     0  stevel 				sys = SYS_open;
    202     0  stevel 				sys64 = SYS_open64;
    203     0  stevel 				goto def;
    204     0  stevel 
    205     0  stevel 			case SYS_xmknod:	/* set both if either */
    206     0  stevel 			case SYS_mknod:
    207     0  stevel 				sysx = SYS_xmknod;
    208     0  stevel 				sys = SYS_mknod;
    209     0  stevel 				goto def;
    210     0  stevel 
    211     0  stevel 			case SYS_forkall:	/* set all if any */
    212     0  stevel 			case SYS_fork1:
    213     0  stevel 			case SYS_vfork:
    214  3235     raf 			case SYS_forksys:
    215     0  stevel 				sys = SYS_forkall;
    216     0  stevel 				sysx = SYS_fork1;
    217     0  stevel 				sys64 = SYS_vfork;
    218  3235     raf 				sysxx = SYS_forksys;
    219     0  stevel 				goto def;
    220     0  stevel 
    221     0  stevel 			case SYS_exec:		/* set both if either */
    222     0  stevel 			case SYS_execve:
    223     0  stevel 				sysx = SYS_exec;
    224     0  stevel 				sys = SYS_execve;
    225     0  stevel 				goto def;
    226     0  stevel 
    227     0  stevel 			case SYS_poll:		/* set both if either */
    228     0  stevel 			case SYS_pollsys:
    229     0  stevel 				sysx = SYS_poll;
    230     0  stevel 				sys = SYS_pollsys;
    231     0  stevel 				goto def;
    232     0  stevel 
    233     0  stevel 			case SYS_sigprocmask:	/* set both if either */
    234     0  stevel 			case SYS_lwp_sigmask:
    235     0  stevel 				sysx = SYS_sigprocmask;
    236     0  stevel 				sys = SYS_lwp_sigmask;
    237     0  stevel 				goto def;
    238     0  stevel 
    239     0  stevel 			case SYS_wait:		/* set both if either */
    240  5891     raf 			case SYS_waitid:
    241     0  stevel 				sysx = SYS_wait;
    242  5891     raf 				sys = SYS_waitid;
    243     0  stevel 				goto def;
    244     0  stevel 
    245     0  stevel 			case SYS_lseek:		/* set both if either */
    246     0  stevel 			case SYS_llseek:
    247     0  stevel 				sysx = SYS_lseek;
    248     0  stevel 				sys = SYS_llseek;
    249     0  stevel 				goto def;
    250     0  stevel 
    251     0  stevel 			case SYS_lwp_mutex_lock: /* set both if either */
    252     0  stevel 			case SYS_lwp_mutex_timedlock:
    253     0  stevel 				sysx = SYS_lwp_mutex_lock;
    254     0  stevel 				sys = SYS_lwp_mutex_timedlock;
    255     0  stevel 				goto def;
    256     0  stevel 
    257     0  stevel 			case SYS_lwp_sema_wait: /* set both if either */
    258     0  stevel 			case SYS_lwp_sema_timedwait:
    259     0  stevel 				sysx = SYS_lwp_sema_wait;
    260     0  stevel 				sys = SYS_lwp_sema_timedwait;
    261     0  stevel 				goto def;
    262     0  stevel 
    263     0  stevel 			default:
    264     0  stevel 			def:
    265     0  stevel 				if (exclude) {
    266     0  stevel 					prdelset(setp, sys);
    267     0  stevel 					if (sysx)
    268     0  stevel 						prdelset(setp, sysx);
    269  3235     raf 					if (sysxx)
    270  3235     raf 						prdelset(setp, sysxx);
    271     0  stevel 					if (sys64)
    272     0  stevel 						prdelset(setp, sys64);
    273     0  stevel 				} else {
    274     0  stevel 					praddset(setp, sys);
    275     0  stevel 					if (sysx)
    276     0  stevel 						praddset(setp, sysx);
    277  3235     raf 					if (sysxx)
    278  3235     raf 						praddset(setp, sysxx);
    279     0  stevel 					if (sys64)
    280     0  stevel 						praddset(setp, sys64);
    281     0  stevel 				}
    282     0  stevel 				break;
    283     0  stevel 			}
    284     0  stevel 		} else if (strcmp(name, "all") == 0 ||
    285     0  stevel 		    strcmp(name, "ALL") == 0) {
    286     0  stevel 			if (exclude) {
    287     0  stevel 				premptyset(setp);
    288     0  stevel 			} else {
    289     0  stevel 				prfillset(setp);
    290     0  stevel 			}
    291     0  stevel 		} else {
    292     0  stevel 			(void) fprintf(stderr,
    293  5891     raf 			    "%s: unrecognized syscall: %s\n",
    294  5891     raf 			    command, name);
    295     0  stevel 			rc = -1;
    296     0  stevel 		}
    297     0  stevel 	}
    298     0  stevel 
    299     0  stevel 	return (rc);
    300     0  stevel }
    301     0  stevel 
    302     0  stevel /*
    303     0  stevel  * List of signals to trace.
    304     0  stevel  * Return 0 on success, != 0 on any failure.
    305     0  stevel  */
    306     0  stevel int
    307     0  stevel siglist(private_t *pri,
    308     0  stevel 	char *str,			/* string of signal names */
    309     0  stevel 	sigset_t *setp,			/* signal set */
    310     0  stevel 	int *fp)			/* first-time flag */
    311     0  stevel {
    312     0  stevel 	char *name;
    313     0  stevel 	int exclude = FALSE;
    314     0  stevel 	int rc = 0;
    315     0  stevel 	char *lasts;
    316     0  stevel 
    317     0  stevel 	upcase(str);
    318     0  stevel 	name = strtok_r(str, sepr, &lasts);
    319     0  stevel 
    320     0  stevel 	if (name != NULL && *name == '!') {	/* exclude from set */
    321     0  stevel 		exclude = TRUE;
    322     0  stevel 		if (*++name == '\0')
    323     0  stevel 			name = strtok_r(NULL, sepr, &lasts);
    324     0  stevel 	} else if (!*fp) {	/* first time, clear the set */
    325     0  stevel 		premptyset(setp);
    326     0  stevel 		*fp = TRUE;
    327     0  stevel 	}
    328     0  stevel 
    329     0  stevel 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
    330     0  stevel 		int sig;
    331     0  stevel 		char *next;
    332     0  stevel 
    333     0  stevel 		if (*name == '!') {	/* exclude remainder from set */
    334     0  stevel 			exclude = TRUE;
    335     0  stevel 			while (*++name == '!')
    336     0  stevel 				/* empty */;
    337     0  stevel 			if (*name == '\0')
    338     0  stevel 				continue;
    339     0  stevel 		}
    340     0  stevel 
    341     0  stevel 		sig = strtol(name, &next, 0);
    342     0  stevel 		if (sig <= 0 || sig > PRMAXSIG || *next != '\0') {
    343     0  stevel 			for (sig = 1; sig <= PRMAXSIG; sig++) {
    344     0  stevel 				const char *sname = rawsigname(pri, sig);
    345     0  stevel 				if (sname == NULL)
    346     0  stevel 					continue;
    347     0  stevel 				if (strcmp(sname, name) == 0 ||
    348     0  stevel 				    strcmp(sname+3, name) == 0)
    349     0  stevel 					break;
    350     0  stevel 			}
    351     0  stevel 			if (sig > PRMAXSIG)
    352     0  stevel 				sig = 0;
    353     0  stevel 		}
    354     0  stevel 		if (sig > 0 && sig <= PRMAXSIG) {
    355     0  stevel 			if (exclude) {
    356     0  stevel 				prdelset(setp, sig);
    357     0  stevel 			} else {
    358     0  stevel 				praddset(setp, sig);
    359     0  stevel 			}
    360     0  stevel 		} else if (strcmp(name, "ALL") == 0) {
    361     0  stevel 			if (exclude) {
    362     0  stevel 				premptyset(setp);
    363     0  stevel 			} else {
    364     0  stevel 				prfillset(setp);
    365     0  stevel 			}
    366     0  stevel 		} else {
    367     0  stevel 			(void) fprintf(stderr,
    368  5891     raf 			    "%s: unrecognized signal name/number: %s\n",
    369  5891     raf 			    command, name);
    370     0  stevel 			rc = -1;
    371     0  stevel 		}
    372     0  stevel 	}
    373     0  stevel 
    374     0  stevel 	return (rc);
    375     0  stevel }
    376     0  stevel 
    377     0  stevel /*
    378     0  stevel  * List of faults to trace.
    379     0  stevel  * return 0 on success, != 0 on any failure.
    380     0  stevel  */
    381     0  stevel int
    382     0  stevel fltlist(char *str,			/* string of fault names */
    383     0  stevel 	fltset_t *setp,			/* fault set */
    384     0  stevel 	int *fp)			/* first-time flag */
    385     0  stevel {
    386     0  stevel 	char *name;
    387     0  stevel 	int exclude = FALSE;
    388     0  stevel 	int rc = 0;
    389     0  stevel 	char *lasts;
    390     0  stevel 
    391     0  stevel 	upcase(str);
    392     0  stevel 	name = strtok_r(str, sepr, &lasts);
    393     0  stevel 
    394     0  stevel 	if (name != NULL && *name == '!') {	/* exclude from set */
    395     0  stevel 		exclude = TRUE;
    396     0  stevel 		if (*++name == '\0')
    397     0  stevel 			name = strtok_r(NULL, sepr, &lasts);
    398     0  stevel 	} else if (!*fp) {	/* first time, clear the set */
    399     0  stevel 		premptyset(setp);
    400     0  stevel 		*fp = TRUE;
    401     0  stevel 	}
    402     0  stevel 
    403     0  stevel 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
    404     0  stevel 		int flt;
    405     0  stevel 		char *next;
    406     0  stevel 
    407     0  stevel 		if (*name == '!') {	/* exclude remainder from set */
    408     0  stevel 			exclude = TRUE;
    409     0  stevel 			while (*++name == '!')
    410     0  stevel 				/* empty */;
    411     0  stevel 			if (*name == '\0')
    412     0  stevel 				continue;
    413     0  stevel 		}
    414     0  stevel 
    415     0  stevel 		flt = strtol(name, &next, 0);
    416     0  stevel 		if (flt <= 0 || flt > PRMAXFAULT || *next != '\0') {
    417     0  stevel 			for (flt = 1; flt <= PRMAXFAULT; flt++) {
    418     0  stevel 				char fname[32];
    419     0  stevel 
    420     0  stevel 				if (proc_fltname(flt, fname,
    421     0  stevel 				    sizeof (fname)) == NULL)
    422     0  stevel 					continue;
    423     0  stevel 
    424     0  stevel 				if (strcmp(fname, name) == 0 ||
    425     0  stevel 				    strcmp(fname+3, name) == 0)
    426     0  stevel 					break;
    427     0  stevel 			}
    428     0  stevel 			if (flt > PRMAXFAULT)
    429     0  stevel 				flt = 0;
    430     0  stevel 		}
    431     0  stevel 		if (flt > 0 && flt <= PRMAXFAULT) {
    432     0  stevel 			if (exclude) {
    433     0  stevel 				prdelset(setp, flt);
    434     0  stevel 			} else {
    435     0  stevel 				praddset(setp, flt);
    436     0  stevel 			}
    437     0  stevel 		} else if (strcmp(name, "ALL") == 0) {
    438     0  stevel 			if (exclude) {
    439     0  stevel 				premptyset(setp);
    440     0  stevel 			} else {
    441     0  stevel 				prfillset(setp);
    442     0  stevel 			}
    443     0  stevel 		} else {
    444     0  stevel 			(void) fprintf(stderr,
    445  5891     raf 			    "%s: unrecognized fault name/number: %s\n",
    446  5891     raf 			    command, name);
    447     0  stevel 			rc = -1;
    448     0  stevel 		}
    449     0  stevel 	}
    450     0  stevel 
    451     0  stevel 	return (rc);
    452     0  stevel }
    453     0  stevel 
    454     0  stevel /*
    455     0  stevel  * Gather file descriptors to dump.
    456     0  stevel  * Return 0 on success, != 0 on any failure.
    457     0  stevel  */
    458     0  stevel int
    459     0  stevel fdlist(char *str,		/* string of filedescriptors */
    460     0  stevel 	fileset_t *setp)	/* set of boolean flags */
    461     0  stevel {
    462     0  stevel 	char *name;
    463     0  stevel 	int exclude = FALSE;
    464     0  stevel 	int rc = 0;
    465     0  stevel 	char *lasts;
    466     0  stevel 
    467     0  stevel 	upcase(str);
    468     0  stevel 	name = strtok_r(str, sepr, &lasts);
    469     0  stevel 
    470     0  stevel 	if (name != NULL && *name == '!') {	/* exclude from set */
    471     0  stevel 		exclude = TRUE;
    472     0  stevel 		if (*++name == '\0')
    473     0  stevel 			name = strtok_r(NULL, sepr, &lasts);
    474     0  stevel 	}
    475     0  stevel 
    476     0  stevel 	for (; name; name = strtok_r(NULL, sepr, &lasts)) {
    477     0  stevel 		int fd;
    478     0  stevel 		char *next;
    479     0  stevel 
    480     0  stevel 		if (*name == '!') {	/* exclude remainder from set */
    481     0  stevel 			exclude = TRUE;
    482     0  stevel 			while (*++name == '!')
    483     0  stevel 				/* empty */;
    484     0  stevel 			if (*name == '\0')
    485     0  stevel 				continue;
    486     0  stevel 		}
    487     0  stevel 
    488     0  stevel 		fd = strtol(name, &next, 0);
    489     0  stevel 		if (fd >= 0 && fd < NOFILES_MAX && *next == '\0') {
    490     0  stevel 			fd++;
    491     0  stevel 			if (exclude) {
    492     0  stevel 				prdelset(setp, fd);
    493     0  stevel 			} else {
    494     0  stevel 				praddset(setp, fd);
    495     0  stevel 			}
    496     0  stevel 		} else if (strcmp(name, "ALL") == 0) {
    497     0  stevel 			if (exclude) {
    498     0  stevel 				premptyset(setp);
    499     0  stevel 			} else {
    500     0  stevel 				prfillset(setp);
    501     0  stevel 			}
    502     0  stevel 		} else {
    503     0  stevel 			(void) fprintf(stderr,
    504  5891     raf 			    "%s: filedescriptor not in range[0..%d]: %s\n",
    505  5891     raf 			    command, NOFILES_MAX-1, name);
    506     0  stevel 			rc = -1;
    507     0  stevel 		}
    508     0  stevel 	}
    509     0  stevel 
    510     0  stevel 	return (rc);
    511     0  stevel }
    512     0  stevel 
    513     0  stevel void
    514     0  stevel upcase(char *str)
    515     0  stevel {
    516     0  stevel 	int c;
    517     0  stevel 
    518     0  stevel 	while ((c = *str) != '\0')
    519     0  stevel 		*str++ = toupper(c);
    520     0  stevel }
    521     0  stevel 
    522     0  stevel /*
    523     0  stevel  * 'arg' points to a string like:
    524     0  stevel  *	libc,libnsl,... : printf,read,write,...
    525     0  stevel  * or
    526     0  stevel  *	libc,libnsl,... :: printf,read,write,...
    527     0  stevel  * with possible filename pattern-matching metacharacters.
    528     0  stevel  *
    529     0  stevel  * Assumption:  No library or function name can contain ',' or ':'.
    530     0  stevel  */
    531     0  stevel int
    532     0  stevel liblist(char *arg, int hang)
    533     0  stevel {
    534     0  stevel 	const char *star = "*";
    535     0  stevel 	struct dynpat *Dyp;
    536     0  stevel 	char *pat;
    537     0  stevel 	char *fpat;
    538     0  stevel 	char *lasts;
    539     0  stevel 	uint_t maxpat;
    540     0  stevel 
    541     0  stevel 	/* append a new dynpat structure to the end of the Dynpat list */
    542     0  stevel 	Dyp = my_malloc(sizeof (struct dynpat), NULL);
    543     0  stevel 	Dyp->next = NULL;
    544     0  stevel 	if (Lastpat == NULL)
    545     0  stevel 		Dynpat = Lastpat = Dyp;
    546     0  stevel 	else {
    547     0  stevel 		Lastpat->next = Dyp;
    548     0  stevel 		Lastpat = Dyp;
    549     0  stevel 	}
    550     0  stevel 	Dyp->flag = hang? BPT_HANG : 0;
    551     0  stevel 	Dyp->exclude_lib = 0;
    552     0  stevel 	Dyp->exclude = 0;
    553     0  stevel 	Dyp->internal = 0;
    554     0  stevel 	Dyp->Dp = NULL;
    555     0  stevel 
    556     0  stevel 	/*
    557     0  stevel 	 * Find the beginning of the filename patterns
    558     0  stevel 	 * and null-terminate the library name patterns.
    559     0  stevel 	 */
    560     0  stevel 	if ((fpat = strchr(arg, ':')) != NULL)
    561     0  stevel 		*fpat++ = '\0';
    562     0  stevel 
    563     0  stevel 	/*
    564     0  stevel 	 * Library name patterns.
    565     0  stevel 	 */
    566     0  stevel 	pat = strtok_r(arg, sepr, &lasts);
    567     0  stevel 
    568     0  stevel 	/* '!' introduces an exclusion list */
    569     0  stevel 	if (pat != NULL && *pat == '!') {
    570     0  stevel 		Dyp->exclude_lib = 1;
    571     0  stevel 		pat += strspn(pat, "!");
    572     0  stevel 		if (*pat == '\0')
    573     0  stevel 			pat = strtok_r(NULL, sepr, &lasts);
    574     0  stevel 		/* force exclusion of all functions as well */
    575     0  stevel 		Dyp->exclude = 1;
    576     0  stevel 		Dyp->internal = 1;
    577     0  stevel 		fpat = NULL;
    578     0  stevel 	}
    579     0  stevel 
    580     0  stevel 	if (pat == NULL) {
    581     0  stevel 		/* empty list means all libraries */
    582     0  stevel 		Dyp->libpat = my_malloc(sizeof (char *), NULL);
    583     0  stevel 		Dyp->libpat[0] = star;
    584     0  stevel 		Dyp->nlibpat = 1;
    585     0  stevel 	} else {
    586     0  stevel 		/*
    587     0  stevel 		 * We are now at the library list.
    588     0  stevel 		 * Generate the list and count the library name patterns.
    589     0  stevel 		 */
    590     0  stevel 		maxpat = 1;
    591     0  stevel 		Dyp->libpat = my_malloc(maxpat * sizeof (char *), NULL);
    592     0  stevel 		Dyp->nlibpat = 0;
    593     0  stevel 		Dyp->libpat[Dyp->nlibpat++] = pat;
    594     0  stevel 		while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
    595     0  stevel 			if (Dyp->nlibpat == maxpat) {
    596     0  stevel 				maxpat *= 2;
    597     0  stevel 				Dyp->libpat = my_realloc(Dyp->libpat,
    598  5891     raf 				    maxpat * sizeof (char *), NULL);
    599     0  stevel 			}
    600     0  stevel 			Dyp->libpat[Dyp->nlibpat++] = pat;
    601     0  stevel 		}
    602     0  stevel 	}
    603     0  stevel 
    604     0  stevel 	/*
    605     0  stevel 	 * Function name patterns.
    606     0  stevel 	 */
    607     0  stevel 	if (fpat == NULL)
    608     0  stevel 		pat = NULL;
    609     0  stevel 	else {
    610     0  stevel 		/*
    611     0  stevel 		 * We have already seen a ':'.  Look for another.
    612     0  stevel 		 * Double ':' means trace internal calls.
    613     0  stevel 		 */
    614     0  stevel 		fpat += strspn(fpat, white);
    615     0  stevel 		if (*fpat == ':') {
    616     0  stevel 			Dyp->internal = 1;
    617     0  stevel 			*fpat++ = '\0';
    618     0  stevel 		}
    619     0  stevel 		pat = strtok_r(fpat, csepr, &lasts);
    620     0  stevel 	}
    621     0  stevel 
    622     0  stevel 	/* '!' introduces an exclusion list */
    623     0  stevel 	if (pat != NULL && *pat == '!') {
    624     0  stevel 		Dyp->exclude = 1;
    625     0  stevel 		Dyp->internal = 1;
    626     0  stevel 		pat += strspn(pat, "!");
    627     0  stevel 		if (*pat == '\0')
    628     0  stevel 			pat = strtok_r(NULL, sepr, &lasts);
    629     0  stevel 	}
    630     0  stevel 
    631     0  stevel 	if (pat == NULL) {
    632     0  stevel 		/* empty function list means exclude all functions */
    633     0  stevel 		Dyp->sympat = my_malloc(sizeof (char *), NULL);
    634     0  stevel 		Dyp->sympat[0] = star;
    635     0  stevel 		Dyp->nsympat = 1;
    636     0  stevel 	} else {
    637     0  stevel 		/*
    638     0  stevel 		 * We are now at the function list.
    639     0  stevel 		 * Generate the list and count the symbol name patterns.
    640     0  stevel 		 */
    641     0  stevel 		maxpat = 1;
    642     0  stevel 		Dyp->sympat = my_malloc(maxpat * sizeof (char *), NULL);
    643     0  stevel 		Dyp->nsympat = 0;
    644     0  stevel 		Dyp->sympat[Dyp->nsympat++] = pat;
    645     0  stevel 		while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
    646     0  stevel 			if (Dyp->nsympat == maxpat) {
    647     0  stevel 				maxpat *= 2;
    648     0  stevel 				Dyp->sympat = my_realloc(Dyp->sympat,
    649  5891     raf 				    maxpat * sizeof (char *), NULL);
    650     0  stevel 			}
    651     0  stevel 			Dyp->sympat[Dyp->nsympat++] = pat;
    652     0  stevel 		}
    653     0  stevel 	}
    654     0  stevel 
    655     0  stevel 	return (0);
    656     0  stevel }
    657