show.c revision 22988
1252330Sjeff/*- 2252330Sjeff * Copyright (c) 1991, 1993 3252330Sjeff * The Regents of the University of California. All rights reserved. 4252330Sjeff * 5252330Sjeff * This code is derived from software contributed to Berkeley by 6252330Sjeff * Kenneth Almquist. 7252330Sjeff * 8252330Sjeff * Redistribution and use in source and binary forms, with or without 9252330Sjeff * modification, are permitted provided that the following conditions 10252330Sjeff * are met: 11252330Sjeff * 1. Redistributions of source code must retain the above copyright 12252330Sjeff * notice, this list of conditions and the following disclaimer. 13252330Sjeff * 2. Redistributions in binary form must reproduce the above copyright 14252330Sjeff * notice, this list of conditions and the following disclaimer in the 15252330Sjeff * documentation and/or other materials provided with the distribution. 16252330Sjeff * 3. All advertising materials mentioning features or use of this software 17252330Sjeff * must display the following acknowledgement: 18252330Sjeff * This product includes software developed by the University of 19252330Sjeff * California, Berkeley and its contributors. 20252330Sjeff * 4. Neither the name of the University nor the names of its contributors 21252330Sjeff * may be used to endorse or promote products derived from this software 22252330Sjeff * without specific prior written permission. 23252330Sjeff * 24252330Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25252330Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26252330Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27252330Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28252330Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29252330Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30252330Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31252330Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32252330Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33252330Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34252330Sjeff * SUCH DAMAGE. 35252330Sjeff * 36252330Sjeff * $Id$ 37252330Sjeff */ 38252330Sjeff 39252330Sjeff#ifndef lint 40252330Sjeffstatic char const sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 41252330Sjeff#endif /* not lint */ 42252330Sjeff 43252330Sjeff#include <stdio.h> 44252330Sjeff#if __STDC__ 45252330Sjeff#include <stdarg.h> 46252330Sjeff#else 47252330Sjeff#include <varargs.h> 48252330Sjeff#endif 49252330Sjeff 50252330Sjeff#include "shell.h" 51252330Sjeff#include "parser.h" 52252330Sjeff#include "nodes.h" 53252330Sjeff#include "mystring.h" 54252330Sjeff#include "show.h" 55252330Sjeff 56252330Sjeff 57252330Sjeff#ifdef DEBUG 58252330Sjeffstatic void shtree __P((union node *, int, char *, FILE*)); 59252330Sjeffstatic void shcmd __P((union node *, FILE *)); 60252330Sjeffstatic void sharg __P((union node *, FILE *)); 61252330Sjeffstatic void indent __P((int, char *, FILE *)); 62252330Sjeffstatic void trstring __P((char *)); 63252330Sjeff 64252330Sjeff 65252330Sjeffvoid 66252330Sjeffshowtree(n) 67252330Sjeff union node *n; 68252330Sjeff{ 69252330Sjeff trputs("showtree called\n"); 70252330Sjeff shtree(n, 1, NULL, stdout); 71252330Sjeff} 72252330Sjeff 73252330Sjeff 74252330Sjeffstatic void 75252330Sjeffshtree(n, ind, pfx, fp) 76252330Sjeff union node *n; 77252330Sjeff int ind; 78252330Sjeff char *pfx; 79252330Sjeff FILE *fp; 80252330Sjeff{ 81252330Sjeff struct nodelist *lp; 82252330Sjeff char *s; 83252330Sjeff 84252330Sjeff if (n == NULL) 85252330Sjeff return; 86252330Sjeff 87252330Sjeff indent(ind, pfx, fp); 88252330Sjeff switch(n->type) { 89252330Sjeff case NSEMI: 90252330Sjeff s = "; "; 91252330Sjeff goto binop; 92252330Sjeff case NAND: 93252330Sjeff s = " && "; 94252330Sjeff goto binop; 95252330Sjeff case NOR: 96252330Sjeff s = " || "; 97252330Sjeffbinop: 98252330Sjeff shtree(n->nbinary.ch1, ind, NULL, fp); 99252330Sjeff /* if (ind < 0) */ 100252330Sjeff fputs(s, fp); 101252330Sjeff shtree(n->nbinary.ch2, ind, NULL, fp); 102252330Sjeff break; 103252330Sjeff case NCMD: 104252330Sjeff shcmd(n, fp); 105252330Sjeff if (ind >= 0) 106252330Sjeff putc('\n', fp); 107252330Sjeff break; 108252330Sjeff case NPIPE: 109252330Sjeff for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 110252330Sjeff shcmd(lp->n, fp); 111252330Sjeff if (lp->next) 112252330Sjeff fputs(" | ", fp); 113252330Sjeff } 114252330Sjeff if (n->npipe.backgnd) 115252330Sjeff fputs(" &", fp); 116252330Sjeff if (ind >= 0) 117252330Sjeff putc('\n', fp); 118252330Sjeff break; 119252330Sjeff default: 120252330Sjeff fprintf(fp, "<node type %d>", n->type); 121252330Sjeff if (ind >= 0) 122252330Sjeff putc('\n', fp); 123252330Sjeff break; 124252330Sjeff } 125252330Sjeff} 126252330Sjeff 127252330Sjeff 128252330Sjeff 129252330Sjeffstatic void 130252330Sjeffshcmd(cmd, fp) 131252330Sjeff union node *cmd; 132282361Smav FILE *fp; 133252330Sjeff{ 134252330Sjeff union node *np; 135252330Sjeff int first; 136252330Sjeff char *s; 137 int dftfd; 138 139 first = 1; 140 for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 141 if (! first) 142 putchar(' '); 143 sharg(np, fp); 144 first = 0; 145 } 146 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 147 if (! first) 148 putchar(' '); 149 switch (np->nfile.type) { 150 case NTO: s = ">"; dftfd = 1; break; 151 case NAPPEND: s = ">>"; dftfd = 1; break; 152 case NTOFD: s = ">&"; dftfd = 1; break; 153 case NFROM: s = "<"; dftfd = 0; break; 154 case NFROMFD: s = "<&"; dftfd = 0; break; 155 default: s = "*error*"; dftfd = 0; break; 156 } 157 if (np->nfile.fd != dftfd) 158 fprintf(fp, "%d", np->nfile.fd); 159 fputs(s, fp); 160 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 161 fprintf(fp, "%d", np->ndup.dupfd); 162 } else { 163 sharg(np->nfile.fname, fp); 164 } 165 first = 0; 166 } 167} 168 169 170 171static void 172sharg(arg, fp) 173 union node *arg; 174 FILE *fp; 175 { 176 char *p; 177 struct nodelist *bqlist; 178 int subtype; 179 180 if (arg->type != NARG) { 181 printf("<node type %d>\n", arg->type); 182 fflush(stdout); 183 abort(); 184 } 185 bqlist = arg->narg.backquote; 186 for (p = arg->narg.text ; *p ; p++) { 187 switch (*p) { 188 case CTLESC: 189 putc(*++p, fp); 190 break; 191 case CTLVAR: 192 putc('$', fp); 193 putc('{', fp); 194 subtype = *++p; 195 if (subtype == VSLENGTH) 196 putc('#', fp); 197 198 while (*p != '=') 199 putc(*p++, fp); 200 201 if (subtype & VSNUL) 202 putc(':', fp); 203 204 switch (subtype & VSTYPE) { 205 case VSNORMAL: 206 putc('}', fp); 207 break; 208 case VSMINUS: 209 putc('-', fp); 210 break; 211 case VSPLUS: 212 putc('+', fp); 213 break; 214 case VSQUESTION: 215 putc('?', fp); 216 break; 217 case VSASSIGN: 218 putc('=', fp); 219 break; 220 case VSTRIMLEFT: 221 putc('#', fp); 222 break; 223 case VSTRIMLEFTMAX: 224 putc('#', fp); 225 putc('#', fp); 226 break; 227 case VSTRIMRIGHT: 228 putc('%', fp); 229 break; 230 case VSTRIMRIGHTMAX: 231 putc('%', fp); 232 putc('%', fp); 233 break; 234 case VSLENGTH: 235 break; 236 default: 237 printf("<subtype %d>", subtype); 238 } 239 break; 240 case CTLENDVAR: 241 putc('}', fp); 242 break; 243 case CTLBACKQ: 244 case CTLBACKQ|CTLQUOTE: 245 putc('$', fp); 246 putc('(', fp); 247 shtree(bqlist->n, -1, NULL, fp); 248 putc(')', fp); 249 break; 250 default: 251 putc(*p, fp); 252 break; 253 } 254 } 255} 256 257 258static void 259indent(amount, pfx, fp) 260 int amount; 261 char *pfx; 262 FILE *fp; 263{ 264 int i; 265 266 for (i = 0 ; i < amount ; i++) { 267 if (pfx && i == amount - 1) 268 fputs(pfx, fp); 269 putc('\t', fp); 270 } 271} 272 273 274/* 275 * Debugging stuff. 276 */ 277 278 279FILE *tracefile; 280 281#if DEBUG == 2 282int debug = 1; 283#else 284int debug = 0; 285#endif 286 287 288void 289trputc(c) 290 int c; 291{ 292 if (tracefile == NULL) 293 return; 294 putc(c, tracefile); 295 if (c == '\n') 296 fflush(tracefile); 297} 298 299 300void 301#if __STDC__ 302trace(const char *fmt, ...) 303#else 304trace(va_alist) 305 va_dcl 306#endif 307{ 308 va_list va; 309#if __STDC__ 310 va_start(va, fmt); 311#else 312 char *fmt; 313 va_start(va); 314 fmt = va_arg(va, char *); 315#endif 316 if (tracefile != NULL) { 317 (void) vfprintf(tracefile, fmt, va); 318 if (strchr(fmt, '\n')) 319 (void) fflush(tracefile); 320 } 321 va_end(va); 322} 323 324 325void 326trputs(s) 327 char *s; 328{ 329 if (tracefile == NULL) 330 return; 331 fputs(s, tracefile); 332 if (strchr(s, '\n')) 333 fflush(tracefile); 334} 335 336 337static void 338trstring(s) 339 char *s; 340{ 341 register char *p; 342 char c; 343 344 if (tracefile == NULL) 345 return; 346 putc('"', tracefile); 347 for (p = s ; *p ; p++) { 348 switch (*p) { 349 case '\n': c = 'n'; goto backslash; 350 case '\t': c = 't'; goto backslash; 351 case '\r': c = 'r'; goto backslash; 352 case '"': c = '"'; goto backslash; 353 case '\\': c = '\\'; goto backslash; 354 case CTLESC: c = 'e'; goto backslash; 355 case CTLVAR: c = 'v'; goto backslash; 356 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 357 case CTLBACKQ: c = 'q'; goto backslash; 358 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 359backslash: putc('\\', tracefile); 360 putc(c, tracefile); 361 break; 362 default: 363 if (*p >= ' ' && *p <= '~') 364 putc(*p, tracefile); 365 else { 366 putc('\\', tracefile); 367 putc(*p >> 6 & 03, tracefile); 368 putc(*p >> 3 & 07, tracefile); 369 putc(*p & 07, tracefile); 370 } 371 break; 372 } 373 } 374 putc('"', tracefile); 375} 376 377 378void 379trargs(ap) 380 char **ap; 381{ 382 if (tracefile == NULL) 383 return; 384 while (*ap) { 385 trstring(*ap++); 386 if (*ap) 387 putc(' ', tracefile); 388 else 389 putc('\n', tracefile); 390 } 391 fflush(tracefile); 392} 393 394 395void 396opentrace() { 397 char s[100]; 398 char *getenv(); 399#ifdef O_APPEND 400 int flags; 401#endif 402 403 if (!debug) 404 return; 405#ifdef not_this_way 406 { 407 char *p; 408 if ((p = getenv("HOME")) == NULL) { 409 if (geteuid() == 0) 410 p = "/"; 411 else 412 p = "/tmp"; 413 } 414 scopy(p, s); 415 strcat(s, "/trace"); 416 } 417#else 418 scopy("./trace", s); 419#endif /* not_this_way */ 420 if ((tracefile = fopen(s, "a")) == NULL) { 421 fprintf(stderr, "Can't open %s\n", s); 422 return; 423 } 424#ifdef O_APPEND 425 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 426 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 427#endif 428 fputs("\nTracing started.\n", tracefile); 429 fflush(tracefile); 430} 431#endif /* DEBUG */ 432