show.c revision 36150
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kenneth Almquist. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 3836150Scharnier#if 0 3936150Scharnierstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 4036150Scharnier#endif 4136150Scharnierstatic const char rcsid[] = 4236150Scharnier "$Id$"; 431556Srgrimes#endif /* not lint */ 441556Srgrimes 451556Srgrimes#include <stdio.h> 4625222Ssteve#ifdef __STDC__ 4717987Speter#include <stdarg.h> 4817987Speter#else 4917987Speter#include <varargs.h> 5017987Speter#endif 5117987Speter 521556Srgrimes#include "shell.h" 531556Srgrimes#include "parser.h" 541556Srgrimes#include "nodes.h" 551556Srgrimes#include "mystring.h" 5617987Speter#include "show.h" 571556Srgrimes 581556Srgrimes 591556Srgrimes#ifdef DEBUG 6017987Speterstatic void shtree __P((union node *, int, char *, FILE*)); 6117987Speterstatic void shcmd __P((union node *, FILE *)); 6217987Speterstatic void sharg __P((union node *, FILE *)); 6317987Speterstatic void indent __P((int, char *, FILE *)); 6417987Speterstatic void trstring __P((char *)); 651556Srgrimes 661556Srgrimes 6717987Spetervoid 681556Srgrimesshowtree(n) 691556Srgrimes union node *n; 7017987Speter{ 711556Srgrimes trputs("showtree called\n"); 721556Srgrimes shtree(n, 1, NULL, stdout); 731556Srgrimes} 741556Srgrimes 751556Srgrimes 7617987Speterstatic void 771556Srgrimesshtree(n, ind, pfx, fp) 781556Srgrimes union node *n; 7917987Speter int ind; 801556Srgrimes char *pfx; 811556Srgrimes FILE *fp; 8217987Speter{ 831556Srgrimes struct nodelist *lp; 841556Srgrimes char *s; 851556Srgrimes 8617987Speter if (n == NULL) 8717987Speter return; 8817987Speter 891556Srgrimes indent(ind, pfx, fp); 901556Srgrimes switch(n->type) { 911556Srgrimes case NSEMI: 921556Srgrimes s = "; "; 931556Srgrimes goto binop; 941556Srgrimes case NAND: 951556Srgrimes s = " && "; 961556Srgrimes goto binop; 971556Srgrimes case NOR: 981556Srgrimes s = " || "; 991556Srgrimesbinop: 1001556Srgrimes shtree(n->nbinary.ch1, ind, NULL, fp); 1011556Srgrimes /* if (ind < 0) */ 1021556Srgrimes fputs(s, fp); 1031556Srgrimes shtree(n->nbinary.ch2, ind, NULL, fp); 1041556Srgrimes break; 1051556Srgrimes case NCMD: 1061556Srgrimes shcmd(n, fp); 1071556Srgrimes if (ind >= 0) 1081556Srgrimes putc('\n', fp); 1091556Srgrimes break; 1101556Srgrimes case NPIPE: 1111556Srgrimes for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1121556Srgrimes shcmd(lp->n, fp); 1131556Srgrimes if (lp->next) 1141556Srgrimes fputs(" | ", fp); 1151556Srgrimes } 1161556Srgrimes if (n->npipe.backgnd) 1171556Srgrimes fputs(" &", fp); 1181556Srgrimes if (ind >= 0) 1191556Srgrimes putc('\n', fp); 1201556Srgrimes break; 1211556Srgrimes default: 1221556Srgrimes fprintf(fp, "<node type %d>", n->type); 1231556Srgrimes if (ind >= 0) 1241556Srgrimes putc('\n', fp); 1251556Srgrimes break; 1261556Srgrimes } 1271556Srgrimes} 1281556Srgrimes 1291556Srgrimes 1301556Srgrimes 13117987Speterstatic void 1321556Srgrimesshcmd(cmd, fp) 1331556Srgrimes union node *cmd; 1341556Srgrimes FILE *fp; 13517987Speter{ 1361556Srgrimes union node *np; 1371556Srgrimes int first; 1381556Srgrimes char *s; 1391556Srgrimes int dftfd; 1401556Srgrimes 1411556Srgrimes first = 1; 1421556Srgrimes for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 1431556Srgrimes if (! first) 1441556Srgrimes putchar(' '); 1451556Srgrimes sharg(np, fp); 1461556Srgrimes first = 0; 1471556Srgrimes } 1481556Srgrimes for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 1491556Srgrimes if (! first) 1501556Srgrimes putchar(' '); 1511556Srgrimes switch (np->nfile.type) { 1521556Srgrimes case NTO: s = ">"; dftfd = 1; break; 1531556Srgrimes case NAPPEND: s = ">>"; dftfd = 1; break; 1541556Srgrimes case NTOFD: s = ">&"; dftfd = 1; break; 1551556Srgrimes case NFROM: s = "<"; dftfd = 0; break; 1561556Srgrimes case NFROMFD: s = "<&"; dftfd = 0; break; 15717987Speter default: s = "*error*"; dftfd = 0; break; 1581556Srgrimes } 1591556Srgrimes if (np->nfile.fd != dftfd) 1601556Srgrimes fprintf(fp, "%d", np->nfile.fd); 1611556Srgrimes fputs(s, fp); 1621556Srgrimes if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 1631556Srgrimes fprintf(fp, "%d", np->ndup.dupfd); 1641556Srgrimes } else { 1651556Srgrimes sharg(np->nfile.fname, fp); 1661556Srgrimes } 1671556Srgrimes first = 0; 1681556Srgrimes } 1691556Srgrimes} 1701556Srgrimes 1711556Srgrimes 1721556Srgrimes 17317987Speterstatic void 1741556Srgrimessharg(arg, fp) 1751556Srgrimes union node *arg; 1761556Srgrimes FILE *fp; 1771556Srgrimes { 1781556Srgrimes char *p; 1791556Srgrimes struct nodelist *bqlist; 1801556Srgrimes int subtype; 1811556Srgrimes 1821556Srgrimes if (arg->type != NARG) { 1831556Srgrimes printf("<node type %d>\n", arg->type); 1841556Srgrimes fflush(stdout); 1851556Srgrimes abort(); 1861556Srgrimes } 1871556Srgrimes bqlist = arg->narg.backquote; 1881556Srgrimes for (p = arg->narg.text ; *p ; p++) { 1891556Srgrimes switch (*p) { 1901556Srgrimes case CTLESC: 1911556Srgrimes putc(*++p, fp); 1921556Srgrimes break; 1931556Srgrimes case CTLVAR: 1941556Srgrimes putc('$', fp); 1951556Srgrimes putc('{', fp); 1961556Srgrimes subtype = *++p; 19717987Speter if (subtype == VSLENGTH) 19817987Speter putc('#', fp); 19917987Speter 2001556Srgrimes while (*p != '=') 2011556Srgrimes putc(*p++, fp); 20217987Speter 2031556Srgrimes if (subtype & VSNUL) 2041556Srgrimes putc(':', fp); 20517987Speter 2061556Srgrimes switch (subtype & VSTYPE) { 2071556Srgrimes case VSNORMAL: 2081556Srgrimes putc('}', fp); 2091556Srgrimes break; 2101556Srgrimes case VSMINUS: 2111556Srgrimes putc('-', fp); 2121556Srgrimes break; 2131556Srgrimes case VSPLUS: 2141556Srgrimes putc('+', fp); 2151556Srgrimes break; 2161556Srgrimes case VSQUESTION: 2171556Srgrimes putc('?', fp); 2181556Srgrimes break; 2191556Srgrimes case VSASSIGN: 2201556Srgrimes putc('=', fp); 2211556Srgrimes break; 22217987Speter case VSTRIMLEFT: 22317987Speter putc('#', fp); 22417987Speter break; 22517987Speter case VSTRIMLEFTMAX: 22617987Speter putc('#', fp); 22717987Speter putc('#', fp); 22817987Speter break; 22917987Speter case VSTRIMRIGHT: 23017987Speter putc('%', fp); 23117987Speter break; 23217987Speter case VSTRIMRIGHTMAX: 23317987Speter putc('%', fp); 23417987Speter putc('%', fp); 23517987Speter break; 23617987Speter case VSLENGTH: 23717987Speter break; 2381556Srgrimes default: 2391556Srgrimes printf("<subtype %d>", subtype); 2401556Srgrimes } 2411556Srgrimes break; 2421556Srgrimes case CTLENDVAR: 2431556Srgrimes putc('}', fp); 2441556Srgrimes break; 2451556Srgrimes case CTLBACKQ: 2461556Srgrimes case CTLBACKQ|CTLQUOTE: 2471556Srgrimes putc('$', fp); 2481556Srgrimes putc('(', fp); 2491556Srgrimes shtree(bqlist->n, -1, NULL, fp); 2501556Srgrimes putc(')', fp); 2511556Srgrimes break; 2521556Srgrimes default: 2531556Srgrimes putc(*p, fp); 2541556Srgrimes break; 2551556Srgrimes } 2561556Srgrimes } 2571556Srgrimes} 2581556Srgrimes 2591556Srgrimes 26017987Speterstatic void 2611556Srgrimesindent(amount, pfx, fp) 26217987Speter int amount; 2631556Srgrimes char *pfx; 2641556Srgrimes FILE *fp; 26517987Speter{ 2661556Srgrimes int i; 2671556Srgrimes 2681556Srgrimes for (i = 0 ; i < amount ; i++) { 2691556Srgrimes if (pfx && i == amount - 1) 2701556Srgrimes fputs(pfx, fp); 2711556Srgrimes putc('\t', fp); 2721556Srgrimes } 2731556Srgrimes} 2741556Srgrimes 2751556Srgrimes 2761556Srgrimes/* 2771556Srgrimes * Debugging stuff. 2781556Srgrimes */ 2791556Srgrimes 2801556Srgrimes 2811556SrgrimesFILE *tracefile; 2821556Srgrimes 2831556Srgrimes#if DEBUG == 2 2841556Srgrimesint debug = 1; 2851556Srgrimes#else 2861556Srgrimesint debug = 0; 2871556Srgrimes#endif 2881556Srgrimes 2891556Srgrimes 29017987Spetervoid 29120425Sstevetrputc(c) 29217987Speter int c; 29317987Speter{ 2941556Srgrimes if (tracefile == NULL) 2951556Srgrimes return; 2961556Srgrimes putc(c, tracefile); 2971556Srgrimes if (c == '\n') 2981556Srgrimes fflush(tracefile); 2991556Srgrimes} 3001556Srgrimes 30120425Ssteve 30217987Spetervoid 30325222Ssteve#ifdef __STDC__ 30420425Sstevetrace(const char *fmt, ...) 30517987Speter#else 30620425Sstevetrace(va_alist) 30717987Speter va_dcl 30817987Speter#endif 30917987Speter{ 31017987Speter va_list va; 31125222Ssteve#ifdef __STDC__ 31217987Speter va_start(va, fmt); 31317987Speter#else 3141556Srgrimes char *fmt; 31517987Speter va_start(va); 31617987Speter fmt = va_arg(va, char *); 3171556Srgrimes#endif 31817987Speter if (tracefile != NULL) { 31917987Speter (void) vfprintf(tracefile, fmt, va); 32017987Speter if (strchr(fmt, '\n')) 32117987Speter (void) fflush(tracefile); 32217987Speter } 32317987Speter va_end(va); 3241556Srgrimes} 3251556Srgrimes 3261556Srgrimes 32717987Spetervoid 3281556Srgrimestrputs(s) 3291556Srgrimes char *s; 33017987Speter{ 3311556Srgrimes if (tracefile == NULL) 3321556Srgrimes return; 3331556Srgrimes fputs(s, tracefile); 3341556Srgrimes if (strchr(s, '\n')) 3351556Srgrimes fflush(tracefile); 3361556Srgrimes} 3371556Srgrimes 3381556Srgrimes 33917987Speterstatic void 3401556Srgrimestrstring(s) 3411556Srgrimes char *s; 34217987Speter{ 34325222Ssteve char *p; 3441556Srgrimes char c; 3451556Srgrimes 3461556Srgrimes if (tracefile == NULL) 3471556Srgrimes return; 3481556Srgrimes putc('"', tracefile); 3491556Srgrimes for (p = s ; *p ; p++) { 3501556Srgrimes switch (*p) { 3511556Srgrimes case '\n': c = 'n'; goto backslash; 3521556Srgrimes case '\t': c = 't'; goto backslash; 3531556Srgrimes case '\r': c = 'r'; goto backslash; 3541556Srgrimes case '"': c = '"'; goto backslash; 3551556Srgrimes case '\\': c = '\\'; goto backslash; 3561556Srgrimes case CTLESC: c = 'e'; goto backslash; 3571556Srgrimes case CTLVAR: c = 'v'; goto backslash; 3581556Srgrimes case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 3591556Srgrimes case CTLBACKQ: c = 'q'; goto backslash; 3601556Srgrimes case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 3611556Srgrimesbackslash: putc('\\', tracefile); 3621556Srgrimes putc(c, tracefile); 3631556Srgrimes break; 3641556Srgrimes default: 3651556Srgrimes if (*p >= ' ' && *p <= '~') 3661556Srgrimes putc(*p, tracefile); 3671556Srgrimes else { 3681556Srgrimes putc('\\', tracefile); 3691556Srgrimes putc(*p >> 6 & 03, tracefile); 3701556Srgrimes putc(*p >> 3 & 07, tracefile); 3711556Srgrimes putc(*p & 07, tracefile); 3721556Srgrimes } 3731556Srgrimes break; 3741556Srgrimes } 3751556Srgrimes } 3761556Srgrimes putc('"', tracefile); 37718018Speter} 3781556Srgrimes 3791556Srgrimes 38017987Spetervoid 3811556Srgrimestrargs(ap) 3821556Srgrimes char **ap; 38317987Speter{ 3841556Srgrimes if (tracefile == NULL) 3851556Srgrimes return; 3861556Srgrimes while (*ap) { 3871556Srgrimes trstring(*ap++); 3881556Srgrimes if (*ap) 3891556Srgrimes putc(' ', tracefile); 3901556Srgrimes else 3911556Srgrimes putc('\n', tracefile); 3921556Srgrimes } 3931556Srgrimes fflush(tracefile); 3941556Srgrimes} 3951556Srgrimes 3961556Srgrimes 39717987Spetervoid 3981556Srgrimesopentrace() { 3991556Srgrimes char s[100]; 4001556Srgrimes char *getenv(); 40117987Speter#ifdef O_APPEND 4021556Srgrimes int flags; 40317987Speter#endif 4041556Srgrimes 4051556Srgrimes if (!debug) 4061556Srgrimes return; 4071556Srgrimes#ifdef not_this_way 40817987Speter { 40917987Speter char *p; 41017987Speter if ((p = getenv("HOME")) == NULL) { 41117987Speter if (geteuid() == 0) 41217987Speter p = "/"; 41317987Speter else 41417987Speter p = "/tmp"; 41517987Speter } 41617987Speter scopy(p, s); 41717987Speter strcat(s, "/trace"); 4181556Srgrimes } 4191556Srgrimes#else 4201556Srgrimes scopy("./trace", s); 4211556Srgrimes#endif /* not_this_way */ 4221556Srgrimes if ((tracefile = fopen(s, "a")) == NULL) { 4231556Srgrimes fprintf(stderr, "Can't open %s\n", s); 4241556Srgrimes return; 4251556Srgrimes } 4261556Srgrimes#ifdef O_APPEND 4271556Srgrimes if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 4281556Srgrimes fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 4291556Srgrimes#endif 4301556Srgrimes fputs("\nTracing started.\n", tracefile); 4311556Srgrimes fflush(tracefile); 43220425Ssteve} 4331556Srgrimes#endif /* DEBUG */ 434