xref: /illumos-gate/usr/src/cmd/tnf/prex/list.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Includes
30  */
31 
32 #ifndef DEBUG
33 #define	NDEBUG	1
34 #endif
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <libintl.h>
41 #include <search.h>
42 
43 #include "source.h"
44 #include "queue.h"
45 #include "list.h"
46 #include "spec.h"
47 #include "new.h"
48 #include "fcn.h"
49 
50 extern caddr_t  g_commitfunc;
51 
52 
53 /*
54  * Typedefs
55  */
56 
57 typedef struct list_probe_args {
58 	spec_t		 *speclist_p;
59 	expr_t		 *exprlist_p;
60 } list_probe_args_t;
61 
62 typedef struct list_attrs_args {
63 	spec_t		 *speclist_p;
64 	void		   *attrroot_p;
65 } list_attrs_args_t;
66 
67 typedef struct attr_node {
68 	char		   *name;
69 	void		   *valsroot_p;
70 } attr_node_t;
71 
72 typedef struct vals_node {
73 	char		   *name;
74 } vals_node_t;
75 
76 
77 /*
78  * Globals
79  */
80 
81 
82 /*
83  * Declarations
84  */
85 
86 static tnfctl_errcode_t listprobe(tnfctl_handle_t *hndl,
87 	tnfctl_probe_t *ref_p, void *calldata_p);
88 static tnfctl_errcode_t probescan(tnfctl_handle_t *hndl,
89 	tnfctl_probe_t *ref_p, void *calldata_p);
90 static void printattrval(spec_t * spec_p, char *attr, char *value,
91 	void *pdata);
92 static void attrscan(spec_t * spec_p, char *attr, char *values, void *pdata);
93 static int attrcompare(const void *node1, const void *node2);
94 static int valscompare(const void *node1, const void *node2);
95 static void printattrs(const void *node, VISIT order, int level);
96 static void printvals(const void *node, VISIT order, int level);
97 
98 #if 0
99 static void	 attrnodedel(attr_node_t * an_p);
100 #endif
101 
102 static void valadd(spec_t * spec_p, char *val, void *calldata_p);
103 
104 
105 /* ---------------------------------------------------------------- */
106 /* ----------------------- Public Functions ----------------------- */
107 /* ---------------------------------------------------------------- */
108 
109 extern tnfctl_handle_t	*g_hndl;
110 
111 /*
112  * list_set() - lists all of the current probes in a target process
113  */
114 
115 void
list_set(spec_t * speclist_p,char * setname_p)116 list_set(spec_t * speclist_p, char *setname_p)
117 {
118 	set_t *set_p;
119 	list_probe_args_t args;
120 	tnfctl_errcode_t err;
121 
122 	set_p = set_find(setname_p);
123 	if (!set_p) {
124 		semantic_err(gettext("missing or invalid set"));
125 		return;
126 	}
127 	args.speclist_p = speclist_p;
128 	args.exprlist_p = set_p->exprlist_p;
129 	err = tnfctl_probe_apply(g_hndl, listprobe, &args);
130 	if (err) {
131 		semantic_err(gettext("listing error : %s"),
132 				tnfctl_strerror(err));
133 	}
134 }
135 
136 
137 /*
138  * list_expr() - lists all of the current probes in an expression list
139  */
140 
141 void
list_expr(spec_t * speclist_p,expr_t * expr_p)142 list_expr(spec_t * speclist_p, expr_t * expr_p)
143 {
144 	list_probe_args_t args;
145 	tnfctl_errcode_t err;
146 
147 	args.speclist_p = speclist_p;
148 	args.exprlist_p = expr_p;
149 	err = tnfctl_probe_apply(g_hndl, listprobe, &args);
150 	if (err) {
151 		semantic_err(gettext("listing error : %s"),
152 				tnfctl_strerror(err));
153 	}
154 }
155 
156 
157 /*
158  * list_values() - list all the values for a supplied spec
159  */
160 
161 void
list_values(spec_t * speclist_p)162 list_values(spec_t * speclist_p)
163 {
164 	list_attrs_args_t args;
165 	tnfctl_errcode_t err;
166 
167 	/* setup argument block */
168 	args.speclist_p = speclist_p;
169 	args.attrroot_p = NULL;
170 
171 	/* traverse the probes, recording attributes that match */
172 	err = tnfctl_probe_apply(g_hndl, probescan, &args);
173 	if (err) {
174 		semantic_err(gettext("probe traversal error : %s"),
175 				tnfctl_strerror(err));
176 	}
177 
178 	/* pretty print the results */
179 	twalk(args.attrroot_p, printattrs);
180 
181 	/* destroy the attribute tree */
182 	while (args.attrroot_p) {
183 		attr_node_t   **aptr;
184 		char			*anameptr;
185 
186 		aptr = (attr_node_t **) args.attrroot_p;
187 
188 		/* destroy the value tree */
189 		while ((*aptr)->valsroot_p) {
190 			vals_node_t   **vptr;
191 			char			*vnameptr;
192 
193 			vptr = (vals_node_t **) (*aptr)->valsroot_p;
194 			vnameptr = (*vptr)->name;
195 #ifdef LEAKCHK
196 			(void) fprintf(stderr, "freeing value \"%s\"\n",
197 				vnameptr);
198 #endif
199 			(void) tdelete((void *) *vptr, &(*aptr)->valsroot_p,
200 				valscompare);
201 			if (vnameptr) free(vnameptr);
202 		}
203 
204 		anameptr = (*aptr)->name;
205 #ifdef LEAKCHK
206 		(void) fprintf(stderr, "freeing attr \"%s\"\n", anameptr);
207 #endif
208 		(void) tdelete((void *) *aptr, &args.attrroot_p, attrcompare);
209 		if (anameptr) free(anameptr);
210 	}
211 
212 }				/* end list_values */
213 
214 
215 /*
216  * list_getattrs() - build an attribute string for this probe.
217  */
218 
219 
220 #define	BUF_LIMIT	2048
221 
222 char *
list_getattrs(tnfctl_probe_t * probe_p)223 list_getattrs(tnfctl_probe_t *probe_p)
224 {
225 	tnfctl_errcode_t	err;
226 	tnfctl_probe_state_t	p_state;
227 	char			*attrs;
228 	char			buffer[BUF_LIMIT];
229 	char			*buf_p;
230 	char			*buf_end;
231 	int			str_len;
232 	size_t			len;
233 
234 	err = tnfctl_probe_state_get(g_hndl, probe_p, &p_state);
235 	if (err) {
236 		attrs = malloc(2);
237 		if (attrs)
238 			attrs[0] = '\0';
239 		return (attrs);
240 	}
241 
242 	buf_p = buffer;
243 	buf_end = buf_p + BUF_LIMIT;
244 	str_len = sprintf(buf_p, "enable %s; trace %s; ",
245 				(p_state.enabled) ? "on" : "off",
246 				(p_state.traced) ? "on" : "off");
247 	buf_p += str_len;
248 	if (p_state.obj_name) {
249 		str_len = strlen(p_state.obj_name);
250 		if (buf_p + str_len < buf_end) {
251 			str_len = sprintf(buf_p, "object %s; ",
252 							p_state.obj_name);
253 			buf_p += str_len;
254 		}
255 	}
256 	str_len = sprintf(buf_p, "funcs");
257 	buf_p += str_len;
258 
259 	/* REMIND: add limit for string size */
260 	if (p_state.func_names) {
261 		int 	i = 0;
262 		char	*fcnname;
263 
264 		while (p_state.func_names[i]) {
265 			(void) strcat(buffer, " ");
266 
267 			fcnname = fcn_findname(p_state.func_names[i]);
268 			if (fcnname) {
269 				(void) strcat(buffer, "&");
270 				(void) strcat(buffer, fcnname);
271 			} else
272 				(void) strcat(buffer, p_state.func_names[i]);
273 			i++;
274 		}
275 	}
276 
277 	(void) strcat(buffer, ";");
278 
279 	len = strlen(buffer) + strlen(p_state.attr_string) + 1;
280 	attrs = (char *) malloc(len);
281 
282 	if (attrs) {
283 		(void) strcpy(attrs, buffer);
284 		(void) strcat(attrs, p_state.attr_string);
285 	}
286 
287 	return (attrs);
288 }
289 
290 
291 /* ---------------------------------------------------------------- */
292 /* ----------------------- Private Functions ---------------------- */
293 /* ---------------------------------------------------------------- */
294 
295 /*
296  * probescan() - function used as a callback, gathers probe attributes and
297  * values
298  */
299 /*ARGSUSED*/
300 static tnfctl_errcode_t
probescan(tnfctl_handle_t * hndl,tnfctl_probe_t * ref_p,void * calldata_p)301 probescan(tnfctl_handle_t *hndl, tnfctl_probe_t *ref_p, void *calldata_p)
302 {
303 	list_attrs_args_t *args_p = (list_attrs_args_t *) calldata_p;
304 	spec_t		*speclist_p;
305 	spec_t		*spec_p;
306 	char		*attrs;
307 
308 	speclist_p = args_p->speclist_p;
309 	spec_p = NULL;
310 
311 	attrs = list_getattrs(ref_p);
312 
313 	while (spec_p = (spec_t *) queue_next(&speclist_p->qn, &spec_p->qn)) {
314 		spec_attrtrav(spec_p, attrs, attrscan, calldata_p);
315 	}
316 
317 	if (attrs)
318 		free(attrs);
319 
320 	return (TNFCTL_ERR_NONE);
321 }
322 
323 
324 /*
325  * attrscan() - called on each matching attr/values component
326  */
327 
328 /*ARGSUSED*/
329 static void
attrscan(spec_t * spec_p,char * attr,char * values,void * pdata)330 attrscan(spec_t * spec_p,
331 	char *attr,
332 	char *values,
333 	void *pdata)
334 {
335 	list_attrs_args_t *args_p = (list_attrs_args_t *) pdata;
336 	attr_node_t	*an_p;
337 	attr_node_t   **ret_pp;
338 	static spec_t  *allspec = NULL;
339 
340 	if (!allspec)
341 		allspec = spec(".*", SPEC_REGEXP);
342 
343 	an_p = new(attr_node_t);
344 
345 #ifdef LEAKCHK
346 	(void) fprintf(stderr, "creating attr \"%s\"\n", attr);
347 #endif
348 	an_p->name = strdup(attr);
349 	an_p->valsroot_p = NULL;
350 
351 	ret_pp = tfind((void *) an_p, &args_p->attrroot_p, attrcompare);
352 
353 	if (ret_pp) {
354 		/*
355 		 * we already had a node for this attribute; delete ours *
356 		 * and point at the original instead.
357 		 */
358 #ifdef LEAKCHK
359 		(void) fprintf(stderr, "attr already there \"%s\"\n", attr);
360 #endif
361 		if (an_p->name)
362 			free(an_p->name);
363 		free(an_p);
364 
365 		an_p = *ret_pp;
366 	} else {
367 		(void) tsearch((void *) an_p, &args_p->attrroot_p, attrcompare);
368 	}
369 
370 	spec_valtrav(allspec, values, valadd, (void *) an_p);
371 
372 }				/* end attrscan */
373 
374 
375 /*
376  * valadd() - add vals to an attributes tree
377  */
378 
379 /*ARGSUSED*/
380 static void
valadd(spec_t * spec_p,char * val,void * calldata_p)381 valadd(spec_t * spec_p,
382 	char *val,
383 	void *calldata_p)
384 {
385 	attr_node_t	*an_p = (attr_node_t *) calldata_p;
386 
387 	vals_node_t	*vn_p;
388 	vals_node_t   **ret_pp;
389 
390 	vn_p = new(vals_node_t);
391 #ifdef LEAKCHK
392 	(void) fprintf(stderr, "creating value \"%s\"\n", val);
393 #endif
394 	vn_p->name = strdup(val);
395 
396 	ret_pp = tfind((void *) vn_p, &an_p->valsroot_p, valscompare);
397 
398 	if (ret_pp) {
399 		/* we already had a node for this value */
400 #ifdef LEAKCHK
401 		(void) fprintf(stderr, "value already there \"%s\"\n", val);
402 #endif
403 		if (vn_p->name)
404 			free(vn_p->name);
405 		free(vn_p);
406 	} else {
407 		(void) tsearch((void *) vn_p, &an_p->valsroot_p, valscompare);
408 	}
409 
410 
411 }				/* end valadd */
412 
413 
414 /*
415  * attrcompare() - compares attribute nodes, alphabetically
416  */
417 
418 static int
attrcompare(const void * node1,const void * node2)419 attrcompare(const void *node1,
420 		const void *node2)
421 {
422 	return strcmp(((attr_node_t *) node1)->name,
423 		((attr_node_t *) node2)->name);
424 
425 }				/* end attrcompare */
426 
427 
428 /*
429  * valscompare() - compares attribute nodes, alphabetically
430  */
431 
432 static int
valscompare(const void * node1,const void * node2)433 valscompare(const void *node1,
434 		const void *node2)
435 {
436 	return strcmp(((vals_node_t *) node1)->name,
437 		((vals_node_t *) node2)->name);
438 
439 }				/* end valscompare */
440 
441 
442 /*
443  * printattrs() - prints attributes from the attr tree
444  */
445 
446 /*ARGSUSED*/
447 static void
printattrs(const void * node,VISIT order,int level)448 printattrs(const void *node,
449 	VISIT order,
450 	int level)
451 {
452 	attr_node_t	*an_p = (*(attr_node_t **) node);
453 
454 	if (order == postorder || order == leaf) {
455 		(void) printf("%s =\n", an_p->name);
456 		twalk(an_p->valsroot_p, printvals);
457 	}
458 }				/* end printattrs */
459 
460 
461 /*
462  * printvals() - prints values from a value tree
463  */
464 
465 /*ARGSUSED*/
466 static void
printvals(const void * node,VISIT order,int level)467 printvals(const void *node,
468 	VISIT order,
469 	int level)
470 {
471 	vals_node_t	*vn_p = (*(vals_node_t **) node);
472 
473 	if (order == postorder || order == leaf)
474 		(void) printf("	   %s\n", vn_p->name);
475 
476 }				/* end printvals */
477 
478 
479 #if 0
480 /*
481  * attrnodedel() - deletes an attr_node_t after the action
482  */
483 
484 static void
485 attrnodedel(attr_node_t * an_p)
486 {
487 	if (an_p->name)
488 		free(an_p->name);
489 
490 	/* destroy the value tree */
491 	while (an_p->valsroot_p) {
492 		vals_node_t   **ptr;
493 
494 		ptr = (vals_node_t **) an_p->valsroot_p;
495 		(void) tdelete((void *) *ptr, &an_p->valsroot_p, valscompare);
496 	}
497 
498 	/* We don't need to free this object, since tdelete() appears to */
499 	/* free(an_p); */
500 
501 }				/* end attrnodedel */
502 #endif
503 
504 
505 /*
506  * listprobe() - function used as a callback, pretty prints a probe
507  */
508 /*ARGSUSED*/
509 static tnfctl_errcode_t
listprobe(tnfctl_handle_t * hndl,tnfctl_probe_t * ref_p,void * calldata_p)510 listprobe(tnfctl_handle_t *hndl, tnfctl_probe_t *ref_p, void *calldata_p)
511 {
512 	static spec_t	*default_speclist = NULL;
513 	list_probe_args_t *args_p = (list_probe_args_t *) calldata_p;
514 	spec_t		*speclist_p;
515 	spec_t		*spec_p;
516 	boolean_t	sawattr;
517 	char		*attrs;
518 
519 	/* build a default speclist if there is not one built already */
520 	if (!default_speclist) {
521 		default_speclist = spec_list(
522 			spec_list(
523 				spec_list(
524 					spec_list(
525 						spec_list(
526 							spec("name",
527 								SPEC_EXACT),
528 							spec("enable",
529 								SPEC_EXACT)),
530 						spec("trace", SPEC_EXACT)),
531 					spec("file", SPEC_EXACT)),
532 				spec("line", SPEC_EXACT)),
533 			spec("funcs", SPEC_EXACT));
534 	}
535 	attrs = list_getattrs(ref_p);
536 
537 	if (expr_match(args_p->exprlist_p, attrs)) {
538 		speclist_p = args_p->speclist_p;
539 		speclist_p = (speclist_p) ? speclist_p : default_speclist;
540 
541 		spec_p = NULL;
542 		while (spec_p = (spec_t *)
543 			queue_next(&speclist_p->qn, &spec_p->qn)) {
544 			sawattr = B_FALSE;
545 			spec_attrtrav(spec_p, attrs, printattrval, &sawattr);
546 			if (!sawattr)
547 				(void) printf("<no attr> ");
548 		}
549 		(void) printf("\n");
550 	}
551 	if (attrs)
552 		free(attrs);
553 
554 	return (TNFCTL_ERR_NONE);
555 }
556 
557 
558 /*ARGSUSED*/
559 static void
printattrval(spec_t * spec_p,char * attr,char * value,void * pdata)560 printattrval(spec_t * spec_p,
561 	char *attr,
562 	char *value,
563 	void *pdata)
564 {
565 	boolean_t	  *bptr = (boolean_t *) pdata;
566 
567 	*bptr = B_TRUE;
568 
569 	(void) printf("%s=%s ", attr, (value && *value) ? value : "<no value>");
570 
571 }				/* end printattrval */
572