show.c revision 104141
1243730Srwatson/*- 2243730Srwatson * Copyright (c) 1991, 1993 3243730Srwatson * The Regents of the University of California. All rights reserved. 4243730Srwatson * 5243730Srwatson * This code is derived from software contributed to Berkeley by 6243730Srwatson * Kenneth Almquist. 7243730Srwatson * 8243730Srwatson * Redistribution and use in source and binary forms, with or without 9243730Srwatson * modification, are permitted provided that the following conditions 10243730Srwatson * are met: 11243730Srwatson * 1. Redistributions of source code must retain the above copyright 12243730Srwatson * notice, this list of conditions and the following disclaimer. 13243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 14243730Srwatson * notice, this list of conditions and the following disclaimer in the 15243730Srwatson * documentation and/or other materials provided with the distribution. 16243730Srwatson * 3. All advertising materials mentioning features or use of this software 17243730Srwatson * must display the following acknowledgement: 18243730Srwatson * This product includes software developed by the University of 19243730Srwatson * California, Berkeley and its contributors. 20243730Srwatson * 4. Neither the name of the University nor the names of its contributors 21243730Srwatson * may be used to endorse or promote products derived from this software 22243730Srwatson * without specific prior written permission. 23243730Srwatson * 24243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29243734Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34243730Srwatson * SUCH DAMAGE. 35243730Srwatson */ 36243730Srwatson 37243730Srwatson#ifndef lint 38243730Srwatson#if 0 39243730Srwatsonstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 40243730Srwatson#endif 41243730Srwatson#endif /* not lint */ 42243730Srwatson#include <sys/cdefs.h> 43243734Srwatson__FBSDID("$FreeBSD: head/bin/sh/show.c 104141 2002-09-29 12:38:25Z tjr $"); 44243730Srwatson 45243730Srwatson#include <stdio.h> 46243730Srwatson#include <stdarg.h> 47243730Srwatson#include <errno.h> 48243730Srwatson 49243730Srwatson#include "shell.h" 50243730Srwatson#include "parser.h" 51243730Srwatson#include "nodes.h" 52243730Srwatson#include "mystring.h" 53243730Srwatson#include "show.h" 54243730Srwatson 55243730Srwatson 56243730Srwatson#ifdef DEBUG 57243730Srwatsonstatic void shtree(union node *, int, char *, FILE*); 58243730Srwatsonstatic void shcmd(union node *, FILE *); 59243730Srwatsonstatic void sharg(union node *, FILE *); 60243730Srwatsonstatic void indent(int, char *, FILE *); 61243730Srwatsonstatic void trstring(char *); 62243730Srwatson 63243730Srwatson 64243730Srwatsonvoid 65243730Srwatsonshowtree(union node *n) 66243730Srwatson{ 67243730Srwatson trputs("showtree called\n"); 68243730Srwatson shtree(n, 1, NULL, stdout); 69243730Srwatson} 70243730Srwatson 71243730Srwatson 72243730Srwatsonstatic void 73243730Srwatsonshtree(union node *n, int ind, char *pfx, FILE *fp) 74243730Srwatson{ 75243730Srwatson struct nodelist *lp; 76243730Srwatson char *s; 77243730Srwatson 78243730Srwatson if (n == NULL) 79243730Srwatson return; 80243730Srwatson 81243730Srwatson indent(ind, pfx, fp); 82243730Srwatson switch(n->type) { 83243730Srwatson case NSEMI: 84243730Srwatson s = "; "; 85243730Srwatson goto binop; 86243730Srwatson case NAND: 87243730Srwatson s = " && "; 88243730Srwatson goto binop; 89243730Srwatson case NOR: 90243730Srwatson s = " || "; 91243730Srwatsonbinop: 92243730Srwatson shtree(n->nbinary.ch1, ind, NULL, fp); 93243730Srwatson /* if (ind < 0) */ 94243730Srwatson fputs(s, fp); 95243730Srwatson shtree(n->nbinary.ch2, ind, NULL, fp); 96243730Srwatson break; 97243730Srwatson case NCMD: 98243730Srwatson shcmd(n, fp); 99243730Srwatson if (ind >= 0) 100243730Srwatson putc('\n', fp); 101243730Srwatson break; 102243730Srwatson case NPIPE: 103243730Srwatson for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 104243730Srwatson shcmd(lp->n, fp); 105243730Srwatson if (lp->next) 106243730Srwatson fputs(" | ", fp); 107243730Srwatson } 108243730Srwatson if (n->npipe.backgnd) 109243730Srwatson fputs(" &", fp); 110243730Srwatson if (ind >= 0) 111243730Srwatson putc('\n', fp); 112243730Srwatson break; 113243730Srwatson default: 114243730Srwatson fprintf(fp, "<node type %d>", n->type); 115243730Srwatson if (ind >= 0) 116243730Srwatson putc('\n', fp); 117243730Srwatson break; 118243730Srwatson } 119243730Srwatson} 120243730Srwatson 121243730Srwatson 122243730Srwatson 123243730Srwatsonstatic void 124243730Srwatsonshcmd(union node *cmd, FILE *fp) 125243730Srwatson{ 126243730Srwatson union node *np; 127243730Srwatson int first; 128243730Srwatson char *s; 129243730Srwatson int dftfd; 130243730Srwatson 131243730Srwatson first = 1; 132243730Srwatson for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 133243730Srwatson if (! first) 134243730Srwatson putchar(' '); 135243730Srwatson sharg(np, fp); 136243730Srwatson first = 0; 137243730Srwatson } 138243730Srwatson for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 139243730Srwatson if (! first) 140243730Srwatson putchar(' '); 141243730Srwatson switch (np->nfile.type) { 142243730Srwatson case NTO: s = ">"; dftfd = 1; break; 143243730Srwatson case NAPPEND: s = ">>"; dftfd = 1; break; 144243730Srwatson case NTOFD: s = ">&"; dftfd = 1; break; 145243730Srwatson case NCLOBBER: s = ">|"; dftfd = 1; break; 146243730Srwatson case NFROM: s = "<"; dftfd = 0; break; 147243730Srwatson case NFROMTO: s = "<>"; dftfd = 0; break; 148243730Srwatson case NFROMFD: s = "<&"; dftfd = 0; break; 149243730Srwatson default: s = "*error*"; dftfd = 0; break; 150243730Srwatson } 151243730Srwatson if (np->nfile.fd != dftfd) 152243730Srwatson fprintf(fp, "%d", np->nfile.fd); 153243730Srwatson fputs(s, fp); 154243730Srwatson if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 155243730Srwatson if (np->ndup.dupfd >= 0) 156243730Srwatson fprintf(fp, "%d", np->ndup.dupfd); 157243730Srwatson else 158243730Srwatson fprintf(fp, "-"); 159243730Srwatson } else { 160243730Srwatson sharg(np->nfile.fname, fp); 161243730Srwatson } 162243730Srwatson first = 0; 163243730Srwatson } 164243730Srwatson} 165243730Srwatson 166243730Srwatson 167243730Srwatson 168243730Srwatsonstatic void 169243730Srwatsonsharg(union node *arg, FILE *fp) 170243730Srwatson{ 171243730Srwatson char *p; 172243730Srwatson struct nodelist *bqlist; 173243730Srwatson int subtype; 174243730Srwatson 175243730Srwatson if (arg->type != NARG) { 176243730Srwatson printf("<node type %d>\n", arg->type); 177243730Srwatson fflush(stdout); 178243730Srwatson abort(); 179243730Srwatson } 180243730Srwatson bqlist = arg->narg.backquote; 181243730Srwatson for (p = arg->narg.text ; *p ; p++) { 182243730Srwatson switch (*p) { 183243730Srwatson case CTLESC: 184243730Srwatson putc(*++p, fp); 185243730Srwatson break; 186243730Srwatson case CTLVAR: 187243730Srwatson putc('$', fp); 188243730Srwatson putc('{', fp); 189243730Srwatson subtype = *++p; 190243730Srwatson if (subtype == VSLENGTH) 191243730Srwatson putc('#', fp); 192243730Srwatson 193243730Srwatson while (*p != '=') 194243730Srwatson putc(*p++, fp); 195243730Srwatson 196243730Srwatson if (subtype & VSNUL) 197243730Srwatson putc(':', fp); 198243730Srwatson 199243730Srwatson switch (subtype & VSTYPE) { 200243730Srwatson case VSNORMAL: 201243730Srwatson putc('}', fp); 202243730Srwatson break; 203243730Srwatson case VSMINUS: 204243730Srwatson putc('-', fp); 205243730Srwatson break; 206243730Srwatson case VSPLUS: 207 putc('+', fp); 208 break; 209 case VSQUESTION: 210 putc('?', fp); 211 break; 212 case VSASSIGN: 213 putc('=', fp); 214 break; 215 case VSTRIMLEFT: 216 putc('#', fp); 217 break; 218 case VSTRIMLEFTMAX: 219 putc('#', fp); 220 putc('#', fp); 221 break; 222 case VSTRIMRIGHT: 223 putc('%', fp); 224 break; 225 case VSTRIMRIGHTMAX: 226 putc('%', fp); 227 putc('%', fp); 228 break; 229 case VSLENGTH: 230 break; 231 default: 232 printf("<subtype %d>", subtype); 233 } 234 break; 235 case CTLENDVAR: 236 putc('}', fp); 237 break; 238 case CTLBACKQ: 239 case CTLBACKQ|CTLQUOTE: 240 putc('$', fp); 241 putc('(', fp); 242 shtree(bqlist->n, -1, NULL, fp); 243 putc(')', fp); 244 break; 245 default: 246 putc(*p, fp); 247 break; 248 } 249 } 250} 251 252 253static void 254indent(int amount, char *pfx, FILE *fp) 255{ 256 int i; 257 258 for (i = 0 ; i < amount ; i++) { 259 if (pfx && i == amount - 1) 260 fputs(pfx, fp); 261 putc('\t', fp); 262 } 263} 264 265 266/* 267 * Debugging stuff. 268 */ 269 270 271FILE *tracefile; 272 273#if DEBUG == 2 274int debug = 1; 275#else 276int debug = 0; 277#endif 278 279 280void 281trputc(int c) 282{ 283 if (tracefile == NULL) 284 return; 285 putc(c, tracefile); 286 if (c == '\n') 287 fflush(tracefile); 288} 289 290 291void 292sh_trace(const char *fmt, ...) 293{ 294 va_list va; 295 va_start(va, fmt); 296 if (tracefile != NULL) { 297 (void) vfprintf(tracefile, fmt, va); 298 if (strchr(fmt, '\n')) 299 (void) fflush(tracefile); 300 } 301 va_end(va); 302} 303 304 305void 306trputs(char *s) 307{ 308 if (tracefile == NULL) 309 return; 310 fputs(s, tracefile); 311 if (strchr(s, '\n')) 312 fflush(tracefile); 313} 314 315 316static void 317trstring(char *s) 318{ 319 char *p; 320 char c; 321 322 if (tracefile == NULL) 323 return; 324 putc('"', tracefile); 325 for (p = s ; *p ; p++) { 326 switch (*p) { 327 case '\n': c = 'n'; goto backslash; 328 case '\t': c = 't'; goto backslash; 329 case '\r': c = 'r'; goto backslash; 330 case '"': c = '"'; goto backslash; 331 case '\\': c = '\\'; goto backslash; 332 case CTLESC: c = 'e'; goto backslash; 333 case CTLVAR: c = 'v'; goto backslash; 334 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 335 case CTLBACKQ: c = 'q'; goto backslash; 336 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 337backslash: putc('\\', tracefile); 338 putc(c, tracefile); 339 break; 340 default: 341 if (*p >= ' ' && *p <= '~') 342 putc(*p, tracefile); 343 else { 344 putc('\\', tracefile); 345 putc(*p >> 6 & 03, tracefile); 346 putc(*p >> 3 & 07, tracefile); 347 putc(*p & 07, tracefile); 348 } 349 break; 350 } 351 } 352 putc('"', tracefile); 353} 354 355 356void 357trargs(char **ap) 358{ 359 if (tracefile == NULL) 360 return; 361 while (*ap) { 362 trstring(*ap++); 363 if (*ap) 364 putc(' ', tracefile); 365 else 366 putc('\n', tracefile); 367 } 368 fflush(tracefile); 369} 370 371 372void 373opentrace(void) 374{ 375 char s[100]; 376 char *getenv(); 377 int flags; 378 379 if (!debug) 380 return; 381#ifdef not_this_way 382 { 383 char *p; 384 if ((p = getenv("HOME")) == NULL) { 385 if (geteuid() == 0) 386 p = "/"; 387 else 388 p = "/tmp"; 389 } 390 scopy(p, s); 391 strcat(s, "/trace"); 392 } 393#else 394 scopy("./trace", s); 395#endif /* not_this_way */ 396 if ((tracefile = fopen(s, "a")) == NULL) { 397 fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 398 return; 399 } 400 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 401 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 402 fputs("\nTracing started.\n", tracefile); 403 fflush(tracefile); 404} 405#endif /* DEBUG */ 406