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