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