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