a9c9d32e2d0a561ad702cd1fa0f00d7fc053672c
[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                     code = 0;
665                     continue;   /* missing slot, nothing to worry about */
666                 }
667                 break;
668             }
669             code =
670                 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
671                             (long)&dummy, (long)&dummy2, 0, 0, 0);
672             if (code)
673                 break;
674             found++;
675             if (dummy > bufferSize)     /* find biggest log */
676                 bufferSize = dummy;
677             lip = (struct logInfo *)malloc(sizeof(struct logInfo));
678             memset(lip, 0, sizeof(*lip));
679             lip->nextp = allInfo;
680             allInfo = lip;
681             lip->name = (char *)malloc(strlen(tname) + 1);
682             strcpy(lip->name, tname);
683         }
684         i = found;
685     } else {
686         /* dump all logs */
687         for (i = 0; i < 1000; i++) {
688             code =
689                 afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGS, i, (long)tname,
690                             sizeof(tname), (long)&dummy, 0, 0);
691             if (code)
692                 break;
693             if (dummy > bufferSize)     /* find biggest log */
694                 bufferSize = dummy;
695             lip = (struct logInfo *)malloc(sizeof(struct logInfo));
696             memset(lip, 0, sizeof(*lip));
697             lip->nextp = allInfo;
698             allInfo = lip;
699             lip->name = (char *)malloc(strlen(tname) + 1);
700             strcpy(lip->name, tname);
701         }
702     }
703
704     if (bufferSize == 0)
705         return -1;
706     bufferp = (afs_int32 *) malloc(sizeof(afs_int32) * bufferSize);
707     if (!bufferp)
708         return -1;
709
710     fprintf(outFilep, "Found %d logs.\n", i);
711
712     /* now print out the contents of each log */
713     for (lip = allInfo; lip; lip = lip->nextp) {
714         fprintf(outFilep, "\nContents of log %s:\n", lip->name);
715         /* read out everything first; gets a more consistent
716          * snapshot.
717          */
718         nwords = 0;             /* total words copied out */
719         for (i = 0;;) {
720             /* display all the entries in the log */
721             if (bufferSize - nwords <= 0)
722                 break;          /* filled whole buffer */
723             code =
724                 afs_syscall(AFSCALL_ICL, ICL_OP_COPYOUT, (long)lip->name,
725                             (long)(bufferp + nwords), bufferSize - nwords,
726                             (long)&i, 0, 0);
727             if (code < 0) {
728                 /* otherwise we've got an error */
729                 fprintf(outFilep, "Returned error %d dumping log.\n", errno);
730                 break;
731             }
732             /* otherwise, we have flags in the high order byte, and
733              * a length (in words) in the remainder.
734              */
735             if ((code >> 24) & ICL_COPYOUTF_MISSEDSOME)
736                 fprintf(outFilep, "Log wrapped; data missing.\n");
737             code &= 0xffffff;
738             if (code == 0) {
739                 /* we're done */
740                 break;
741             }
742             nwords += code;
743             i += code;
744         }                       /* for loop over all cookies */
745
746         /* otherwise we should display all of the log entries here.
747          * Note that a record may end in the middle, in which case
748          * we should start over with the cookie value of the start
749          * of that record.
750          */
751         for (ix = 0; ix < nwords;) {
752             /* start of a record */
753             rlength = (bufferp[ix] >> 24) & 0xff;
754             if (rlength <= 0) {
755                 fprintf(outFilep, "Internal error: 0 length record\n");
756                 retVal = -1;
757                 goto done;
758             }
759             /* ensure that entire record fits */
760             if (ix + rlength > nwords) {
761                 /* doesn't fit, adjust cookie and break */
762                 break;
763             }
764             /* print the record */
765             DisplayRecord(outFilep, &bufferp[ix], rlength);
766             ix += rlength;
767 #ifdef notdef
768             /* obsolete: read entire buffer first */
769             i += rlength;       /* update cookie value, too */
770 #endif
771         }                       /* for loop displaying buffer */
772     }                           /* for loop over all logs */
773
774   done:
775     free(bufferp);
776     return (retVal);
777 }
778
779 /* clear out log 'name' */
780 int
781 icl_ClearLog(char *name)
782 {
783     afs_int32 code;
784
785     code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRLOG, (long)name, 0, 0, 0, 0, 0);
786     return code;
787 }
788
789 /* clear out set 'name' */
790 int
791 icl_ClearSet(char *name)
792 {
793     afs_int32 code;
794
795     code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRSET, (long)name, 0, 0, 0, 0, 0);
796     return code;
797 }
798
799 /* clear out all logs */
800 int
801 icl_ClearAll(void)
802 {
803     afs_int32 code;
804
805     code = afs_syscall(AFSCALL_ICL, ICL_OP_CLRALL, 0, 0, 0, 0, 0, 0);
806     return code;
807 }
808
809 /* list out all available sets to outFileP */
810 int
811 icl_ListSets(FILE *outFileP)
812 {
813     int i;
814     afs_int32 code = 0;
815     afs_int32 states;
816     char tname[64];
817
818     for (i = 0; i < 1000; i++) {
819         code =
820             afs_syscall(AFSCALL_ICL, ICL_OP_ENUMSETS, i, (long)tname,
821                         sizeof(tname), (long)&states, 0, 0);
822         if (code)
823             break;
824         (void)fprintf(outFileP, "%s %s%s%s\n", tname,
825                       (states & ICL_SETF_ACTIVE) ? "active" : "inactive",
826                       (states & ICL_SETF_FREED) ? " (dormant)" : "",
827                       (states & ICL_SETF_PERSISTENT) ? " persistent" : "");
828     }
829
830     return 0;
831 }
832
833 /* list out all available logs to outFileP */
834 int
835 icl_ListLogs(FILE *outFileP, int int32flg)
836 {
837     int i;
838     int allocated;
839     afs_int32 code = 0;
840     afs_int32 logSize;
841     char tname[64];
842
843     for (i = 0; i < 1000; i++) {
844         code =
845             afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGS, i, (long)tname,
846                         sizeof(tname), (long)&logSize, 0, 0);
847         if (code)
848             break;
849         if (int32flg) {
850             /* get more information on the log */
851             code =
852                 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
853                             (long)&logSize, (long)&allocated, 0, 0, 0);
854             if (code)
855                 break;
856             (void)fprintf(outFileP, "%s : %d kbytes (%s)\n", tname,
857                           logSize / 1024,
858                           allocated ? "allocated" : "unallocated");
859         } else
860             (void)fprintf(outFileP, "%s\n", tname);
861     }
862
863     return 0;
864 }
865
866 /* list out all available logs to outFileP */
867 int
868 icl_ListLogsBySet(FILE *outFileP, char *setname, int int32flg)
869 {
870     int i;
871     afs_int32 code = 0;
872     afs_int32 logSize;
873     int allocated;
874     char tname[64];
875
876     for (i = 0; i < ICL_LOGSPERSET; i++) {
877         code =
878             afs_syscall(AFSCALL_ICL, ICL_OP_ENUMLOGSBYSET, (long)setname, i,
879                         (long)tname, sizeof(tname), 0, 0);
880         if (code) {
881             if (errno == EBADF) {
882                 code = 0;
883                 continue;       /* missing */
884             }
885             break;
886         }
887         if (int32flg) {
888             /* get more information on the log */
889             code =
890                 afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)tname,
891                             (long)&logSize, (long)&allocated, 0, 0, 0);
892             if (code)
893                 break;
894             (void)fprintf(outFileP, "%s : %d kbytes (%s)\n", tname,
895                           logSize / 1024,
896                           allocated ? "allocated" : "unallocated");
897         } else
898             (void)fprintf(outFileP, "%s\n", tname);
899     }
900
901     return code;
902 }
903
904 /* activate/deactivate/free specified set */
905 int
906 icl_ChangeSetState(char *name, afs_int32 op)
907 {
908     afs_int32 code;
909
910     code = afs_syscall(AFSCALL_ICL, ICL_OP_SETSTAT, (long)name, op, 0, 0, 0, 0);
911     return code;
912 }
913
914 /* activate/deactivate/free all sets */
915 int
916 icl_ChangeAllSetState(afs_int32 op)
917 {
918     afs_int32 code;
919
920     code = afs_syscall(AFSCALL_ICL, ICL_OP_SETSTATALL, op, 0, 0, 0, 0, 0);
921     return code;
922 }
923
924 /* set size if log */
925 int
926 icl_ChangeLogSize(char *name, afs_int32 logSize)
927 {
928     afs_int32 code;
929
930     code =
931         afs_syscall(AFSCALL_ICL, ICL_OP_SETLOGSIZE, (long)name, logSize, 0,
932                     0, 0, 0);
933     return code;
934 }
935
936 /* get logsize of specified log */
937 int
938 icl_GetLogsize(char *logname, afs_int32 *logSizeP, int *allocatedP)
939 {
940     afs_int32 code;
941     code =
942         afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
943                     (long)logSizeP, (long)allocatedP, 0, 0, 0);
944     return code;
945 }
946
947 /* get state of specified set */
948 int
949 icl_GetSetState(char *setname, afs_int32 *stateP)
950 {
951     afs_int32 code;
952     code =
953         afs_syscall(AFSCALL_ICL, ICL_OP_GETSETINFO, (long)setname,
954                     (long)stateP, 0, 0, 0, 0);
955     return code;
956 }
957
958 int
959 icl_TailKernel(FILE *outFilep, char *logname, afs_int32 waitTime)
960 {
961     afs_int32 bufferSize = 0;
962     afs_int32 newBufferSize;
963     afs_int32 *bufferp;
964     afs_int32 i;
965     afs_int32 code, retVal = 0;
966     afs_int32 nwords;
967     afs_int32 ix;
968     afs_int32 rlength;
969     int allocated;
970
971     /* get information about the specified log */
972     code =
973         afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
974                     (long)&bufferSize, (long)&allocated, 0, 0, 0);
975     if (code) {
976         if (errno == ENOENT)
977             (void)fprintf(stderr, "'%s' not found\n", logname);
978         else
979             (void)fprintf(stderr,
980                           "cannot get information on log '%s' (errno = %d)\n",
981                           logname, errno);
982         return -1;
983     }
984
985     if (!allocated) {
986         (void)fprintf(stderr, "'%s' not allocated\n", logname);
987         return 0;
988     }
989
990     if (bufferSize == 0)
991         return -1;
992     bufferp = (afs_int32 *) malloc(sizeof(afs_int32) * bufferSize);
993     if (!bufferp) {
994         (void)fprintf(stderr, "cannot allocate %d words for buffer\n",
995                       bufferSize);
996         return -1;
997     }
998
999     /* start "infinite" loop */
1000     for (;;) {
1001         /* read out all that's currently there */
1002         nwords = 0;             /* total words copied out */
1003         i = 0;                  /* initialize cookie */
1004         for (;;) {
1005             /* display all the entries in the log */
1006             if (bufferSize - nwords <= 0)
1007                 break;          /* filled whole buffer, clear when done */
1008             code =
1009                 afs_syscall(AFSCALL_ICL, ICL_OP_COPYOUTCLR, (long)logname,
1010                             (long)(bufferp + nwords), bufferSize - nwords,
1011                             (long)&i, 0, 0);
1012             if (code < 0) {
1013                 /* otherwise we've got an error */
1014                 fprintf(stderr, "returned error %d dumping log.\n", errno);
1015                 retVal = -1;
1016                 goto tail_done;
1017             }
1018             /* otherwise, we have flags in the high order byte, and
1019              * a length (in words) in the remainder.
1020              */
1021             code &= 0xffffff;
1022             if (code == 0) {
1023                 /* we're done */
1024                 break;
1025             }
1026             nwords += code;
1027             i += code;
1028         }                       /* for loop over all cookies */
1029
1030         /* otherwise we should display all of the log entries here.
1031          * Note that a record may end in the middle, in which case
1032          * we should start over with the cookie value of the start
1033          * of that record.
1034          */
1035         for (ix = 0; ix < nwords;) {
1036             /* start of a record */
1037             rlength = (bufferp[ix] >> 24) & 0xff;
1038             /* ensure that entire record fits */
1039             if (ix + rlength > nwords) {
1040                 /* doesn't fit, adjust cookie and break */
1041                 if (rlength <= 0) {
1042                     fprintf(stderr, "BOGUS: 0 length record\n");
1043                     retVal = -1;
1044                     goto tail_done;
1045                 }
1046                 break;
1047             }
1048             /* print the record */
1049             DisplayRecord(outFilep, &bufferp[ix], rlength);
1050             ix += rlength;
1051         }                       /* for loop displaying buffer */
1052
1053         if (waitTime)
1054             sleep(waitTime);
1055
1056         /* see if things have changed */
1057         code =
1058             afs_syscall(AFSCALL_ICL, ICL_OP_GETLOGINFO, (long)logname,
1059                         (long)&newBufferSize, (long)&allocated, 0, 0, 0);
1060         if (code) {
1061             if (errno == ENOENT)
1062                 (void)fprintf(stderr, "'%s' not found\n", logname);
1063             else
1064                 (void)fprintf(stderr,
1065                               "cannot get information on log '%s' (errno = %d)\n",
1066                               logname, errno);
1067             retVal = -1;
1068             goto tail_done;
1069         }
1070
1071         if (!allocated) {
1072             (void)fprintf(stderr, "'%s' no int32er allocated\n", logname);
1073             retVal = -1;
1074             goto tail_done;
1075         }
1076
1077         if (bufferSize == 0) {
1078             (void)fprintf(stderr, "buffer size has become 0\n");
1079             retVal = -1;
1080             goto tail_done;
1081         }
1082         if (bufferSize != newBufferSize) {
1083             /* have to reallocate a buffer */
1084             bufferSize = newBufferSize;
1085             free(bufferp);
1086             bufferp = (afs_int32 *) malloc(sizeof(afs_int32) * bufferSize);
1087             if (!bufferp) {
1088                 (void)fprintf(stderr, "cannot allocate %d words for buffer\n",
1089                               bufferSize);
1090                 retVal = -1;
1091                 goto tail_done;
1092             }
1093         }
1094     }                           /* infinite loop */
1095
1096   tail_done:
1097     free(bufferp);
1098     return (retVal);
1099 }
1100
1101 #if !defined(AFS_SGI_ENV)
1102 int
1103 afs_syscall(long call, long parm0, long parm1, long parm2, long parm3,
1104             long parm4, long parm5, long parm6)
1105 {
1106     int code, rval;
1107 #ifdef AFS_LINUX20_ENV
1108 #if defined AFS_LINUX_64BIT_KERNEL
1109     long long eparm[4];
1110     /* don't want to sign extend it to 64bit, so using ulong */
1111     eparm[0] = (unsigned long)parm3;
1112     eparm[1] = (unsigned long)parm4;
1113     eparm[2] = (unsigned long)parm5;
1114     eparm[3] = (unsigned long)parm6;
1115 #else
1116     int eparm[4];
1117     eparm[0] = parm3;
1118     eparm[1] = parm4;
1119     eparm[2] = parm5;
1120     eparm[3] = parm6;
1121 #endif
1122     /* Linux can only handle 5 arguments in the actual syscall. */
1123     if (call == AFSCALL_ICL) {
1124         rval = proc_afs_syscall(call, parm0, parm1, parm2, (long)eparm, &code);
1125         if (rval)
1126             code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, eparm);
1127     } else {
1128         rval = proc_afs_syscall(call, parm0, parm1, parm2, parm3, &code);
1129         if (rval)
1130             code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, parm3);
1131     }
1132 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV)
1133     /* on sparc this function returns none value, so do it myself */
1134     __asm__ __volatile__("mov   %o0, %i0; ret; restore");
1135 #endif
1136 #else
1137 #ifdef AFS_DARWIN80_ENV
1138     code = ioctl_afs_syscall(call, parm0, parm1, parm2, parm3, parm4, parm5, &rval);
1139     if (!code) code = rval;
1140 #else
1141 #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV)
1142     code = syscall(AFS_SYSCALL, call, parm0, parm1, parm2, parm3, parm4);
1143 #else
1144 #if defined(AFS_SGI_ENV)
1145     code = syscall(AFS_ICL, call, parm0, parm1, parm2, parm3, parm4);   /* XXX */
1146 #else
1147     code = syscall(AFSCALL_ICL, parm0, parm1, parm2, parm3, parm4);
1148 #endif
1149 #endif
1150 #endif
1151 #endif /* AFS_LINUX20_ENV */
1152     return code;
1153 }
1154 #endif
1155
1156
1157 int icl_inited = 0;
1158
1159 /* init function, called once, under icl_lock */
1160 int
1161 icl_Init(void)
1162 {
1163     icl_inited = 1;
1164
1165 #ifndef KERNEL
1166     /* setup signal handler, in user space */
1167 #endif /* KERNEL */
1168
1169     return 0;
1170 }
1171
1172 int
1173 icl_CreateSet(char *name, struct afs_icl_log *baseLogp,
1174               struct afs_icl_log *fatalLogp, struct afs_icl_set **outSetpp)
1175 {
1176     return icl_CreateSetWithFlags(name, baseLogp, fatalLogp, /*flags */ 0,
1177                                   outSetpp);
1178 }
1179
1180 /* create a set, given pointers to base and fatal logs, if any.
1181  * Logs are unlocked, but referenced, and *outSetpp is returned
1182  * referenced.  Function bumps reference count on logs, since it
1183  * addds references from the new icl_set.  When the set is destroyed,
1184  * those references will be released.
1185  */
1186 int
1187 icl_CreateSetWithFlags(char *name, struct afs_icl_log *baseLogp,
1188                        struct afs_icl_log *fatalLogp, afs_uint32 flags,
1189                        struct afs_icl_set **outSetpp)
1190 {
1191     struct afs_icl_set *setp;
1192     int i;
1193     afs_int32 states = ICL_DEFAULT_SET_STATES;
1194
1195     if (!icl_inited)
1196         icl_Init();
1197
1198     for (setp = icl_allSets; setp; setp = setp->nextp) {
1199         if (strcmp(setp->name, name) == 0) {
1200             setp->refCount++;
1201             *outSetpp = setp;
1202             if (flags & ICL_CRSET_FLAG_PERSISTENT) {
1203                 setp->states |= ICL_SETF_PERSISTENT;
1204             }
1205             return 0;
1206         }
1207     }
1208
1209     /* determine initial state */
1210     if (flags & ICL_CRSET_FLAG_DEFAULT_ON)
1211         states = ICL_SETF_ACTIVE;
1212     else if (flags & ICL_CRSET_FLAG_DEFAULT_OFF)
1213         states = ICL_SETF_FREED;
1214     if (flags & ICL_CRSET_FLAG_PERSISTENT)
1215         states |= ICL_SETF_PERSISTENT;
1216
1217     setp = (struct afs_icl_set *)osi_Alloc(sizeof(struct afs_icl_set));
1218     memset((caddr_t) setp, 0, sizeof(*setp));
1219     setp->refCount = 1;
1220     if (states & ICL_SETF_FREED)
1221         states &= ~ICL_SETF_ACTIVE;     /* if freed, can't be active */
1222     setp->states = states;
1223
1224     setp->name = (char *)osi_Alloc(strlen(name) + 1);
1225     strcpy(setp->name, name);
1226     setp->nevents = ICL_DEFAULTEVENTS;
1227     setp->eventFlags = (char *)osi_Alloc(ICL_DEFAULTEVENTS);
1228     for (i = 0; i < ICL_DEFAULTEVENTS; i++)
1229         setp->eventFlags[i] = 0xff;     /* default to enabled */
1230
1231     /* update this global info under the icl_lock */
1232     setp->nextp = icl_allSets;
1233     icl_allSets = setp;
1234
1235     /* set's basic lock is still held, so we can finish init */
1236     if (baseLogp) {
1237         setp->logs[0] = baseLogp;
1238         icl_LogHold(baseLogp);
1239         if (!(setp->states & ICL_SETF_FREED))
1240             icl_LogUse(baseLogp);       /* log is actually being used */
1241     }
1242     if (fatalLogp) {
1243         setp->logs[1] = fatalLogp;
1244         icl_LogHold(fatalLogp);
1245         if (!(setp->states & ICL_SETF_FREED))
1246             icl_LogUse(fatalLogp);      /* log is actually being used */
1247     }
1248
1249     *outSetpp = setp;
1250     return 0;
1251 }
1252
1253 /* function to change event enabling information for a particular set */
1254 int
1255 icl_SetEnable(struct afs_icl_set *setp, afs_int32 eventID, int setValue)
1256 {
1257     char *tp;
1258
1259     if (!ICL_EVENTOK(setp, eventID)) {
1260         return -1;
1261     }
1262     tp = &setp->eventFlags[ICL_EVENTBYTE(eventID)];
1263     if (setValue)
1264         *tp |= ICL_EVENTMASK(eventID);
1265     else
1266         *tp &= ~(ICL_EVENTMASK(eventID));
1267     return 0;
1268 }
1269
1270 /* return indication of whether a particular event ID is enabled
1271  * for tracing.  If *getValuep is set to 0, the event is disabled,
1272  * otherwise it is enabled.  All events start out enabled by default.
1273  */
1274 int
1275 icl_GetEnable(struct afs_icl_set *setp, afs_int32 eventID, int *getValuep)
1276 {
1277     if (!ICL_EVENTOK(setp, eventID)) {
1278         return -1;
1279     }
1280     if (setp->eventFlags[ICL_EVENTBYTE(eventID)] & ICL_EVENTMASK(eventID))
1281         *getValuep = 1;
1282     else
1283         *getValuep = 0;
1284     return 0;
1285 }
1286
1287 /* hold and release event sets */
1288 int
1289 icl_SetHold(struct afs_icl_set *setp)
1290 {
1291     setp->refCount++;
1292     return 0;
1293 }
1294
1295 /* free a set.  Called with icl_lock locked */
1296 int
1297 icl_ZapSet(struct afs_icl_set *setp)
1298 {
1299     struct afs_icl_set **lpp, *tp;
1300     int i;
1301     struct afs_icl_log *tlp;
1302
1303     for (lpp = &icl_allSets, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1304         if (tp == setp) {
1305             /* found the dude we want to remove */
1306             *lpp = setp->nextp;
1307             osi_Free(setp->name, 1 + strlen(setp->name));
1308             osi_Free(setp->eventFlags, ICL_EVENTBYTES(setp->nevents));
1309             for (i = 0; i < ICL_LOGSPERSET; i++) {
1310                 if ((tlp = setp->logs[i]))
1311                     icl_LogReleNL(tlp);
1312             }
1313             osi_Free(setp, sizeof(struct afs_icl_set));
1314             break;              /* won't find it twice */
1315         }
1316     }
1317     return 0;
1318 }
1319
1320 /* do the release, watching for deleted entries */
1321 int
1322 icl_SetRele(struct afs_icl_set *setp)
1323 {
1324     if (--setp->refCount == 0 && (setp->states & ICL_SETF_DELETED)) {
1325         icl_ZapSet(setp);       /* destroys setp's lock! */
1326     }
1327     return 0;
1328 }
1329
1330 /* free a set entry, dropping its reference count */
1331 int
1332 icl_SetFree(struct afs_icl_set *setp)
1333 {
1334     setp->states |= ICL_SETF_DELETED;
1335     icl_SetRele(setp);
1336     return 0;
1337 }
1338
1339 /* find a set by name, returning it held */
1340 struct afs_icl_set *
1341 icl_FindSet(char *name)
1342 {
1343     struct afs_icl_set *tp;
1344
1345     for (tp = icl_allSets; tp; tp = tp->nextp) {
1346         if (strcmp(tp->name, name) == 0) {
1347             /* this is the dude we want */
1348             tp->refCount++;
1349             break;
1350         }
1351     }
1352     return tp;
1353 }
1354
1355 /* zero out all the logs in the set */
1356 int
1357 icl_ZeroSet(struct afs_icl_set *setp)
1358 {
1359     int i;
1360     int code = 0;
1361     int tcode;
1362     struct afs_icl_log *logp;
1363
1364     for (i = 0; i < ICL_LOGSPERSET; i++) {
1365         logp = setp->logs[i];
1366         if (logp) {
1367             icl_LogHold(logp);
1368             tcode = icl_ZeroLog(logp);
1369             if (tcode != 0)
1370                 code = tcode;   /* save the last bad one */
1371             icl_LogRele(logp);
1372         }
1373     }
1374     return code;
1375 }
1376
1377 int
1378 icl_EnumerateSets(int (*aproc) (char *, void *, struct afs_icl_set *),
1379                   void *arock)
1380 {
1381     struct afs_icl_set *tp, *np;
1382     afs_int32 code;
1383
1384     code = 0;
1385     for (tp = icl_allSets; tp; tp = np) {
1386         tp->refCount++;         /* hold this guy */
1387         code = (*aproc) (tp->name, arock, tp);
1388         np = tp->nextp;         /* tp may disappear next, but not np */
1389         if (--tp->refCount == 0 && (tp->states & ICL_SETF_DELETED))
1390             icl_ZapSet(tp);
1391         if (code)
1392             break;
1393     }
1394     return code;
1395 }
1396
1397 int
1398 icl_AddLogToSet(struct afs_icl_set *setp, struct afs_icl_log *newlogp)
1399 {
1400     int i;
1401     int code = -1;
1402
1403     for (i = 0; i < ICL_LOGSPERSET; i++) {
1404         if (!setp->logs[i]) {
1405             setp->logs[i] = newlogp;
1406             code = i;
1407             icl_LogHold(newlogp);
1408             if (!(setp->states & ICL_SETF_FREED)) {
1409                 /* bump up the number of sets using the log */
1410                 icl_LogUse(newlogp);
1411             }
1412             break;
1413         }
1414     }
1415     return code;
1416 }
1417
1418 int
1419 icl_SetSetStat(struct afs_icl_set *setp, int op)
1420 {
1421     int i;
1422     afs_int32 code;
1423     struct afs_icl_log *logp;
1424
1425     switch (op) {
1426     case ICL_OP_SS_ACTIVATE:    /* activate a log */
1427         /*
1428          * If we are not already active, see if we have released
1429          * our demand that the log be allocated (FREED set).  If
1430          * we have, reassert our desire.
1431          */
1432         if (!(setp->states & ICL_SETF_ACTIVE)) {
1433             if (setp->states & ICL_SETF_FREED) {
1434                 /* have to reassert desire for logs */
1435                 for (i = 0; i < ICL_LOGSPERSET; i++) {
1436                     logp = setp->logs[i];
1437                     if (logp) {
1438                         icl_LogHold(logp);
1439                         icl_LogUse(logp);
1440                         icl_LogRele(logp);
1441                     }
1442                 }
1443                 setp->states &= ~ICL_SETF_FREED;
1444             }
1445             setp->states |= ICL_SETF_ACTIVE;
1446         }
1447         code = 0;
1448         break;
1449
1450     case ICL_OP_SS_DEACTIVATE:  /* deactivate a log */
1451         /* this doesn't require anything beyond clearing the ACTIVE flag */
1452         setp->states &= ~ICL_SETF_ACTIVE;
1453         code = 0;
1454         break;
1455
1456     case ICL_OP_SS_FREE:        /* deassert design for log */
1457         /*
1458          * if we are already in this state, do nothing; otherwise
1459          * deassert desire for log
1460          */
1461         if (setp->states & ICL_SETF_ACTIVE)
1462             code = EINVAL;
1463         else {
1464             if (!(setp->states & ICL_SETF_FREED)) {
1465                 for (i = 0; i < ICL_LOGSPERSET; i++) {
1466                     logp = setp->logs[i];
1467                     if (logp) {
1468                         icl_LogHold(logp);
1469                         icl_LogFreeUse(logp);
1470                         icl_LogRele(logp);
1471                     }
1472                 }
1473                 setp->states |= ICL_SETF_FREED;
1474             }
1475             code = 0;
1476         }
1477         break;
1478
1479     default:
1480         code = EINVAL;
1481     }
1482
1483     return code;
1484 }
1485
1486 struct afs_icl_log *afs_icl_allLogs = 0;
1487
1488 /* hold and release logs */
1489 int
1490 icl_LogHold(struct afs_icl_log *logp)
1491 {
1492     logp->refCount++;
1493     return 0;
1494 }
1495
1496 /* hold and release logs, called with lock already held */
1497 int
1498 icl_LogHoldNL(struct afs_icl_log *logp)
1499 {
1500     logp->refCount++;
1501     return 0;
1502 }
1503
1504 /* keep track of how many sets believe the log itself is allocated */
1505 int
1506 icl_LogUse(struct afs_icl_log *logp)
1507 {
1508     if (logp->setCount == 0) {
1509         /* this is the first set actually using the log -- allocate it */
1510         if (logp->logSize == 0) {
1511             /* we weren't passed in a hint and it wasn't set */
1512             logp->logSize = ICL_DEFAULT_LOGSIZE;
1513         }
1514         logp->datap =
1515             (afs_int32 *) osi_Alloc(sizeof(afs_int32) * logp->logSize);
1516     }
1517     logp->setCount++;
1518     return 0;
1519 }
1520
1521 /* decrement the number of real users of the log, free if possible */
1522 int
1523 icl_LogFreeUse(struct afs_icl_log *logp)
1524 {
1525     if (--logp->setCount == 0) {
1526         /* no more users -- free it (but keep log structure around) */
1527         osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
1528         logp->firstUsed = logp->firstFree = 0;
1529         logp->logElements = 0;
1530         logp->datap = NULL;
1531     }
1532     return 0;
1533 }
1534
1535 /* set the size of the log to 'logSize' */
1536 int
1537 icl_LogSetSize(struct afs_icl_log *logp, afs_int32 logSize)
1538 {
1539     if (!logp->datap) {
1540         /* nothing to worry about since it's not allocated */
1541         logp->logSize = logSize;
1542     } else {
1543         /* reset log */
1544         logp->firstUsed = logp->firstFree = 0;
1545         logp->logElements = 0;
1546
1547         /* free and allocate a new one */
1548         osi_Free(logp->datap, sizeof(afs_int32) * logp->logSize);
1549         logp->datap = (afs_int32 *) osi_Alloc(sizeof(afs_int32) * logSize);
1550         logp->logSize = logSize;
1551     }
1552
1553     return 0;
1554 }
1555
1556 /* free a log.  Called with icl_lock locked. */
1557 int
1558 icl_ZapLog(struct afs_icl_log *logp)
1559 {
1560     struct afs_icl_log **lpp, *tp;
1561
1562     for (lpp = &afs_icl_allLogs, tp = *lpp; tp; lpp = &tp->nextp, tp = *lpp) {
1563         if (tp == logp) {
1564             /* found the dude we want to remove */
1565             *lpp = logp->nextp;
1566             osi_Free(logp->name, 1 + strlen(logp->name));
1567             osi_Free(logp->datap, logp->logSize * sizeof(afs_int32));
1568             osi_Free(logp, sizeof(struct icl_log));
1569             break;              /* won't find it twice */
1570         }
1571     }
1572     return 0;
1573 }
1574
1575 /* do the release, watching for deleted entries */
1576 int
1577 icl_LogRele(struct afs_icl_log *logp)
1578 {
1579     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1580         icl_ZapLog(logp);       /* destroys logp's lock! */
1581     }
1582     return 0;
1583 }
1584
1585 /* do the release, watching for deleted entries, log already held */
1586 int
1587 icl_LogReleNL(struct afs_icl_log *logp)
1588 {
1589     if (--logp->refCount == 0 && (logp->states & ICL_LOGF_DELETED)) {
1590         icl_ZapLog(logp);       /* destroys logp's lock! */
1591     }
1592     return 0;
1593 }
1594
1595 /* zero out the log */
1596 int
1597 icl_ZeroLog(struct afs_icl_log *logp)
1598 {
1599     logp->firstUsed = logp->firstFree = 0;
1600     logp->logElements = 0;
1601     return 0;
1602 }
1603
1604 /* free a log entry, and drop its reference count */
1605 int
1606 icl_LogFree(struct afs_icl_log *logp)
1607 {
1608     logp->states |= ICL_LOGF_DELETED;
1609     icl_LogRele(logp);
1610     return 0;
1611 }
1612
1613
1614 int
1615 icl_EnumerateLogs(int (*aproc)
1616                     (char *name, void *arock, struct afs_icl_log * tp),
1617                   void *arock)
1618 {
1619     struct afs_icl_log *tp;
1620     afs_int32 code;
1621
1622     code = 0;
1623     for (tp = afs_icl_allLogs; tp; tp = tp->nextp) {
1624         tp->refCount++;         /* hold this guy */
1625         code = (*aproc) (tp->name, arock, tp);
1626         if (--tp->refCount == 0)
1627             icl_ZapLog(tp);
1628         if (code)
1629             break;
1630     }
1631     return code;
1632 }
1633
1634
1635 afs_icl_bulkSetinfo_t *
1636 GetBulkSetInfo(void)
1637 {
1638     unsigned int infoSize;
1639
1640     infoSize =
1641         sizeof(afs_icl_bulkSetinfo_t) + (ICL_RPC_MAX_SETS -
1642                                          1) * sizeof(afs_icl_setinfo_t);
1643     if (!setInfo) {
1644         setInfo = (afs_icl_bulkSetinfo_t *) malloc(infoSize);
1645         if (!setInfo) {
1646             (void)fprintf(stderr,
1647                           "Could not allocate the memory for bulk set info structure\n");
1648             exit(1);
1649         }
1650     }
1651     memset(setInfo, 0, infoSize);
1652
1653     return setInfo;
1654 }
1655
1656 afs_icl_bulkLoginfo_t *
1657 GetBulkLogInfo(void)
1658 {
1659     unsigned int infoSize;
1660
1661     infoSize =
1662         sizeof(afs_icl_bulkLoginfo_t) + (ICL_RPC_MAX_LOGS -
1663                                          1) * sizeof(afs_icl_loginfo_t);
1664     if (!logInfo) {
1665         logInfo = (afs_icl_bulkLoginfo_t *) malloc(infoSize);
1666         if (!logInfo) {
1667             (void)fprintf(stderr,
1668                           "Could not allocate the memory for bulk log info structure\n");
1669             exit(1);
1670         }
1671     }
1672
1673     memset(logInfo, 0, infoSize);
1674     return logInfo;
1675 }
1676
1677
1678 static int
1679 DoDump(struct cmd_syndesc *as, void *arock)
1680 {
1681     afs_int32 code = 0;
1682     afs_int32 tcode;
1683     afs_int32 waitTime = 10 /* seconds */ ;
1684     char *logname;
1685     FILE *outfp = stdout;
1686     time_t startTime;
1687     struct cmd_item *itemp;
1688
1689     if (geteuid() != 0) {
1690         printf("fstrace must be run as root\n");
1691         exit(1);
1692     }
1693
1694     if (as->parms[3].items) {
1695         if (!as->parms[1].items) {
1696             (void)fprintf(stderr, "-sleep can only be used with -follow\n");
1697             return 1;
1698         }
1699         waitTime = strtol(as->parms[3].items->data, NULL, 0);
1700     }
1701
1702     if (as->parms[2].items) {
1703         /* try to open the specified output file */
1704         if ((outfp = fopen(as->parms[2].items->data, "w")) == NULL) {
1705             (void)fprintf(stderr, "Cannot open file '%s' for writing\n",
1706                           as->parms[2].items->data);
1707             return 1;
1708         }
1709     }
1710 #ifdef AFS_SGI64_ENV
1711     startTime = time((time_t *) 0);
1712 #else
1713     startTime = time(0);
1714 #endif
1715     (void)fprintf(outfp, "AFS Trace Dump -\n\n   Date: %s\n",
1716                   ctime(&startTime));
1717
1718     if (as->parms[0].items) {
1719         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1720             tcode = icl_DumpKernel(outfp, itemp->data);
1721             if (tcode) {
1722                 (void)fprintf(stderr, "Unable to dump set %s (errno = %d)\n",
1723                               itemp->data, errno);
1724                 code = tcode;
1725             }
1726         }
1727     } else if (as->parms[1].items) {
1728         logname = as->parms[1].items->data;
1729         code = icl_TailKernel(outfp, logname, waitTime);
1730         if (code) {
1731             (void)fprintf(stderr,
1732                           "Error tailing kernel log '%s' (errno = %d)\n",
1733                           logname, errno);
1734         }
1735     } else
1736         code = icl_DumpKernel(outfp, NULL);
1737
1738     (void)fprintf(outfp, "\nAFS Trace Dump - %s\n",
1739                   code ? "FAILED" : "Completed");
1740
1741     if (outfp != stdout)
1742         (void)fclose(outfp);
1743
1744     return code;
1745 }
1746
1747 static void
1748 SetUpDump(void)
1749 {
1750     struct cmd_syndesc *dumpSyntax;
1751
1752     dumpSyntax =
1753         cmd_CreateSyntax("dump", DoDump, NULL, "dump AFS trace logs");
1754     (void)cmd_AddParm(dumpSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1755                       "event set name");
1756     (void)cmd_AddParm(dumpSyntax, "-follow", CMD_SINGLE, CMD_OPTIONAL,
1757                       "trace log name");
1758     (void)cmd_AddParm(dumpSyntax, "-file", CMD_SINGLE, CMD_OPTIONAL,
1759                       "path to trace log file for writing");
1760     (void)cmd_AddParm(dumpSyntax, "-sleep", CMD_SINGLE, CMD_OPTIONAL,
1761                       "interval (secs) for writes when using -follow");
1762 }
1763
1764
1765 static int
1766 DoShowLog(struct cmd_syndesc *as, void *arock)
1767 {
1768     afs_int32 retVal = 0;
1769     afs_int32 code = 0;
1770     afs_int32 logSize;
1771     int allocated;
1772     int int32flg = 0;
1773     struct cmd_item *itemp;
1774
1775     if (geteuid() != 0) {
1776         printf("fstrace must be run as root\n");
1777         exit(1);
1778     }
1779     if (as->parms[2].items)
1780         int32flg = 1;
1781
1782     if (as->parms[0].items) {
1783         /* enumerate logs for the specified sets */
1784         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1785             (void)fprintf(stdout, "Logs for set '%s':\n", itemp->data);
1786             code = icl_ListLogsBySet(stdout, itemp->data, int32flg);
1787             if (code) {
1788                 (void)fprintf(stderr,
1789                               "Error in enumerating set %s (errno = %d)\n",
1790                               itemp->data, errno);
1791                 retVal = code;
1792             }
1793         }
1794     } else if (as->parms[1].items) {
1795         /* print out log information */
1796         for (itemp = as->parms[1].items; itemp; itemp = itemp->next) {
1797             code = icl_GetLogsize(itemp->data, &logSize, &allocated);
1798             if (!code)
1799                 (void)fprintf(stdout, "%s : %d kbytes (%s)\n", itemp->data,
1800                               logSize / 1024,
1801                               allocated ? "allocated" : "unallocated");
1802             else {
1803                 (void)fprintf(stderr,
1804                               "Could not find log '%s' (errno = %d)\n",
1805                               itemp->data, errno);
1806                 retVal = code;
1807             }
1808         }
1809     } else {
1810         /* show all logs */
1811         (void)fprintf(stdout, "Available logs:\n");
1812         code = icl_ListLogs(stdout, int32flg);
1813         if (code) {
1814             (void)fprintf(stderr, "Error in listing logs (errno = %d)\n",
1815                           errno);
1816             retVal = code;
1817         }
1818     }
1819
1820     return retVal;
1821 }
1822
1823 static void
1824 SetUpShowLog(void)
1825 {
1826     struct cmd_syndesc *showSyntax;
1827
1828     showSyntax =
1829         cmd_CreateSyntax("lslog", DoShowLog, NULL,
1830                          "list available logs");
1831     (void)cmd_AddParm(showSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1832                       "event set name");
1833     (void)cmd_AddParm(showSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
1834                       "trace log name");
1835     (void)cmd_AddParm(showSyntax, "-long", CMD_FLAG, CMD_OPTIONAL,
1836                       "show defined log size in kbytes & if it is allocated in kernel mem");
1837 }
1838
1839 static int
1840 DoShowSet(struct cmd_syndesc *as, void *arock)
1841 {
1842     afs_int32 retVal = 0;
1843     afs_int32 code = 0;
1844     afs_int32 state;
1845     struct cmd_item *itemp;
1846
1847     if (geteuid() != 0) {
1848         printf("fstrace must be run as root\n");
1849         exit(1);
1850     }
1851     if (as->parms[0].items) {
1852         /* print information on the specified sets */
1853         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1854             code = icl_GetSetState(itemp->data, &state);
1855             if (code) {
1856                 (void)fprintf(stderr,
1857                               "Error getting status on set %s (errno = %d)\n",
1858                               itemp->data, errno);
1859                 retVal = code;
1860             } else
1861                 (void)fprintf(stdout, "Set %s: %s%s%s\n", itemp->data,
1862                               (state & ICL_SETF_ACTIVE) ? "active" :
1863                               "inactive",
1864                               (state & ICL_SETF_FREED) ? " (dormant)" : "",
1865                               (state & ICL_SETF_PERSISTENT) ? " persistent" :
1866                               "");
1867         }
1868     } else {
1869         /* show all sets */
1870         (void)fprintf(stdout, "Available sets:\n");
1871         code = icl_ListSets(stdout);
1872         if (code) {
1873             (void)fprintf(stderr, "Error in listing sets (errno = %d)\n",
1874                           errno);
1875             retVal = code;
1876         }
1877     }
1878
1879     return retVal;
1880 }
1881
1882 static void
1883 SetUpShowSet(void)
1884 {
1885     struct cmd_syndesc *showSyntax;
1886
1887     showSyntax =
1888         cmd_CreateSyntax("lsset", DoShowSet, NULL,
1889                          "list available event sets");
1890     (void)cmd_AddParm(showSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1891                       "event set name");
1892 }
1893
1894 static int
1895 DoClear(struct cmd_syndesc *as, void *arock)
1896 {
1897     afs_int32 retVal = 0;
1898     afs_int32 code = 0;
1899     struct cmd_item *itemp;
1900
1901     if (geteuid() != 0) {
1902         printf("fstrace must be run as root\n");
1903         exit(1);
1904     }
1905     if (as->parms[0].items) {
1906         /* clear logs for the specified sets */
1907         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1908             code = icl_ClearSet(itemp->data);
1909             if (code) {
1910                 (void)fprintf(stderr,
1911                               "Error in clearing set %s (errno = %d)\n",
1912                               itemp->data, errno);
1913                 retVal = code;
1914             }
1915         }
1916     } else if (as->parms[1].items) {
1917         /* clear specified log */
1918         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1919             code = icl_ClearLog(itemp->data);
1920             if (code) {
1921                 (void)fprintf(stderr,
1922                               "Error in clearing log %s (errno = %d)\n",
1923                               itemp->data, errno);
1924                 retVal = code;
1925             }
1926         }
1927     } else {
1928         /* clear all logs */
1929         code = icl_ClearAll();
1930         if (code) {
1931             (void)fprintf(stderr, "Error in clearing logs (errno = %d)\n",
1932                           errno);
1933             retVal = code;
1934         }
1935     }
1936
1937     return retVal;
1938 }
1939
1940 static void
1941 SetUpClear(void)
1942 {
1943     struct cmd_syndesc *clearSyntax;
1944
1945     clearSyntax =
1946         cmd_CreateSyntax("clear", DoClear, NULL,
1947                          "clear logs by logname or by event set");
1948     (void)cmd_AddParm(clearSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
1949                       "event set name");
1950     (void)cmd_AddParm(clearSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
1951                       "trace log name");
1952 }
1953
1954 static int
1955 DoSet(struct cmd_syndesc *as, void *arock)
1956 {
1957     afs_int32 retVal = 0;
1958     afs_int32 code = 0;
1959     int op;
1960     int doFree = 0;
1961     char *operation;
1962     struct cmd_item *itemp;
1963
1964     if (geteuid() != 0) {
1965         printf("fstrace must be run as root\n");
1966         exit(1);
1967     }
1968     if (as->parms[1].items) {
1969         op = ICL_OP_SS_ACTIVATE;
1970         operation = "active";
1971     } else if (as->parms[2].items) {
1972         op = ICL_OP_SS_DEACTIVATE;
1973         operation = "inactive";
1974     } else if (as->parms[3].items) {
1975         op = ICL_OP_SS_DEACTIVATE;
1976         operation = "inactive";
1977         doFree = 1;
1978     } else {
1979         /* assume active" */
1980         op = ICL_OP_SS_ACTIVATE;
1981         operation = "active";
1982     }
1983
1984     if (as->parms[0].items) {
1985         /* activate specified sets */
1986         for (itemp = as->parms[0].items; itemp; itemp = itemp->next) {
1987             code = icl_ChangeSetState(itemp->data, op);
1988             if (code) {
1989                 (void)fprintf(stderr,
1990                               "cannot set state of %s to %s (errno = %d)\n",
1991                               itemp->data, operation, errno);
1992                 retVal = code;
1993             } else if (doFree) {
1994                 /* try to make it dormant as well */
1995                 code = icl_ChangeSetState(itemp->data, ICL_OP_SS_FREE);
1996                 if (code) {
1997                     (void)fprintf(stderr,
1998                                   "cannot set state of %s to dormant (errno = %d)\n",
1999                                   itemp->data, errno);
2000                     retVal = code;
2001                 }
2002             }
2003         }
2004     } else {
2005         /* show all sets */
2006         code = icl_ChangeAllSetState(op);
2007         if (code) {
2008             (void)fprintf(stderr,
2009                           "cannot set the state of all sets to %s (errno = %d)\n",
2010                           operation, errno);
2011             retVal = code;
2012         } else if (doFree) {
2013             /* try to make it dormant as well */
2014             code = icl_ChangeAllSetState(ICL_OP_SS_FREE);
2015             if (code) {
2016                 (void)fprintf(stderr,
2017                               "cannot set the state of all sets to dormant (errno = %d)\n",
2018                               errno);
2019                 retVal = code;
2020             }
2021         }
2022     }
2023
2024     return retVal;
2025 }
2026
2027 static void
2028 SetUpSet(void)
2029 {
2030     struct cmd_syndesc *setSyntax;
2031
2032     setSyntax =
2033         cmd_CreateSyntax("setset", DoSet, NULL,
2034                          "set state of event sets");
2035     (void)cmd_AddParm(setSyntax, "-set", CMD_LIST, CMD_OPTIONAL,
2036                       "event set name");
2037     (void)cmd_AddParm(setSyntax, "-active", CMD_FLAG, CMD_OPTIONAL,
2038                       "enable tracing for event set & allocate kernel memory");
2039     (void)cmd_AddParm(setSyntax, "-inactive", CMD_FLAG, CMD_OPTIONAL,
2040                       "disables tracing for event set, keep kernel memory");
2041     (void)cmd_AddParm(setSyntax, "-dormant", CMD_FLAG, CMD_OPTIONAL,
2042                       "disable tracing for event set & free kernel memory");
2043 }
2044
2045 static int
2046 DoResize(struct cmd_syndesc *as, void *arock)
2047 {
2048     afs_int32 retVal = 0;
2049     afs_int32 code = 0;
2050     afs_int32 bufferSize;
2051     struct cmd_item *itemp;
2052
2053     if (geteuid() != 0) {
2054         printf("fstrace must be run as root\n");
2055         exit(1);
2056     }
2057     /* get buffer size */
2058     bufferSize = atoi(as->parms[1].items->data);
2059     bufferSize *= BUFFER_MULTIPLIER;
2060     if (bufferSize == 0)
2061         bufferSize = ICL_DEFAULT_LOGSIZE;
2062
2063     /* set the size of the specified logs */
2064     if ((itemp = as->parms[0].items)) {
2065         for (; itemp; itemp = itemp->next) {
2066             code = icl_ChangeLogSize(itemp->data, bufferSize);
2067             if (code) {
2068                 (void)fprintf(stderr,
2069                               "Error in changing log %s buffer size (errno = %d)\n",
2070                               itemp->data, errno);
2071                 retVal = code;
2072             }
2073         }
2074     } else {
2075         /* Use the only current support log, "cmfx" */
2076         code = icl_ChangeLogSize("cmfx", bufferSize);
2077         if (code) {
2078             (void)fprintf(stderr,
2079                           "Error in changing log cmfx buffer size (errno = %d)\n",
2080                           errno);
2081             retVal = code;
2082         }
2083     }
2084
2085     return retVal;
2086 }
2087
2088 static void
2089 SetUpResize(void)
2090 {
2091     struct cmd_syndesc *setsizeSyntax;
2092
2093     setsizeSyntax =
2094         cmd_CreateSyntax("setlog", DoResize, NULL,
2095                          "set the size of a log");
2096     (void)cmd_AddParm(setsizeSyntax, "-log", CMD_LIST, CMD_OPTIONAL,
2097                       "trace log name");
2098     (void)cmd_AddParm(setsizeSyntax, "-buffersize", CMD_SINGLE, CMD_REQUIRED,
2099                       "# of 1-kbyte blocks to allocate for log");
2100 }
2101
2102 #include "AFS_component_version_number.c"
2103
2104 int
2105 main(int argc, char *argv[])
2106 {
2107     setlocale(LC_ALL, "");
2108 #ifdef AFS_SGI62_ENV
2109     set_kernel_sizeof_long();
2110 #endif
2111
2112     /* set up user interface then dispatch */
2113     SetUpDump();
2114     SetUpShowLog();
2115     SetUpShowSet();
2116     SetUpClear();
2117     SetUpSet();
2118     SetUpResize();
2119
2120     return (cmd_Dispatch(argc, argv));
2121 }