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