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