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