show.c revision 149742
1214501Srpaulo/*- 2214501Srpaulo * Copyright (c) 1991, 1993 3252726Srpaulo * The Regents of the University of California. All rights reserved. 4214501Srpaulo * 5252726Srpaulo * This code is derived from software contributed to Berkeley by 6252726Srpaulo * Kenneth Almquist. 7214501Srpaulo * 8214501Srpaulo * Redistribution and use in source and binary forms, with or without 9214501Srpaulo * modification, are permitted provided that the following conditions 10214501Srpaulo * are met: 11214501Srpaulo * 1. Redistributions of source code must retain the above copyright 12214501Srpaulo * notice, this list of conditions and the following disclaimer. 13214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 14214501Srpaulo * notice, this list of conditions and the following disclaimer in the 15252726Srpaulo * documentation and/or other materials provided with the distribution. 16252726Srpaulo * 4. Neither the name of the University nor the names of its contributors 17214501Srpaulo * may be used to endorse or promote products derived from this software 18214501Srpaulo * without specific prior written permission. 19214501Srpaulo * 20214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21214501Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23214501Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24214501Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25214501Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26214501Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28214501Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29214501Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30214501Srpaulo * SUCH DAMAGE. 31214501Srpaulo */ 32214501Srpaulo 33214501Srpaulo#ifndef lint 34214501Srpaulo#if 0 35214501Srpaulostatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 36214501Srpaulo#endif 37214501Srpaulo#endif /* not lint */ 38214501Srpaulo#include <sys/cdefs.h> 39214501Srpaulo__FBSDID("$FreeBSD: head/bin/sh/show.c 149742 2005-09-02 22:28:27Z stefanf $"); 40214501Srpaulo 41214501Srpaulo#include <fcntl.h> 42214501Srpaulo#include <stdio.h> 43214501Srpaulo#include <stdlib.h> 44214501Srpaulo#include <stdarg.h> 45214501Srpaulo#include <errno.h> 46214501Srpaulo 47214501Srpaulo#include "shell.h" 48214501Srpaulo#include "parser.h" 49214501Srpaulo#include "nodes.h" 50214501Srpaulo#include "mystring.h" 51214501Srpaulo#include "show.h" 52252726Srpaulo 53214501Srpaulo 54252726Srpaulo#ifdef DEBUG 55252726Srpaulostatic void shtree(union node *, int, char *, FILE*); 56214501Srpaulostatic void shcmd(union node *, FILE *); 57214501Srpaulostatic void sharg(union node *, FILE *); 58214501Srpaulostatic void indent(int, char *, FILE *); 59214501Srpaulostatic void trstring(char *); 60214501Srpaulo 61214501Srpaulo 62214501Srpaulovoid 63214501Srpauloshowtree(union node *n) 64214501Srpaulo{ 65214501Srpaulo trputs("showtree called\n"); 66214501Srpaulo shtree(n, 1, NULL, stdout); 67214501Srpaulo} 68214501Srpaulo 69214501Srpaulo 70252726Srpaulostatic void 71252726Srpauloshtree(union node *n, int ind, char *pfx, FILE *fp) 72252726Srpaulo{ 73252726Srpaulo struct nodelist *lp; 74214501Srpaulo char *s; 75214501Srpaulo 76214501Srpaulo if (n == NULL) 77214501Srpaulo return; 78214501Srpaulo 79214501Srpaulo indent(ind, pfx, fp); 80214501Srpaulo switch(n->type) { 81214501Srpaulo case NSEMI: 82214501Srpaulo s = "; "; 83214501Srpaulo goto binop; 84214501Srpaulo case NAND: 85214501Srpaulo s = " && "; 86214501Srpaulo goto binop; 87214501Srpaulo case NOR: 88214501Srpaulo s = " || "; 89214501Srpaulobinop: 90214501Srpaulo shtree(n->nbinary.ch1, ind, NULL, fp); 91214501Srpaulo /* if (ind < 0) */ 92214501Srpaulo fputs(s, fp); 93214501Srpaulo shtree(n->nbinary.ch2, ind, NULL, fp); 94214501Srpaulo break; 95214501Srpaulo case NCMD: 96214501Srpaulo shcmd(n, fp); 97214501Srpaulo if (ind >= 0) 98214501Srpaulo putc('\n', fp); 99214501Srpaulo break; 100252726Srpaulo case NPIPE: 101252726Srpaulo for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 102252726Srpaulo shcmd(lp->n, fp); 103252726Srpaulo if (lp->next) 104252726Srpaulo fputs(" | ", fp); 105214501Srpaulo } 106214501Srpaulo if (n->npipe.backgnd) 107214501Srpaulo fputs(" &", fp); 108214501Srpaulo if (ind >= 0) 109214501Srpaulo putc('\n', fp); 110214501Srpaulo break; 111214501Srpaulo default: 112214501Srpaulo fprintf(fp, "<node type %d>", n->type); 113214501Srpaulo if (ind >= 0) 114214501Srpaulo putc('\n', fp); 115214501Srpaulo break; 116214501Srpaulo } 117214501Srpaulo} 118214501Srpaulo 119252726Srpaulo 120214501Srpaulo 121214501Srpaulostatic void 122214501Srpauloshcmd(union node *cmd, FILE *fp) 123214501Srpaulo{ 124214501Srpaulo union node *np; 125214501Srpaulo int first; 126214501Srpaulo char *s; 127214501Srpaulo int dftfd; 128214501Srpaulo 129214501Srpaulo first = 1; 130252726Srpaulo for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 131252726Srpaulo if (! first) 132252726Srpaulo putchar(' '); 133252726Srpaulo sharg(np, fp); 134252726Srpaulo first = 0; 135214501Srpaulo } 136214501Srpaulo for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 137252726Srpaulo if (! first) 138252726Srpaulo putchar(' '); 139214501Srpaulo switch (np->nfile.type) { 140214501Srpaulo case NTO: s = ">"; dftfd = 1; break; 141214501Srpaulo case NAPPEND: s = ">>"; dftfd = 1; break; 142214501Srpaulo case NTOFD: s = ">&"; dftfd = 1; break; 143214501Srpaulo case NCLOBBER: s = ">|"; dftfd = 1; break; 144214501Srpaulo case NFROM: s = "<"; dftfd = 0; break; 145214501Srpaulo case NFROMTO: s = "<>"; dftfd = 0; break; 146252726Srpaulo case NFROMFD: s = "<&"; dftfd = 0; break; 147252726Srpaulo default: s = "*error*"; dftfd = 0; break; 148252726Srpaulo } 149252726Srpaulo if (np->nfile.fd != dftfd) 150252726Srpaulo fprintf(fp, "%d", np->nfile.fd); 151252726Srpaulo fputs(s, fp); 152214501Srpaulo if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 153214501Srpaulo if (np->ndup.dupfd >= 0) 154252726Srpaulo fprintf(fp, "%d", np->ndup.dupfd); 155252726Srpaulo else 156252726Srpaulo fprintf(fp, "-"); 157252726Srpaulo } else { 158252726Srpaulo sharg(np->nfile.fname, fp); 159214501Srpaulo } 160252726Srpaulo first = 0; 161252726Srpaulo } 162252726Srpaulo} 163252726Srpaulo 164252726Srpaulo 165252726Srpaulo 166252726Srpaulostatic void 167252726Srpaulosharg(union node *arg, FILE *fp) 168252726Srpaulo{ 169252726Srpaulo char *p; 170252726Srpaulo struct nodelist *bqlist; 171252726Srpaulo int subtype; 172252726Srpaulo 173252726Srpaulo if (arg->type != NARG) { 174252726Srpaulo printf("<node type %d>\n", arg->type); 175252726Srpaulo fflush(stdout); 176252726Srpaulo abort(); 177214501Srpaulo } 178214501Srpaulo bqlist = arg->narg.backquote; 179214501Srpaulo for (p = arg->narg.text ; *p ; p++) { 180214501Srpaulo switch (*p) { 181214501Srpaulo case CTLESC: 182214501Srpaulo putc(*++p, fp); 183252726Srpaulo break; 184214501Srpaulo case CTLVAR: 185214501Srpaulo putc('$', fp); 186214501Srpaulo putc('{', fp); 187214501Srpaulo subtype = *++p; 188214501Srpaulo if (subtype == VSLENGTH) 189214501Srpaulo putc('#', fp); 190214501Srpaulo 191214501Srpaulo while (*p != '=') 192214501Srpaulo putc(*p++, fp); 193214501Srpaulo 194214501Srpaulo if (subtype & VSNUL) 195214501Srpaulo putc(':', fp); 196214501Srpaulo 197214501Srpaulo switch (subtype & VSTYPE) { 198214501Srpaulo case VSNORMAL: 199214501Srpaulo putc('}', fp); 200214501Srpaulo break; 201252726Srpaulo case VSMINUS: 202214501Srpaulo putc('-', fp); 203214501Srpaulo break; 204214501Srpaulo case VSPLUS: 205214501Srpaulo putc('+', fp); 206214501Srpaulo break; 207252726Srpaulo case VSQUESTION: 208252726Srpaulo putc('?', fp); 209252726Srpaulo break; 210252726Srpaulo case VSASSIGN: 211252726Srpaulo putc('=', fp); 212252726Srpaulo break; 213252726Srpaulo case VSTRIMLEFT: 214252726Srpaulo putc('#', fp); 215252726Srpaulo break; 216214501Srpaulo case VSTRIMLEFTMAX: 217214501Srpaulo putc('#', fp); 218214501Srpaulo putc('#', fp); 219214501Srpaulo break; 220214501Srpaulo case VSTRIMRIGHT: 221214501Srpaulo putc('%', fp); 222214501Srpaulo break; 223214501Srpaulo case VSTRIMRIGHTMAX: 224214501Srpaulo putc('%', fp); 225214501Srpaulo putc('%', fp); 226214501Srpaulo break; 227214501Srpaulo case VSLENGTH: 228214501Srpaulo break; 229214501Srpaulo default: 230214501Srpaulo printf("<subtype %d>", subtype); 231214501Srpaulo } 232214501Srpaulo break; 233214501Srpaulo case CTLENDVAR: 234214501Srpaulo putc('}', fp); 235214501Srpaulo break; 236214501Srpaulo case CTLBACKQ: 237214501Srpaulo case CTLBACKQ|CTLQUOTE: 238214501Srpaulo putc('$', fp); 239214501Srpaulo putc('(', fp); 240214501Srpaulo shtree(bqlist->n, -1, NULL, fp); 241214501Srpaulo putc(')', fp); 242214501Srpaulo break; 243214501Srpaulo default: 244252726Srpaulo putc(*p, fp); 245214501Srpaulo break; 246214501Srpaulo } 247214501Srpaulo } 248214501Srpaulo} 249214501Srpaulo 250214501Srpaulo 251214501Srpaulostatic void 252214501Srpauloindent(int amount, char *pfx, FILE *fp) 253214501Srpaulo{ 254214501Srpaulo int i; 255214501Srpaulo 256214501Srpaulo for (i = 0 ; i < amount ; i++) { 257214501Srpaulo if (pfx && i == amount - 1) 258252726Srpaulo fputs(pfx, fp); 259252726Srpaulo putc('\t', fp); 260252726Srpaulo } 261252726Srpaulo} 262252726Srpaulo 263214501Srpaulo 264214501Srpaulo/* 265214501Srpaulo * Debugging stuff. 266214501Srpaulo */ 267214501Srpaulo 268214501Srpaulo 269214501SrpauloFILE *tracefile; 270214501Srpaulo 271214501Srpaulo#if DEBUG == 2 272214501Srpauloint debug = 1; 273214501Srpaulo#else 274214501Srpauloint debug = 0; 275214501Srpaulo#endif 276214501Srpaulo 277214501Srpaulo 278214501Srpaulovoid 279214501Srpaulotrputc(int c) 280214501Srpaulo{ 281214501Srpaulo if (tracefile == NULL) 282214501Srpaulo return; 283252726Srpaulo putc(c, tracefile); 284214501Srpaulo if (c == '\n') 285214501Srpaulo fflush(tracefile); 286214501Srpaulo} 287214501Srpaulo 288214501Srpaulo 289214501Srpaulovoid 290214501Srpaulosh_trace(const char *fmt, ...) 291214501Srpaulo{ 292214501Srpaulo va_list va; 293214501Srpaulo va_start(va, fmt); 294214501Srpaulo if (tracefile != NULL) { 295214501Srpaulo (void) vfprintf(tracefile, fmt, va); 296214501Srpaulo if (strchr(fmt, '\n')) 297214501Srpaulo (void) fflush(tracefile); 298214501Srpaulo } 299214501Srpaulo va_end(va); 300214501Srpaulo} 301214501Srpaulo 302214501Srpaulo 303214501Srpaulovoid 304214501Srpaulotrputs(char *s) 305214501Srpaulo{ 306214501Srpaulo if (tracefile == NULL) 307252726Srpaulo return; 308252726Srpaulo fputs(s, tracefile); 309214501Srpaulo if (strchr(s, '\n')) 310214501Srpaulo fflush(tracefile); 311214501Srpaulo} 312214501Srpaulo 313214501Srpaulo 314214501Srpaulostatic void 315214501Srpaulotrstring(char *s) 316214501Srpaulo{ 317214501Srpaulo char *p; 318214501Srpaulo char c; 319214501Srpaulo 320214501Srpaulo if (tracefile == NULL) 321214501Srpaulo return; 322214501Srpaulo putc('"', tracefile); 323214501Srpaulo for (p = s ; *p ; p++) { 324214501Srpaulo switch (*p) { 325214501Srpaulo case '\n': c = 'n'; goto backslash; 326214501Srpaulo case '\t': c = 't'; goto backslash; 327214501Srpaulo case '\r': c = 'r'; goto backslash; 328214501Srpaulo case '"': c = '"'; goto backslash; 329214501Srpaulo case '\\': c = '\\'; goto backslash; 330214501Srpaulo case CTLESC: c = 'e'; goto backslash; 331214501Srpaulo case CTLVAR: c = 'v'; goto backslash; 332214501Srpaulo case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 333214501Srpaulo case CTLBACKQ: c = 'q'; goto backslash; 334214501Srpaulo case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 335214501Srpaulobackslash: putc('\\', tracefile); 336214501Srpaulo putc(c, tracefile); 337214501Srpaulo break; 338252726Srpaulo default: 339214501Srpaulo if (*p >= ' ' && *p <= '~') 340214501Srpaulo putc(*p, tracefile); 341214501Srpaulo else { 342214501Srpaulo putc('\\', tracefile); 343214501Srpaulo putc(*p >> 6 & 03, tracefile); 344214501Srpaulo putc(*p >> 3 & 07, tracefile); 345214501Srpaulo putc(*p & 07, tracefile); 346214501Srpaulo } 347214501Srpaulo break; 348214501Srpaulo } 349214501Srpaulo } 350214501Srpaulo putc('"', tracefile); 351252726Srpaulo} 352214501Srpaulo 353214501Srpaulo 354214501Srpaulovoid 355214501Srpaulotrargs(char **ap) 356214501Srpaulo{ 357214501Srpaulo if (tracefile == NULL) 358214501Srpaulo return; 359214501Srpaulo while (*ap) { 360214501Srpaulo trstring(*ap++); 361214501Srpaulo if (*ap) 362214501Srpaulo putc(' ', tracefile); 363214501Srpaulo else 364214501Srpaulo putc('\n', tracefile); 365214501Srpaulo } 366214501Srpaulo fflush(tracefile); 367252726Srpaulo} 368252726Srpaulo 369252726Srpaulo 370252726Srpaulovoid 371252726Srpauloopentrace(void) 372214501Srpaulo{ 373252726Srpaulo char s[100]; 374252726Srpaulo int flags; 375252726Srpaulo 376252726Srpaulo if (!debug) 377252726Srpaulo return; 378252726Srpaulo#ifdef not_this_way 379252726Srpaulo { 380252726Srpaulo char *p; 381252726Srpaulo if ((p = getenv("HOME")) == NULL) { 382252726Srpaulo if (geteuid() == 0) 383252726Srpaulo p = "/"; 384252726Srpaulo else 385252726Srpaulo p = "/tmp"; 386252726Srpaulo } 387252726Srpaulo scopy(p, s); 388252726Srpaulo strcat(s, "/trace"); 389252726Srpaulo } 390252726Srpaulo#else 391252726Srpaulo scopy("./trace", s); 392252726Srpaulo#endif /* not_this_way */ 393252726Srpaulo if ((tracefile = fopen(s, "a")) == NULL) { 394252726Srpaulo fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 395252726Srpaulo return; 396252726Srpaulo } 397252726Srpaulo if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 398252726Srpaulo fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 399252726Srpaulo fputs("\nTracing started.\n", tracefile); 400252726Srpaulo fflush(tracefile); 401252726Srpaulo} 402252726Srpaulo#endif /* DEBUG */ 403252726Srpaulo