show.c revision 18018
1139825Simp/*- 21541Srgrimes * Copyright (c) 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley by 61541Srgrimes * Kenneth Almquist. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 3. All advertising materials mentioning features or use of this software 171541Srgrimes * must display the following acknowledgement: 181541Srgrimes * This product includes software developed by the University of 191541Srgrimes * California, Berkeley and its contributors. 201541Srgrimes * 4. Neither the name of the University nor the names of its contributors 211541Srgrimes * may be used to endorse or promote products derived from this software 221541Srgrimes * without specific prior written permission. 231541Srgrimes * 241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3050477Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 332165Spaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3459774Sbde * SUCH DAMAGE. 352165Spaul * 36126590Sbde * $Id: show.c,v 1.3 1996/09/01 10:21:43 peter Exp $ 37133741Sjmg */ 38168355Srwatson 39137804Sphk#ifndef lint 40168355Srwatsonstatic char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 4141086Struckman#endif /* not lint */ 42126593Sbde 43126593Sbde#include <stdio.h> 441541Srgrimes#if __STDC__ 451541Srgrimes#include <stdarg.h> 461541Srgrimes#else 471541Srgrimes#include <varargs.h> 48126591Sbde#endif 491541Srgrimes 501541Srgrimes#include "shell.h" 511541Srgrimes#include "parser.h" 521541Srgrimes#include "nodes.h" 531541Srgrimes#include "mystring.h" 541541Srgrimes#include "show.h" 5551649Sphk 561541Srgrimes 57126591Sbde#ifdef DEBUG 5889306Salfredstatic void shtree __P((union node *, int, char *, FILE*)); 5989306Salfredstatic void shcmd __P((union node *, FILE *)); 601541Srgrimesstatic void sharg __P((union node *, FILE *)); 61138838Sphkstatic void indent __P((int, char *, FILE *)); 62138838Sphkstatic void trstring __P((char *)); 63168355Srwatson 64133741Sjmg 65115702Steggevoid 66115702Steggeshowtree(n) 671541Srgrimes union node *n; 681541Srgrimes{ 691541Srgrimes trputs("showtree called\n"); 70115702Stegge shtree(n, 1, NULL, stdout); 71115702Stegge} 72126591Sbde 73115702Stegge 74115702Steggestatic void 75115702Steggeshtree(n, ind, pfx, fp) 76115702Stegge union node *n; 77115702Stegge int ind; 78115702Stegge char *pfx; 79115702Stegge FILE *fp; 80115702Stegge{ 81115702Stegge struct nodelist *lp; 82115702Stegge char *s; 83126591Sbde 84115702Stegge if (n == NULL) 85115702Stegge return; 86115702Stegge 87115702Stegge indent(ind, pfx, fp); 88115702Stegge switch(n->type) { 891541Srgrimes case NSEMI: 901541Srgrimes s = "; "; 91246912Spjd goto binop; 921541Srgrimes case NAND: 9355205Speter s = " && "; 9489306Salfred goto binop; 9589306Salfred case NOR: 96168355Srwatson s = " || "; 97168355Srwatsonbinop: 98168355Srwatson shtree(n->nbinary.ch1, ind, NULL, fp); 99168355Srwatson /* if (ind < 0) */ 100168355Srwatson fputs(s, fp); 101168355Srwatson shtree(n->nbinary.ch2, ind, NULL, fp); 102168355Srwatson break; 103137804Sphk case NCMD: 104168355Srwatson shcmd(n, fp); 105168355Srwatson if (ind >= 0) 106168355Srwatson putc('\n', fp); 107168355Srwatson break; 108237072Spjd case NPIPE: 109137804Sphk for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 110122514Sjhb shcmd(lp->n, fp); 111122514Sjhb if (lp->next) 112126591Sbde fputs(" | ", fp); 113237033Spjd } 114237033Spjd if (n->npipe.backgnd) 115220245Skib fputs(" &", fp); 116219999Skib if (ind >= 0) 117223694Sjonathan putc('\n', fp); 118223694Sjonathan break; 119126591Sbde default: 12092719Salfred fprintf(fp, "<node type %d>", n->type); 121126590Sbde if (ind >= 0) 122137355Sphk putc('\n', fp); 12392719Salfred break; 124108522Salfred } 125138832Sphk} 12692719Salfred 127108520Salfred 128108520Salfred 129115702Steggestatic void 130126591Sbdeshcmd(cmd, fp) 131126591Sbde union node *cmd; 132224778Srwatson FILE *fp; 133224778Srwatson{ 134138835Sphk union node *np; 135126590Sbde int first; 136115702Stegge char *s; 137192080Sjeff int dftfd; 138192080Sjeff 139192080Sjeff first = 1; 140192080Sjeff for (np = cmd->ncmd.args ; np ; np = np->narg.next) { 14189969Salfred if (! first) 142100072Smarkm putchar(' '); 14389969Salfred sharg(np, fp); 14489969Salfred first = 0; 145237081Spjd } 146237081Spjd for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 147237081Spjd if (! first) 148237081Spjd putchar(' '); 149237081Spjd switch (np->nfile.type) { 150237081Spjd case NTO: s = ">"; dftfd = 1; break; 15189969Salfred case NAPPEND: s = ">>"; dftfd = 1; break; 15289969Salfred case NTOFD: s = ">&"; dftfd = 1; break; 15359774Sbde case NFROM: s = "<"; dftfd = 0; break; 1542165Spaul case NFROMFD: s = "<&"; dftfd = 0; break; 15559774Sbde default: s = "*error*"; dftfd = 0; break; 156 } 157 if (np->nfile.fd != dftfd) 158 fprintf(fp, "%d", np->nfile.fd); 159 fputs(s, fp); 160 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 161 fprintf(fp, "%d", np->ndup.dupfd); 162 } else { 163 sharg(np->nfile.fname, fp); 164 } 165 first = 0; 166 } 167} 168 169 170 171static void 172sharg(arg, fp) 173 union node *arg; 174 FILE *fp; 175 { 176 char *p; 177 struct nodelist *bqlist; 178 int subtype; 179 180 if (arg->type != NARG) { 181 printf("<node type %d>\n", arg->type); 182 fflush(stdout); 183 abort(); 184 } 185 bqlist = arg->narg.backquote; 186 for (p = arg->narg.text ; *p ; p++) { 187 switch (*p) { 188 case CTLESC: 189 putc(*++p, fp); 190 break; 191 case CTLVAR: 192 putc('$', fp); 193 putc('{', fp); 194 subtype = *++p; 195 if (subtype == VSLENGTH) 196 putc('#', fp); 197 198 while (*p != '=') 199 putc(*p++, fp); 200 201 if (subtype & VSNUL) 202 putc(':', fp); 203 204 switch (subtype & VSTYPE) { 205 case VSNORMAL: 206 putc('}', fp); 207 break; 208 case VSMINUS: 209 putc('-', fp); 210 break; 211 case VSPLUS: 212 putc('+', fp); 213 break; 214 case VSQUESTION: 215 putc('?', fp); 216 break; 217 case VSASSIGN: 218 putc('=', fp); 219 break; 220 case VSTRIMLEFT: 221 putc('#', fp); 222 break; 223 case VSTRIMLEFTMAX: 224 putc('#', fp); 225 putc('#', fp); 226 break; 227 case VSTRIMRIGHT: 228 putc('%', fp); 229 break; 230 case VSTRIMRIGHTMAX: 231 putc('%', fp); 232 putc('%', fp); 233 break; 234 case VSLENGTH: 235 break; 236 default: 237 printf("<subtype %d>", subtype); 238 } 239 break; 240 case CTLENDVAR: 241 putc('}', fp); 242 break; 243 case CTLBACKQ: 244 case CTLBACKQ|CTLQUOTE: 245 putc('$', fp); 246 putc('(', fp); 247 shtree(bqlist->n, -1, NULL, fp); 248 putc(')', fp); 249 break; 250 default: 251 putc(*p, fp); 252 break; 253 } 254 } 255} 256 257 258static void 259indent(amount, pfx, fp) 260 int amount; 261 char *pfx; 262 FILE *fp; 263{ 264 int i; 265 266 for (i = 0 ; i < amount ; i++) { 267 if (pfx && i == amount - 1) 268 fputs(pfx, fp); 269 putc('\t', fp); 270 } 271} 272#endif 273 274 275 276/* 277 * Debugging stuff. 278 */ 279 280 281FILE *tracefile; 282 283#if DEBUG == 2 284int debug = 1; 285#else 286int debug = 0; 287#endif 288 289 290void 291trputc(c) 292 int c; 293{ 294#ifdef DEBUG 295 if (tracefile == NULL) 296 return; 297 putc(c, tracefile); 298 if (c == '\n') 299 fflush(tracefile); 300#endif 301} 302 303void 304#if __STDC__ 305shtrace(const char *fmt, ...) 306#else 307shtrace(va_alist) 308 va_dcl 309#endif 310{ 311#ifdef DEBUG 312 va_list va; 313#if __STDC__ 314 va_start(va, fmt); 315#else 316 char *fmt; 317 va_start(va); 318 fmt = va_arg(va, char *); 319#endif 320 if (tracefile != NULL) { 321 (void) vfprintf(tracefile, fmt, va); 322 if (strchr(fmt, '\n')) 323 (void) fflush(tracefile); 324 } 325 va_end(va); 326#endif 327} 328 329 330void 331trputs(s) 332 char *s; 333{ 334#ifdef DEBUG 335 if (tracefile == NULL) 336 return; 337 fputs(s, tracefile); 338 if (strchr(s, '\n')) 339 fflush(tracefile); 340#endif 341} 342 343 344#ifdef DEBUG 345static void 346trstring(s) 347 char *s; 348{ 349 register char *p; 350 char c; 351 352 if (tracefile == NULL) 353 return; 354 putc('"', tracefile); 355 for (p = s ; *p ; p++) { 356 switch (*p) { 357 case '\n': c = 'n'; goto backslash; 358 case '\t': c = 't'; goto backslash; 359 case '\r': c = 'r'; goto backslash; 360 case '"': c = '"'; goto backslash; 361 case '\\': c = '\\'; goto backslash; 362 case CTLESC: c = 'e'; goto backslash; 363 case CTLVAR: c = 'v'; goto backslash; 364 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 365 case CTLBACKQ: c = 'q'; goto backslash; 366 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 367backslash: putc('\\', tracefile); 368 putc(c, tracefile); 369 break; 370 default: 371 if (*p >= ' ' && *p <= '~') 372 putc(*p, tracefile); 373 else { 374 putc('\\', tracefile); 375 putc(*p >> 6 & 03, tracefile); 376 putc(*p >> 3 & 07, tracefile); 377 putc(*p & 07, tracefile); 378 } 379 break; 380 } 381 } 382 putc('"', tracefile); 383} 384#endif 385 386 387void 388trargs(ap) 389 char **ap; 390{ 391#ifdef DEBUG 392 if (tracefile == NULL) 393 return; 394 while (*ap) { 395 trstring(*ap++); 396 if (*ap) 397 putc(' ', tracefile); 398 else 399 putc('\n', tracefile); 400 } 401 fflush(tracefile); 402#endif 403} 404 405 406void 407opentrace() { 408#ifdef DEBUG 409 char s[100]; 410 char *getenv(); 411#ifdef O_APPEND 412 int flags; 413#endif 414 415 if (!debug) 416 return; 417#ifdef not_this_way 418 { 419 char *p; 420 if ((p = getenv("HOME")) == NULL) { 421 if (geteuid() == 0) 422 p = "/"; 423 else 424 p = "/tmp"; 425 } 426 scopy(p, s); 427 strcat(s, "/trace"); 428 } 429#else 430 scopy("./trace", s); 431#endif /* not_this_way */ 432 if ((tracefile = fopen(s, "a")) == NULL) { 433 fprintf(stderr, "Can't open %s\n", s); 434 return; 435 } 436#ifdef O_APPEND 437 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 438 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 439#endif 440 fputs("\nTracing started.\n", tracefile); 441 fflush(tracefile); 442#endif /* DEBUG */ 443} 444