Move /var/svc/log to /var/log/svc
[unleashed/lotheac.git] / usr / src / cmd / truss / listopts.c
blob1309b37f368491b69823ba574ab7bd5c62c457b4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <ctype.h>
33 #include <string.h>
34 #include <memory.h>
35 #include <sys/types.h>
36 #include <signal.h>
37 #include <libproc.h>
38 #include "ramdata.h"
39 #include "systable.h"
40 #include "proto.h"
42 /* XXX A bug in the <string.h> header file requires this */
43 extern char *strtok_r(char *s1, const char *s2, char **lasts);
46 * option procesing ---
47 * Routines for scanning syscall, signal, fault
48 * and file descriptor lists.
52 * Function prototypes for static routines in this module.
54 void upcase(char *);
56 const char white[] = " \t\n"; /* white space characters */
57 const char sepr[] = " ,\t\n"; /* list separator characters */
58 const char csepr[] = " :,\t\n"; /* same, with ':' added */
61 * Scan list of syscall names.
62 * Return 0 on success, != 0 on any failure.
64 int
65 syslist(char *str, /* string of syscall names */
66 sysset_t *setp, /* syscall set */
67 int *fp) /* first-time flag */
69 char *name;
70 int exclude = FALSE;
71 int rc = 0;
72 char *lasts;
74 name = strtok_r(str, sepr, &lasts);
76 if (name != NULL && *name == '!') { /* exclude from set */
77 exclude = TRUE;
78 if (*++name == '\0')
79 name = strtok_r(NULL, sepr, &lasts);
80 } else if (!*fp) { /* first time, clear the set */
81 premptyset(setp);
82 *fp = TRUE;
85 for (; name; name = strtok_r(NULL, sepr, &lasts)) {
86 int sys;
87 int sysx;
88 char *next;
90 if (*name == '!') { /* exclude remainder from set */
91 exclude = TRUE;
92 while (*++name == '!')
93 /* empty */;
94 if (*name == '\0')
95 continue;
98 sys = strtol(name, &next, 0);
99 sysx = 0;
100 if (sys < 0 || sys > PRMAXSYS || *next != '\0')
101 sys = 0;
102 if (sys == 0) {
103 const struct systable *stp = systable;
104 for (; sys == 0 && stp->nargs >= 0; stp++)
105 if (stp->name && strcmp(stp->name, name) == 0)
106 sys = stp-systable;
108 if (sys == 0) {
109 const struct sysalias *sap = sysalias;
110 for (; sys == 0 && sap->name; sap++)
111 if (strcmp(sap->name, name) == 0)
112 sys = sap->number;
114 if (sys > 0 && sys <= PRMAXSYS) {
115 switch (sys) {
116 case SYS_fstatat:
117 sys = SYS_fstatat;
118 goto def;
120 case SYS_stat:
121 sys = SYS_stat;
122 sysx = SYS_fstatat;
123 goto def;
125 case SYS_lstat:
126 sys = SYS_lstat;
127 sysx = SYS_fstatat;
128 goto def;
130 case SYS_fstat:
131 sys = SYS_fstat;
132 sysx = SYS_fstatat;
133 goto def;
135 case SYS_getdents:
136 sys = SYS_getdents;
137 goto def;
139 case SYS_mmap:
140 sys = SYS_mmap;
141 goto def;
143 case SYS_statvfs:
144 sys = SYS_statvfs;
145 goto def;
147 case SYS_fstatvfs:
148 sys = SYS_fstatvfs;
149 goto def;
151 case SYS_setrlimit:
152 sys = SYS_setrlimit;
153 goto def;
155 case SYS_getrlimit:
156 sys = SYS_getrlimit;
157 goto def;
159 case SYS_pread:
160 sys = SYS_pread;
161 goto def;
163 case SYS_pwrite:
164 sys = SYS_pwrite;
165 goto def;
167 case SYS_openat:
168 case SYS_open:
169 sys = SYS_openat;
170 sysx = SYS_open;
171 goto def;
173 case SYS_forksys: /* set both if either */
174 case SYS_vfork:
175 sysx = SYS_forksys;
176 sys = SYS_vfork;
177 goto def;
179 case SYS_sigprocmask: /* set both if either */
180 case SYS_lwp_sigmask:
181 sysx = SYS_sigprocmask;
182 sys = SYS_lwp_sigmask;
183 goto def;
185 case SYS_lseek: /* set both if either */
186 case SYS_llseek:
187 sysx = SYS_lseek;
188 sys = SYS_llseek;
189 goto def;
191 case SYS_rename: /* set both */
192 sysx = SYS_renameat;
193 goto def;
195 case SYS_link: /* set both */
196 sysx = SYS_linkat;
197 goto def;
199 case SYS_unlink: /* set both */
200 case SYS_rmdir: /* set both */
201 sysx = SYS_unlinkat;
202 goto def;
204 case SYS_symlink: /* set both */
205 sysx = SYS_symlinkat;
206 goto def;
208 case SYS_readlink: /* set both */
209 sysx = SYS_readlinkat;
210 goto def;
212 case SYS_chmod: /* set both */
213 case SYS_fchmod: /* set both */
214 sysx = SYS_fchmodat;
215 goto def;
217 case SYS_chown: /* set both */
218 case SYS_lchown: /* set both */
219 case SYS_fchown: /* set both */
220 sysx = SYS_fchownat;
221 goto def;
223 case SYS_mkdir: /* set both */
224 sysx = SYS_mkdirat;
225 goto def;
227 case SYS_mknod: /* set both */
228 sysx = SYS_mknodat;
229 goto def;
231 case SYS_access: /* set both */
232 sysx = SYS_faccessat;
233 goto def;
235 default:
236 def:
237 if (exclude) {
238 prdelset(setp, sys);
239 if (sysx)
240 prdelset(setp, sysx);
241 } else {
242 praddset(setp, sys);
243 if (sysx)
244 praddset(setp, sysx);
246 break;
248 } else if (strcmp(name, "all") == 0 ||
249 strcmp(name, "ALL") == 0) {
250 if (exclude) {
251 premptyset(setp);
252 } else {
253 prfillset(setp);
255 } else {
256 (void) fprintf(stderr,
257 "%s: unrecognized syscall: %s\n",
258 command, name);
259 rc = -1;
263 return (rc);
267 * List of signals to trace.
268 * Return 0 on success, != 0 on any failure.
271 siglist(private_t *pri,
272 char *str, /* string of signal names */
273 sigset_t *setp, /* signal set */
274 int *fp) /* first-time flag */
276 char *name;
277 int exclude = FALSE;
278 int rc = 0;
279 char *lasts;
281 upcase(str);
282 name = strtok_r(str, sepr, &lasts);
284 if (name != NULL && *name == '!') { /* exclude from set */
285 exclude = TRUE;
286 if (*++name == '\0')
287 name = strtok_r(NULL, sepr, &lasts);
288 } else if (!*fp) { /* first time, clear the set */
289 premptyset(setp);
290 *fp = TRUE;
293 for (; name; name = strtok_r(NULL, sepr, &lasts)) {
294 int sig;
295 char *next;
297 if (*name == '!') { /* exclude remainder from set */
298 exclude = TRUE;
299 while (*++name == '!')
300 /* empty */;
301 if (*name == '\0')
302 continue;
305 sig = strtol(name, &next, 0);
306 if (sig <= 0 || sig > PRMAXSIG || *next != '\0') {
307 for (sig = 1; sig <= PRMAXSIG; sig++) {
308 const char *sname = rawsigname(pri, sig);
309 if (sname == NULL)
310 continue;
311 if (strcmp(sname, name) == 0 ||
312 strcmp(sname+3, name) == 0)
313 break;
315 if (sig > PRMAXSIG)
316 sig = 0;
318 if (sig > 0 && sig <= PRMAXSIG) {
319 if (exclude) {
320 prdelset(setp, sig);
321 } else {
322 praddset(setp, sig);
324 } else if (strcmp(name, "ALL") == 0) {
325 if (exclude) {
326 premptyset(setp);
327 } else {
328 prfillset(setp);
330 } else {
331 (void) fprintf(stderr,
332 "%s: unrecognized signal name/number: %s\n",
333 command, name);
334 rc = -1;
338 return (rc);
342 * List of faults to trace.
343 * return 0 on success, != 0 on any failure.
346 fltlist(char *str, /* string of fault names */
347 fltset_t *setp, /* fault set */
348 int *fp) /* first-time flag */
350 char *name;
351 int exclude = FALSE;
352 int rc = 0;
353 char *lasts;
355 upcase(str);
356 name = strtok_r(str, sepr, &lasts);
358 if (name != NULL && *name == '!') { /* exclude from set */
359 exclude = TRUE;
360 if (*++name == '\0')
361 name = strtok_r(NULL, sepr, &lasts);
362 } else if (!*fp) { /* first time, clear the set */
363 premptyset(setp);
364 *fp = TRUE;
367 for (; name; name = strtok_r(NULL, sepr, &lasts)) {
368 int flt;
369 char *next;
371 if (*name == '!') { /* exclude remainder from set */
372 exclude = TRUE;
373 while (*++name == '!')
374 /* empty */;
375 if (*name == '\0')
376 continue;
379 flt = strtol(name, &next, 0);
380 if (flt <= 0 || flt > PRMAXFAULT || *next != '\0') {
381 for (flt = 1; flt <= PRMAXFAULT; flt++) {
382 char fname[32];
384 if (proc_fltname(flt, fname,
385 sizeof (fname)) == NULL)
386 continue;
388 if (strcmp(fname, name) == 0 ||
389 strcmp(fname+3, name) == 0)
390 break;
392 if (flt > PRMAXFAULT)
393 flt = 0;
395 if (flt > 0 && flt <= PRMAXFAULT) {
396 if (exclude) {
397 prdelset(setp, flt);
398 } else {
399 praddset(setp, flt);
401 } else if (strcmp(name, "ALL") == 0) {
402 if (exclude) {
403 premptyset(setp);
404 } else {
405 prfillset(setp);
407 } else {
408 (void) fprintf(stderr,
409 "%s: unrecognized fault name/number: %s\n",
410 command, name);
411 rc = -1;
415 return (rc);
419 * Gather file descriptors to dump.
420 * Return 0 on success, != 0 on any failure.
423 fdlist(char *str, /* string of filedescriptors */
424 fileset_t *setp) /* set of boolean flags */
426 char *name;
427 int exclude = FALSE;
428 int rc = 0;
429 char *lasts;
431 upcase(str);
432 name = strtok_r(str, sepr, &lasts);
434 if (name != NULL && *name == '!') { /* exclude from set */
435 exclude = TRUE;
436 if (*++name == '\0')
437 name = strtok_r(NULL, sepr, &lasts);
440 for (; name; name = strtok_r(NULL, sepr, &lasts)) {
441 int fd;
442 char *next;
444 if (*name == '!') { /* exclude remainder from set */
445 exclude = TRUE;
446 while (*++name == '!')
447 /* empty */;
448 if (*name == '\0')
449 continue;
452 fd = strtol(name, &next, 0);
453 if (fd >= 0 && fd < NOFILES_MAX && *next == '\0') {
454 fd++;
455 if (exclude) {
456 prdelset(setp, fd);
457 } else {
458 praddset(setp, fd);
460 } else if (strcmp(name, "ALL") == 0) {
461 if (exclude) {
462 premptyset(setp);
463 } else {
464 prfillset(setp);
466 } else {
467 (void) fprintf(stderr,
468 "%s: filedescriptor not in range[0..%d]: %s\n",
469 command, NOFILES_MAX-1, name);
470 rc = -1;
474 return (rc);
477 void
478 upcase(char *str)
480 int c;
482 while ((c = *str) != '\0')
483 *str++ = toupper(c);
487 * 'arg' points to a string like:
488 * libc,libnsl,... : printf,read,write,...
489 * or
490 * libc,libnsl,... :: printf,read,write,...
491 * with possible filename pattern-matching metacharacters.
493 * Assumption: No library or function name can contain ',' or ':'.
496 liblist(char *arg, int hang)
498 const char *star = "*";
499 struct dynpat *Dyp;
500 char *pat;
501 char *fpat;
502 char *lasts;
503 uint_t maxpat;
505 /* append a new dynpat structure to the end of the Dynpat list */
506 Dyp = my_malloc(sizeof (struct dynpat), NULL);
507 Dyp->next = NULL;
508 if (Lastpat == NULL)
509 Dynpat = Lastpat = Dyp;
510 else {
511 Lastpat->next = Dyp;
512 Lastpat = Dyp;
514 Dyp->flag = hang? BPT_HANG : 0;
515 Dyp->exclude_lib = 0;
516 Dyp->exclude = 0;
517 Dyp->internal = 0;
518 Dyp->Dp = NULL;
521 * Find the beginning of the filename patterns
522 * and null-terminate the library name patterns.
524 if ((fpat = strchr(arg, ':')) != NULL)
525 *fpat++ = '\0';
528 * Library name patterns.
530 pat = strtok_r(arg, sepr, &lasts);
532 /* '!' introduces an exclusion list */
533 if (pat != NULL && *pat == '!') {
534 Dyp->exclude_lib = 1;
535 pat += strspn(pat, "!");
536 if (*pat == '\0')
537 pat = strtok_r(NULL, sepr, &lasts);
538 /* force exclusion of all functions as well */
539 Dyp->exclude = 1;
540 Dyp->internal = 1;
541 fpat = NULL;
544 if (pat == NULL) {
545 /* empty list means all libraries */
546 Dyp->libpat = my_malloc(sizeof (char *), NULL);
547 Dyp->libpat[0] = star;
548 Dyp->nlibpat = 1;
549 } else {
551 * We are now at the library list.
552 * Generate the list and count the library name patterns.
554 maxpat = 1;
555 Dyp->libpat = my_malloc(maxpat * sizeof (char *), NULL);
556 Dyp->nlibpat = 0;
557 Dyp->libpat[Dyp->nlibpat++] = pat;
558 while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
559 if (Dyp->nlibpat == maxpat) {
560 maxpat *= 2;
561 Dyp->libpat = my_realloc(Dyp->libpat,
562 maxpat * sizeof (char *), NULL);
564 Dyp->libpat[Dyp->nlibpat++] = pat;
569 * Function name patterns.
571 if (fpat == NULL)
572 pat = NULL;
573 else {
575 * We have already seen a ':'. Look for another.
576 * Double ':' means trace internal calls.
578 fpat += strspn(fpat, white);
579 if (*fpat == ':') {
580 Dyp->internal = 1;
581 *fpat++ = '\0';
583 pat = strtok_r(fpat, csepr, &lasts);
586 /* '!' introduces an exclusion list */
587 if (pat != NULL && *pat == '!') {
588 Dyp->exclude = 1;
589 Dyp->internal = 1;
590 pat += strspn(pat, "!");
591 if (*pat == '\0')
592 pat = strtok_r(NULL, sepr, &lasts);
595 if (pat == NULL) {
596 /* empty function list means exclude all functions */
597 Dyp->sympat = my_malloc(sizeof (char *), NULL);
598 Dyp->sympat[0] = star;
599 Dyp->nsympat = 1;
600 } else {
602 * We are now at the function list.
603 * Generate the list and count the symbol name patterns.
605 maxpat = 1;
606 Dyp->sympat = my_malloc(maxpat * sizeof (char *), NULL);
607 Dyp->nsympat = 0;
608 Dyp->sympat[Dyp->nsympat++] = pat;
609 while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
610 if (Dyp->nsympat == maxpat) {
611 maxpat *= 2;
612 Dyp->sympat = my_realloc(Dyp->sympat,
613 maxpat * sizeof (char *), NULL);
615 Dyp->sympat[Dyp->nsympat++] = pat;
619 return (0);