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