| 1 | /*      $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $    */
 | 
|---|
| 2 | 
 | 
|---|
| 3 | /*-
 | 
|---|
| 4 |  * Copyright (c) 1991, 1993
 | 
|---|
| 5 |  *      The Regents of the University of California.  All rights reserved.
 | 
|---|
| 6 |  *
 | 
|---|
| 7 |  * This code is derived from software contributed to Berkeley by
 | 
|---|
| 8 |  * Kenneth Almquist.
 | 
|---|
| 9 |  *
 | 
|---|
| 10 |  * Redistribution and use in source and binary forms, with or without
 | 
|---|
| 11 |  * modification, are permitted provided that the following conditions
 | 
|---|
| 12 |  * are met:
 | 
|---|
| 13 |  * 1. Redistributions of source code must retain the above copyright
 | 
|---|
| 14 |  *    notice, this list of conditions and the following disclaimer.
 | 
|---|
| 15 |  * 2. Redistributions in binary form must reproduce the above copyright
 | 
|---|
| 16 |  *    notice, this list of conditions and the following disclaimer in the
 | 
|---|
| 17 |  *    documentation and/or other materials provided with the distribution.
 | 
|---|
| 18 |  * 3. Neither the name of the University nor the names of its contributors
 | 
|---|
| 19 |  *    may be used to endorse or promote products derived from this software
 | 
|---|
| 20 |  *    without specific prior written permission.
 | 
|---|
| 21 |  *
 | 
|---|
| 22 |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
|---|
| 23 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
|---|
| 24 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
|---|
| 25 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
|---|
| 26 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
|---|
| 27 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
|---|
| 28 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
|---|
| 29 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
|---|
| 30 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
|---|
| 31 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
|---|
| 32 |  * SUCH DAMAGE.
 | 
|---|
| 33 |  */
 | 
|---|
| 34 | 
 | 
|---|
| 35 | #include <sys/cdefs.h>
 | 
|---|
| 36 | #ifndef lint
 | 
|---|
| 37 | #if 0
 | 
|---|
| 38 | static char sccsid[] = "@(#)show.c      8.3 (Berkeley) 5/4/95";
 | 
|---|
| 39 | #else
 | 
|---|
| 40 | __RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
 | 
|---|
| 41 | #endif
 | 
|---|
| 42 | #endif /* not lint */
 | 
|---|
| 43 | 
 | 
|---|
| 44 | #include <stdio.h>
 | 
|---|
| 45 | #include <stdarg.h>
 | 
|---|
| 46 | #include <stdlib.h>
 | 
|---|
| 47 | 
 | 
|---|
| 48 | #include "shell.h"
 | 
|---|
| 49 | #include "parser.h"
 | 
|---|
| 50 | #include "nodes.h"
 | 
|---|
| 51 | #include "mystring.h"
 | 
|---|
| 52 | #include "show.h"
 | 
|---|
| 53 | #include "options.h"
 | 
|---|
| 54 | 
 | 
|---|
| 55 | 
 | 
|---|
| 56 | #ifdef DEBUG
 | 
|---|
| 57 | static void shtree(union node *, int, char *, FILE*);
 | 
|---|
| 58 | static void shcmd(union node *, FILE *);
 | 
|---|
| 59 | static void sharg(union node *, FILE *);
 | 
|---|
| 60 | static void indent(int, char *, FILE *);
 | 
|---|
| 61 | static void trstring(char *);
 | 
|---|
| 62 | 
 | 
|---|
| 63 | 
 | 
|---|
| 64 | void
 | 
|---|
| 65 | showtree(union node *n)
 | 
|---|
| 66 | {
 | 
|---|
| 67 |         trputs("showtree called\n");
 | 
|---|
| 68 |         shtree(n, 1, NULL, stdout);
 | 
|---|
| 69 | }
 | 
|---|
| 70 | 
 | 
|---|
| 71 | 
 | 
|---|
| 72 | static void
 | 
|---|
| 73 | shtree(union node *n, int ind, char *pfx, FILE *fp)
 | 
|---|
| 74 | {
 | 
|---|
| 75 |         struct nodelist *lp;
 | 
|---|
| 76 |         const char *s;
 | 
|---|
| 77 | 
 | 
|---|
| 78 |         if (n == NULL)
 | 
|---|
| 79 |                 return;
 | 
|---|
| 80 | 
 | 
|---|
| 81 |         indent(ind, pfx, fp);
 | 
|---|
| 82 |         switch(n->type) {
 | 
|---|
| 83 |         case NSEMI:
 | 
|---|
| 84 |                 s = "; ";
 | 
|---|
| 85 |                 goto binop;
 | 
|---|
| 86 |         case NAND:
 | 
|---|
| 87 |                 s = " && ";
 | 
|---|
| 88 |                 goto binop;
 | 
|---|
| 89 |         case NOR:
 | 
|---|
| 90 |                 s = " || ";
 | 
|---|
| 91 | binop:
 | 
|---|
| 92 |                 shtree(n->nbinary.ch1, ind, NULL, fp);
 | 
|---|
| 93 |            /*    if (ind < 0) */
 | 
|---|
| 94 |                         fputs(s, fp);
 | 
|---|
| 95 |                 shtree(n->nbinary.ch2, ind, NULL, fp);
 | 
|---|
| 96 |                 break;
 | 
|---|
| 97 |         case NCMD:
 | 
|---|
| 98 |                 shcmd(n, fp);
 | 
|---|
| 99 |                 if (ind >= 0)
 | 
|---|
| 100 |                         putc('\n', fp);
 | 
|---|
| 101 |                 break;
 | 
|---|
| 102 |         case NPIPE:
 | 
|---|
| 103 |                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
 | 
|---|
| 104 |                         shcmd(lp->n, fp);
 | 
|---|
| 105 |                         if (lp->next)
 | 
|---|
| 106 |                                 fputs(" | ", fp);
 | 
|---|
| 107 |                 }
 | 
|---|
| 108 |                 if (n->npipe.backgnd)
 | 
|---|
| 109 |                         fputs(" &", fp);
 | 
|---|
| 110 |                 if (ind >= 0)
 | 
|---|
| 111 |                         putc('\n', fp);
 | 
|---|
| 112 |                 break;
 | 
|---|
| 113 |         default:
 | 
|---|
| 114 |                 fprintf(fp, "<node type %d>", n->type);
 | 
|---|
| 115 |                 if (ind >= 0)
 | 
|---|
| 116 |                         putc('\n', fp);
 | 
|---|
| 117 |                 break;
 | 
|---|
| 118 |         }
 | 
|---|
| 119 | }
 | 
|---|
| 120 | 
 | 
|---|
| 121 | 
 | 
|---|
| 122 | 
 | 
|---|
| 123 | static void
 | 
|---|
| 124 | shcmd(union node *cmd, FILE *fp)
 | 
|---|
| 125 | {
 | 
|---|
| 126 |         union node *np;
 | 
|---|
| 127 |         int first;
 | 
|---|
| 128 |         const char *s;
 | 
|---|
| 129 |         int dftfd;
 | 
|---|
| 130 | 
 | 
|---|
| 131 |         first = 1;
 | 
|---|
| 132 |         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
 | 
|---|
| 133 |                 if (! first)
 | 
|---|
| 134 |                         putchar(' ');
 | 
|---|
| 135 |                 sharg(np, fp);
 | 
|---|
| 136 |                 first = 0;
 | 
|---|
| 137 |         }
 | 
|---|
| 138 |         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
 | 
|---|
| 139 |                 if (! first)
 | 
|---|
| 140 |                         putchar(' ');
 | 
|---|
| 141 |                 switch (np->nfile.type) {
 | 
|---|
| 142 |                         case NTO:       s = ">";  dftfd = 1; break;
 | 
|---|
| 143 |                         case NCLOBBER:  s = ">|"; dftfd = 1; break;
 | 
|---|
| 144 |                         case NAPPEND:   s = ">>"; dftfd = 1; break;
 | 
|---|
| 145 |                         case NTOFD:     s = ">&"; dftfd = 1; break;
 | 
|---|
| 146 |                         case NFROM:     s = "<";  dftfd = 0; break;
 | 
|---|
| 147 |                         case NFROMFD:   s = "<&"; dftfd = 0; break;
 | 
|---|
| 148 |                         case NFROMTO:   s = "<>"; dftfd = 0; break;
 | 
|---|
| 149 |                         default:        s = "*error*"; dftfd = 0; break;
 | 
|---|
| 150 |                 }
 | 
|---|
| 151 |                 if (np->nfile.fd != dftfd)
 | 
|---|
| 152 |                         fprintf(fp, "%d", np->nfile.fd);
 | 
|---|
| 153 |                 fputs(s, fp);
 | 
|---|
| 154 |                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
 | 
|---|
| 155 |                         fprintf(fp, "%d", np->ndup.dupfd);
 | 
|---|
| 156 |                 } else {
 | 
|---|
| 157 |                         sharg(np->nfile.fname, fp);
 | 
|---|
| 158 |                 }
 | 
|---|
| 159 |                 first = 0;
 | 
|---|
| 160 |         }
 | 
|---|
| 161 | }
 | 
|---|
| 162 | 
 | 
|---|
| 163 | 
 | 
|---|
| 164 | 
 | 
|---|
| 165 | static void
 | 
|---|
| 166 | sharg(union node *arg, FILE *fp)
 | 
|---|
| 167 | {
 | 
|---|
| 168 |         char *p;
 | 
|---|
| 169 |         struct nodelist *bqlist;
 | 
|---|
| 170 |         int subtype;
 | 
|---|
| 171 | 
 | 
|---|
| 172 |         if (arg->type != NARG) {
 | 
|---|
| 173 |                 printf("<node type %d>\n", arg->type);
 | 
|---|
| 174 |                 abort();
 | 
|---|
| 175 |         }
 | 
|---|
| 176 |         bqlist = arg->narg.backquote;
 | 
|---|
| 177 |         for (p = arg->narg.text ; *p ; p++) {
 | 
|---|
| 178 |                 switch (*p) {
 | 
|---|
| 179 |                 case CTLESC:
 | 
|---|
| 180 |                         putc(*++p, fp);
 | 
|---|
| 181 |                         break;
 | 
|---|
| 182 |                 case CTLVAR:
 | 
|---|
| 183 |                         putc('$', fp);
 | 
|---|
| 184 |                         putc('{', fp);
 | 
|---|
| 185 |                         subtype = *++p;
 | 
|---|
| 186 |                         if (subtype == VSLENGTH)
 | 
|---|
| 187 |                                 putc('#', fp);
 | 
|---|
| 188 | 
 | 
|---|
| 189 |                         while (*p != '=')
 | 
|---|
| 190 |                                 putc(*p++, fp);
 | 
|---|
| 191 | 
 | 
|---|
| 192 |                         if (subtype & VSNUL)
 | 
|---|
| 193 |                                 putc(':', fp);
 | 
|---|
| 194 | 
 | 
|---|
| 195 |                         switch (subtype & VSTYPE) {
 | 
|---|
| 196 |                         case VSNORMAL:
 | 
|---|
| 197 |                                 putc('}', fp);
 | 
|---|
| 198 |                                 break;
 | 
|---|
| 199 |                         case VSMINUS:
 | 
|---|
| 200 |                                 putc('-', fp);
 | 
|---|
| 201 |                                 break;
 | 
|---|
| 202 |                         case VSPLUS:
 | 
|---|
| 203 |                                 putc('+', fp);
 | 
|---|
| 204 |                                 break;
 | 
|---|
| 205 |                         case VSQUESTION:
 | 
|---|
| 206 |                                 putc('?', fp);
 | 
|---|
| 207 |                                 break;
 | 
|---|
| 208 |                         case VSASSIGN:
 | 
|---|
| 209 |                                 putc('=', fp);
 | 
|---|
| 210 |                                 break;
 | 
|---|
| 211 |                         case VSTRIMLEFT:
 | 
|---|
| 212 |                                 putc('#', fp);
 | 
|---|
| 213 |                                 break;
 | 
|---|
| 214 |                         case VSTRIMLEFTMAX:
 | 
|---|
| 215 |                                 putc('#', fp);
 | 
|---|
| 216 |                                 putc('#', fp);
 | 
|---|
| 217 |                                 break;
 | 
|---|
| 218 |                         case VSTRIMRIGHT:
 | 
|---|
| 219 |                                 putc('%', fp);
 | 
|---|
| 220 |                                 break;
 | 
|---|
| 221 |                         case VSTRIMRIGHTMAX:
 | 
|---|
| 222 |                                 putc('%', fp);
 | 
|---|
| 223 |                                 putc('%', fp);
 | 
|---|
| 224 |                                 break;
 | 
|---|
| 225 |                         case VSLENGTH:
 | 
|---|
| 226 |                                 break;
 | 
|---|
| 227 |                         default:
 | 
|---|
| 228 |                                 printf("<subtype %d>", subtype);
 | 
|---|
| 229 |                         }
 | 
|---|
| 230 |                         break;
 | 
|---|
| 231 |                 case CTLENDVAR:
 | 
|---|
| 232 |                      putc('}', fp);
 | 
|---|
| 233 |                      break;
 | 
|---|
| 234 |                 case CTLBACKQ:
 | 
|---|
| 235 |                 case CTLBACKQ|CTLQUOTE:
 | 
|---|
| 236 |                         putc('$', fp);
 | 
|---|
| 237 |                         putc('(', fp);
 | 
|---|
| 238 |                         shtree(bqlist->n, -1, NULL, fp);
 | 
|---|
| 239 |                         putc(')', fp);
 | 
|---|
| 240 |                         break;
 | 
|---|
| 241 |                 default:
 | 
|---|
| 242 |                         putc(*p, fp);
 | 
|---|
| 243 |                         break;
 | 
|---|
| 244 |                 }
 | 
|---|
| 245 |         }
 | 
|---|
| 246 | }
 | 
|---|
| 247 | 
 | 
|---|
| 248 | 
 | 
|---|
| 249 | static void
 | 
|---|
| 250 | indent(int amount, char *pfx, FILE *fp)
 | 
|---|
| 251 | {
 | 
|---|
| 252 |         int i;
 | 
|---|
| 253 | 
 | 
|---|
| 254 |         for (i = 0 ; i < amount ; i++) {
 | 
|---|
| 255 |                 if (pfx && i == amount - 1)
 | 
|---|
| 256 |                         fputs(pfx, fp);
 | 
|---|
| 257 |                 putc('\t', fp);
 | 
|---|
| 258 |         }
 | 
|---|
| 259 | }
 | 
|---|
| 260 | #endif
 | 
|---|
| 261 | 
 | 
|---|
| 262 | 
 | 
|---|
| 263 | 
 | 
|---|
| 264 | /*
 | 
|---|
| 265 |  * Debugging stuff.
 | 
|---|
| 266 |  */
 | 
|---|
| 267 | 
 | 
|---|
| 268 | 
 | 
|---|
| 269 | FILE *tracefile;
 | 
|---|
| 270 | 
 | 
|---|
| 271 | 
 | 
|---|
| 272 | #ifdef DEBUG
 | 
|---|
| 273 | void
 | 
|---|
| 274 | trputc(int c)
 | 
|---|
| 275 | {
 | 
|---|
| 276 |         if (debug != 1)
 | 
|---|
| 277 |                 return;
 | 
|---|
| 278 |         putc(c, tracefile);
 | 
|---|
| 279 | }
 | 
|---|
| 280 | #endif
 | 
|---|
| 281 | 
 | 
|---|
| 282 | void
 | 
|---|
| 283 | trace(const char *fmt, ...)
 | 
|---|
| 284 | {
 | 
|---|
| 285 | #ifdef DEBUG
 | 
|---|
| 286 |         va_list va;
 | 
|---|
| 287 | 
 | 
|---|
| 288 |         if (debug != 1)
 | 
|---|
| 289 |                 return;
 | 
|---|
| 290 |         fprintf(tracefile, "[%d] ", getpid());
 | 
|---|
| 291 |         va_start(va, fmt);
 | 
|---|
| 292 |         (void) vfprintf(tracefile, fmt, va);
 | 
|---|
| 293 |         va_end(va);
 | 
|---|
| 294 | #endif
 | 
|---|
| 295 | }
 | 
|---|
| 296 | 
 | 
|---|
| 297 | void
 | 
|---|
| 298 | tracev(const char *fmt, va_list va)
 | 
|---|
| 299 | {
 | 
|---|
| 300 | #ifdef DEBUG
 | 
|---|
| 301 |         if (debug != 1)
 | 
|---|
| 302 |                 return;
 | 
|---|
| 303 |         fprintf(tracefile, "[%d] ", getpid());
 | 
|---|
| 304 |         (void) vfprintf(tracefile, fmt, va);
 | 
|---|
| 305 | #endif
 | 
|---|
| 306 | }
 | 
|---|
| 307 | 
 | 
|---|
| 308 | 
 | 
|---|
| 309 | #ifdef DEBUG
 | 
|---|
| 310 | void
 | 
|---|
| 311 | trputs(const char *s)
 | 
|---|
| 312 | {
 | 
|---|
| 313 |         if (debug != 1)
 | 
|---|
| 314 |                 return;
 | 
|---|
| 315 |         fputs(s, tracefile);
 | 
|---|
| 316 | }
 | 
|---|
| 317 | 
 | 
|---|
| 318 | 
 | 
|---|
| 319 | static void
 | 
|---|
| 320 | trstring(char *s)
 | 
|---|
| 321 | {
 | 
|---|
| 322 |         char *p;
 | 
|---|
| 323 |         char c;
 | 
|---|
| 324 | 
 | 
|---|
| 325 |         if (debug != 1)
 | 
|---|
| 326 |                 return;
 | 
|---|
| 327 |         putc('"', tracefile);
 | 
|---|
| 328 |         for (p = s ; *p ; p++) {
 | 
|---|
| 329 |                 switch (*p) {
 | 
|---|
| 330 |                 case '\n':  c = 'n';  goto backslash;
 | 
|---|
| 331 |                 case '\t':  c = 't';  goto backslash;
 | 
|---|
| 332 |                 case '\r':  c = 'r';  goto backslash;
 | 
|---|
| 333 |                 case '"':  c = '"';  goto backslash;
 | 
|---|
| 334 |                 case '\\':  c = '\\';  goto backslash;
 | 
|---|
| 335 |                 case CTLESC:  c = 'e';  goto backslash;
 | 
|---|
| 336 |                 case CTLVAR:  c = 'v';  goto backslash;
 | 
|---|
| 337 |                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
 | 
|---|
| 338 |                 case CTLBACKQ:  c = 'q';  goto backslash;
 | 
|---|
| 339 |                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
 | 
|---|
| 340 | backslash:        putc('\\', tracefile);
 | 
|---|
| 341 |                         putc(c, tracefile);
 | 
|---|
| 342 |                         break;
 | 
|---|
| 343 |                 default:
 | 
|---|
| 344 |                         if (*p >= ' ' && *p <= '~')
 | 
|---|
| 345 |                                 putc(*p, tracefile);
 | 
|---|
| 346 |                         else {
 | 
|---|
| 347 |                                 putc('\\', tracefile);
 | 
|---|
| 348 |                                 putc(*p >> 6 & 03, tracefile);
 | 
|---|
| 349 |                                 putc(*p >> 3 & 07, tracefile);
 | 
|---|
| 350 |                                 putc(*p & 07, tracefile);
 | 
|---|
| 351 |                         }
 | 
|---|
| 352 |                         break;
 | 
|---|
| 353 |                 }
 | 
|---|
| 354 |         }
 | 
|---|
| 355 |         putc('"', tracefile);
 | 
|---|
| 356 | }
 | 
|---|
| 357 | #endif
 | 
|---|
| 358 | 
 | 
|---|
| 359 | 
 | 
|---|
| 360 | void
 | 
|---|
| 361 | trargs(char **ap)
 | 
|---|
| 362 | {
 | 
|---|
| 363 | #ifdef DEBUG
 | 
|---|
| 364 |         if (debug != 1)
 | 
|---|
| 365 |                 return;
 | 
|---|
| 366 |         while (*ap) {
 | 
|---|
| 367 |                 trstring(*ap++);
 | 
|---|
| 368 |                 if (*ap)
 | 
|---|
| 369 |                         putc(' ', tracefile);
 | 
|---|
| 370 |                 else
 | 
|---|
| 371 |                         putc('\n', tracefile);
 | 
|---|
| 372 |         }
 | 
|---|
| 373 | #endif
 | 
|---|
| 374 | }
 | 
|---|
| 375 | 
 | 
|---|
| 376 | 
 | 
|---|
| 377 | #ifdef DEBUG
 | 
|---|
| 378 | void
 | 
|---|
| 379 | opentrace(void)
 | 
|---|
| 380 | {
 | 
|---|
| 381 |         char s[100];
 | 
|---|
| 382 | #ifdef O_APPEND
 | 
|---|
| 383 |         int flags;
 | 
|---|
| 384 | #endif
 | 
|---|
| 385 | 
 | 
|---|
| 386 |         if (debug != 1) {
 | 
|---|
| 387 |                 if (tracefile)
 | 
|---|
| 388 |                         fflush(tracefile);
 | 
|---|
| 389 |                 /* leave open because libedit might be using it */
 | 
|---|
| 390 |                 return;
 | 
|---|
| 391 |         }
 | 
|---|
| 392 | #ifdef not_this_way
 | 
|---|
| 393 |         {
 | 
|---|
| 394 |                 char *p;
 | 
|---|
| 395 |                 if ((p = getenv("HOME")) == NULL) {
 | 
|---|
| 396 |                         if (geteuid() == 0)
 | 
|---|
| 397 |                                 p = "/";
 | 
|---|
| 398 |                         else
 | 
|---|
| 399 |                                 p = "/tmp";
 | 
|---|
| 400 |                 }
 | 
|---|
| 401 |                 scopy(p, s);
 | 
|---|
| 402 |                 strcat(s, "/trace");
 | 
|---|
| 403 |         }
 | 
|---|
| 404 | #else
 | 
|---|
| 405 |         scopy("./trace", s);
 | 
|---|
| 406 | #endif /* not_this_way */
 | 
|---|
| 407 |         if (tracefile) {
 | 
|---|
| 408 |                 if (!freopen(s, "a", tracefile)) {
 | 
|---|
| 409 |                         fprintf(stderr, "Can't re-open %s\n", s);
 | 
|---|
| 410 |                         debug = 0;
 | 
|---|
| 411 |                         return;
 | 
|---|
| 412 |                 }
 | 
|---|
| 413 |         } else {
 | 
|---|
| 414 |                 if ((tracefile = fopen(s, "a")) == NULL) {
 | 
|---|
| 415 |                         fprintf(stderr, "Can't open %s\n", s);
 | 
|---|
| 416 |                         debug = 0;
 | 
|---|
| 417 |                         return;
 | 
|---|
| 418 |                 }
 | 
|---|
| 419 |         }
 | 
|---|
| 420 | #ifdef O_APPEND
 | 
|---|
| 421 |         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
 | 
|---|
| 422 |                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
 | 
|---|
| 423 | #endif
 | 
|---|
| 424 |         setlinebuf(tracefile);
 | 
|---|
| 425 |         fputs("\nTracing started.\n", tracefile);
 | 
|---|
| 426 | }
 | 
|---|
| 427 | #endif /* DEBUG */
 | 
|---|