Home | History | Annotate | Line # | Download | only in sh
show.c revision 1.25
      1 /*	$NetBSD: show.c,v 1.25 2003/08/07 09:05:38 agc Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1991, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software contributed to Berkeley by
      8  * Kenneth Almquist.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. Neither the name of the University nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 #ifndef lint
     37 #if 0
     38 static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
     39 #else
     40 __RCSID("$NetBSD: show.c,v 1.25 2003/08/07 09:05:38 agc Exp $");
     41 #endif
     42 #endif /* not lint */
     43 
     44 #include <stdio.h>
     45 #include <stdarg.h>
     46 
     47 #include "shell.h"
     48 #include "parser.h"
     49 #include "nodes.h"
     50 #include "mystring.h"
     51 #include "show.h"
     52 #include "options.h"
     53 
     54 
     55 #ifdef DEBUG
     56 static void shtree(union node *, int, char *, FILE*);
     57 static void shcmd(union node *, FILE *);
     58 static void sharg(union node *, FILE *);
     59 static void indent(int, char *, FILE *);
     60 static void trstring(char *);
     61 
     62 
     63 void
     64 showtree(union node *n)
     65 {
     66 	trputs("showtree called\n");
     67 	shtree(n, 1, NULL, stdout);
     68 }
     69 
     70 
     71 static void
     72 shtree(union node *n, int ind, char *pfx, FILE *fp)
     73 {
     74 	struct nodelist *lp;
     75 	const char *s;
     76 
     77 	if (n == NULL)
     78 		return;
     79 
     80 	indent(ind, pfx, fp);
     81 	switch(n->type) {
     82 	case NSEMI:
     83 		s = "; ";
     84 		goto binop;
     85 	case NAND:
     86 		s = " && ";
     87 		goto binop;
     88 	case NOR:
     89 		s = " || ";
     90 binop:
     91 		shtree(n->nbinary.ch1, ind, NULL, fp);
     92 	   /*    if (ind < 0) */
     93 			fputs(s, fp);
     94 		shtree(n->nbinary.ch2, ind, NULL, fp);
     95 		break;
     96 	case NCMD:
     97 		shcmd(n, fp);
     98 		if (ind >= 0)
     99 			putc('\n', fp);
    100 		break;
    101 	case NPIPE:
    102 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
    103 			shcmd(lp->n, fp);
    104 			if (lp->next)
    105 				fputs(" | ", fp);
    106 		}
    107 		if (n->npipe.backgnd)
    108 			fputs(" &", fp);
    109 		if (ind >= 0)
    110 			putc('\n', fp);
    111 		break;
    112 	default:
    113 		fprintf(fp, "<node type %d>", n->type);
    114 		if (ind >= 0)
    115 			putc('\n', fp);
    116 		break;
    117 	}
    118 }
    119 
    120 
    121 
    122 static void
    123 shcmd(union node *cmd, FILE *fp)
    124 {
    125 	union node *np;
    126 	int first;
    127 	const char *s;
    128 	int dftfd;
    129 
    130 	first = 1;
    131 	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
    132 		if (! first)
    133 			putchar(' ');
    134 		sharg(np, fp);
    135 		first = 0;
    136 	}
    137 	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
    138 		if (! first)
    139 			putchar(' ');
    140 		switch (np->nfile.type) {
    141 			case NTO:	s = ">";  dftfd = 1; break;
    142 			case NCLOBBER:	s = ">|"; dftfd = 1; break;
    143 			case NAPPEND:	s = ">>"; dftfd = 1; break;
    144 			case NTOFD:	s = ">&"; dftfd = 1; break;
    145 			case NFROM:	s = "<";  dftfd = 0; break;
    146 			case NFROMFD:	s = "<&"; dftfd = 0; break;
    147 			case NFROMTO:	s = "<>"; dftfd = 0; break;
    148 			default:  	s = "*error*"; dftfd = 0; break;
    149 		}
    150 		if (np->nfile.fd != dftfd)
    151 			fprintf(fp, "%d", np->nfile.fd);
    152 		fputs(s, fp);
    153 		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
    154 			fprintf(fp, "%d", np->ndup.dupfd);
    155 		} else {
    156 			sharg(np->nfile.fname, fp);
    157 		}
    158 		first = 0;
    159 	}
    160 }
    161 
    162 
    163 
    164 static void
    165 sharg(union node *arg, FILE *fp)
    166 {
    167 	char *p;
    168 	struct nodelist *bqlist;
    169 	int subtype;
    170 
    171 	if (arg->type != NARG) {
    172 		printf("<node type %d>\n", arg->type);
    173 		abort();
    174 	}
    175 	bqlist = arg->narg.backquote;
    176 	for (p = arg->narg.text ; *p ; p++) {
    177 		switch (*p) {
    178 		case CTLESC:
    179 			putc(*++p, fp);
    180 			break;
    181 		case CTLVAR:
    182 			putc('$', fp);
    183 			putc('{', fp);
    184 			subtype = *++p;
    185 			if (subtype == VSLENGTH)
    186 				putc('#', fp);
    187 
    188 			while (*p != '=')
    189 				putc(*p++, fp);
    190 
    191 			if (subtype & VSNUL)
    192 				putc(':', fp);
    193 
    194 			switch (subtype & VSTYPE) {
    195 			case VSNORMAL:
    196 				putc('}', fp);
    197 				break;
    198 			case VSMINUS:
    199 				putc('-', fp);
    200 				break;
    201 			case VSPLUS:
    202 				putc('+', fp);
    203 				break;
    204 			case VSQUESTION:
    205 				putc('?', fp);
    206 				break;
    207 			case VSASSIGN:
    208 				putc('=', fp);
    209 				break;
    210 			case VSTRIMLEFT:
    211 				putc('#', fp);
    212 				break;
    213 			case VSTRIMLEFTMAX:
    214 				putc('#', fp);
    215 				putc('#', fp);
    216 				break;
    217 			case VSTRIMRIGHT:
    218 				putc('%', fp);
    219 				break;
    220 			case VSTRIMRIGHTMAX:
    221 				putc('%', fp);
    222 				putc('%', fp);
    223 				break;
    224 			case VSLENGTH:
    225 				break;
    226 			default:
    227 				printf("<subtype %d>", subtype);
    228 			}
    229 			break;
    230 		case CTLENDVAR:
    231 		     putc('}', fp);
    232 		     break;
    233 		case CTLBACKQ:
    234 		case CTLBACKQ|CTLQUOTE:
    235 			putc('$', fp);
    236 			putc('(', fp);
    237 			shtree(bqlist->n, -1, NULL, fp);
    238 			putc(')', fp);
    239 			break;
    240 		default:
    241 			putc(*p, fp);
    242 			break;
    243 		}
    244 	}
    245 }
    246 
    247 
    248 static void
    249 indent(int amount, char *pfx, FILE *fp)
    250 {
    251 	int i;
    252 
    253 	for (i = 0 ; i < amount ; i++) {
    254 		if (pfx && i == amount - 1)
    255 			fputs(pfx, fp);
    256 		putc('\t', fp);
    257 	}
    258 }
    259 #endif
    260 
    261 
    262 
    263 /*
    264  * Debugging stuff.
    265  */
    266 
    267 
    268 FILE *tracefile;
    269 
    270 
    271 #ifdef DEBUG
    272 void
    273 trputc(int c)
    274 {
    275 	if (debug != 1)
    276 		return;
    277 	putc(c, tracefile);
    278 }
    279 #endif
    280 
    281 void
    282 trace(const char *fmt, ...)
    283 {
    284 #ifdef DEBUG
    285 	va_list va;
    286 
    287 	if (debug != 1)
    288 		return;
    289 	va_start(va, fmt);
    290 	(void) vfprintf(tracefile, fmt, va);
    291 	va_end(va);
    292 #endif
    293 }
    294 
    295 void
    296 tracev(const char *fmt, va_list va)
    297 {
    298 #ifdef DEBUG
    299 	if (debug != 1)
    300 		return;
    301 	(void) vfprintf(tracefile, fmt, va);
    302 #endif
    303 }
    304 
    305 
    306 #ifdef DEBUG
    307 void
    308 trputs(const char *s)
    309 {
    310 	if (debug != 1)
    311 		return;
    312 	fputs(s, tracefile);
    313 }
    314 
    315 
    316 static void
    317 trstring(char *s)
    318 {
    319 	char *p;
    320 	char c;
    321 
    322 	if (debug != 1)
    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;
    337 backslash:	  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 #endif
    355 
    356 
    357 void
    358 trargs(char **ap)
    359 {
    360 #ifdef DEBUG
    361 	if (debug != 1)
    362 		return;
    363 	while (*ap) {
    364 		trstring(*ap++);
    365 		if (*ap)
    366 			putc(' ', tracefile);
    367 		else
    368 			putc('\n', tracefile);
    369 	}
    370 #endif
    371 }
    372 
    373 
    374 #ifdef DEBUG
    375 void
    376 opentrace(void)
    377 {
    378 	char s[100];
    379 #ifdef O_APPEND
    380 	int flags;
    381 #endif
    382 
    383 	if (debug != 1) {
    384 		if (tracefile)
    385 			fflush(tracefile);
    386 		/* leave open because libedit might be using it */
    387 		return;
    388 	}
    389 #ifdef not_this_way
    390 	{
    391 		char *p;
    392 		if ((p = getenv("HOME")) == NULL) {
    393 			if (geteuid() == 0)
    394 				p = "/";
    395 			else
    396 				p = "/tmp";
    397 		}
    398 		scopy(p, s);
    399 		strcat(s, "/trace");
    400 	}
    401 #else
    402 	scopy("./trace", s);
    403 #endif /* not_this_way */
    404 	if (tracefile) {
    405 		if (!freopen(s, "a", tracefile)) {
    406 			fprintf(stderr, "Can't re-open %s\n", s);
    407 			debug = 0;
    408 			return;
    409 		}
    410 	} else {
    411 		if ((tracefile = fopen(s, "a")) == NULL) {
    412 			fprintf(stderr, "Can't open %s\n", s);
    413 			debug = 0;
    414 			return;
    415 		}
    416 	}
    417 #ifdef O_APPEND
    418 	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
    419 		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
    420 #endif
    421 	setlinebuf(tracefile);
    422 	fputs("\nTracing started.\n", tracefile);
    423 }
    424 #endif /* DEBUG */
    425