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