show.c revision 17987
1133819Stjr/*- 2133819Stjr * Copyright (c) 1991, 1993 3133819Stjr * The Regents of the University of California. All rights reserved. 4133819Stjr * 5133819Stjr * This code is derived from software contributed to Berkeley by 6213545Skib * Kenneth Almquist. 7133819Stjr * 8133819Stjr * Redistribution and use in source and binary forms, with or without 9133819Stjr * modification, are permitted provided that the following conditions 10133819Stjr * are met: 11133819Stjr * 1. Redistributions of source code must retain the above copyright 12133819Stjr * notice, this list of conditions and the following disclaimer. 13133819Stjr * 2. Redistributions in binary form must reproduce the above copyright 14177999Skib * notice, this list of conditions and the following disclaimer in the 15164199Sru * documentation and/or other materials provided with the distribution. 16133819Stjr * 3. All advertising materials mentioning features or use of this software 17133819Stjr * must display the following acknowledgement: 18161330Sjhb * This product includes software developed by the University of 19161330Sjhb * California, Berkeley and its contributors. 20133819Stjr * 4. Neither the name of the University nor the names of its contributors 21133819Stjr * may be used to endorse or promote products derived from this software 22133819Stjr * without specific prior written permission. 23133819Stjr * 24133819Stjr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25133819Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26133819Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27133819Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28133819Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29133819Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30133819Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31133819Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32133819Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33133819Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34133819Stjr * SUCH DAMAGE. 35143198Ssobomax * 36133819Stjr * $Id: show.c,v 1.2 1994/09/24 02:58:16 davidg Exp $ 37133819Stjr */ 38133819Stjr 39133819Stjr#ifndef lint 40133819Stjrstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 41133819Stjr#endif /* not lint */ 42133819Stjr 43133819Stjr#include <stdio.h> 44133819Stjr#if __STDC__ 45133819Stjr#include <stdarg.h> 46133819Stjr#else 47133819Stjr#include <varargs.h> 48133819Stjr#endif 49133819Stjr 50133819Stjr#include "shell.h" 51133819Stjr#include "parser.h" 52133819Stjr#include "nodes.h" 53133819Stjr#include "mystring.h" 54133819Stjr#include "show.h" 55133819Stjr 56133819Stjr 57133819Stjr#ifdef DEBUG 58133819Stjrstatic void shtree __P((union node *, int, char *, FILE*)); 59133819Stjrstatic void shcmd __P((union node *, FILE *)); 60133819Stjrstatic void sharg __P((union node *, FILE *)); 61133819Stjrstatic void indent __P((int, char *, FILE *)); 62210432Skibstatic void trstring __P((char *)); 63210432Skib 64133819Stjr 65133819Stjrvoid 66133819Stjrshowtree(n) 67133819Stjr union node *n; 68133819Stjr{ 69133819Stjr trputs("showtree called\n"); 70133819Stjr shtree(n, 1, NULL, stdout); 71133819Stjr} 72133819Stjr 73133819Stjr 74133819Stjrstatic void 75133819Stjrshtree(n, ind, pfx, fp) 76133819Stjr union node *n; 77133819Stjr int ind; 78133819Stjr char *pfx; 79133819Stjr FILE *fp; 80133819Stjr{ 81133819Stjr struct nodelist *lp; 82133819Stjr char *s; 83133819Stjr 84133819Stjr if (n == NULL) 85156919Snetchild return; 86156919Snetchild 87156919Snetchild indent(ind, pfx, fp); 88156919Snetchild switch(n->type) { 89133819Stjr case NSEMI: 90133819Stjr s = "; "; 91133819Stjr goto binop; 92133819Stjr case NAND: 93133819Stjr s = " && "; 94133819Stjr goto binop; 95133819Stjr case NOR: 96133819Stjr s = " || "; 97133819Stjrbinop: 98133819Stjr shtree(n->nbinary.ch1, ind, NULL, fp); 99133819Stjr /* if (ind < 0) */ 100133819Stjr fputs(s, fp); 101133819Stjr shtree(n->nbinary.ch2, ind, NULL, fp); 102133819Stjr break; 103133819Stjr case NCMD: 104133819Stjr shcmd(n, fp); 105133819Stjr if (ind >= 0) 106133819Stjr putc('\n', fp); 107133819Stjr break; 108133819Stjr case NPIPE: 109133819Stjr for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 110133819Stjr shcmd(lp->n, fp); 111133819Stjr if (lp->next) 112133819Stjr fputs(" | ", fp); 113133819Stjr } 114133819Stjr if (n->npipe.backgnd) 115133819Stjr fputs(" &", fp); 116133819Stjr if (ind >= 0) 117133819Stjr putc('\n', fp); 118133819Stjr break; 119133819Stjr default: 120133819Stjr fprintf(fp, "<node type %d>", n->type); 121133819Stjr if (ind >= 0) 122133819Stjr putc('\n', fp); 123133819Stjr break; 124133819Stjr } 125133819Stjr} 126133819Stjr 127133819Stjr 128133819Stjr 129133819Stjrstatic void 130133819Stjrshcmd(cmd, fp) 131133819Stjr union node *cmd; 132133819Stjr FILE *fp; 133133819Stjr{ 134133819Stjr union node *np; 135133819Stjr int first; 136133819Stjr char *s; 137133819Stjr int dftfd; 138133819Stjr 139133819Stjr first = 1; 140133819Stjr for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 141133819Stjr if (! first) 142133819Stjr putchar(' '); 143133819Stjr sharg(np, fp); 144133819Stjr first = 0; 145133819Stjr } 146133819Stjr for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 147133819Stjr if (! first) 148133819Stjr putchar(' '); 149133819Stjr switch (np->nfile.type) { 150133819Stjr case NTO: s = ">"; dftfd = 1; break; 151133819Stjr case NAPPEND: s = ">>"; dftfd = 1; break; 152133819Stjr case NTOFD: s = ">&"; dftfd = 1; break; 153133819Stjr case NFROM: s = "<"; dftfd = 0; break; 154133819Stjr case NFROMFD: s = "<&"; dftfd = 0; break; 155133819Stjr default: s = "*error*"; dftfd = 0; break; 156133819Stjr } 157133819Stjr if (np->nfile.fd != dftfd) 158133819Stjr fprintf(fp, "%d", np->nfile.fd); 159133819Stjr fputs(s, fp); 160133819Stjr if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 161133819Stjr fprintf(fp, "%d", np->ndup.dupfd); 162133819Stjr } else { 163133819Stjr sharg(np->nfile.fname, fp); 164133819Stjr } 165133819Stjr first = 0; 166133819Stjr } 167133819Stjr} 168133819Stjr 169133819Stjr 170133819Stjr 171133819Stjrstatic void 172133819Stjrsharg(arg, fp) 173133819Stjr union node *arg; 174133819Stjr FILE *fp; 175133819Stjr { 176133819Stjr char *p; 177133819Stjr struct nodelist *bqlist; 178133819Stjr int subtype; 179133819Stjr 180133819Stjr if (arg->type != NARG) { 181133819Stjr printf("<node type %d>\n", arg->type); 182133819Stjr fflush(stdout); 183133819Stjr abort(); 184133819Stjr } 185133819Stjr bqlist = arg->narg.backquote; 186133819Stjr for (p = arg->narg.text ; *p ; p++) { 187133819Stjr switch (*p) { 188133819Stjr case CTLESC: 189133819Stjr putc(*++p, fp); 190133819Stjr break; 191133819Stjr case CTLVAR: 192133819Stjr putc('$', fp); 193133819Stjr putc('{', fp); 194133819Stjr subtype = *++p; 195133819Stjr if (subtype == VSLENGTH) 196133819Stjr putc('#', fp); 197133819Stjr 198133819Stjr while (*p != '=') 199133819Stjr putc(*p++, fp); 200161309Snetchild 201161309Snetchild if (subtype & VSNUL) 202161309Snetchild putc(':', fp); 203133819Stjr 204133819Stjr switch (subtype & VSTYPE) { 205133819Stjr case VSNORMAL: 206133819Stjr putc('}', fp); 207133819Stjr break; 208133819Stjr case VSMINUS: 209133819Stjr putc('-', fp); 210133819Stjr break; 211133819Stjr case VSPLUS: 212133819Stjr putc('+', fp); 213133819Stjr break; 214133819Stjr case VSQUESTION: 215133819Stjr putc('?', fp); 216133819Stjr break; 217133819Stjr case VSASSIGN: 218133819Stjr putc('=', fp); 219133819Stjr break; 220133819Stjr case VSTRIMLEFT: 221133819Stjr putc('#', fp); 222133819Stjr break; 223133819Stjr case VSTRIMLEFTMAX: 224133819Stjr putc('#', fp); 225133819Stjr putc('#', fp); 226133819Stjr break; 227133819Stjr case VSTRIMRIGHT: 228133819Stjr putc('%', fp); 229133819Stjr break; 230156843Snetchild case VSTRIMRIGHTMAX: 231156843Snetchild putc('%', fp); 232156843Snetchild putc('%', fp); 233156843Snetchild break; 234133819Stjr case VSLENGTH: 235133819Stjr break; 236133819Stjr default: 237133819Stjr printf("<subtype %d>", subtype); 238133819Stjr } 239133819Stjr break; 240133819Stjr case CTLENDVAR: 241133819Stjr putc('}', fp); 242133819Stjr break; 243133819Stjr case CTLBACKQ: 244133819Stjr case CTLBACKQ|CTLQUOTE: 245133819Stjr putc('$', fp); 246133819Stjr putc('(', fp); 247133819Stjr shtree(bqlist->n, -1, NULL, fp); 248133819Stjr putc(')', fp); 249133819Stjr break; 250133819Stjr default: 251133819Stjr putc(*p, fp); 252133819Stjr break; 253133819Stjr } 254133819Stjr } 255133819Stjr} 256133819Stjr 257133819Stjr 258133819Stjrstatic void 259133819Stjrindent(amount, pfx, fp) 260133819Stjr int amount; 261133819Stjr char *pfx; 262133819Stjr FILE *fp; 263133819Stjr{ 264133819Stjr int i; 265133819Stjr 266133819Stjr for (i = 0 ; i < amount ; i++) { 267133819Stjr if (pfx && i == amount - 1) 268133819Stjr fputs(pfx, fp); 269156919Snetchild putc('\t', fp); 270156843Snetchild } 271156919Snetchild} 272156843Snetchild#endif 273133819Stjr 274133819Stjr 275133819Stjr 276133819Stjr/* 277133819Stjr * Debugging stuff. 278133819Stjr */ 279133819Stjr 280133819Stjr 281133819StjrFILE *tracefile; 282133819Stjr 283133819Stjr#if DEBUG == 2 284133819Stjrint debug = 1; 285133819Stjr#else 286133819Stjrint debug = 0; 287133819Stjr#endif 288133819Stjr 289133819Stjr 290133819Stjrvoid 291133819Stjrtrputc(c) 292133819Stjr int c; 293133819Stjr{ 294133819Stjr#ifdef DEBUG 295133819Stjr if (tracefile == NULL) 296156843Snetchild return; 297156843Snetchild putc(c, tracefile); 298156843Snetchild if (c == '\n') 299156843Snetchild fflush(tracefile); 300147142Ssobomax#endif 301147142Ssobomax} 302147142Ssobomax 303147142Ssobomaxvoid 304133819Stjr#if __STDC__ 305133819Stjrshtrace(const char *fmt, ...) 306133819Stjr#else 307133819Stjrshtrace(va_alist) 308133819Stjr va_dcl 309133819Stjr#endif 310133819Stjr{ 311133819Stjr#ifdef DEBUG 312133819Stjr va_list va; 313133819Stjr#if __STDC__ 314133819Stjr va_start(va, fmt); 315133819Stjr#else 316133819Stjr char *fmt; 317133819Stjr va_start(va); 318133819Stjr fmt = va_arg(va, char *); 319133819Stjr#endif 320133819Stjr if (tracefile != NULL) { 321133819Stjr (void) vfprintf(tracefile, fmt, va); 322133819Stjr if (strchr(fmt, '\n')) 323133819Stjr (void) fflush(tracefile); 324133819Stjr } 325133819Stjr va_end(va); 326133819Stjr#endif 327133819Stjr} 328133819Stjr 329133819Stjr 330133819Stjrvoid 331133819Stjrtrputs(s) 332133819Stjr char *s; 333133819Stjr{ 334133819Stjr#ifdef DEBUG 335133819Stjr if (tracefile == NULL) 336133819Stjr return; 337133819Stjr fputs(s, tracefile); 338133819Stjr if (strchr(s, '\n')) 339133819Stjr fflush(tracefile); 340133819Stjr#endif 341133819Stjr} 342133819Stjr 343133819Stjr 344133819Stjrstatic void 345166730Sjkimtrstring(s) 346166730Sjkim char *s; 347166730Sjkim{ 348133819Stjr register char *p; 349133819Stjr char c; 350133819Stjr 351133819Stjr#ifdef DEBUG 352133819Stjr if (tracefile == NULL) 353133819Stjr return; 354133819Stjr putc('"', tracefile); 355133819Stjr for (p = s ; *p ; p++) { 356133819Stjr switch (*p) { 357133819Stjr case '\n': c = 'n'; goto backslash; 358133819Stjr case '\t': c = 't'; goto backslash; 359133819Stjr case '\r': c = 'r'; goto backslash; 360133819Stjr case '"': c = '"'; goto backslash; 361133819Stjr case '\\': c = '\\'; goto backslash; 362133819Stjr case CTLESC: c = 'e'; goto backslash; 363133819Stjr case CTLVAR: c = 'v'; goto backslash; 364133819Stjr case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 365133819Stjr case CTLBACKQ: c = 'q'; goto backslash; 366133819Stjr case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 367133819Stjrbackslash: putc('\\', tracefile); 368133819Stjr putc(c, tracefile); 369133819Stjr break; 370133819Stjr default: 371133819Stjr if (*p >= ' ' && *p <= '~') 372133819Stjr putc(*p, tracefile); 373133819Stjr else { 374133819Stjr putc('\\', tracefile); 375133819Stjr putc(*p >> 6 & 03, tracefile); 376133819Stjr putc(*p >> 3 & 07, tracefile); 377161309Snetchild putc(*p & 07, tracefile); 378161309Snetchild } 379161309Snetchild break; 380133819Stjr } 381184790Sed } 382184790Sed putc('"', tracefile); 383184790Sed#endif 384184790Sed} 385133819Stjr 386133819Stjr 387133819Stjrvoid 388133819Stjrtrargs(ap) 389133819Stjr char **ap; 390133819Stjr{ 391133819Stjr#ifdef DEBUG 392133819Stjr if (tracefile == NULL) 393133819Stjr return; 394133819Stjr while (*ap) { 395133819Stjr trstring(*ap++); 396133819Stjr if (*ap) 397133819Stjr putc(' ', tracefile); 398133819Stjr else 399133819Stjr putc('\n', tracefile); 400133819Stjr } 401133819Stjr fflush(tracefile); 402133819Stjr#endif 403133819Stjr} 404133819Stjr 405133819Stjr 406133819Stjrvoid 407133819Stjropentrace() { 408133819Stjr char s[100]; 409133819Stjr char *getenv(); 410133819Stjr#ifdef O_APPEND 411133819Stjr int flags; 412133819Stjr#endif 413133819Stjr 414133819Stjr#ifdef DEBUG 415133819Stjr if (!debug) 416133819Stjr return; 417133819Stjr#ifdef not_this_way 418133819Stjr { 419133819Stjr char *p; 420133819Stjr if ((p = getenv("HOME")) == NULL) { 421133819Stjr if (geteuid() == 0) 422133819Stjr p = "/"; 423133819Stjr else 424133819Stjr p = "/tmp"; 425133819Stjr } 426133819Stjr scopy(p, s); 427133819Stjr strcat(s, "/trace"); 428133819Stjr } 429133819Stjr#else 430133819Stjr scopy("./trace", s); 431133819Stjr#endif /* not_this_way */ 432133819Stjr if ((tracefile = fopen(s, "a")) == NULL) { 433133819Stjr fprintf(stderr, "Can't open %s\n", s); 434133819Stjr return; 435133819Stjr } 436133819Stjr#ifdef O_APPEND 437133819Stjr if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 438133819Stjr fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 439133819Stjr#endif 440133819Stjr fputs("\nTracing started.\n", tracefile); 441133819Stjr fflush(tracefile); 442133819Stjr#endif /* DEBUG */ 443133819Stjr} 444133819Stjr