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