show.c revision 22988
1252330Sjeff/*-
2252330Sjeff * Copyright (c) 1991, 1993
3252330Sjeff *	The Regents of the University of California.  All rights reserved.
4252330Sjeff *
5252330Sjeff * This code is derived from software contributed to Berkeley by
6252330Sjeff * Kenneth Almquist.
7252330Sjeff *
8252330Sjeff * Redistribution and use in source and binary forms, with or without
9252330Sjeff * modification, are permitted provided that the following conditions
10252330Sjeff * are met:
11252330Sjeff * 1. Redistributions of source code must retain the above copyright
12252330Sjeff *    notice, this list of conditions and the following disclaimer.
13252330Sjeff * 2. Redistributions in binary form must reproduce the above copyright
14252330Sjeff *    notice, this list of conditions and the following disclaimer in the
15252330Sjeff *    documentation and/or other materials provided with the distribution.
16252330Sjeff * 3. All advertising materials mentioning features or use of this software
17252330Sjeff *    must display the following acknowledgement:
18252330Sjeff *	This product includes software developed by the University of
19252330Sjeff *	California, Berkeley and its contributors.
20252330Sjeff * 4. Neither the name of the University nor the names of its contributors
21252330Sjeff *    may be used to endorse or promote products derived from this software
22252330Sjeff *    without specific prior written permission.
23252330Sjeff *
24252330Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25252330Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26252330Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27252330Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28252330Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29252330Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30252330Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31252330Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32252330Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33252330Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34252330Sjeff * SUCH DAMAGE.
35252330Sjeff *
36252330Sjeff *	$Id$
37252330Sjeff */
38252330Sjeff
39252330Sjeff#ifndef lint
40252330Sjeffstatic char const sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
41252330Sjeff#endif /* not lint */
42252330Sjeff
43252330Sjeff#include <stdio.h>
44252330Sjeff#if __STDC__
45252330Sjeff#include <stdarg.h>
46252330Sjeff#else
47252330Sjeff#include <varargs.h>
48252330Sjeff#endif
49252330Sjeff
50252330Sjeff#include "shell.h"
51252330Sjeff#include "parser.h"
52252330Sjeff#include "nodes.h"
53252330Sjeff#include "mystring.h"
54252330Sjeff#include "show.h"
55252330Sjeff
56252330Sjeff
57252330Sjeff#ifdef DEBUG
58252330Sjeffstatic void shtree __P((union node *, int, char *, FILE*));
59252330Sjeffstatic void shcmd __P((union node *, FILE *));
60252330Sjeffstatic void sharg __P((union node *, FILE *));
61252330Sjeffstatic void indent __P((int, char *, FILE *));
62252330Sjeffstatic void trstring __P((char *));
63252330Sjeff
64252330Sjeff
65252330Sjeffvoid
66252330Sjeffshowtree(n)
67252330Sjeff	union node *n;
68252330Sjeff{
69252330Sjeff	trputs("showtree called\n");
70252330Sjeff	shtree(n, 1, NULL, stdout);
71252330Sjeff}
72252330Sjeff
73252330Sjeff
74252330Sjeffstatic void
75252330Sjeffshtree(n, ind, pfx, fp)
76252330Sjeff	union node *n;
77252330Sjeff	int ind;
78252330Sjeff	char *pfx;
79252330Sjeff	FILE *fp;
80252330Sjeff{
81252330Sjeff	struct nodelist *lp;
82252330Sjeff	char *s;
83252330Sjeff
84252330Sjeff	if (n == NULL)
85252330Sjeff		return;
86252330Sjeff
87252330Sjeff	indent(ind, pfx, fp);
88252330Sjeff	switch(n->type) {
89252330Sjeff	case NSEMI:
90252330Sjeff		s = "; ";
91252330Sjeff		goto binop;
92252330Sjeff	case NAND:
93252330Sjeff		s = " && ";
94252330Sjeff		goto binop;
95252330Sjeff	case NOR:
96252330Sjeff		s = " || ";
97252330Sjeffbinop:
98252330Sjeff		shtree(n->nbinary.ch1, ind, NULL, fp);
99252330Sjeff	   /*    if (ind < 0) */
100252330Sjeff			fputs(s, fp);
101252330Sjeff		shtree(n->nbinary.ch2, ind, NULL, fp);
102252330Sjeff		break;
103252330Sjeff	case NCMD:
104252330Sjeff		shcmd(n, fp);
105252330Sjeff		if (ind >= 0)
106252330Sjeff			putc('\n', fp);
107252330Sjeff		break;
108252330Sjeff	case NPIPE:
109252330Sjeff		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
110252330Sjeff			shcmd(lp->n, fp);
111252330Sjeff			if (lp->next)
112252330Sjeff				fputs(" | ", fp);
113252330Sjeff		}
114252330Sjeff		if (n->npipe.backgnd)
115252330Sjeff			fputs(" &", fp);
116252330Sjeff		if (ind >= 0)
117252330Sjeff			putc('\n', fp);
118252330Sjeff		break;
119252330Sjeff	default:
120252330Sjeff		fprintf(fp, "<node type %d>", n->type);
121252330Sjeff		if (ind >= 0)
122252330Sjeff			putc('\n', fp);
123252330Sjeff		break;
124252330Sjeff	}
125252330Sjeff}
126252330Sjeff
127252330Sjeff
128252330Sjeff
129252330Sjeffstatic void
130252330Sjeffshcmd(cmd, fp)
131252330Sjeff	union node *cmd;
132282361Smav	FILE *fp;
133252330Sjeff{
134252330Sjeff	union node *np;
135252330Sjeff	int first;
136252330Sjeff	char *s;
137	int dftfd;
138
139	first = 1;
140	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
141		if (! first)
142			putchar(' ');
143		sharg(np, fp);
144		first = 0;
145	}
146	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
147		if (! first)
148			putchar(' ');
149		switch (np->nfile.type) {
150			case NTO:	s = ">";  dftfd = 1; break;
151			case NAPPEND:	s = ">>"; dftfd = 1; break;
152			case NTOFD:	s = ">&"; dftfd = 1; break;
153			case NFROM:	s = "<";  dftfd = 0; break;
154			case NFROMFD:	s = "<&"; dftfd = 0; break;
155			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
273
274/*
275 * Debugging stuff.
276 */
277
278
279FILE *tracefile;
280
281#if DEBUG == 2
282int debug = 1;
283#else
284int debug = 0;
285#endif
286
287
288void
289trputc(c)
290	int c;
291{
292	if (tracefile == NULL)
293		return;
294	putc(c, tracefile);
295	if (c == '\n')
296		fflush(tracefile);
297}
298
299
300void
301#if __STDC__
302trace(const char *fmt, ...)
303#else
304trace(va_alist)
305	va_dcl
306#endif
307{
308	va_list va;
309#if __STDC__
310	va_start(va, fmt);
311#else
312	char *fmt;
313	va_start(va);
314	fmt = va_arg(va, char *);
315#endif
316	if (tracefile != NULL) {
317		(void) vfprintf(tracefile, fmt, va);
318		if (strchr(fmt, '\n'))
319			(void) fflush(tracefile);
320	}
321	va_end(va);
322}
323
324
325void
326trputs(s)
327	char *s;
328{
329	if (tracefile == NULL)
330		return;
331	fputs(s, tracefile);
332	if (strchr(s, '\n'))
333		fflush(tracefile);
334}
335
336
337static void
338trstring(s)
339	char *s;
340{
341	register char *p;
342	char c;
343
344	if (tracefile == NULL)
345		return;
346	putc('"', tracefile);
347	for (p = s ; *p ; p++) {
348		switch (*p) {
349		case '\n':  c = 'n';  goto backslash;
350		case '\t':  c = 't';  goto backslash;
351		case '\r':  c = 'r';  goto backslash;
352		case '"':  c = '"';  goto backslash;
353		case '\\':  c = '\\';  goto backslash;
354		case CTLESC:  c = 'e';  goto backslash;
355		case CTLVAR:  c = 'v';  goto backslash;
356		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
357		case CTLBACKQ:  c = 'q';  goto backslash;
358		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
359backslash:	  putc('\\', tracefile);
360			putc(c, tracefile);
361			break;
362		default:
363			if (*p >= ' ' && *p <= '~')
364				putc(*p, tracefile);
365			else {
366				putc('\\', tracefile);
367				putc(*p >> 6 & 03, tracefile);
368				putc(*p >> 3 & 07, tracefile);
369				putc(*p & 07, tracefile);
370			}
371			break;
372		}
373	}
374	putc('"', tracefile);
375}
376
377
378void
379trargs(ap)
380	char **ap;
381{
382	if (tracefile == NULL)
383		return;
384	while (*ap) {
385		trstring(*ap++);
386		if (*ap)
387			putc(' ', tracefile);
388		else
389			putc('\n', tracefile);
390	}
391	fflush(tracefile);
392}
393
394
395void
396opentrace() {
397	char s[100];
398	char *getenv();
399#ifdef O_APPEND
400	int flags;
401#endif
402
403	if (!debug)
404		return;
405#ifdef not_this_way
406	{
407		char *p;
408		if ((p = getenv("HOME")) == NULL) {
409			if (geteuid() == 0)
410				p = "/";
411			else
412				p = "/tmp";
413		}
414		scopy(p, s);
415		strcat(s, "/trace");
416	}
417#else
418	scopy("./trace", s);
419#endif /* not_this_way */
420	if ((tracefile = fopen(s, "a")) == NULL) {
421		fprintf(stderr, "Can't open %s\n", s);
422		return;
423	}
424#ifdef O_APPEND
425	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
426		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
427#endif
428	fputs("\nTracing started.\n", tracefile);
429	fflush(tracefile);
430}
431#endif /* DEBUG */
432