show.c revision 36150
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 3. All advertising materials mentioning features or use of this software
171556Srgrimes *    must display the following acknowledgement:
181556Srgrimes *	This product includes software developed by the University of
191556Srgrimes *	California, Berkeley and its contributors.
201556Srgrimes * 4. Neither the name of the University nor the names of its contributors
211556Srgrimes *    may be used to endorse or promote products derived from this software
221556Srgrimes *    without specific prior written permission.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341556Srgrimes * SUCH DAMAGE.
351556Srgrimes */
361556Srgrimes
371556Srgrimes#ifndef lint
3836150Scharnier#if 0
3936150Scharnierstatic char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
4036150Scharnier#endif
4136150Scharnierstatic const char rcsid[] =
4236150Scharnier	"$Id$";
431556Srgrimes#endif /* not lint */
441556Srgrimes
451556Srgrimes#include <stdio.h>
4625222Ssteve#ifdef __STDC__
4717987Speter#include <stdarg.h>
4817987Speter#else
4917987Speter#include <varargs.h>
5017987Speter#endif
5117987Speter
521556Srgrimes#include "shell.h"
531556Srgrimes#include "parser.h"
541556Srgrimes#include "nodes.h"
551556Srgrimes#include "mystring.h"
5617987Speter#include "show.h"
571556Srgrimes
581556Srgrimes
591556Srgrimes#ifdef DEBUG
6017987Speterstatic void shtree __P((union node *, int, char *, FILE*));
6117987Speterstatic void shcmd __P((union node *, FILE *));
6217987Speterstatic void sharg __P((union node *, FILE *));
6317987Speterstatic void indent __P((int, char *, FILE *));
6417987Speterstatic void trstring __P((char *));
651556Srgrimes
661556Srgrimes
6717987Spetervoid
681556Srgrimesshowtree(n)
691556Srgrimes	union node *n;
7017987Speter{
711556Srgrimes	trputs("showtree called\n");
721556Srgrimes	shtree(n, 1, NULL, stdout);
731556Srgrimes}
741556Srgrimes
751556Srgrimes
7617987Speterstatic void
771556Srgrimesshtree(n, ind, pfx, fp)
781556Srgrimes	union node *n;
7917987Speter	int ind;
801556Srgrimes	char *pfx;
811556Srgrimes	FILE *fp;
8217987Speter{
831556Srgrimes	struct nodelist *lp;
841556Srgrimes	char *s;
851556Srgrimes
8617987Speter	if (n == NULL)
8717987Speter		return;
8817987Speter
891556Srgrimes	indent(ind, pfx, fp);
901556Srgrimes	switch(n->type) {
911556Srgrimes	case NSEMI:
921556Srgrimes		s = "; ";
931556Srgrimes		goto binop;
941556Srgrimes	case NAND:
951556Srgrimes		s = " && ";
961556Srgrimes		goto binop;
971556Srgrimes	case NOR:
981556Srgrimes		s = " || ";
991556Srgrimesbinop:
1001556Srgrimes		shtree(n->nbinary.ch1, ind, NULL, fp);
1011556Srgrimes	   /*    if (ind < 0) */
1021556Srgrimes			fputs(s, fp);
1031556Srgrimes		shtree(n->nbinary.ch2, ind, NULL, fp);
1041556Srgrimes		break;
1051556Srgrimes	case NCMD:
1061556Srgrimes		shcmd(n, fp);
1071556Srgrimes		if (ind >= 0)
1081556Srgrimes			putc('\n', fp);
1091556Srgrimes		break;
1101556Srgrimes	case NPIPE:
1111556Srgrimes		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1121556Srgrimes			shcmd(lp->n, fp);
1131556Srgrimes			if (lp->next)
1141556Srgrimes				fputs(" | ", fp);
1151556Srgrimes		}
1161556Srgrimes		if (n->npipe.backgnd)
1171556Srgrimes			fputs(" &", fp);
1181556Srgrimes		if (ind >= 0)
1191556Srgrimes			putc('\n', fp);
1201556Srgrimes		break;
1211556Srgrimes	default:
1221556Srgrimes		fprintf(fp, "<node type %d>", n->type);
1231556Srgrimes		if (ind >= 0)
1241556Srgrimes			putc('\n', fp);
1251556Srgrimes		break;
1261556Srgrimes	}
1271556Srgrimes}
1281556Srgrimes
1291556Srgrimes
1301556Srgrimes
13117987Speterstatic void
1321556Srgrimesshcmd(cmd, fp)
1331556Srgrimes	union node *cmd;
1341556Srgrimes	FILE *fp;
13517987Speter{
1361556Srgrimes	union node *np;
1371556Srgrimes	int first;
1381556Srgrimes	char *s;
1391556Srgrimes	int dftfd;
1401556Srgrimes
1411556Srgrimes	first = 1;
1421556Srgrimes	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
1431556Srgrimes		if (! first)
1441556Srgrimes			putchar(' ');
1451556Srgrimes		sharg(np, fp);
1461556Srgrimes		first = 0;
1471556Srgrimes	}
1481556Srgrimes	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
1491556Srgrimes		if (! first)
1501556Srgrimes			putchar(' ');
1511556Srgrimes		switch (np->nfile.type) {
1521556Srgrimes			case NTO:	s = ">";  dftfd = 1; break;
1531556Srgrimes			case NAPPEND:	s = ">>"; dftfd = 1; break;
1541556Srgrimes			case NTOFD:	s = ">&"; dftfd = 1; break;
1551556Srgrimes			case NFROM:	s = "<";  dftfd = 0; break;
1561556Srgrimes			case NFROMFD:	s = "<&"; dftfd = 0; break;
15717987Speter			default:  	s = "*error*"; dftfd = 0; break;
1581556Srgrimes		}
1591556Srgrimes		if (np->nfile.fd != dftfd)
1601556Srgrimes			fprintf(fp, "%d", np->nfile.fd);
1611556Srgrimes		fputs(s, fp);
1621556Srgrimes		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1631556Srgrimes			fprintf(fp, "%d", np->ndup.dupfd);
1641556Srgrimes		} else {
1651556Srgrimes			sharg(np->nfile.fname, fp);
1661556Srgrimes		}
1671556Srgrimes		first = 0;
1681556Srgrimes	}
1691556Srgrimes}
1701556Srgrimes
1711556Srgrimes
1721556Srgrimes
17317987Speterstatic void
1741556Srgrimessharg(arg, fp)
1751556Srgrimes	union node *arg;
1761556Srgrimes	FILE *fp;
1771556Srgrimes	{
1781556Srgrimes	char *p;
1791556Srgrimes	struct nodelist *bqlist;
1801556Srgrimes	int subtype;
1811556Srgrimes
1821556Srgrimes	if (arg->type != NARG) {
1831556Srgrimes		printf("<node type %d>\n", arg->type);
1841556Srgrimes		fflush(stdout);
1851556Srgrimes		abort();
1861556Srgrimes	}
1871556Srgrimes	bqlist = arg->narg.backquote;
1881556Srgrimes	for (p = arg->narg.text ; *p ; p++) {
1891556Srgrimes		switch (*p) {
1901556Srgrimes		case CTLESC:
1911556Srgrimes			putc(*++p, fp);
1921556Srgrimes			break;
1931556Srgrimes		case CTLVAR:
1941556Srgrimes			putc('$', fp);
1951556Srgrimes			putc('{', fp);
1961556Srgrimes			subtype = *++p;
19717987Speter			if (subtype == VSLENGTH)
19817987Speter				putc('#', fp);
19917987Speter
2001556Srgrimes			while (*p != '=')
2011556Srgrimes				putc(*p++, fp);
20217987Speter
2031556Srgrimes			if (subtype & VSNUL)
2041556Srgrimes				putc(':', fp);
20517987Speter
2061556Srgrimes			switch (subtype & VSTYPE) {
2071556Srgrimes			case VSNORMAL:
2081556Srgrimes				putc('}', fp);
2091556Srgrimes				break;
2101556Srgrimes			case VSMINUS:
2111556Srgrimes				putc('-', fp);
2121556Srgrimes				break;
2131556Srgrimes			case VSPLUS:
2141556Srgrimes				putc('+', fp);
2151556Srgrimes				break;
2161556Srgrimes			case VSQUESTION:
2171556Srgrimes				putc('?', fp);
2181556Srgrimes				break;
2191556Srgrimes			case VSASSIGN:
2201556Srgrimes				putc('=', fp);
2211556Srgrimes				break;
22217987Speter			case VSTRIMLEFT:
22317987Speter				putc('#', fp);
22417987Speter				break;
22517987Speter			case VSTRIMLEFTMAX:
22617987Speter				putc('#', fp);
22717987Speter				putc('#', fp);
22817987Speter				break;
22917987Speter			case VSTRIMRIGHT:
23017987Speter				putc('%', fp);
23117987Speter				break;
23217987Speter			case VSTRIMRIGHTMAX:
23317987Speter				putc('%', fp);
23417987Speter				putc('%', fp);
23517987Speter				break;
23617987Speter			case VSLENGTH:
23717987Speter				break;
2381556Srgrimes			default:
2391556Srgrimes				printf("<subtype %d>", subtype);
2401556Srgrimes			}
2411556Srgrimes			break;
2421556Srgrimes		case CTLENDVAR:
2431556Srgrimes		     putc('}', fp);
2441556Srgrimes		     break;
2451556Srgrimes		case CTLBACKQ:
2461556Srgrimes		case CTLBACKQ|CTLQUOTE:
2471556Srgrimes			putc('$', fp);
2481556Srgrimes			putc('(', fp);
2491556Srgrimes			shtree(bqlist->n, -1, NULL, fp);
2501556Srgrimes			putc(')', fp);
2511556Srgrimes			break;
2521556Srgrimes		default:
2531556Srgrimes			putc(*p, fp);
2541556Srgrimes			break;
2551556Srgrimes		}
2561556Srgrimes	}
2571556Srgrimes}
2581556Srgrimes
2591556Srgrimes
26017987Speterstatic void
2611556Srgrimesindent(amount, pfx, fp)
26217987Speter	int amount;
2631556Srgrimes	char *pfx;
2641556Srgrimes	FILE *fp;
26517987Speter{
2661556Srgrimes	int i;
2671556Srgrimes
2681556Srgrimes	for (i = 0 ; i < amount ; i++) {
2691556Srgrimes		if (pfx && i == amount - 1)
2701556Srgrimes			fputs(pfx, fp);
2711556Srgrimes		putc('\t', fp);
2721556Srgrimes	}
2731556Srgrimes}
2741556Srgrimes
2751556Srgrimes
2761556Srgrimes/*
2771556Srgrimes * Debugging stuff.
2781556Srgrimes */
2791556Srgrimes
2801556Srgrimes
2811556SrgrimesFILE *tracefile;
2821556Srgrimes
2831556Srgrimes#if DEBUG == 2
2841556Srgrimesint debug = 1;
2851556Srgrimes#else
2861556Srgrimesint debug = 0;
2871556Srgrimes#endif
2881556Srgrimes
2891556Srgrimes
29017987Spetervoid
29120425Sstevetrputc(c)
29217987Speter	int c;
29317987Speter{
2941556Srgrimes	if (tracefile == NULL)
2951556Srgrimes		return;
2961556Srgrimes	putc(c, tracefile);
2971556Srgrimes	if (c == '\n')
2981556Srgrimes		fflush(tracefile);
2991556Srgrimes}
3001556Srgrimes
30120425Ssteve
30217987Spetervoid
30325222Ssteve#ifdef __STDC__
30420425Sstevetrace(const char *fmt, ...)
30517987Speter#else
30620425Sstevetrace(va_alist)
30717987Speter	va_dcl
30817987Speter#endif
30917987Speter{
31017987Speter	va_list va;
31125222Ssteve#ifdef __STDC__
31217987Speter	va_start(va, fmt);
31317987Speter#else
3141556Srgrimes	char *fmt;
31517987Speter	va_start(va);
31617987Speter	fmt = va_arg(va, char *);
3171556Srgrimes#endif
31817987Speter	if (tracefile != NULL) {
31917987Speter		(void) vfprintf(tracefile, fmt, va);
32017987Speter		if (strchr(fmt, '\n'))
32117987Speter			(void) fflush(tracefile);
32217987Speter	}
32317987Speter	va_end(va);
3241556Srgrimes}
3251556Srgrimes
3261556Srgrimes
32717987Spetervoid
3281556Srgrimestrputs(s)
3291556Srgrimes	char *s;
33017987Speter{
3311556Srgrimes	if (tracefile == NULL)
3321556Srgrimes		return;
3331556Srgrimes	fputs(s, tracefile);
3341556Srgrimes	if (strchr(s, '\n'))
3351556Srgrimes		fflush(tracefile);
3361556Srgrimes}
3371556Srgrimes
3381556Srgrimes
33917987Speterstatic void
3401556Srgrimestrstring(s)
3411556Srgrimes	char *s;
34217987Speter{
34325222Ssteve	char *p;
3441556Srgrimes	char c;
3451556Srgrimes
3461556Srgrimes	if (tracefile == NULL)
3471556Srgrimes		return;
3481556Srgrimes	putc('"', tracefile);
3491556Srgrimes	for (p = s ; *p ; p++) {
3501556Srgrimes		switch (*p) {
3511556Srgrimes		case '\n':  c = 'n';  goto backslash;
3521556Srgrimes		case '\t':  c = 't';  goto backslash;
3531556Srgrimes		case '\r':  c = 'r';  goto backslash;
3541556Srgrimes		case '"':  c = '"';  goto backslash;
3551556Srgrimes		case '\\':  c = '\\';  goto backslash;
3561556Srgrimes		case CTLESC:  c = 'e';  goto backslash;
3571556Srgrimes		case CTLVAR:  c = 'v';  goto backslash;
3581556Srgrimes		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
3591556Srgrimes		case CTLBACKQ:  c = 'q';  goto backslash;
3601556Srgrimes		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
3611556Srgrimesbackslash:	  putc('\\', tracefile);
3621556Srgrimes			putc(c, tracefile);
3631556Srgrimes			break;
3641556Srgrimes		default:
3651556Srgrimes			if (*p >= ' ' && *p <= '~')
3661556Srgrimes				putc(*p, tracefile);
3671556Srgrimes			else {
3681556Srgrimes				putc('\\', tracefile);
3691556Srgrimes				putc(*p >> 6 & 03, tracefile);
3701556Srgrimes				putc(*p >> 3 & 07, tracefile);
3711556Srgrimes				putc(*p & 07, tracefile);
3721556Srgrimes			}
3731556Srgrimes			break;
3741556Srgrimes		}
3751556Srgrimes	}
3761556Srgrimes	putc('"', tracefile);
37718018Speter}
3781556Srgrimes
3791556Srgrimes
38017987Spetervoid
3811556Srgrimestrargs(ap)
3821556Srgrimes	char **ap;
38317987Speter{
3841556Srgrimes	if (tracefile == NULL)
3851556Srgrimes		return;
3861556Srgrimes	while (*ap) {
3871556Srgrimes		trstring(*ap++);
3881556Srgrimes		if (*ap)
3891556Srgrimes			putc(' ', tracefile);
3901556Srgrimes		else
3911556Srgrimes			putc('\n', tracefile);
3921556Srgrimes	}
3931556Srgrimes	fflush(tracefile);
3941556Srgrimes}
3951556Srgrimes
3961556Srgrimes
39717987Spetervoid
3981556Srgrimesopentrace() {
3991556Srgrimes	char s[100];
4001556Srgrimes	char *getenv();
40117987Speter#ifdef O_APPEND
4021556Srgrimes	int flags;
40317987Speter#endif
4041556Srgrimes
4051556Srgrimes	if (!debug)
4061556Srgrimes		return;
4071556Srgrimes#ifdef not_this_way
40817987Speter	{
40917987Speter		char *p;
41017987Speter		if ((p = getenv("HOME")) == NULL) {
41117987Speter			if (geteuid() == 0)
41217987Speter				p = "/";
41317987Speter			else
41417987Speter				p = "/tmp";
41517987Speter		}
41617987Speter		scopy(p, s);
41717987Speter		strcat(s, "/trace");
4181556Srgrimes	}
4191556Srgrimes#else
4201556Srgrimes	scopy("./trace", s);
4211556Srgrimes#endif /* not_this_way */
4221556Srgrimes	if ((tracefile = fopen(s, "a")) == NULL) {
4231556Srgrimes		fprintf(stderr, "Can't open %s\n", s);
4241556Srgrimes		return;
4251556Srgrimes	}
4261556Srgrimes#ifdef O_APPEND
4271556Srgrimes	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
4281556Srgrimes		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
4291556Srgrimes#endif
4301556Srgrimes	fputs("\nTracing started.\n", tracefile);
4311556Srgrimes	fflush(tracefile);
43220425Ssteve}
4331556Srgrimes#endif /* DEBUG */
434