Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / venus / fstrace.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 * All Rights Reserved
12 */
13 #include <afsconfig.h>
14 #include <afs/param.h>
15 #include <afs/stds.h>
16
17 #include <roken.h>
18
19 #include <afs/cmd.h>
20 #include <afs/afs_args.h>
21 #include <afs/icl.h>
22 #include <afs/afsutil.h>
23 #include <rx/rx.h>
24 #include <afs/vice.h>
25 #include <afs/sys_prototypes.h>
26
27 #if defined(AFS_OSF_ENV) || defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
28 /* For SGI 6.2, this is changed to 1 if it's a 32 bit kernel. */
29 int afs_icl_sizeofLong = 2;
30 #else
31 int afs_icl_sizeofLong = 1;
32 #endif
33
34 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
35 int afs_64bit_kernel = 1; /* Default for 6.2+, and always for 6.1 */
36 extern int afs_icl_sizeofLong; /* Used in ICL_SIZEHACK() */
37 #ifdef AFS_SGI62_ENV
38
39 /* If _SC_KERN_POINTERS not in sysconf, then we can assume a 32 bit abi. */
40 void
41 set_kernel_sizeof_long(void)
42 {
43 int retval;
44
45
46 retval = sysconf(_SC_KERN_POINTERS);
47 if (retval == 64) {
48 afs_64bit_kernel = 1;
49 afs_icl_sizeofLong = 2;
50 } else {
51 afs_64bit_kernel = 0;
52 afs_icl_sizeofLong = 1;
53 }
54 }
55
56 #endif /* AFS_SGI62_ENV */
57 #endif /* AFS_SGI61_ENV */
58
59 int afs_syscall(long call, long parm0, long parm1, long parm2, long parm3,
60 long parm4, long parm5, long parm6);
61 void dce1_error_inq_text(afs_uint32 status_to_convert,
62 char *error_text, int *status);
63 int icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
64 struct afs_icl_log *fatalLogp, afs_uint32 flags,
65 struct afs_icl_set **outSetpp);
66 int icl_LogHold(struct afs_icl_log *logp);
67 int icl_LogUse(struct afs_icl_log *logp);
68 int icl_LogReleNL(struct afs_icl_log *logp);
69 int icl_LogRele(struct afs_icl_log *logp);
70 int icl_ZeroLog(struct afs_icl_log *logp);
71 int icl_LogFreeUse(struct afs_icl_log *logp);
72
73 #define BUFFER_MULTIPLIER 1024
74
75 /* make it big enough to snapshot everything at once, since
76 * decoding takes so long.
77 */
78 #define IBSIZE 100000 /* default size */
79
80 struct logInfo {
81 struct logInfo *nextp;
82 char *name;
83 } *allInfo = 0;
84
85 char dumpFileName[256] = "";
86 void
87 RegisterIclDumpFileName(char *name)
88 {
89 (void)sprintf(dumpFileName, "icl.%.250s", name);
90 }
91
92 /* define globals to use for bulk info */
93 afs_icl_bulkSetinfo_t *setInfo = (afs_icl_bulkSetinfo_t *) 0;
94 afs_icl_bulkLoginfo_t *logInfo = (afs_icl_bulkLoginfo_t *) 0;
95
96 struct afs_icl_set *icl_allSets = 0;
97
98
99 char *name;
100 /* given a type and an address, get the size of the thing
101 * in words.
102 */
103 static int
104 icl_GetSize(afs_int32 type, char *addr)
105 {
106 int rsize;
107 int tsize;
108
109 rsize = 0;
110 ICL_SIZEHACK(type, addr, tsize, rsize);
111 return rsize;
112 }
113
114 /* Check types in printf string "bufferp", making sure that each
115 * is compatible with the corresponding parameter type described
116 * by typesp. Also watch for prematurely running out of parameters
117 * before the string is gone.
118 */
119 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
120 static int
121 CheckTypes(char *bufferp, int *typesp, int typeCount, char *outMsgBuffer)
122 {
123 char tc;
124 int inPercent;
125 int tix;
126
127 inPercent = 0;
128 tix = 0;
129 for (tc = *bufferp;; outMsgBuffer++, tc = *(++bufferp)) {
130 *outMsgBuffer = tc;
131 if (tc == 0) {
132 /* hit end of string. We win as long as we aren't
133 * in a '%'.
134 */
135 if (inPercent)
136 return 0;
137 else
138 return 1;
139 }
140 if (tc == '%') {
141 inPercent = 1 - inPercent;
142 continue;
143 }
144 if (inPercent) {
145 if (tc >= '0' && tc <= '9') {
146 /* skip digits in % string */
147 outMsgBuffer--;
148 continue;
149 }
150 if (tc == 'l') {
151 /* 'l' is a type modifier. */
152 outMsgBuffer--;
153 continue;
154 }
155 /* otherwise, we've finally gotten to the type-describing
156 * character. Make sure there's a type descriptor, and then
157 * check the type descriptor.
158 */
159 inPercent = 0;
160 if (tix >= typeCount)
161 return 0; /* no more type descriptors left */
162 if (tc == 's') {
163 if (typesp[tix] != 1) /* not a string descriptor */
164 return 0;
165 outMsgBuffer--;
166 *outMsgBuffer = (char)1;
167 }
168 if (tc == 'u' || tc == 'x' || tc == 'd' || tc == 'o') {
169 if (typesp[tix] != 0)
170 return 0; /* not an integer descriptor */
171 outMsgBuffer--;
172 switch (tc) {
173 case 'd':
174 *outMsgBuffer = (char)2;
175 break;
176 case 'u':
177 *outMsgBuffer = (char)3;
178 break;
179 case 'o':
180 *outMsgBuffer = (char)4;
181 break;
182 case 'x':
183 default:
184 *outMsgBuffer = (char)5;
185 break;
186 }
187 }
188 /* otherwise we're fine, so eat this descriptor */
189 tix++;
190 }
191 }
192 /* not reached */
193 }
194 #else /* AFS_SGI61_ENV */
195 static int
196 CheckTypes(char *bufferp, int *typesp, int typeCount)
197 {
198 char tc;
199 int inPercent;
200 int tix;
201
202 inPercent = 0;
203 tix = 0;
204 for (tc = *bufferp;; tc = *(++bufferp)) {
205 if (tc == 0) {
206 /* hit end of string. We win as long as we aren't
207 * in a '%'.
208 */
209 if (inPercent)
210 return 0;
211 else
212 return 1;
213 }
214 if (tc == '%') {
215 inPercent = 1 - inPercent;
216 continue;
217 }
218 if (inPercent) {
219 if (tc >= '0' && tc <= '9')
220 continue; /* skip digits in % string */
221 /* otherwise, we've finally gotten to the type-describing
222 * character. Make sure there's a type descriptor, and then
223 * check the type descriptor.
224 */
225 inPercent = 0;
226 if (tix >= typeCount)
227 return 0; /* no more type descriptors left */
228 if (tc == 's' && typesp[tix] != 1) /* not a string descriptor */
229 return 0;
230 if ((tc == 'u' || tc == 'l' || tc == 'x' || tc == 'd')
231 && (typesp[tix] != 0))
232 return 0; /* not an integer descriptor */
233 /* otherwise we're fine, so eat this descriptor */
234 tix++;
235 }
236 }
237 /* not reached */
238 }
239 #endif /* AFS_SGI61_ENV */
240
241 /* display a single record.
242 * alp points at the first word in the array to be interpreted
243 * rsize gives the # of words in the array
244 */
245 #if defined(AFS_SGI61_ENV) && !defined(AFS_SGI62_ENV)
246 #define uint64_t long long
247 #endif
248 static void
249 DisplayRecord(FILE *outFilep, afs_int32 *alp, afs_int32 rsize)
250 {
251 char msgBuffer[1024];
252 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
253 char outMsgBuffer[1024];
254 uint64_t tempParam;
255 uint64_t printfParms[ICL_MAXEXPANSION * /* max parms */ 4];
256 char *printfStrings[ICL_MAXEXPANSION * /* max parms */ 4];
257 #else /* AFS_SGI61_ENV */
258 long printfParms[ICL_MAXEXPANSION * /* max parms */ 4];
259 #endif /* AFS_SGI61_ENV */
260 int printfTypes[ICL_MAXEXPANSION * 4];
261 int i;
262 afs_int32 done = 0;
263 afs_int32 temp;
264 int j;
265 int type;
266 int pix; /* index in alp */
267 int pfpix; /* index in printfParms */
268 int pftix; /* index in printfTypes */
269 int status;
270 int printed; /* did we print the string yet? */
271 time_t tmv;
272
273 /* decode parameters */
274 temp = alp[0]; /* type encoded in low-order 24 bits, t0 high */
275 pix = 4;
276 pfpix = 0;
277 pftix = 0;
278 /* init things */
279
280 for (i = 0; i < 4 * ICL_MAXEXPANSION; i++)
281 printfParms[i] = 0;
282 /* decode each parameter, getting addrs for afs_hyper_t and strings */
283 for (i = 0; !done && i < 4; i++) {
284 type = (temp >> (18 - i * 6)) & 0x3f;
285 switch (type) {
286 case ICL_TYPE_NONE:
287 done = 1;
288 break;
289 case ICL_TYPE_LONG:
290 case ICL_TYPE_POINTER:
291 printfTypes[pftix++] = 0;
292 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
293 printfParms[pfpix] = alp[pix];
294 printfParms[pfpix] &= 0xffffffff;
295 if (afs_64bit_kernel) {
296 printfParms[pfpix] <<= 32;
297 printfParms[pfpix] |= alp[pix + 1];
298 }
299 #elif defined(AFS_OSF_ENV)
300 printfParms[pfpix] = alp[pix + 1];
301 printfParms[pfpix] |= (alp[pix] <<= 32);
302 #else /* !AFS_OSF_ENV && !AFS_SGI61_ENV */
303 printfParms[pfpix] = alp[pix];
304 #endif
305 pfpix++;
306 break;
307 case ICL_TYPE_INT32:
308 printfTypes[pftix++] = 0;
309 printfParms[pfpix++] = alp[pix];
310 break;
311 case ICL_TYPE_HYPER:
312 case ICL_TYPE_INT64:
313 printfTypes[pftix++] = 0;
314 printfParms[pfpix++] = alp[pix];
315 printfTypes[pftix++] = 0;
316 printfParms[pfpix++] = alp[pix + 1];
317 break;
318 case ICL_TYPE_FID:
319 printfTypes[pftix++] = 0;
320 printfParms[pfpix++] = alp[pix];
321 printfTypes[pftix++] = 0;
322 printfParms[pfpix++] = alp[pix + 1];
323 printfTypes[pftix++] = 0;
324 printfParms[pfpix++] = alp[pix + 2];
325 printfTypes[pftix++] = 0;
326 printfParms[pfpix++] = alp[pix + 3];
327 break;
328 case ICL_TYPE_STRING:
329 printfTypes[pftix++] = 1;
330 #ifdef AFS_SGI64_ENV
331 printfStrings[pfpix++] = (char *)&alp[pix];
332 #else /* AFS_SGI64_ENV */
333 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
334 printfStrings[pfpix++] = (char *)&alp[pix];
335 #else /* AFS_SGI61_ENV */
336 printfParms[pfpix++] = (long)&alp[pix];
337 #endif /* AFS_SGI61_ENV */
338 #endif /* AFS_SGI64_ENV */
339 break;
340 case ICL_TYPE_UNIXDATE:
341 tmv = alp[pix];
342 printfParms[pfpix++] = (long)ctime(&tmv);
343 break;
344 default:
345 printf("DisplayRecord: Bad type %d in decode switch.\n", type);
346 done = 1;
347 break;
348 }
349 if (done)
350 break;
351
352 pix += icl_GetSize(type, (char *)&alp[pix]);
353 }
354
355 /* next, try to decode the opcode into a printf string */
356 dce1_error_inq_text(alp[1], msgBuffer, &status);
357
358 /* if we got a string back, and it is compatible with the
359 * parms we've got, then print it.
360 */
361 printed = 0;
362 if (status == 0) {
363 #if defined(AFS_SGI61_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
364 if (CheckTypes(msgBuffer, printfTypes, pftix, outMsgBuffer)) {
365 /* we have a string to use, but it ends "(dfs / zcm)",
366 * so we remove the extra gunk.
367 */
368 j = strlen(outMsgBuffer);
369 if (j > 12) {
370 outMsgBuffer[j - 11] = 0;
371 j -= 11;
372 }
373 pfpix = 0;
374 fprintf(outFilep, "time %d.%06d, pid %u: ", alp[3] / 1000000,
375 alp[3] % 1000000, alp[2]);
376 for (i = 0; i < j; i++) {
377 if ((int)outMsgBuffer[i] > 5)
378 fputc(outMsgBuffer[i], outFilep);
379 else {
380 switch (outMsgBuffer[i]) {
381 case 0: /* done */
382 break;
383 case 1: /* string */
384 fprintf(outFilep, "%s", printfStrings[pfpix++]);
385 break;
386 case 2: /* signed integer */
387 fprintf(outFilep, "%" AFS_INT64_FMT, printfParms[pfpix++]);
388 break;
389 case 3: /* unsigned integer */
390 fprintf(outFilep, "%llu", printfParms[pfpix++]);
391 break;
392 case 4: /* octal integer */
393 fprintf(outFilep, "%llo", printfParms[pfpix++]);
394 break;
395 case 5: /* hex integer */
396 fprintf(outFilep, "%llx", printfParms[pfpix++]);
397 break;
398 default:
399 fprintf(outFilep,
400 "fstrace: Bad char %d in outMsgBuffer for parm %d\n",
401 outMsgBuffer[i], pfpix);
402 fprintf(outFilep, "fstrace: msgBuffer='%s'\n",
403 msgBuffer);
404 break;
405 }
406 }
407 }
408 fprintf(outFilep, "\n");
409 printed = 1;
410 }
411 #else /* AFS_SGI61_ENV */
412 if (CheckTypes(msgBuffer, printfTypes, pftix)) {
413 /* we have a string to use, but it ends "(dfs / zcm)",
414 * so we remove the extra gunk.
415 */
416 j = strlen(msgBuffer);
417 if (j > 12)
418 msgBuffer[j - 11] = 0;
419 fprintf(outFilep, "time %d.%06d, pid %u: ", alp[3] / 1000000,
420 alp[3] % 1000000, alp[2]);
421 fprintf(outFilep, msgBuffer, printfParms[0], printfParms[1],
422 printfParms[2], printfParms[3], printfParms[4],
423 printfParms[5], printfParms[6], printfParms[7],
424 printfParms[8], printfParms[9], printfParms[10],
425 printfParms[11], printfParms[12], printfParms[13],
426 printfParms[14], printfParms[15]);
427 fprintf(outFilep, "\n");
428 printed = 1;
429 }
430 #endif /* AFS_SGI61_ENV */
431 else {
432 fprintf(outFilep, "Type mismatch, using raw print.\n");
433 fprintf(outFilep, "%s", msgBuffer);
434 }
435 }
436 if (!printed) {
437 if (alp[1] == ICL_INFO_TIMESTAMP) {
438 tmv = alp[4];
439 fprintf(outFilep, "time %d.%06d, pid %u: %s\n", alp[3] / 1000000,
440 alp[3] % 1000000, alp[2], ctime(&tmv));
441 } else {
442 fprintf(outFilep, "raw op %d, time %d.%06d, pid %u\n", alp[1],
443 alp[3] / 1000000, alp[3] % 1000000, alp[2]);
444 /* now decode each parameter and print it */
445 pix = 4;
446 done = 0;
447 for (i = 0; !done && i < 4; i++) {
448 type = (temp >> (18 - i * 6)) & 0x3f;
449 switch (type) {
450 case ICL_TYPE_NONE:
451 done = 1;
452 break;
453 case ICL_TYPE_INT32:
454 fprintf(outFilep, "p%d:%d ", i, alp[pix]);
455 break;
456 case ICL_TYPE_LONG:
457 #ifdef AFS_SGI61_ENV
458 tempParam = alp[pix];
459 tempParam <<= 32;
460 tempParam |= alp[pix + 1];
461 fprintf(outFilep, "p%d:%" AFS_INT64_FMT " ", i, tempParam);
462 #else /* AFS_SGI61_ENV */
463 fprintf(outFilep, "p%d:%d ", i, alp[pix]);
464 #endif /* AFS_SGI61_ENV */
465 break;
466 case ICL_TYPE_POINTER:
467 #ifdef AFS_SGI61_ENV
468 tempParam = alp[pix];
469 tempParam <<= 32;
470 tempParam |= alp[pix + 1];
471 fprintf(outFilep, "p%d:0x%llx ", i, tempParam);
472 #else /* AFS_SGI61_ENV */
473 fprintf(outFilep, "p%d:0x%x ", i, alp[pix]);
474 #endif /* AFS_SGI61_ENV */
475 break;
476 case ICL_TYPE_HYPER:
477 case ICL_TYPE_INT64:
478 fprintf(outFilep, "p%d:%x.%x ", i, alp[pix],
479 alp[pix + 1]);
480 break;
481 case ICL_TYPE_FID:
482 fprintf(outFilep, "p%d:%d.%d.%d.%d ", i, alp[pix],
483 alp[pix + 1], alp[pix + 2], alp[pix + 3]);
484 break;
485 case ICL_TYPE_STRING:
486 fprintf(outFilep, "p%d:%s ", i, (char *)&alp[pix]);
487 break;
488 case ICL_TYPE_UNIXDATE:
489 tmv = alp[pix];
490 fprintf(outFilep, "p%d:%s ", i,
491 ctime(&tmv));
492 break;
493 default:
494 printf
495 ("DisplayRecord: Bad type %d in raw print switch.\n",
496 type);
497 done = 1;
498 break;
499 }
500 if (done)
501 break;
502
503 pix += icl_GetSize(type, (char *)&alp[pix]);
504 }
505 }
506 fprintf(outFilep, "\n"); /* done with line */
507 }
508 }
509
510
511
512 #include <locale.h>
513 #ifdef AFS_OSF_ENV
514 #include <limits.h>
515 #endif
516 #include <nl_types.h>
517
518 #define FACILITY_CODE_MASK 0xF0000000
519 #define FACILITY_CODE_SHIFT 28
520
521 #define COMPONENT_CODE_MASK 0x0FFFF000
522 #define COMPONENT_CODE_SHIFT 12
523
524 #define STATUS_CODE_MASK 0x00000FFF
525 #define STATUS_CODE_SHIFT 0
526
527 #define NO_MESSAGE "THIS IS NOT A MESSAGE"
528
529 /*
530 * We use NLS message catalog functions to convert numbers to human-readable
531 * strings. The message catalog will be in AFSDIR_DATA_DIR, which is
532 * ${datadir}/openafs with normal paths and /usr/vice/etc (for historical
533 * compatibility) for Transarc paths.
534 */
535
536 void
537 dce1_error_inq_text(afs_uint32 status_to_convert,
538 char *error_text, int *status)
539 {
540 unsigned short facility_code;
541 unsigned short component_code;
542 unsigned short status_code;
543 unsigned short i;
544 nl_catd catd;
545 char component_name[4];
546 char *facility_name;
547 char filename_prefix[7];
548 char nls_filename[80];
549 char *message;
550 static char *facility_names[] = {
551 "xxx",
552 "afs"
553 };
554
555 /*
556 * set up output status for future error returns
557 */
558 if (status != NULL) {
559 *status = -1;
560 }
561 /*
562 * check for ok input status
563 */
564 if (status_to_convert == 0) {
565 if (status != NULL) {
566 *status = 0;
567 }
568 strcpy((char *)error_text, "successful completion");
569 return;
570 }
571
572 /*
573 * extract the component, facility and status codes
574 */
575 facility_code =
576 (status_to_convert & FACILITY_CODE_MASK) >> FACILITY_CODE_SHIFT;
577 component_code =
578 (status_to_convert & COMPONENT_CODE_MASK) >> COMPONENT_CODE_SHIFT;
579 status_code = (status_to_convert & STATUS_CODE_MASK) >> STATUS_CODE_SHIFT;
580
581 /*
582 * see if this is a recognized facility
583 */
584 if (facility_code == 0
585 || facility_code > sizeof(facility_names) / sizeof(char *)) {
586 sprintf((char *)error_text, "status %08x (unknown facility)",
587 status_to_convert);
588 return;
589 }
590 facility_name = facility_names[facility_code - 1];
591 /*
592 * Convert component name from RAD-50 component code. (Mapping is:
593 * 0 => 'a', ..., 25 => 'z', 26 => '{', 27 => '0', ..., 36 => '9'.)
594 */
595 component_name[3] = 0;
596 component_name[2] = component_code % 40;
597 component_code /= 40;
598 component_name[1] = component_code % 40;
599 component_name[0] = component_code / 40;
600 for (i = 0; i < 3; i++) {
601 component_name[i] += (component_name[i] <= 26) ? 'a' : ('0' - 27);
602 }
603 sprintf(filename_prefix, "%3s%3s", facility_name, component_name);
604
605 /*
606 * We do not use the normal NLS message catalog search path since our use
607 * message catalogs isn't a typical use. It wouldn't make sense to
608 * install this special message catalog in with internationalization
609 * catalogs.
610 */
611 snprintf(nls_filename, sizeof(nls_filename), "%s/C/%s.cat",
612 AFSDIR_CLIENT_DATA_DIRPATH, filename_prefix);
613
614 catd = catopen(nls_filename, 0);
615 if (catd == (nl_catd) -1) {
616 sprintf((char *)error_text, "status %08x (%s / %s)",
617 status_to_convert, facility_name, component_name);
618 return;
619 }
620 /*
621 * try to get the specified message from the file
622 */
623 message = (char *)catgets(catd, 1, status_code, NO_MESSAGE);
624 /*
625 * if everything went well, return the resulting message
626 */
627 if (strcmp(message, NO_MESSAGE) != 0) {
628 sprintf((char *)error_text, "%s (%s / %s)", message, facility_name,
629 component_name);
630 if (status != NULL) {
631 *status = 0;
632 }
633 } else {
634 sprintf((char *)error_text, "status %08x (%s / %s)",
635 status_to_convert, facility_name, component_name);
636 }
637 catclose(catd);
638 }
639
640 int
641 icl_DumpKernel(FILE *outFilep, char *setname)
642 {
643 afs_int32 bufferSize = 0;
644 afs_int32 *bufferp;
645 afs_int32 i;
646 afs_int32 code, retVal = 0;
647 char tname[64];
648 afs_int32 nwords;
649 afs_int32 ix;
650 afs_int32 rlength;
651 afs_int32 dummy, dummy2;
652 struct logInfo *lip;
653
654 /* first, enumerate the logs we're interested in */
655 if (setname) {
656 int found = 0;
657 /* dump logs for a particular set */
658 for (i = 0; i < ICL_LOGSPERSET; i++) {
659 code =
660 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGSBYSET, (long)setname,
661 i, (long)tname, sizeof(tname), 0, 0);
662 if (code) {
663 if (errno == EBADF) {
664 continue; /* missing slot, nothing to worry about */
665 }
666 break;
667 }
668 code =
669 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
670 (long)&dummy, (long)&dummy2, 0, 0, 0);
671 if (code)
672 break;
673 found++;
674 if (dummy > bufferSize) /* find biggest log */
675 bufferSize = dummy;
676 lip = calloc(1, sizeof(struct logInfo));
677 lip->nextp = allInfo;
678 allInfo = lip;
679 lip->name = strdup(tname);
680 }
681 i = found;
682 } else {
683 /* dump all logs */
684 for (i = 0; i < 1000; i++) {
685 code =
686 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGS, i, (long)tname,
687 sizeof(tname), (long)&dummy, 0, 0);
688 if (code)
689 break;
690 if (dummy > bufferSize) /* find biggest log */
691 bufferSize = dummy;
692 lip = calloc(1, sizeof(struct logInfo));
693 lip->nextp = allInfo;
694 allInfo = lip;
695 lip->name = strdup(tname);
696 }
697 }
698
699 if (bufferSize == 0)
700 return -1;
701 bufferp = malloc(sizeof(afs_int32) * bufferSize);
702 if (!bufferp)
703 return -1;
704
705 fprintf(outFilep, "Found %d logs.\n", i);
706
707 /* now print out the contents of each log */
708 for (lip = allInfo; lip; lip = lip->nextp) {
709 fprintf(outFilep, "\nContents of log %s:\n", lip->name);
710 /* read out everything first; gets a more consistent
711 * snapshot.
712 */
713 nwords = 0; /* total words copied out */
714 for (i = 0;;) {
715 /* display all the entries in the log */
716 if (bufferSize - nwords <= 0)
717 break; /* filled whole buffer */
718 code =
719 afs_syscall(AFSCALL_ICL, ICL_OP_COPYOUT, (long)lip->name,
720 (long)(bufferp + nwords), bufferSize - nwords,
721 (long)&i, 0, 0);
722 if (code < 0) {
723 /* otherwise we've got an error */
724 fprintf(outFilep, "Returned error %d dumping log.\n", errno);
725 break;
726 }
727 /* otherwise, we have flags in the high order byte, and
728 * a length (in words) in the remainder.
729 */
730 if ((code >> 24) & ICL_COPYOUTF_MISSEDSOME)
731 fprintf(outFilep, "Log wrapped; data missing.\n");
732 code &= 0xffffff;
733 if (code == 0) {
734 /* we're done */
735 break;
736 }
737 nwords += code;
738 i += code;
739 } /* for loop over all cookies */
740
741 /* otherwise we should display all of the log entries here.
742 * Note that a record may end in the middle, in which case
743 * we should start over with the cookie value of the start
744 * of that record.
745 */
746 for (ix = 0; ix < nwords;) {
747 /* start of a record */
748 rlength = (bufferp[ix] >> 24) & 0xff;
749 if (rlength <= 0) {
750 fprintf(outFilep, "Internal error: 0 length record\n");
751 retVal = -1;
752 goto done;
753 }
754 /* ensure that entire record fits */
755 if (ix + rlength > nwords) {
756 /* doesn't fit, adjust cookie and break */
757 break;
758 }
759 /* print the record */
760 DisplayRecord(outFilep, &bufferp[ix], rlength);
761 ix += rlength;
762 #ifdef notdef
763 /* obsolete: read entire buffer first */
764 i += rlength; /* update cookie value, too */
765 #endif
766 } /* for loop displaying buffer */
767 } /* for loop over all logs */
768
769 done:
770 free(bufferp);
771 return (retVal);
772 }
773
774 /* clear out log 'name' */
775 int
776 icl_ClearLog(char *name)
777 {
778 afs_int32 code;
779
780 code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRLOG, (long)name, 0, 0, 0, 0, 0);
781 return code;
782 }
783
784 /* clear out set 'name' */
785 int
786 icl_ClearSet(char *name)
787 {
788 afs_int32 code;
789
790 code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRSET, (long)name, 0, 0, 0, 0, 0);
791 return code;
792 }
793
794 /* clear out all logs */
795 int
796 icl_ClearAll(void)
797 {
798 afs_int32 code;
799
800 code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRALL, 0, 0, 0, 0, 0, 0);
801 return code;
802 }
803
804 /* list out all available sets to outFileP */
805 int
806 icl_ListSets(FILE *outFileP)
807 {
808 int i;
809 afs_int32 code = 0;
810 afs_int32 states;
811 char tname[64];
812
813 for (i = 0; i < 1000; i++) {
814 code =
815 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMSETS, i, (long)tname,
816 sizeof(tname), (long)&states, 0, 0);
817 if (code)
818 break;
819 (void)fprintf(outFileP, "%s %s%s%s\n", tname,
820 (states & ICL_SETF_ACTIVE) ? "active" : "inactive",
821 (states & ICL_SETF_FREED) ? " (dormant)" : "",
822 (states & ICL_SETF_PERSISTENT) ? " persistent" : "");
823 }
824
825 return 0;
826 }
827
828 /* list out all available logs to outFileP */
829 int
830 icl_ListLogs(FILE *outFileP, int int32flg)
831 {
832 int i;
833 int allocated;
834 afs_int32 code = 0;
835 afs_int32 logSize;
836 char tname[64];
837
838 for (i = 0; i < 1000; i++) {
839 code =
840 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGS, i, (long)tname,
841 sizeof(tname), (long)&logSize, 0, 0);
842 if (code)
843 break;
844 if (int32flg) {
845 /* get more information on the log */
846 code =
847 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
848 (long)&logSize, (long)&allocated, 0, 0, 0);
849 if (code)
850 break;
851 (void)fprintf(outFileP, "%s : %d kbytes (%s)\n", tname,
852 logSize / 1024,
853 allocated ? "allocated" : "unallocated");
854 } else
855 (void)fprintf(outFileP, "%s\n", tname);
856 }
857
858 return 0;
859 }
860
861 /* list out all available logs to outFileP */
862 int
863 icl_ListLogsBySet(FILE *outFileP, char *setname, int int32flg)
864 {
865 int i;
866 afs_int32 code = 0;
867 afs_int32 logSize;
868 int allocated;
869 char tname[64];
870
871 for (i = 0; i < ICL_LOGSPERSET; i++) {
872 code =
873 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGSBYSET, (long)setname, i,
874 (long)tname, sizeof(tname), 0, 0);
875 if (code) {
876 if (errno == EBADF) {
877 code = 0;
878 continue; /* missing */
879 }
880 break;
881 }
882 if (int32flg) {
883 /* get more information on the log */
884 code =
885 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
886 (long)&logSize, (long)&allocated, 0, 0, 0);
887 if (code)
888 break;
889 (void)fprintf(outFileP, "%s : %d kbytes (%s)\n", tname,
890 logSize / 1024,
891 allocated ? "allocated" : "unallocated");
892 } else
893 (void)fprintf(outFileP, "%s\n", tname);
894 }
895
896 return code;
897 }
898
899 /* activate/deactivate/free specified set */
900 int
901 icl_ChangeSetState(char *name, afs_int32 op)
902 {
903 afs_int32 code;
904
905 code = afs_syscall(AFSCALL_ICL, ICL_OP_SETSTAT, (long)name, op, 0, 0, 0, 0);
906 return code;
907 }
908
909 /* activate/deactivate/free all sets */
910 int
911 icl_ChangeAllSetState(afs_int32 op)
912 {
913 afs_int32 code;
914
915 code = afs_syscall(AFSCALL_ICL, ICL_OP_SETSTATALL, op, 0, 0, 0, 0, 0);
916 return code;
917 }
918
919 /* set size if log */
920 int
921 icl_ChangeLogSize(char *name, afs_int32 logSize)
922 {
923 afs_int32 code;
924
925 code =
926 afs_syscall(AFSCALL_ICL, ICL_OP_SETLOGSIZE, (long)name, logSize, 0,
927 0, 0, 0);
928 return code;
929 }
930
931 /* get logsize of specified log */
932 int
933 icl_GetLogsize(char *logname, afs_int32 *logSizeP, int *allocatedP)
934 {
935 afs_int32 code;
936 code =
937 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
938 (long)logSizeP, (long)allocatedP, 0, 0, 0);
939 return code;
940 }
941
942 /* get state of specified set */
943 int
944 icl_GetSetState(char *setname, afs_int32 *stateP)
945 {
946 afs_int32 code;
947 code =
948 afs_syscall(AFSCALL_ICL, ICL_OP_GETSETINFO, (long)setname,
949 (long)stateP, 0, 0, 0, 0);
950 return code;
951 }
952
953 int
954 icl_TailKernel(FILE *outFilep, char *logname, afs_int32 waitTime)
955 {
956 afs_int32 bufferSize = 0;
957 afs_int32 newBufferSize;
958 afs_int32 *bufferp;
959 afs_int32 i;
960 afs_int32 code, retVal = 0;
961 afs_int32 nwords;
962 afs_int32 ix;
963 afs_int32 rlength;
964 int allocated;
965
966 /* get information about the specified log */
967 code =
968 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
969 (long)&bufferSize, (long)&allocated, 0, 0, 0);
970 if (code) {
971 if (errno == ENOENT)
972 (void)fprintf(stderr, "'%s' not found\n", logname);
973 else
974 (void)fprintf(stderr,
975 "cannot get information on log '%s' (errno = %d)\n",
976 logname, errno);
977 return -1;
978 }
979
980 if (!allocated) {
981 (void)fprintf(stderr, "'%s' not allocated\n", logname);
982 return 0;
983 }
984
985 if (bufferSize == 0)
986 return -1;
987 bufferp = malloc(sizeof(afs_int32) * bufferSize);
988 if (!bufferp) {
989 (void)fprintf(stderr, "cannot allocate %d words for buffer\n",
990 bufferSize);
991 return -1;
992 }
993
994 /* start "infinite" loop */
995 for (;;) {
996 /* read out all that's currently there */
997 nwords = 0; /* total words copied out */
998 i = 0; /* initialize cookie */
999 for (;;) {
1000 /* display all the entries in the log */
1001 if (bufferSize - nwords <= 0)
1002 break; /* filled whole buffer, clear when done */
1003 code =
1004 afs_syscall(AFSCALL_ICL, ICL_OP_COPYOUTCLR, (long)logname,
1005 (long)(bufferp + nwords), bufferSize - nwords,
1006 (long)&i, 0, 0);
1007 if (code < 0) {
1008 /* otherwise we've got an error */
1009 fprintf(stderr, "returned error %d dumping log.\n", errno);
1010 retVal = -1;
1011 goto tail_done;
1012 }
1013 /* otherwise, we have flags in the high order byte, and
1014 * a length (in words) in the remainder.
1015 */
1016 code &= 0xffffff;
1017 if (code == 0) {
1018 /* we're done */
1019 break;
1020 }
1021 nwords += code;
1022 i += code;
1023 } /* for loop over all cookies */
1024
1025 /* otherwise we should display all of the log entries here.
1026 * Note that a record may end in the middle, in which case
1027 * we should start over with the cookie value of the start
1028 * of that record.
1029 */
1030 for (ix = 0; ix < nwords;) {
1031 /* start of a record */
1032 rlength = (bufferp[ix] >> 24) & 0xff;
1033 /* ensure that entire record fits */
1034 if (ix + rlength > nwords) {
1035 /* doesn't fit, adjust cookie and break */
1036 if (rlength <= 0) {
1037 fprintf(stderr, "BOGUS: 0 length record\n");
1038 retVal = -1;
1039 goto tail_done;
1040 }
1041 break;
1042 }
1043 /* print the record */
1044 DisplayRecord(outFilep, &bufferp[ix], rlength);
1045 ix += rlength;
1046 } /* for loop displaying buffer */
1047
1048 if (waitTime)
1049 sleep(waitTime);
1050
1051 /* see if things have changed */
1052 code =
1053 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
1054 (long)&newBufferSize, (long)&allocated, 0, 0, 0);
1055 if (code) {
1056 if (errno == ENOENT)
1057 (void)fprintf(stderr, "'%s' not found\n", logname);
1058 else
1059 (void)fprintf(stderr,
1060 "cannot get information on log '%s' (errno = %d)\n",
1061 logname, errno);
1062 retVal = -1;
1063 goto tail_done;
1064 }
1065
1066 if (!allocated) {
1067 (void)fprintf(stderr, "'%s' no int32er allocated\n", logname);
1068 retVal = -1;
1069 goto tail_done;
1070 }
1071
1072 if (bufferSize == 0) {
1073 (void)fprintf(stderr, "buffer size has become 0\n");
1074 retVal = -1;
1075 goto tail_done;
1076 }
1077 if (bufferSize != newBufferSize) {
1078 /* have to reallocate a buffer */
1079 bufferSize = newBufferSize;
1080 free(bufferp);
1081 bufferp = malloc(sizeof(afs_int32) * bufferSize);
1082 if (!bufferp) {
1083 (void)fprintf(stderr, "cannot allocate %d words for buffer\n",
1084 bufferSize);
1085 retVal = -1;
1086 goto tail_done;
1087 }
1088 }
1089 } /* infinite loop */
1090
1091 tail_done:
1092 free(bufferp);
1093 return (retVal);
1094 }
1095
1096 #if !defined(AFS_SGI_ENV)
1097 int
1098 afs_syscall(long call, long parm0, long parm1, long parm2, long parm3,
1099 long parm4, long parm5, long parm6)
1100 {
1101 int code;
1102 #if defined(AFS_DARWIN80_ENV) || defined(AFS_LINUX20_ENV)
1103 int rval;
1104 #endif
1105 #ifdef AFS_LINUX20_ENV
1106 #if defined AFS_LINUX_64BIT_KERNEL
1107 long long eparm[4];
1108 /* don't want to sign extend it to 64bit, so using ulong */
1109 eparm[0] = (unsigned long)parm3;
1110 eparm[1] = (unsigned long)parm4;
1111 eparm[2] = (unsigned long)parm5;
1112 eparm[3] = (unsigned long)parm6;
1113 #else
1114 int eparm[4];
1115 eparm[0] = parm3;
1116 eparm[1] = parm4;
1117 eparm[2] = parm5;
1118 eparm[3] = parm6;
1119 #endif
1120 /* Linux can only handle 5 arguments in the actual syscall. */
1121 if (call == AFSCALL_ICL) {
1122 rval = proc_afs_syscall(call, parm0, parm1, parm2, (long)eparm, &code);
1123 if (rval) {
1124 #ifdef AFS_SYSCALL
1125 code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, eparm);
1126 #else
1127 code = -1;
1128 #endif
1129 }
1130 } else {
1131 rval = proc_afs_syscall(call, parm0, parm1, parm2, parm3, &code);
1132 if (rval) {
1133 #ifdef AFS_SYSCALL
1134 code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, parm3);
1135 #else
1136 code = -1;
1137 #endif
1138 }
1139 }
1140 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
1141 /* on sparc this function returns none value, so do it myself */
1142 __asm__ __volatile__("mov %o0, %i0; ret; restore");
1143 #endif
1144 #else
1145 #ifdef AFS_DARWIN80_ENV
1146 code = ioctl_afs_syscall(call, parm0, parm1, parm2, parm3, parm4, parm5, &rval);
1147 if (!code) code = rval;
1148 #else
1149 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
1150 # if defined(AFS_SYSCALL)
1151 code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, parm3, parm4);
1152 # else
1153 code = -1;
1154 # endif
1155 #else
1156 #if defined(AFS_SGI_ENV)
1157 code = syscall(AFS_ICL, call, parm0, parm1, parm2, parm3, parm4); /* XXX */
1158 #else
1159 code = syscall(AFSCALL_ICL, parm0, parm1, parm2, parm3, parm4);
1160 #endif
1161 #endif
1162 #endif
1163 #endif /* AFS_LINUX20_ENV */
1164 return code;
1165 }
1166 #endif
1167
1168
1169 int icl_inited = 0;
1170
1171 /* init function, called once, under icl_lock */
1172 int
1173 icl_Init(void)
1174 {
1175 icl_inited = 1;
1176
1177 #ifndef KERNEL
1178 /* setup signal handler, in user space */
1179 #endif /* KERNEL */
1180
1181 return 0;
1182 }
1183
1184 int
1185 icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
1186 struct afs_icl_log *fatalLogp, struct afs_icl_set **outSetpp)
1187 {
1188 return icl_CreateSetWithFlags(name, baseLogp, fatalLogp, /*flags */ 0,
1189 outSetpp);
1190 }
1191
1192 /* create a set, given pointers to base and fatal logs, if any.
1193 * Logs are unlocked, but referenced, and *outSetpp is returned
1194 * referenced. Function bumps reference count on logs, since it
1195 * addds references from the new icl_set. When the set is destroyed,
1196 * those references will be released.
1197 */
1198 int
1199 icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
1200 struct afs_icl_log *fatalLogp, afs_uint32 flags,
1201 struct afs_icl_set **outSetpp)
1202 {
1203 struct afs_icl_set *setp;
1204 int i;
1205 afs_int32 states = ICL_DEFAULT_SET_STATES;
1206
1207 if (!icl_inited)
1208 icl_Init();
1209
1210 for (setp = icl_allSets; setp; setp = setp->nextp) {
1211 if (strcmp(setp->name, name) == 0) {
1212 setp->refCount++;
1213 *outSetpp = setp;
1214 if (flags & ICL_CRSET_FLAG_PERSISTENT) {
1215 setp->states |= ICL_SETF_PERSISTENT;
1216 }
1217 return 0;
1218 }
1219 }
1220
1221 /* determine initial state */
1222 if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
1223 states = ICL_SETF_ACTIVE;
1224 else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
1225 states = ICL_SETF_FREED;
1226 if (flags & ICL_CRSET_FLAG_PERSISTENT)
1227 states |= ICL_SETF_PERSISTENT;
1228
1229 setp = osi_Alloc(sizeof(struct afs_icl_set));
1230 memset((caddr_t) setp, 0, sizeof(*setp));
1231 setp->refCount = 1;
1232 if (states & ICL_SETF_FREED)
1233 states &= ~ICL_SETF_ACTIVE; /* if freed, can't be active */
1234 setp->states = states;
1235
1236 setp->name = osi_Alloc(strlen(name) + 1);
1237 strcpy(setp->name, name);
1238 setp->nevents = ICL_DEFAULTEVENTS;
1239 setp->eventFlags = osi_Alloc(ICL_DEFAULTEVENTS);
1240 for (i = 0; i < ICL_DEFAULTEVENTS; i++)
1241 setp->eventFlags[i] = 0xff; /* default to enabled */
1242
1243 /* update this global info under the icl_lock */
1244 setp->nextp = icl_allSets;
1245 icl_allSets = setp;
1246
1247 /* set's basic lock is still held, so we can finish init */
1248 if (baseLogp) {
1249 setp->logs[0] = baseLogp;
1250 icl_LogHold(baseLogp);
1251 if (!(setp->states & ICL_SETF_FREED))
1252 icl_LogUse(baseLogp); /* log is actually being used */
1253 }
1254 if (fatalLogp) {
1255 setp->logs[1] = fatalLogp;
1256 icl_LogHold(fatalLogp);
1257 if (!(setp->states & ICL_SETF_FREED))
1258 icl_LogUse(fatalLogp); /* log is actually being used */
1259 }
1260
1261 *outSetpp = setp;
1262 return 0;
1263 }
1264
1265 /* function to change event enabling information for a particular set */
1266 int
1267 icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
1268 {
1269 char *tp;
1270
1271 if (!ICL_EVENTOK(setp, eventID)) {
1272 return -1;
1273 }
1274 tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
1275 if (setValue)
1276 *tp |= ICL_EVENTMASK(eventID);
1277 else
1278 *tp &= ~(ICL_EVENTMASK(eventID));
1279 return 0;
1280 }
1281
1282 /* return indication of whether a particular event ID is enabled
1283 * for tracing. If *getValuep is set to 0, the event is disabled,
1284 * otherwise it is enabled. All events start out enabled by default.
1285 */
1286 int
1287 icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
1288 {
1289 if (!ICL_EVENTOK(setp, eventID)) {
1290 return -1;
1291 }
1292 if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
1293 *getValuep = 1;
1294 else
1295 *getValuep = 0;
1296 return 0;
1297 }
1298
1299 /* hold and release event sets */
1300 int
1301 icl_SetHold(struct afs_icl_set *setp)
1302 {
1303 setp->refCount++;
1304 return 0;
1305 }
1306
1307 /* free a set. Called with icl_lock locked */
1308 int
1309 icl_ZapSet(struct afs_icl_set *setp)
1310 {
1311 struct afs_icl_set **lpp, *tp;
1312 int i;
1313 struct afs_icl_log *tlp;
1314
1315 for (lpp = &icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1316 if (tp == setp) {
1317 /* found the dude we want to remove */
1318 *lpp = setp->nextp;
1319 osi_Free(setp->name, 1 + strlen(setp->name));
1320 osi_Free(setp->eventFlags, ICL_EVENTBYTES(setp->nevents));
1321 for (i = 0; i < ICL_LOGSPERSET; i++) {
1322 if ((tlp = setp->logs[i]))
1323 icl_LogReleNL(tlp);
1324 }
1325 osi_Free(setp, sizeof(struct afs_icl_set));
1326 break; /* won't find it twice */
1327 }
1328 }
1329 return 0;
1330 }
1331
1332 /* do the release, watching for deleted entries */
1333 int
1334 icl_SetRele(struct afs_icl_set *setp)
1335 {
1336 if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
1337 icl_ZapSet(setp); /* destroys setp's lock! */
1338 }
1339 return 0;
1340 }
1341
1342 /* free a set entry, dropping its reference count */
1343 int
1344 icl_SetFree(struct afs_icl_set *setp)
1345 {
1346 setp->states |= ICL_SETF_DELETED;
1347 icl_SetRele(setp);
1348 return 0;
1349 }
1350
1351 /* find a set by name, returning it held */
1352 struct afs_icl_set *
1353 icl_FindSet(char *name)
1354 {
1355 struct afs_icl_set *tp;
1356
1357 for (tp = icl_allSets; tp; tp = tp->nextp) {
1358 if (strcmp(tp->name, name) == 0) {
1359 /* this is the dude we want */
1360 tp->refCount++;
1361 break;
1362 }
1363 }
1364 return tp;
1365 }
1366
1367 /* zero out all the logs in the set */
1368 int
1369 icl_ZeroSet(struct afs_icl_set *setp)
1370 {
1371 int i;
1372 int code = 0;
1373 int tcode;
1374 struct afs_icl_log *logp;
1375
1376 for (i = 0; i < ICL_LOGSPERSET; i++) {
1377 logp = setp->logs[i];
1378 if (logp) {
1379 icl_LogHold(logp);
1380 tcode = icl_ZeroLog(logp);
1381 if (tcode != 0)
1382 code = tcode; /* save the last bad one */
1383 icl_LogRele(logp);
1384 }
1385 }
1386 return code;
1387 }
1388
1389 int
1390 icl_EnumerateSets(int (*aproc) (char *, void *, struct afs_icl_set *),
1391 void *arock)
1392 {
1393 struct afs_icl_set *tp, *np;
1394 afs_int32 code;
1395
1396 code = 0;
1397 for (tp = icl_allSets; tp; tp = np) {
1398 tp->refCount++; /* hold this guy */
1399 code = (*aproc) (tp->name, arock, tp);
1400 np = tp->nextp; /* tp may disappear next, but not np */
1401 if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
1402 icl_ZapSet(tp);
1403 if (code)
1404 break;
1405 }
1406 return code;
1407 }
1408
1409 int
1410 icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
1411 {
1412 int i;
1413 int code = -1;
1414
1415 for (i = 0; i < ICL_LOGSPERSET; i++) {
1416 if (!setp->logs[i]) {
1417 setp->logs[i] = newlogp;
1418 code = i;
1419 icl_LogHold(newlogp);
1420 if (!(setp->states & ICL_SETF_FREED)) {
1421 /* bump up the number of sets using the log */
1422 icl_LogUse(newlogp);
1423 }
1424 break;
1425 }
1426 }
1427 return code;
1428 }
1429
1430 int
1431 icl_SetSetStat(struct afs_icl_set *setp, int op)
1432 {
1433 int i;
1434 afs_int32 code;
1435 struct afs_icl_log *logp;
1436
1437 switch (op) {
1438 case ICL_OP_SS_ACTIVATE: /* activate a log */
1439 /*
1440 * If we are not already active, see if we have released
1441 * our demand that the log be allocated (FREED set). If
1442 * we have, reassert our desire.
1443 */
1444 if (!(setp->states & ICL_SETF_ACTIVE)) {
1445 if (setp->states & ICL_SETF_FREED) {
1446 /* have to reassert desire for logs */
1447 for (i = 0; i < ICL_LOGSPERSET; i++) {
1448 logp = setp->logs[i];
1449 if (logp) {
1450 icl_LogHold(logp);
1451 icl_LogUse(logp);
1452 icl_LogRele(logp);
1453 }
1454 }
1455 setp->states &= ~ICL_SETF_FREED;
1456 }
1457 setp->states |= ICL_SETF_ACTIVE;
1458 }
1459 code = 0;
1460 break;
1461
1462 case ICL_OP_SS_DEACTIVATE: /* deactivate a log */
1463 /* this doesn't require anything beyond clearing the ACTIVE flag */
1464 setp->states &= ~ICL_SETF_ACTIVE;
1465 code = 0;
1466 break;
1467
1468 case ICL_OP_SS_FREE: /* deassert design for log */
1469 /*
1470 * if we are already in this state, do nothing; otherwise
1471 * deassert desire for log
1472 */
1473 if (setp->states & ICL_SETF_ACTIVE)
1474 code = EINVAL;
1475 else {
1476 if (!(setp->states & ICL_SETF_FREED)) {
1477 for (i = 0; i < ICL_LOGSPERSET; i++) {
1478 logp = setp->logs[i];
1479 if (logp) {
1480 icl_LogHold(logp);
1481 icl_LogFreeUse(logp);
1482 icl_LogRele(logp);
1483 }
1484 }
1485 setp->states |= ICL_SETF_FREED;
1486 }
1487 code = 0;
1488 }
1489 break;
1490
1491 default:
1492 code = EINVAL;
1493 }
1494
1495 return code;
1496 }
1497
1498 struct afs_icl_log *afs_icl_allLogs = 0;
1499
1500 /* hold and release logs */
1501 int
1502 icl_LogHold(struct afs_icl_log *logp)
1503 {
1504 logp->refCount++;
1505 return 0;
1506 }
1507
1508 /* hold and release logs, called with lock already held */
1509 int
1510 icl_LogHoldNL(struct afs_icl_log *logp)
1511 {
1512 logp->refCount++;
1513 return 0;
1514 }
1515
1516 /* keep track of how many sets believe the log itself is allocated */
1517 int
1518 icl_LogUse(struct afs_icl_log *logp)
1519 {
1520 if (logp->setCount == 0) {
1521 /* this is the first set actually using the log -- allocate it */
1522 if (logp->logSize == 0) {
1523 /* we weren't passed in a hint and it wasn't set */
1524 logp->logSize = ICL_DEFAULT_LOGSIZE;
1525 }
1526 logp->datap = osi_Alloc(sizeof(afs_int32) * logp->logSize);
1527 }
1528 logp->setCount++;
1529 return 0;
1530 }
1531
1532 /* decrement the number of real users of the log, free if possible */
1533 int
1534 icl_LogFreeUse(struct afs_icl_log *logp)
1535 {
1536 if (--logp->setCount == 0) {
1537 /* no more users -- free it (but keep log structure around) */
1538 osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
1539 logp->firstUsed = logp->firstFree = 0;
1540 logp->logElements = 0;
1541 logp->datap = NULL;
1542 }
1543 return 0;
1544 }
1545
1546 /* set the size of the log to 'logSize' */
1547 int
1548 icl_LogSetSize(struct afs_icl_log *logp, afs_int32 logSize)
1549 {
1550 if (!logp->datap) {
1551 /* nothing to worry about since it's not allocated */
1552 logp->logSize = logSize;
1553 } else {
1554 /* reset log */
1555 logp->firstUsed = logp->firstFree = 0;
1556 logp->logElements = 0;
1557
1558 /* free and allocate a new one */
1559 osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
1560 logp->datap = osi_Alloc(sizeof(afs_int32) * logSize);
1561 logp->logSize = logSize;
1562 }
1563
1564 return 0;
1565 }
1566
1567 /* free a log. Called with icl_lock locked. */
1568 int
1569 icl_ZapLog(struct afs_icl_log *logp)
1570 {
1571 struct afs_icl_log **lpp, *tp;
1572
1573 for (lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1574 if (tp == logp) {
1575 /* found the dude we want to remove */
1576 *lpp = logp->nextp;
1577 osi_Free(logp->name, 1 + strlen(logp->name));
1578 osi_Free(logp->datap, logp->logSize * sizeof(afs_int32));
1579 osi_Free(logp, sizeof(struct icl_log));
1580 break; /* won't find it twice */
1581 }
1582 }
1583 return 0;
1584 }
1585
1586 /* do the release, watching for deleted entries */
1587 int
1588 icl_LogRele(struct afs_icl_log *logp)
1589 {
1590 if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1591 icl_ZapLog(logp); /* destroys logp's lock! */
1592 }
1593 return 0;
1594 }
1595
1596 /* do the release, watching for deleted entries, log already held */
1597 int
1598 icl_LogReleNL(struct afs_icl_log *logp)
1599 {
1600 if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1601 icl_ZapLog(logp); /* destroys logp's lock! */
1602 }
1603 return 0;
1604 }
1605
1606 /* zero out the log */
1607 int
1608 icl_ZeroLog(struct afs_icl_log *logp)
1609 {
1610 logp->firstUsed = logp->firstFree = 0;
1611 logp->logElements = 0;
1612 return 0;
1613 }
1614
1615 /* free a log entry, and drop its reference count */
1616 int
1617 icl_LogFree(struct afs_icl_log *logp)
1618 {
1619 logp->states |= ICL_LOGF_DELETED;
1620 icl_LogRele(logp);
1621 return 0;
1622 }
1623
1624
1625 int
1626 icl_EnumerateLogs(int (*aproc)
1627 (char *name, void *arock, struct afs_icl_log * tp),
1628 void *arock)
1629 {
1630 struct afs_icl_log *tp, *np;
1631 afs_int32 code;
1632
1633 code = 0;
1634 for (tp = afs_icl_allLogs; tp; tp = np) {
1635 tp->refCount++; /* hold this guy */
1636 np = tp->nextp;
1637 code = (*aproc) (tp->name, arock, tp);
1638 if (--tp->refCount == 0)
1639 icl_ZapLog(tp);
1640 if (code)
1641 break;
1642 }
1643 return code;
1644 }
1645
1646
1647 afs_icl_bulkSetinfo_t *
1648 GetBulkSetInfo(void)
1649 {
1650 unsigned int infoSize;
1651
1652 infoSize =
1653 sizeof(afs_icl_bulkSetinfo_t) + (ICL_RPC_MAX_SETS -
1654 1) * sizeof(afs_icl_setinfo_t);
1655 if (!setInfo) {
1656 setInfo = calloc(1, infoSize);
1657 if (!setInfo) {
1658 (void)fprintf(stderr,
1659 "Could not allocate the memory for bulk set info structure\n");
1660 exit(1);
1661 }
1662 }
1663
1664 return setInfo;
1665 }
1666
1667 afs_icl_bulkLoginfo_t *
1668 GetBulkLogInfo(void)
1669 {
1670 unsigned int infoSize;
1671
1672 infoSize =
1673 sizeof(afs_icl_bulkLoginfo_t) + (ICL_RPC_MAX_LOGS -
1674 1) * sizeof(afs_icl_loginfo_t);
1675 if (!logInfo) {
1676 logInfo = calloc(1, infoSize);
1677 if (!logInfo) {
1678 (void)fprintf(stderr,
1679 "Could not allocate the memory for bulk log info structure\n");
1680 exit(1);
1681 }
1682 }
1683
1684 return logInfo;
1685 }
1686
1687
1688 static int
1689 DoDump(struct cmd_syndesc *as, void *arock)
1690 {
1691 afs_int32 code = 0;
1692 afs_int32 tcode;
1693 afs_int32 waitTime = 10 /* seconds */ ;
1694 char *logname;
1695 FILE *outfp = stdout;
1696 time_t startTime;
1697 struct cmd_item *itemp;
1698
1699 if (geteuid() != 0) {
1700 printf("fstrace must be run as root\n");
1701 exit(1);
1702 }
1703
1704 if (as->parms[3].items) {
1705 if (!as->parms[1].items) {
1706 (void)fprintf(stderr, "-sleep can only be used with -follow\n");
1707 return 1;
1708 }
1709 waitTime = strtol(as->parms[3].items->data, NULL, 0);
1710 }
1711
1712 if (as->parms[2].items) {
1713 /* try to open the specified output file */
1714 if ((outfp = fopen(as->parms[2].items->data, "w")) == NULL) {
1715 (void)fprintf(stderr, "Cannot open file '%s' for writing\n",
1716 as->parms[2].items->data);
1717 return 1;
1718 }
1719 }
1720 #ifdef AFS_SGI64_ENV
1721 startTime = time((time_t *) 0);
1722 #else
1723 startTime = time(0);
1724 #endif
1725 (void)fprintf(outfp, "AFS Trace Dump -\n\n Date: %s\n",
1726 ctime(&startTime));
1727
1728 if (as->parms[0].items) {
1729 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1730 tcode = icl_DumpKernel(outfp, itemp->data);
1731 if (tcode) {
1732 (void)fprintf(stderr, "Unable to dump set %s (errno = %d)\n",
1733 itemp->data, errno);
1734 code = tcode;
1735 }
1736 }
1737 } else if (as->parms[1].items) {
1738 logname = as->parms[1].items->data;
1739 code = icl_TailKernel(outfp, logname, waitTime);
1740 if (code) {
1741 (void)fprintf(stderr,
1742 "Error tailing kernel log '%s' (errno = %d)\n",
1743 logname, errno);
1744 }
1745 } else
1746 code = icl_DumpKernel(outfp, NULL);
1747
1748 (void)fprintf(outfp, "\nAFS Trace Dump - %s\n",
1749 code ? "FAILED" : "Completed");
1750
1751 if (outfp != stdout)
1752 (void)fclose(outfp);
1753
1754 return code;
1755 }
1756
1757 static void
1758 SetUpDump(void)
1759 {
1760 struct cmd_syndesc *dumpSyntax;
1761
1762 dumpSyntax =
1763 cmd_CreateSyntax("dump", DoDump, NULL, 0, "dump AFS trace logs");
1764 (void)cmd_AddParm(dumpSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1765 "event set name");
1766 (void)cmd_AddParm(dumpSyntax, "-follow", CMD_SINGLE, CMD_OPTIONAL,
1767 "trace log name");
1768 (void)cmd_AddParm(dumpSyntax, "-file", CMD_SINGLE, CMD_OPTIONAL,
1769 "path to trace log file for writing");
1770 (void)cmd_AddParm(dumpSyntax, "-sleep", CMD_SINGLE, CMD_OPTIONAL,
1771 "interval (secs) for writes when using -follow");
1772 }
1773
1774
1775 static int
1776 DoShowLog(struct cmd_syndesc *as, void *arock)
1777 {
1778 afs_int32 retVal = 0;
1779 afs_int32 code = 0;
1780 afs_int32 logSize;
1781 int allocated;
1782 int int32flg = 0;
1783 struct cmd_item *itemp;
1784
1785 if (geteuid() != 0) {
1786 printf("fstrace must be run as root\n");
1787 exit(1);
1788 }
1789 if (as->parms[2].items)
1790 int32flg = 1;
1791
1792 if (as->parms[0].items) {
1793 /* enumerate logs for the specified sets */
1794 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1795 (void)fprintf(stdout, "Logs for set '%s':\n", itemp->data);
1796 code = icl_ListLogsBySet(stdout, itemp->data, int32flg);
1797 if (code) {
1798 (void)fprintf(stderr,
1799 "Error in enumerating set %s (errno = %d)\n",
1800 itemp->data, errno);
1801 retVal = code;
1802 }
1803 }
1804 } else if (as->parms[1].items) {
1805 /* print out log information */
1806 for (itemp = as->parms[1].items; itemp; itemp = itemp->next) {
1807 code = icl_GetLogsize(itemp->data, &logSize, &allocated);
1808 if (!code)
1809 (void)fprintf(stdout, "%s : %d kbytes (%s)\n", itemp->data,
1810 logSize / 1024,
1811 allocated ? "allocated" : "unallocated");
1812 else {
1813 (void)fprintf(stderr,
1814 "Could not find log '%s' (errno = %d)\n",
1815 itemp->data, errno);
1816 retVal = code;
1817 }
1818 }
1819 } else {
1820 /* show all logs */
1821 (void)fprintf(stdout, "Available logs:\n");
1822 code = icl_ListLogs(stdout, int32flg);
1823 if (code) {
1824 (void)fprintf(stderr, "Error in listing logs (errno = %d)\n",
1825 errno);
1826 retVal = code;
1827 }
1828 }
1829
1830 return retVal;
1831 }
1832
1833 static void
1834 SetUpShowLog(void)
1835 {
1836 struct cmd_syndesc *showSyntax;
1837
1838 showSyntax =
1839 cmd_CreateSyntax("lslog", DoShowLog, NULL, 0,
1840 "list available logs");
1841 (void)cmd_AddParm(showSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1842 "event set name");
1843 (void)cmd_AddParm(showSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
1844 "trace log name");
1845 (void)cmd_AddParm(showSyntax, "-long", CMD_FLAG, CMD_OPTIONAL,
1846 "show defined log size in kbytes & if it is allocated in kernel mem");
1847 }
1848
1849 static int
1850 DoShowSet(struct cmd_syndesc *as, void *arock)
1851 {
1852 afs_int32 retVal = 0;
1853 afs_int32 code = 0;
1854 afs_int32 state;
1855 struct cmd_item *itemp;
1856
1857 if (geteuid() != 0) {
1858 printf("fstrace must be run as root\n");
1859 exit(1);
1860 }
1861 if (as->parms[0].items) {
1862 /* print information on the specified sets */
1863 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1864 code = icl_GetSetState(itemp->data, &state);
1865 if (code) {
1866 (void)fprintf(stderr,
1867 "Error getting status on set %s (errno = %d)\n",
1868 itemp->data, errno);
1869 retVal = code;
1870 } else
1871 (void)fprintf(stdout, "Set %s: %s%s%s\n", itemp->data,
1872 (state & ICL_SETF_ACTIVE) ? "active" :
1873 "inactive",
1874 (state & ICL_SETF_FREED) ? " (dormant)" : "",
1875 (state & ICL_SETF_PERSISTENT) ? " persistent" :
1876 "");
1877 }
1878 } else {
1879 /* show all sets */
1880 (void)fprintf(stdout, "Available sets:\n");
1881 code = icl_ListSets(stdout);
1882 if (code) {
1883 (void)fprintf(stderr, "Error in listing sets (errno = %d)\n",
1884 errno);
1885 retVal = code;
1886 }
1887 }
1888
1889 return retVal;
1890 }
1891
1892 static void
1893 SetUpShowSet(void)
1894 {
1895 struct cmd_syndesc *showSyntax;
1896
1897 showSyntax =
1898 cmd_CreateSyntax("lsset", DoShowSet, NULL, 0,
1899 "list available event sets");
1900 (void)cmd_AddParm(showSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1901 "event set name");
1902 }
1903
1904 static int
1905 DoClear(struct cmd_syndesc *as, void *arock)
1906 {
1907 afs_int32 retVal = 0;
1908 afs_int32 code = 0;
1909 struct cmd_item *itemp;
1910
1911 if (geteuid() != 0) {
1912 printf("fstrace must be run as root\n");
1913 exit(1);
1914 }
1915 if (as->parms[0].items) {
1916 /* clear logs for the specified sets */
1917 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1918 code = icl_ClearSet(itemp->data);
1919 if (code) {
1920 (void)fprintf(stderr,
1921 "Error in clearing set %s (errno = %d)\n",
1922 itemp->data, errno);
1923 retVal = code;
1924 }
1925 }
1926 } else if (as->parms[1].items) {
1927 /* clear specified log */
1928 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1929 code = icl_ClearLog(itemp->data);
1930 if (code) {
1931 (void)fprintf(stderr,
1932 "Error in clearing log %s (errno = %d)\n",
1933 itemp->data, errno);
1934 retVal = code;
1935 }
1936 }
1937 } else {
1938 /* clear all logs */
1939 code = icl_ClearAll();
1940 if (code) {
1941 (void)fprintf(stderr, "Error in clearing logs (errno = %d)\n",
1942 errno);
1943 retVal = code;
1944 }
1945 }
1946
1947 return retVal;
1948 }
1949
1950 static void
1951 SetUpClear(void)
1952 {
1953 struct cmd_syndesc *clearSyntax;
1954
1955 clearSyntax =
1956 cmd_CreateSyntax("clear", DoClear, NULL, 0,
1957 "clear logs by logname or by event set");
1958 (void)cmd_AddParm(clearSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1959 "event set name");
1960 (void)cmd_AddParm(clearSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
1961 "trace log name");
1962 }
1963
1964 static int
1965 DoSet(struct cmd_syndesc *as, void *arock)
1966 {
1967 afs_int32 retVal = 0;
1968 afs_int32 code = 0;
1969 int op;
1970 int doFree = 0;
1971 char *operation;
1972 struct cmd_item *itemp;
1973
1974 if (geteuid() != 0) {
1975 printf("fstrace must be run as root\n");
1976 exit(1);
1977 }
1978 if (as->parms[1].items) {
1979 op = ICL_OP_SS_ACTIVATE;
1980 operation = "active";
1981 } else if (as->parms[2].items) {
1982 op = ICL_OP_SS_DEACTIVATE;
1983 operation = "inactive";
1984 } else if (as->parms[3].items) {
1985 op = ICL_OP_SS_DEACTIVATE;
1986 operation = "inactive";
1987 doFree = 1;
1988 } else {
1989 /* assume active" */
1990 op = ICL_OP_SS_ACTIVATE;
1991 operation = "active";
1992 }
1993
1994 if (as->parms[0].items) {
1995 /* activate specified sets */
1996 for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1997 code = icl_ChangeSetState(itemp->data, op);
1998 if (code) {
1999 (void)fprintf(stderr,
2000 "cannot set state of %s to %s (errno = %d)\n",
2001 itemp->data, operation, errno);
2002 retVal = code;
2003 } else if (doFree) {
2004 /* try to make it dormant as well */
2005 code = icl_ChangeSetState(itemp->data, ICL_OP_SS_FREE);
2006 if (code) {
2007 (void)fprintf(stderr,
2008 "cannot set state of %s to dormant (errno = %d)\n",
2009 itemp->data, errno);
2010 retVal = code;
2011 }
2012 }
2013 }
2014 } else {
2015 /* show all sets */
2016 code = icl_ChangeAllSetState(op);
2017 if (code) {
2018 (void)fprintf(stderr,
2019 "cannot set the state of all sets to %s (errno = %d)\n",
2020 operation, errno);
2021 retVal = code;
2022 } else if (doFree) {
2023 /* try to make it dormant as well */
2024 code = icl_ChangeAllSetState(ICL_OP_SS_FREE);
2025 if (code) {
2026 (void)fprintf(stderr,
2027 "cannot set the state of all sets to dormant (errno = %d)\n",
2028 errno);
2029 retVal = code;
2030 }
2031 }
2032 }
2033
2034 return retVal;
2035 }
2036
2037 static void
2038 SetUpSet(void)
2039 {
2040 struct cmd_syndesc *setSyntax;
2041
2042 setSyntax =
2043 cmd_CreateSyntax("setset", DoSet, NULL, 0,
2044 "set state of event sets");
2045 (void)cmd_AddParm(setSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
2046 "event set name");
2047 (void)cmd_AddParm(setSyntax, "-active", CMD_FLAG, CMD_OPTIONAL,
2048 "enable tracing for event set & allocate kernel memory");
2049 (void)cmd_AddParm(setSyntax, "-inactive", CMD_FLAG, CMD_OPTIONAL,
2050 "disables tracing for event set, keep kernel memory");
2051 (void)cmd_AddParm(setSyntax, "-dormant", CMD_FLAG, CMD_OPTIONAL,
2052 "disable tracing for event set & free kernel memory");
2053 }
2054
2055 static int
2056 DoResize(struct cmd_syndesc *as, void *arock)
2057 {
2058 afs_int32 retVal = 0;
2059 afs_int32 code = 0;
2060 afs_int32 bufferSize;
2061 struct cmd_item *itemp;
2062
2063 if (geteuid() != 0) {
2064 printf("fstrace must be run as root\n");
2065 exit(1);
2066 }
2067 /* get buffer size */
2068 bufferSize = atoi(as->parms[1].items->data);
2069 bufferSize *= BUFFER_MULTIPLIER;
2070 if (bufferSize == 0)
2071 bufferSize = ICL_DEFAULT_LOGSIZE;
2072
2073 /* set the size of the specified logs */
2074 if ((itemp = as->parms[0].items)) {
2075 for (; itemp; itemp = itemp->next) {
2076 code = icl_ChangeLogSize(itemp->data, bufferSize);
2077 if (code) {
2078 (void)fprintf(stderr,
2079 "Error in changing log %s buffer size (errno = %d)\n",
2080 itemp->data, errno);
2081 retVal = code;
2082 }
2083 }
2084 } else {
2085 /* Use the only current support log, "cmfx" */
2086 code = icl_ChangeLogSize("cmfx", bufferSize);
2087 if (code) {
2088 (void)fprintf(stderr,
2089 "Error in changing log cmfx buffer size (errno = %d)\n",
2090 errno);
2091 retVal = code;
2092 }
2093 }
2094
2095 return retVal;
2096 }
2097
2098 static void
2099 SetUpResize(void)
2100 {
2101 struct cmd_syndesc *setsizeSyntax;
2102
2103 setsizeSyntax =
2104 cmd_CreateSyntax("setlog", DoResize, NULL, 0,
2105 "set the size of a log");
2106 (void)cmd_AddParm(setsizeSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
2107 "trace log name");
2108 (void)cmd_AddParm(setsizeSyntax, "-buffersize", CMD_SINGLE, CMD_REQUIRED,
2109 "# of 1-kbyte blocks to allocate for log");
2110 }
2111
2112 #include "AFS_component_version_number.c"
2113
2114 int
2115 main(int argc, char *argv[])
2116 {
2117 setlocale(LC_ALL, "");
2118 #ifdef AFS_SGI62_ENV
2119 set_kernel_sizeof_long();
2120 #endif
2121
2122 /* set up user interface then dispatch */
2123 SetUpDump();
2124 SetUpShowLog();
2125 SetUpShowSet();
2126 SetUpClear();
2127 SetUpSet();
2128 SetUpResize();
2129
2130 return (cmd_Dispatch(argc, argv));
2131 }