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 * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3436150Scharnier#if 0 3536150Scharnierstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 3636150Scharnier#endif 371556Srgrimes#endif /* not lint */ 3899110Sobrien#include <sys/cdefs.h> 3999110Sobrien__FBSDID("$FreeBSD$"); 401556Srgrimes 41109627Stjr#include <fcntl.h> 421556Srgrimes#include <stdio.h> 43109627Stjr#include <stdlib.h> 4417987Speter#include <stdarg.h> 4559437Scracauer#include <errno.h> 4617987Speter 471556Srgrimes#include "shell.h" 481556Srgrimes#include "parser.h" 491556Srgrimes#include "nodes.h" 501556Srgrimes#include "mystring.h" 5117987Speter#include "show.h" 521556Srgrimes 531556Srgrimes 541556Srgrimes#ifdef DEBUG 55213811Sobrienstatic void shtree(union node *, int, char *, FILE*); 56213811Sobrienstatic void shcmd(union node *, FILE *); 57213811Sobrienstatic void sharg(union node *, FILE *); 58213811Sobrienstatic void indent(int, char *, FILE *); 59213811Sobrienstatic void trstring(char *); 601556Srgrimes 611556Srgrimes 6217987Spetervoid 6390111Simpshowtree(union node *n) 6417987Speter{ 651556Srgrimes trputs("showtree called\n"); 661556Srgrimes shtree(n, 1, NULL, stdout); 671556Srgrimes} 681556Srgrimes 691556Srgrimes 70213811Sobrienstatic void 7190111Simpshtree(union node *n, int ind, char *pfx, FILE *fp) 7217987Speter{ 731556Srgrimes struct nodelist *lp; 741556Srgrimes char *s; 751556Srgrimes 7617987Speter if (n == NULL) 7717987Speter return; 7817987Speter 791556Srgrimes indent(ind, pfx, fp); 801556Srgrimes switch(n->type) { 811556Srgrimes case NSEMI: 821556Srgrimes s = "; "; 831556Srgrimes goto binop; 841556Srgrimes case NAND: 851556Srgrimes s = " && "; 861556Srgrimes goto binop; 871556Srgrimes case NOR: 881556Srgrimes s = " || "; 891556Srgrimesbinop: 901556Srgrimes shtree(n->nbinary.ch1, ind, NULL, fp); 911556Srgrimes /* if (ind < 0) */ 921556Srgrimes fputs(s, fp); 931556Srgrimes shtree(n->nbinary.ch2, ind, NULL, fp); 941556Srgrimes break; 951556Srgrimes case NCMD: 961556Srgrimes shcmd(n, fp); 971556Srgrimes if (ind >= 0) 981556Srgrimes putc('\n', fp); 991556Srgrimes break; 1001556Srgrimes case NPIPE: 1011556Srgrimes for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1021556Srgrimes shcmd(lp->n, fp); 1031556Srgrimes if (lp->next) 1041556Srgrimes fputs(" | ", fp); 1051556Srgrimes } 1061556Srgrimes if (n->npipe.backgnd) 1071556Srgrimes fputs(" &", fp); 1081556Srgrimes if (ind >= 0) 1091556Srgrimes putc('\n', fp); 1101556Srgrimes break; 1111556Srgrimes default: 1121556Srgrimes fprintf(fp, "<node type %d>", n->type); 1131556Srgrimes if (ind >= 0) 1141556Srgrimes putc('\n', fp); 1151556Srgrimes break; 1161556Srgrimes } 1171556Srgrimes} 1181556Srgrimes 1191556Srgrimes 1201556Srgrimes 121213811Sobrienstatic void 12290111Simpshcmd(union node *cmd, FILE *fp) 12317987Speter{ 1241556Srgrimes union node *np; 1251556Srgrimes int first; 1261556Srgrimes char *s; 1271556Srgrimes int dftfd; 1281556Srgrimes 1291556Srgrimes first = 1; 1301556Srgrimes for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 1311556Srgrimes if (! first) 1321556Srgrimes putchar(' '); 1331556Srgrimes sharg(np, fp); 1341556Srgrimes first = 0; 1351556Srgrimes } 1361556Srgrimes for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 1371556Srgrimes if (! first) 1381556Srgrimes putchar(' '); 1391556Srgrimes switch (np->nfile.type) { 1401556Srgrimes case NTO: s = ">"; dftfd = 1; break; 1411556Srgrimes case NAPPEND: s = ">>"; dftfd = 1; break; 1421556Srgrimes case NTOFD: s = ">&"; dftfd = 1; break; 14396922Stjr case NCLOBBER: s = ">|"; dftfd = 1; break; 1441556Srgrimes case NFROM: s = "<"; dftfd = 0; break; 14566612Sbrian case NFROMTO: s = "<>"; dftfd = 0; break; 1461556Srgrimes case NFROMFD: s = "<&"; dftfd = 0; break; 147157750Sschweikh case NHERE: s = "<<"; dftfd = 0; break; 148157750Sschweikh case NXHERE: s = "<<"; dftfd = 0; break; 14917987Speter default: s = "*error*"; dftfd = 0; break; 1501556Srgrimes } 1511556Srgrimes if (np->nfile.fd != dftfd) 1521556Srgrimes fprintf(fp, "%d", np->nfile.fd); 1531556Srgrimes fputs(s, fp); 1541556Srgrimes if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 15599634Stjr if (np->ndup.dupfd >= 0) 15699634Stjr fprintf(fp, "%d", np->ndup.dupfd); 15799634Stjr else 15899634Stjr fprintf(fp, "-"); 159157750Sschweikh } else if (np->nfile.type == NHERE) { 160157750Sschweikh fprintf(fp, "HERE"); 161157750Sschweikh } else if (np->nfile.type == NXHERE) { 162157750Sschweikh fprintf(fp, "XHERE"); 1631556Srgrimes } else { 1641556Srgrimes sharg(np->nfile.fname, fp); 1651556Srgrimes } 1661556Srgrimes first = 0; 1671556Srgrimes } 1681556Srgrimes} 1691556Srgrimes 1701556Srgrimes 1711556Srgrimes 172213811Sobrienstatic void 17390111Simpsharg(union node *arg, FILE *fp) 17490111Simp{ 1751556Srgrimes char *p; 1761556Srgrimes struct nodelist *bqlist; 1771556Srgrimes int subtype; 1781556Srgrimes 1791556Srgrimes if (arg->type != NARG) { 1801556Srgrimes printf("<node type %d>\n", arg->type); 1811556Srgrimes fflush(stdout); 1821556Srgrimes abort(); 1831556Srgrimes } 1841556Srgrimes bqlist = arg->narg.backquote; 1851556Srgrimes for (p = arg->narg.text ; *p ; p++) { 1861556Srgrimes switch (*p) { 1871556Srgrimes case CTLESC: 1881556Srgrimes putc(*++p, fp); 1891556Srgrimes break; 1901556Srgrimes case CTLVAR: 1911556Srgrimes putc('$', fp); 1921556Srgrimes putc('{', fp); 1931556Srgrimes subtype = *++p; 19417987Speter if (subtype == VSLENGTH) 19517987Speter putc('#', fp); 19617987Speter 1971556Srgrimes while (*p != '=') 1981556Srgrimes putc(*p++, fp); 19917987Speter 2001556Srgrimes if (subtype & VSNUL) 2011556Srgrimes putc(':', fp); 20217987Speter 2031556Srgrimes switch (subtype & VSTYPE) { 2041556Srgrimes case VSNORMAL: 2051556Srgrimes putc('}', fp); 2061556Srgrimes break; 2071556Srgrimes case VSMINUS: 2081556Srgrimes putc('-', fp); 2091556Srgrimes break; 2101556Srgrimes case VSPLUS: 2111556Srgrimes putc('+', fp); 2121556Srgrimes break; 2131556Srgrimes case VSQUESTION: 2141556Srgrimes putc('?', fp); 2151556Srgrimes break; 2161556Srgrimes case VSASSIGN: 2171556Srgrimes putc('=', fp); 2181556Srgrimes break; 21917987Speter case VSTRIMLEFT: 22017987Speter putc('#', fp); 22117987Speter break; 22217987Speter case VSTRIMLEFTMAX: 22317987Speter putc('#', fp); 22417987Speter putc('#', fp); 22517987Speter break; 22617987Speter case VSTRIMRIGHT: 22717987Speter putc('%', fp); 22817987Speter break; 22917987Speter case VSTRIMRIGHTMAX: 23017987Speter putc('%', fp); 23117987Speter putc('%', fp); 23217987Speter break; 23317987Speter case VSLENGTH: 23417987Speter break; 2351556Srgrimes default: 2361556Srgrimes printf("<subtype %d>", subtype); 2371556Srgrimes } 2381556Srgrimes break; 2391556Srgrimes case CTLENDVAR: 2401556Srgrimes putc('}', fp); 2411556Srgrimes break; 2421556Srgrimes case CTLBACKQ: 2431556Srgrimes case CTLBACKQ|CTLQUOTE: 2441556Srgrimes putc('$', fp); 2451556Srgrimes putc('(', fp); 2461556Srgrimes shtree(bqlist->n, -1, NULL, fp); 2471556Srgrimes putc(')', fp); 2481556Srgrimes break; 2491556Srgrimes default: 2501556Srgrimes putc(*p, fp); 2511556Srgrimes break; 2521556Srgrimes } 2531556Srgrimes } 2541556Srgrimes} 2551556Srgrimes 2561556Srgrimes 257213811Sobrienstatic void 25890111Simpindent(int amount, char *pfx, FILE *fp) 25917987Speter{ 2601556Srgrimes int i; 2611556Srgrimes 2621556Srgrimes for (i = 0 ; i < amount ; i++) { 2631556Srgrimes if (pfx && i == amount - 1) 2641556Srgrimes fputs(pfx, fp); 2651556Srgrimes putc('\t', fp); 2661556Srgrimes } 2671556Srgrimes} 2681556Srgrimes 2691556Srgrimes 2701556Srgrimes/* 2711556Srgrimes * Debugging stuff. 2721556Srgrimes */ 2731556Srgrimes 2741556Srgrimes 2751556SrgrimesFILE *tracefile; 2761556Srgrimes 277213744Sobrien#if DEBUG >= 2 2781556Srgrimesint debug = 1; 2791556Srgrimes#else 2801556Srgrimesint debug = 0; 2811556Srgrimes#endif 2821556Srgrimes 2831556Srgrimes 28417987Spetervoid 28590111Simptrputc(int c) 28617987Speter{ 2871556Srgrimes if (tracefile == NULL) 2881556Srgrimes return; 2891556Srgrimes putc(c, tracefile); 2901556Srgrimes if (c == '\n') 2911556Srgrimes fflush(tracefile); 2921556Srgrimes} 2931556Srgrimes 29420425Ssteve 29517987Spetervoid 29659438Scracauersh_trace(const char *fmt, ...) 29717987Speter{ 29817987Speter va_list va; 29917987Speter va_start(va, fmt); 30017987Speter if (tracefile != NULL) { 30117987Speter (void) vfprintf(tracefile, fmt, va); 30217987Speter if (strchr(fmt, '\n')) 30317987Speter (void) fflush(tracefile); 30417987Speter } 30517987Speter va_end(va); 3061556Srgrimes} 3071556Srgrimes 3081556Srgrimes 30917987Spetervoid 310200956Sjillestrputs(const char *s) 31117987Speter{ 3121556Srgrimes if (tracefile == NULL) 3131556Srgrimes return; 3141556Srgrimes fputs(s, tracefile); 3151556Srgrimes if (strchr(s, '\n')) 3161556Srgrimes fflush(tracefile); 3171556Srgrimes} 3181556Srgrimes 3191556Srgrimes 320213811Sobrienstatic void 32190111Simptrstring(char *s) 32217987Speter{ 32325222Ssteve char *p; 3241556Srgrimes char c; 3251556Srgrimes 3261556Srgrimes if (tracefile == NULL) 3271556Srgrimes return; 3281556Srgrimes putc('"', tracefile); 3291556Srgrimes for (p = s ; *p ; p++) { 3301556Srgrimes switch (*p) { 3311556Srgrimes case '\n': c = 'n'; goto backslash; 3321556Srgrimes case '\t': c = 't'; goto backslash; 3331556Srgrimes case '\r': c = 'r'; goto backslash; 3341556Srgrimes case '"': c = '"'; goto backslash; 3351556Srgrimes case '\\': c = '\\'; goto backslash; 3361556Srgrimes case CTLESC: c = 'e'; goto backslash; 3371556Srgrimes case CTLVAR: c = 'v'; goto backslash; 3381556Srgrimes case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 3391556Srgrimes case CTLBACKQ: c = 'q'; goto backslash; 3401556Srgrimes case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 3411556Srgrimesbackslash: putc('\\', tracefile); 3421556Srgrimes putc(c, tracefile); 3431556Srgrimes break; 3441556Srgrimes default: 3451556Srgrimes if (*p >= ' ' && *p <= '~') 3461556Srgrimes putc(*p, tracefile); 3471556Srgrimes else { 3481556Srgrimes putc('\\', tracefile); 3491556Srgrimes putc(*p >> 6 & 03, tracefile); 3501556Srgrimes putc(*p >> 3 & 07, tracefile); 3511556Srgrimes putc(*p & 07, tracefile); 3521556Srgrimes } 3531556Srgrimes break; 3541556Srgrimes } 3551556Srgrimes } 3561556Srgrimes putc('"', tracefile); 35718018Speter} 3581556Srgrimes 3591556Srgrimes 36017987Spetervoid 36190111Simptrargs(char **ap) 36217987Speter{ 3631556Srgrimes if (tracefile == NULL) 3641556Srgrimes return; 3651556Srgrimes while (*ap) { 3661556Srgrimes trstring(*ap++); 3671556Srgrimes if (*ap) 3681556Srgrimes putc(' ', tracefile); 3691556Srgrimes else 3701556Srgrimes putc('\n', tracefile); 3711556Srgrimes } 3721556Srgrimes fflush(tracefile); 3731556Srgrimes} 3741556Srgrimes 3751556Srgrimes 37617987Spetervoid 37790111Simpopentrace(void) 37890111Simp{ 3791556Srgrimes char s[100]; 3801556Srgrimes int flags; 3811556Srgrimes 3821556Srgrimes if (!debug) 3831556Srgrimes return; 3841556Srgrimes#ifdef not_this_way 38517987Speter { 38617987Speter char *p; 38717987Speter if ((p = getenv("HOME")) == NULL) { 38817987Speter if (geteuid() == 0) 38917987Speter p = "/"; 39017987Speter else 39117987Speter p = "/tmp"; 39217987Speter } 39317987Speter scopy(p, s); 39417987Speter strcat(s, "/trace"); 3951556Srgrimes } 3961556Srgrimes#else 3971556Srgrimes scopy("./trace", s); 3981556Srgrimes#endif /* not_this_way */ 3991556Srgrimes if ((tracefile = fopen(s, "a")) == NULL) { 40053891Scracauer fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 4011556Srgrimes return; 4021556Srgrimes } 4031556Srgrimes if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 4041556Srgrimes fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 4051556Srgrimes fputs("\nTracing started.\n", tracefile); 4061556Srgrimes fflush(tracefile); 40720425Ssteve} 4081556Srgrimes#endif /* DEBUG */ 409