show.c revision 17987
1133819Stjr/*-
2133819Stjr * Copyright (c) 1991, 1993
3133819Stjr *	The Regents of the University of California.  All rights reserved.
4133819Stjr *
5133819Stjr * This code is derived from software contributed to Berkeley by
6213545Skib * Kenneth Almquist.
7133819Stjr *
8133819Stjr * Redistribution and use in source and binary forms, with or without
9133819Stjr * modification, are permitted provided that the following conditions
10133819Stjr * are met:
11133819Stjr * 1. Redistributions of source code must retain the above copyright
12133819Stjr *    notice, this list of conditions and the following disclaimer.
13133819Stjr * 2. Redistributions in binary form must reproduce the above copyright
14177999Skib *    notice, this list of conditions and the following disclaimer in the
15164199Sru *    documentation and/or other materials provided with the distribution.
16133819Stjr * 3. All advertising materials mentioning features or use of this software
17133819Stjr *    must display the following acknowledgement:
18161330Sjhb *	This product includes software developed by the University of
19161330Sjhb *	California, Berkeley and its contributors.
20133819Stjr * 4. Neither the name of the University nor the names of its contributors
21133819Stjr *    may be used to endorse or promote products derived from this software
22133819Stjr *    without specific prior written permission.
23133819Stjr *
24133819Stjr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25133819Stjr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26133819Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27133819Stjr * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28133819Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29133819Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30133819Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31133819Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32133819Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33133819Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34133819Stjr * SUCH DAMAGE.
35143198Ssobomax *
36133819Stjr *	$Id: show.c,v 1.2 1994/09/24 02:58:16 davidg Exp $
37133819Stjr */
38133819Stjr
39133819Stjr#ifndef lint
40133819Stjrstatic char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
41133819Stjr#endif /* not lint */
42133819Stjr
43133819Stjr#include <stdio.h>
44133819Stjr#if __STDC__
45133819Stjr#include <stdarg.h>
46133819Stjr#else
47133819Stjr#include <varargs.h>
48133819Stjr#endif
49133819Stjr
50133819Stjr#include "shell.h"
51133819Stjr#include "parser.h"
52133819Stjr#include "nodes.h"
53133819Stjr#include "mystring.h"
54133819Stjr#include "show.h"
55133819Stjr
56133819Stjr
57133819Stjr#ifdef DEBUG
58133819Stjrstatic void shtree __P((union node *, int, char *, FILE*));
59133819Stjrstatic void shcmd __P((union node *, FILE *));
60133819Stjrstatic void sharg __P((union node *, FILE *));
61133819Stjrstatic void indent __P((int, char *, FILE *));
62210432Skibstatic void trstring __P((char *));
63210432Skib
64133819Stjr
65133819Stjrvoid
66133819Stjrshowtree(n)
67133819Stjr	union node *n;
68133819Stjr{
69133819Stjr	trputs("showtree called\n");
70133819Stjr	shtree(n, 1, NULL, stdout);
71133819Stjr}
72133819Stjr
73133819Stjr
74133819Stjrstatic void
75133819Stjrshtree(n, ind, pfx, fp)
76133819Stjr	union node *n;
77133819Stjr	int ind;
78133819Stjr	char *pfx;
79133819Stjr	FILE *fp;
80133819Stjr{
81133819Stjr	struct nodelist *lp;
82133819Stjr	char *s;
83133819Stjr
84133819Stjr	if (n == NULL)
85156919Snetchild		return;
86156919Snetchild
87156919Snetchild	indent(ind, pfx, fp);
88156919Snetchild	switch(n->type) {
89133819Stjr	case NSEMI:
90133819Stjr		s = "; ";
91133819Stjr		goto binop;
92133819Stjr	case NAND:
93133819Stjr		s = " && ";
94133819Stjr		goto binop;
95133819Stjr	case NOR:
96133819Stjr		s = " || ";
97133819Stjrbinop:
98133819Stjr		shtree(n->nbinary.ch1, ind, NULL, fp);
99133819Stjr	   /*    if (ind < 0) */
100133819Stjr			fputs(s, fp);
101133819Stjr		shtree(n->nbinary.ch2, ind, NULL, fp);
102133819Stjr		break;
103133819Stjr	case NCMD:
104133819Stjr		shcmd(n, fp);
105133819Stjr		if (ind >= 0)
106133819Stjr			putc('\n', fp);
107133819Stjr		break;
108133819Stjr	case NPIPE:
109133819Stjr		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
110133819Stjr			shcmd(lp->n, fp);
111133819Stjr			if (lp->next)
112133819Stjr				fputs(" | ", fp);
113133819Stjr		}
114133819Stjr		if (n->npipe.backgnd)
115133819Stjr			fputs(" &", fp);
116133819Stjr		if (ind >= 0)
117133819Stjr			putc('\n', fp);
118133819Stjr		break;
119133819Stjr	default:
120133819Stjr		fprintf(fp, "<node type %d>", n->type);
121133819Stjr		if (ind >= 0)
122133819Stjr			putc('\n', fp);
123133819Stjr		break;
124133819Stjr	}
125133819Stjr}
126133819Stjr
127133819Stjr
128133819Stjr
129133819Stjrstatic void
130133819Stjrshcmd(cmd, fp)
131133819Stjr	union node *cmd;
132133819Stjr	FILE *fp;
133133819Stjr{
134133819Stjr	union node *np;
135133819Stjr	int first;
136133819Stjr	char *s;
137133819Stjr	int dftfd;
138133819Stjr
139133819Stjr	first = 1;
140133819Stjr	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
141133819Stjr		if (! first)
142133819Stjr			putchar(' ');
143133819Stjr		sharg(np, fp);
144133819Stjr		first = 0;
145133819Stjr	}
146133819Stjr	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
147133819Stjr		if (! first)
148133819Stjr			putchar(' ');
149133819Stjr		switch (np->nfile.type) {
150133819Stjr			case NTO:	s = ">";  dftfd = 1; break;
151133819Stjr			case NAPPEND:	s = ">>"; dftfd = 1; break;
152133819Stjr			case NTOFD:	s = ">&"; dftfd = 1; break;
153133819Stjr			case NFROM:	s = "<";  dftfd = 0; break;
154133819Stjr			case NFROMFD:	s = "<&"; dftfd = 0; break;
155133819Stjr			default:  	s = "*error*"; dftfd = 0; break;
156133819Stjr		}
157133819Stjr		if (np->nfile.fd != dftfd)
158133819Stjr			fprintf(fp, "%d", np->nfile.fd);
159133819Stjr		fputs(s, fp);
160133819Stjr		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
161133819Stjr			fprintf(fp, "%d", np->ndup.dupfd);
162133819Stjr		} else {
163133819Stjr			sharg(np->nfile.fname, fp);
164133819Stjr		}
165133819Stjr		first = 0;
166133819Stjr	}
167133819Stjr}
168133819Stjr
169133819Stjr
170133819Stjr
171133819Stjrstatic void
172133819Stjrsharg(arg, fp)
173133819Stjr	union node *arg;
174133819Stjr	FILE *fp;
175133819Stjr	{
176133819Stjr	char *p;
177133819Stjr	struct nodelist *bqlist;
178133819Stjr	int subtype;
179133819Stjr
180133819Stjr	if (arg->type != NARG) {
181133819Stjr		printf("<node type %d>\n", arg->type);
182133819Stjr		fflush(stdout);
183133819Stjr		abort();
184133819Stjr	}
185133819Stjr	bqlist = arg->narg.backquote;
186133819Stjr	for (p = arg->narg.text ; *p ; p++) {
187133819Stjr		switch (*p) {
188133819Stjr		case CTLESC:
189133819Stjr			putc(*++p, fp);
190133819Stjr			break;
191133819Stjr		case CTLVAR:
192133819Stjr			putc('$', fp);
193133819Stjr			putc('{', fp);
194133819Stjr			subtype = *++p;
195133819Stjr			if (subtype == VSLENGTH)
196133819Stjr				putc('#', fp);
197133819Stjr
198133819Stjr			while (*p != '=')
199133819Stjr				putc(*p++, fp);
200161309Snetchild
201161309Snetchild			if (subtype & VSNUL)
202161309Snetchild				putc(':', fp);
203133819Stjr
204133819Stjr			switch (subtype & VSTYPE) {
205133819Stjr			case VSNORMAL:
206133819Stjr				putc('}', fp);
207133819Stjr				break;
208133819Stjr			case VSMINUS:
209133819Stjr				putc('-', fp);
210133819Stjr				break;
211133819Stjr			case VSPLUS:
212133819Stjr				putc('+', fp);
213133819Stjr				break;
214133819Stjr			case VSQUESTION:
215133819Stjr				putc('?', fp);
216133819Stjr				break;
217133819Stjr			case VSASSIGN:
218133819Stjr				putc('=', fp);
219133819Stjr				break;
220133819Stjr			case VSTRIMLEFT:
221133819Stjr				putc('#', fp);
222133819Stjr				break;
223133819Stjr			case VSTRIMLEFTMAX:
224133819Stjr				putc('#', fp);
225133819Stjr				putc('#', fp);
226133819Stjr				break;
227133819Stjr			case VSTRIMRIGHT:
228133819Stjr				putc('%', fp);
229133819Stjr				break;
230156843Snetchild			case VSTRIMRIGHTMAX:
231156843Snetchild				putc('%', fp);
232156843Snetchild				putc('%', fp);
233156843Snetchild				break;
234133819Stjr			case VSLENGTH:
235133819Stjr				break;
236133819Stjr			default:
237133819Stjr				printf("<subtype %d>", subtype);
238133819Stjr			}
239133819Stjr			break;
240133819Stjr		case CTLENDVAR:
241133819Stjr		     putc('}', fp);
242133819Stjr		     break;
243133819Stjr		case CTLBACKQ:
244133819Stjr		case CTLBACKQ|CTLQUOTE:
245133819Stjr			putc('$', fp);
246133819Stjr			putc('(', fp);
247133819Stjr			shtree(bqlist->n, -1, NULL, fp);
248133819Stjr			putc(')', fp);
249133819Stjr			break;
250133819Stjr		default:
251133819Stjr			putc(*p, fp);
252133819Stjr			break;
253133819Stjr		}
254133819Stjr	}
255133819Stjr}
256133819Stjr
257133819Stjr
258133819Stjrstatic void
259133819Stjrindent(amount, pfx, fp)
260133819Stjr	int amount;
261133819Stjr	char *pfx;
262133819Stjr	FILE *fp;
263133819Stjr{
264133819Stjr	int i;
265133819Stjr
266133819Stjr	for (i = 0 ; i < amount ; i++) {
267133819Stjr		if (pfx && i == amount - 1)
268133819Stjr			fputs(pfx, fp);
269156919Snetchild		putc('\t', fp);
270156843Snetchild	}
271156919Snetchild}
272156843Snetchild#endif
273133819Stjr
274133819Stjr
275133819Stjr
276133819Stjr/*
277133819Stjr * Debugging stuff.
278133819Stjr */
279133819Stjr
280133819Stjr
281133819StjrFILE *tracefile;
282133819Stjr
283133819Stjr#if DEBUG == 2
284133819Stjrint debug = 1;
285133819Stjr#else
286133819Stjrint debug = 0;
287133819Stjr#endif
288133819Stjr
289133819Stjr
290133819Stjrvoid
291133819Stjrtrputc(c)
292133819Stjr	int c;
293133819Stjr{
294133819Stjr#ifdef DEBUG
295133819Stjr	if (tracefile == NULL)
296156843Snetchild		return;
297156843Snetchild	putc(c, tracefile);
298156843Snetchild	if (c == '\n')
299156843Snetchild		fflush(tracefile);
300147142Ssobomax#endif
301147142Ssobomax}
302147142Ssobomax
303147142Ssobomaxvoid
304133819Stjr#if __STDC__
305133819Stjrshtrace(const char *fmt, ...)
306133819Stjr#else
307133819Stjrshtrace(va_alist)
308133819Stjr	va_dcl
309133819Stjr#endif
310133819Stjr{
311133819Stjr#ifdef DEBUG
312133819Stjr	va_list va;
313133819Stjr#if __STDC__
314133819Stjr	va_start(va, fmt);
315133819Stjr#else
316133819Stjr	char *fmt;
317133819Stjr	va_start(va);
318133819Stjr	fmt = va_arg(va, char *);
319133819Stjr#endif
320133819Stjr	if (tracefile != NULL) {
321133819Stjr		(void) vfprintf(tracefile, fmt, va);
322133819Stjr		if (strchr(fmt, '\n'))
323133819Stjr			(void) fflush(tracefile);
324133819Stjr	}
325133819Stjr	va_end(va);
326133819Stjr#endif
327133819Stjr}
328133819Stjr
329133819Stjr
330133819Stjrvoid
331133819Stjrtrputs(s)
332133819Stjr	char *s;
333133819Stjr{
334133819Stjr#ifdef DEBUG
335133819Stjr	if (tracefile == NULL)
336133819Stjr		return;
337133819Stjr	fputs(s, tracefile);
338133819Stjr	if (strchr(s, '\n'))
339133819Stjr		fflush(tracefile);
340133819Stjr#endif
341133819Stjr}
342133819Stjr
343133819Stjr
344133819Stjrstatic void
345166730Sjkimtrstring(s)
346166730Sjkim	char *s;
347166730Sjkim{
348133819Stjr	register char *p;
349133819Stjr	char c;
350133819Stjr
351133819Stjr#ifdef DEBUG
352133819Stjr	if (tracefile == NULL)
353133819Stjr		return;
354133819Stjr	putc('"', tracefile);
355133819Stjr	for (p = s ; *p ; p++) {
356133819Stjr		switch (*p) {
357133819Stjr		case '\n':  c = 'n';  goto backslash;
358133819Stjr		case '\t':  c = 't';  goto backslash;
359133819Stjr		case '\r':  c = 'r';  goto backslash;
360133819Stjr		case '"':  c = '"';  goto backslash;
361133819Stjr		case '\\':  c = '\\';  goto backslash;
362133819Stjr		case CTLESC:  c = 'e';  goto backslash;
363133819Stjr		case CTLVAR:  c = 'v';  goto backslash;
364133819Stjr		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
365133819Stjr		case CTLBACKQ:  c = 'q';  goto backslash;
366133819Stjr		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
367133819Stjrbackslash:	  putc('\\', tracefile);
368133819Stjr			putc(c, tracefile);
369133819Stjr			break;
370133819Stjr		default:
371133819Stjr			if (*p >= ' ' && *p <= '~')
372133819Stjr				putc(*p, tracefile);
373133819Stjr			else {
374133819Stjr				putc('\\', tracefile);
375133819Stjr				putc(*p >> 6 & 03, tracefile);
376133819Stjr				putc(*p >> 3 & 07, tracefile);
377161309Snetchild				putc(*p & 07, tracefile);
378161309Snetchild			}
379161309Snetchild			break;
380133819Stjr		}
381184790Sed	}
382184790Sed	putc('"', tracefile);
383184790Sed#endif
384184790Sed}
385133819Stjr
386133819Stjr
387133819Stjrvoid
388133819Stjrtrargs(ap)
389133819Stjr	char **ap;
390133819Stjr{
391133819Stjr#ifdef DEBUG
392133819Stjr	if (tracefile == NULL)
393133819Stjr		return;
394133819Stjr	while (*ap) {
395133819Stjr		trstring(*ap++);
396133819Stjr		if (*ap)
397133819Stjr			putc(' ', tracefile);
398133819Stjr		else
399133819Stjr			putc('\n', tracefile);
400133819Stjr	}
401133819Stjr	fflush(tracefile);
402133819Stjr#endif
403133819Stjr}
404133819Stjr
405133819Stjr
406133819Stjrvoid
407133819Stjropentrace() {
408133819Stjr	char s[100];
409133819Stjr	char *getenv();
410133819Stjr#ifdef O_APPEND
411133819Stjr	int flags;
412133819Stjr#endif
413133819Stjr
414133819Stjr#ifdef DEBUG
415133819Stjr	if (!debug)
416133819Stjr		return;
417133819Stjr#ifdef not_this_way
418133819Stjr	{
419133819Stjr		char *p;
420133819Stjr		if ((p = getenv("HOME")) == NULL) {
421133819Stjr			if (geteuid() == 0)
422133819Stjr				p = "/";
423133819Stjr			else
424133819Stjr				p = "/tmp";
425133819Stjr		}
426133819Stjr		scopy(p, s);
427133819Stjr		strcat(s, "/trace");
428133819Stjr	}
429133819Stjr#else
430133819Stjr	scopy("./trace", s);
431133819Stjr#endif /* not_this_way */
432133819Stjr	if ((tracefile = fopen(s, "a")) == NULL) {
433133819Stjr		fprintf(stderr, "Can't open %s\n", s);
434133819Stjr		return;
435133819Stjr	}
436133819Stjr#ifdef O_APPEND
437133819Stjr	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
438133819Stjr		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
439133819Stjr#endif
440133819Stjr	fputs("\nTracing started.\n", tracefile);
441133819Stjr	fflush(tracefile);
442133819Stjr#endif /* DEBUG */
443133819Stjr}
444133819Stjr