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