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