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