/* $OpenBSD: show.c,v 1.3 1996/10/20 00:55:06 millert Exp $ */ /* $NetBSD: show.c,v 1.11 1995/05/11 21:30:24 christos Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; #else static char rcsid[] = "$OpenBSD: show.c,v 1.3 1996/10/20 00:55:06 millert Exp $"; #endif #endif /* not lint */ #include #if __STDC__ #include #else #include #endif #include "shell.h" #include "parser.h" #include "nodes.h" #include "mystring.h" #include "show.h" #ifdef DEBUG static void shtree __P((union node *, int, char *, FILE*)); static void shcmd __P((union node *, FILE *)); static void sharg __P((union node *, FILE *)); static void indent __P((int, char *, FILE *)); static void trstring __P((char *)); void showtree(n) union node *n; { trputs("showtree called\n"); shtree(n, 1, NULL, stdout); } static void shtree(n, ind, pfx, fp) union node *n; int ind; char *pfx; FILE *fp; { struct nodelist *lp; char *s; if (n == NULL) return; indent(ind, pfx, fp); switch(n->type) { case NSEMI: s = "; "; goto binop; case NAND: s = " && "; goto binop; case NOR: s = " || "; binop: shtree(n->nbinary.ch1, ind, NULL, fp); /* if (ind < 0) */ fputs(s, fp); shtree(n->nbinary.ch2, ind, NULL, fp); break; case NCMD: shcmd(n, fp); if (ind >= 0) putc('\n', fp); break; case NPIPE: for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { shcmd(lp->n, fp); if (lp->next) fputs(" | ", fp); } if (n->npipe.backgnd) fputs(" &", fp); if (ind >= 0) putc('\n', fp); break; default: fprintf(fp, "", n->type); if (ind >= 0) putc('\n', fp); break; } } static void shcmd(cmd, fp) union node *cmd; FILE *fp; { union node *np; int first; char *s; int dftfd; first = 1; for (np = cmd->ncmd.args ; np ; np = np->narg.next) { if (! first) putchar(' '); sharg(np, fp); first = 0; } for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { if (! first) putchar(' '); switch (np->nfile.type) { case NTO: s = ">"; dftfd = 1; break; case NAPPEND: s = ">>"; dftfd = 1; break; case NTOFD: s = ">&"; dftfd = 1; break; case NFROM: s = "<"; dftfd = 0; break; case NFROMFD: s = "<&"; dftfd = 0; break; default: s = "*error*"; dftfd = 0; break; } if (np->nfile.fd != dftfd) fprintf(fp, "%d", np->nfile.fd); fputs(s, fp); if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { fprintf(fp, "%d", np->ndup.dupfd); } else { sharg(np->nfile.fname, fp); } first = 0; } } static void sharg(arg, fp) union node *arg; FILE *fp; { char *p; struct nodelist *bqlist; int subtype; if (arg->type != NARG) { printf("\n", arg->type); fflush(stdout); abort(); } bqlist = arg->narg.backquote; for (p = arg->narg.text ; *p ; p++) { switch (*p) { case CTLESC: putc(*++p, fp); break; case CTLVAR: putc('$', fp); putc('{', fp); subtype = *++p; if (subtype == VSLENGTH) putc('#', fp); while (*p != '=') putc(*p++, fp); if (subtype & VSNUL) putc(':', fp); switch (subtype & VSTYPE) { case VSNORMAL: putc('}', fp); break; case VSMINUS: putc('-', fp); break; case VSPLUS: putc('+', fp); break; case VSQUESTION: putc('?', fp); break; case VSASSIGN: putc('=', fp); break; case VSTRIMLEFT: putc('#', fp); break; case VSTRIMLEFTMAX: putc('#', fp); putc('#', fp); break; case VSTRIMRIGHT: putc('%', fp); break; case VSTRIMRIGHTMAX: putc('%', fp); putc('%', fp); break; case VSLENGTH: break; default: printf("", subtype); } break; case CTLENDVAR: putc('}', fp); break; case CTLBACKQ: case CTLBACKQ|CTLQUOTE: putc('$', fp); putc('(', fp); shtree(bqlist->n, -1, NULL, fp); putc(')', fp); break; default: putc(*p, fp); break; } } } static void indent(amount, pfx, fp) int amount; char *pfx; FILE *fp; { int i; for (i = 0 ; i < amount ; i++) { if (pfx && i == amount - 1) fputs(pfx, fp); putc('\t', fp); } } #endif /* * Debugging stuff. */ FILE *tracefile; #if DEBUG == 2 int debug = 1; #else int debug = 0; #endif #ifdef DEBUG void trputc(c) int c; { if (tracefile == NULL) return; putc(c, tracefile); if (c == '\n') fflush(tracefile); } #endif void #if __STDC__ trace(const char *fmt, ...) #else trace(va_alist) va_dcl #endif { #ifdef DEBUG va_list va; #if __STDC__ va_start(va, fmt); #else char *fmt; va_start(va); fmt = va_arg(va, char *); #endif if (tracefile != NULL) { (void) vfprintf(tracefile, fmt, va); if (strchr(fmt, '\n')) (void) fflush(tracefile); } va_end(va); #endif } #ifdef DEBUG void trputs(s) char *s; { if (tracefile == NULL) return; fputs(s, tracefile); if (strchr(s, '\n')) fflush(tracefile); } static void trstring(s) char *s; { register char *p; char c; if (tracefile == NULL) return; putc('"', tracefile); for (p = s ; *p ; p++) { switch (*p) { case '\n': c = 'n'; goto backslash; case '\t': c = 't'; goto backslash; case '\r': c = 'r'; goto backslash; case '"': c = '"'; goto backslash; case '\\': c = '\\'; goto backslash; case CTLESC: c = 'e'; goto backslash; case CTLVAR: c = 'v'; goto backslash; case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; case CTLBACKQ: c = 'q'; goto backslash; case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; backslash: putc('\\', tracefile); putc(c, tracefile); break; default: if (*p >= ' ' && *p <= '~') putc(*p, tracefile); else { putc('\\', tracefile); putc(*p >> 6 & 03, tracefile); putc(*p >> 3 & 07, tracefile); putc(*p & 07, tracefile); } break; } } putc('"', tracefile); } #endif void trargs(ap) char **ap; { #ifdef DEBUG if (tracefile == NULL) return; while (*ap) { trstring(*ap++); if (*ap) putc(' ', tracefile); else putc('\n', tracefile); } fflush(tracefile); #endif } #ifdef DEBUG void opentrace() { char s[100]; char *getenv(); #ifdef O_APPEND int flags; #endif if (!debug) return; #ifdef not_this_way { char *p; if ((p = getenv("HOME")) == NULL) { if (geteuid() == 0) p = "/"; else p = "/tmp"; } scopy(p, s); strcat(s, "/trace"); } #else scopy("./trace", s); #endif /* not_this_way */ if ((tracefile = fopen(s, "a")) == NULL) { fprintf(stderr, "Can't open %s\n", s); return; } #ifdef O_APPEND if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); #endif fputs("\nTracing started.\n", tracefile); fflush(tracefile); } #endif /* DEBUG */