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 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 40 #endif 41 static const char rcsid[] = 42 "$FreeBSD$"; 43 #endif /* not lint */ 44 45 #include <stdio.h> 46 #ifdef __STDC__ 47 #include <stdarg.h> 48 #else 49 #include <varargs.h> 50 #endif 51 52 #include "shell.h" 53 #include "parser.h" 54 #include "nodes.h" 55 #include "mystring.h" 56 #include "show.h" 57 58 59 #ifdef DEBUG 60 static void shtree __P((union node *, int, char *, FILE*)); 61 static void shcmd __P((union node *, FILE *)); 62 static void sharg __P((union node *, FILE *)); 63 static void indent __P((int, char *, FILE *)); 64 static void trstring __P((char *)); 65 66 67 void 68 showtree(n) 69 union node *n; 70 { 71 trputs("showtree called\n"); 72 shtree(n, 1, NULL, stdout); 73 } 74 75 76 static void 77 shtree(n, ind, pfx, fp) 78 union node *n; 79 int ind; 80 char *pfx; 81 FILE *fp; 82 { 83 struct nodelist *lp; 84 char *s; 85 86 if (n == NULL) 87 return; 88 89 indent(ind, pfx, fp); 90 switch(n->type) { 91 case NSEMI: 92 s = "; "; 93 goto binop; 94 case NAND: 95 s = " && "; 96 goto binop; 97 case NOR: 98 s = " || "; 99 binop: 100 shtree(n->nbinary.ch1, ind, NULL, fp); 101 /* if (ind < 0) */ 102 fputs(s, fp); 103 shtree(n->nbinary.ch2, ind, NULL, fp); 104 break; 105 case NCMD: 106 shcmd(n, fp); 107 if (ind >= 0) 108 putc('\n', fp); 109 break; 110 case NPIPE: 111 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 112 shcmd(lp->n, fp); 113 if (lp->next) 114 fputs(" | ", fp); 115 } 116 if (n->npipe.backgnd) 117 fputs(" &", fp); 118 if (ind >= 0) 119 putc('\n', fp); 120 break; 121 default: 122 fprintf(fp, "<node type %d>", n->type); 123 if (ind >= 0) 124 putc('\n', fp); 125 break; 126 } 127 } 128 129 130 131 static void 132 shcmd(cmd, fp) 133 union node *cmd; 134 FILE *fp; 135 { 136 union node *np; 137 int first; 138 char *s; 139 int dftfd; 140 141 first = 1; 142 for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 143 if (! first) 144 putchar(' '); 145 sharg(np, fp); 146 first = 0; 147 } 148 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 149 if (! first) 150 putchar(' '); 151 switch (np->nfile.type) { 152 case NTO: s = ">"; dftfd = 1; break; 153 case NAPPEND: s = ">>"; dftfd = 1; break; 154 case NTOFD: s = ">&"; dftfd = 1; break; 155 case NFROM: s = "<"; dftfd = 0; break; 156 case NFROMFD: s = "<&"; dftfd = 0; break; 157 default: s = "*error*"; dftfd = 0; break; 158 } 159 if (np->nfile.fd != dftfd) 160 fprintf(fp, "%d", np->nfile.fd); 161 fputs(s, fp); 162 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 163 fprintf(fp, "%d", np->ndup.dupfd); 164 } else { 165 sharg(np->nfile.fname, fp); 166 } 167 first = 0; 168 } 169 } 170 171 172 173 static void 174 sharg(arg, fp) 175 union node *arg; 176 FILE *fp; 177 { 178 char *p; 179 struct nodelist *bqlist; 180 int subtype; 181 182 if (arg->type != NARG) { 183 printf("<node type %d>\n", arg->type); 184 fflush(stdout); 185 abort(); 186 } 187 bqlist = arg->narg.backquote; 188 for (p = arg->narg.text ; *p ; p++) { 189 switch (*p) { 190 case CTLESC: 191 putc(*++p, fp); 192 break; 193 case CTLVAR: 194 putc('$', fp); 195 putc('{', fp); 196 subtype = *++p; 197 if (subtype == VSLENGTH) 198 putc('#', fp); 199 200 while (*p != '=') 201 putc(*p++, fp); 202 203 if (subtype & VSNUL) 204 putc(':', fp); 205 206 switch (subtype & VSTYPE) { 207 case VSNORMAL: 208 putc('}', fp); 209 break; 210 case VSMINUS: 211 putc('-', fp); 212 break; 213 case VSPLUS: 214 putc('+', fp); 215 break; 216 case VSQUESTION: 217 putc('?', fp); 218 break; 219 case VSASSIGN: 220 putc('=', fp); 221 break; 222 case VSTRIMLEFT: 223 putc('#', fp); 224 break; 225 case VSTRIMLEFTMAX: 226 putc('#', fp); 227 putc('#', fp); 228 break; 229 case VSTRIMRIGHT: 230 putc('%', fp); 231 break; 232 case VSTRIMRIGHTMAX: 233 putc('%', fp); 234 putc('%', fp); 235 break; 236 case VSLENGTH: 237 break; 238 default: 239 printf("<subtype %d>", subtype); 240 } 241 break; 242 case CTLENDVAR: 243 putc('}', fp); 244 break; 245 case CTLBACKQ: 246 case CTLBACKQ|CTLQUOTE: 247 putc('$', fp); 248 putc('(', fp); 249 shtree(bqlist->n, -1, NULL, fp); 250 putc(')', fp); 251 break; 252 default: 253 putc(*p, fp); 254 break; 255 } 256 } 257 } 258 259 260 static void 261 indent(amount, pfx, fp) 262 int amount; 263 char *pfx; 264 FILE *fp; 265 { 266 int i; 267 268 for (i = 0 ; i < amount ; i++) { 269 if (pfx && i == amount - 1) 270 fputs(pfx, fp); 271 putc('\t', fp); 272 } 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 if (tracefile == NULL) 295 return; 296 putc(c, tracefile); 297 if (c == '\n') 298 fflush(tracefile); 299 } 300 301 302 void 303 #ifdef __STDC__ 304 trace(const char *fmt, ...) 305 #else 306 trace(va_alist) 307 va_dcl 308 #endif 309 { 310 va_list va; 311 #ifdef __STDC__ 312 va_start(va, fmt); 313 #else 314 char *fmt; 315 va_start(va); 316 fmt = va_arg(va, char *); 317 #endif 318 if (tracefile != NULL) { 319 (void) vfprintf(tracefile, fmt, va); 320 if (strchr(fmt, '\n')) 321 (void) fflush(tracefile); 322 } 323 va_end(va); 324 } 325 326 327 void 328 trputs(s) 329 char *s; 330 { 331 if (tracefile == NULL) 332 return; 333 fputs(s, tracefile); 334 if (strchr(s, '\n')) 335 fflush(tracefile); 336 } 337 338 339 static void 340 trstring(s) 341 char *s; 342 { 343 char *p; 344 char c; 345 346 if (tracefile == NULL) 347 return; 348 putc('"', tracefile); 349 for (p = s ; *p ; p++) { 350 switch (*p) { 351 case '\n': c = 'n'; goto backslash; 352 case '\t': c = 't'; goto backslash; 353 case '\r': c = 'r'; goto backslash; 354 case '"': c = '"'; goto backslash; 355 case '\\': c = '\\'; goto backslash; 356 case CTLESC: c = 'e'; goto backslash; 357 case CTLVAR: c = 'v'; goto backslash; 358 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 359 case CTLBACKQ: c = 'q'; goto backslash; 360 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 361 backslash: putc('\\', tracefile); 362 putc(c, tracefile); 363 break; 364 default: 365 if (*p >= ' ' && *p <= '~') 366 putc(*p, tracefile); 367 else { 368 putc('\\', tracefile); 369 putc(*p >> 6 & 03, tracefile); 370 putc(*p >> 3 & 07, tracefile); 371 putc(*p & 07, tracefile); 372 } 373 break; 374 } 375 } 376 putc('"', tracefile); 377 } 378 379 380 void 381 trargs(ap) 382 char **ap; 383 { 384 if (tracefile == NULL) 385 return; 386 while (*ap) { 387 trstring(*ap++); 388 if (*ap) 389 putc(' ', tracefile); 390 else 391 putc('\n', tracefile); 392 } 393 fflush(tracefile); 394 } 395 396 397 void 398 opentrace() { 399 char s[100]; 400 char *getenv(); 401 #ifdef O_APPEND 402 int flags; 403 #endif 404 405 if (!debug) 406 return; 407 #ifdef not_this_way 408 { 409 char *p; 410 if ((p = getenv("HOME")) == NULL) { 411 if (geteuid() == 0) 412 p = "/"; 413 else 414 p = "/tmp"; 415 } 416 scopy(p, s); 417 strcat(s, "/trace"); 418 } 419 #else 420 scopy("./trace", s); 421 #endif /* not_this_way */ 422 if ((tracefile = fopen(s, "a")) == NULL) { 423 fprintf(stderr, "Can't open %s\n", s); 424 return; 425 } 426 #ifdef O_APPEND 427 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 428 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 429 #endif 430 fputs("\nTracing started.\n", tracefile); 431 fflush(tracefile); 432 } 433 #endif /* DEBUG */ 434