+
+#endif
+
+ /* --- Tracing support --- *
+ *
+ * Be careful not to zap a file I wouldn't normally be allowed to write
+ * to!
+ */
+
+#ifdef TRACING
+
+ case 'T': {
+ FILE *fp;
+
+ if (optarg == 0 || strcmp(optarg, "-") == 0)
+ fp = stdout;
+ else {
+ if ((flags & f_setuid) && access(optarg, W_OK)) {
+ die("no write permission for trace file file `%s': %s",
+ optarg, strerror(errno));
+ }
+ if ((fp = fopen(optarg, "w")) == 0) {
+ die("couldn't open trace file `%s' for writing: %s",
+ optarg, strerror(errno));
+ }
+ }
+ traceon(fp, TRACE_DFL);
+ trace(TRACE_MISC, "become: tracing enabled");
+ } break;
+
+#endif
+
+ /* --- Setting trace levels --- */
+
+#ifdef TRACING
+
+ case 'L': {
+ int sense = 1;
+ unsigned int lvl = 0, l;
+ const char *p = optarg;
+
+ /* --- Table of tracing facilities --- */
+
+ typedef struct tr {
+ char ch;
+ unsigned int l;
+ const char *help;
+ } tr;
+
+ static tr lvltbl[] = {
+ { 'm', TRACE_MISC, "miscellaneous messages" },
+ { 's', TRACE_SETUP, "building the request block" },
+ { 'd', TRACE_DAEMON, "server process" },
+ { 'r', TRACE_RULE, "ruleset scanning" },
+ { 'c', TRACE_CHECK, "request checking" },
+ { 'l', TRACE_CLIENT, "client process" },
+ { 'R', TRACE_RAND, "random number generator" },
+ { 'C', TRACE_CRYPTO, "cryptographic processing of requests" },
+ { 'y', TRACE_YACC, "parsing configuration file" },
+ { 'D', TRACE_DFL, "default tracing options" },
+ { 'A', TRACE_ALL, "all tracing options" },
+ { 0, 0, 0 }
+ };
+ tr *tp;
+
+ /* --- Output some help if there's no arguemnt --- */
+
+ if (!optarg) {
+ bc__banner(stdout);
+ bc__write(stdout,
+ "\n"
+ "Tracing options:\n"
+ "\n");
+ for (tp = lvltbl; tp->l; tp++) {
+ if ((flags & f_setuid) == 0 || tp->l & ~TRACE_PRIV)
+ printf("%c -- %s\n", tp->ch, tp->help);
+ }
+ bc__write(stdout,
+"\n"
+"Also, `+' and `-' options are recognised to turn on and off vavrious\n"
+"tracing options. For example, `A-r' enables everything except ruleset\n"
+"tracing, and `A-D+c' is everything except the defaults, but with request\n"
+"check tracing.\n"
+);
+ exit(0);
+ }
+
+ while (*p) {
+ if (*p == '+')
+ sense = 1;
+ else if (*p == '-')
+ sense = 0;
+ else {
+ for (tp = lvltbl; tp->l && *p != tp->ch; tp++)
+ ;
+ l = tp->l;
+ if (flags & f_setuid)
+ l &= ~TRACE_PRIV;
+ if (l)
+ lvl = sense ? (lvl | l) : (lvl & ~l);
+ else
+ moan("unknown trace option `%c'", *p);
+ }
+ p++;
+ }
+
+ tracesetlvl(lvl);
+ yydebug = ((lvl & TRACE_YACC) != 0);
+ } break;
+
+#endif
+
+ /* --- Something I didn't understand has occurred --- */
+