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