show.c revision 25222
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	$Id: show.c,v 1.7 1997/02/22 13:58:45 peter Exp $
37 */
38
39#ifndef lint
40static char const sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
41#endif /* not lint */
42
43#include <stdio.h>
44#ifdef __STDC__
45#include <stdarg.h>
46#else
47#include <varargs.h>
48#endif
49
50#include "shell.h"
51#include "parser.h"
52#include "nodes.h"
53#include "mystring.h"
54#include "show.h"
55
56
57#ifdef DEBUG
58static void shtree __P((union node *, int, char *, FILE*));
59static void shcmd __P((union node *, FILE *));
60static void sharg __P((union node *, FILE *));
61static void indent __P((int, char *, FILE *));
62static void trstring __P((char *));
63
64
65void
66showtree(n)
67	union node *n;
68{
69	trputs("showtree called\n");
70	shtree(n, 1, NULL, stdout);
71}
72
73
74static void
75shtree(n, ind, pfx, fp)
76	union node *n;
77	int ind;
78	char *pfx;
79	FILE *fp;
80{
81	struct nodelist *lp;
82	char *s;
83
84	if (n == NULL)
85		return;
86
87	indent(ind, pfx, fp);
88	switch(n->type) {
89	case NSEMI:
90		s = "; ";
91		goto binop;
92	case NAND:
93		s = " && ";
94		goto binop;
95	case NOR:
96		s = " || ";
97binop:
98		shtree(n->nbinary.ch1, ind, NULL, fp);
99	   /*    if (ind < 0) */
100			fputs(s, fp);
101		shtree(n->nbinary.ch2, ind, NULL, fp);
102		break;
103	case NCMD:
104		shcmd(n, fp);
105		if (ind >= 0)
106			putc('\n', fp);
107		break;
108	case NPIPE:
109		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
110			shcmd(lp->n, fp);
111			if (lp->next)
112				fputs(" | ", fp);
113		}
114		if (n->npipe.backgnd)
115			fputs(" &", fp);
116		if (ind >= 0)
117			putc('\n', fp);
118		break;
119	default:
120		fprintf(fp, "<node type %d>", n->type);
121		if (ind >= 0)
122			putc('\n', fp);
123		break;
124	}
125}
126
127
128
129static void
130shcmd(cmd, fp)
131	union node *cmd;
132	FILE *fp;
133{
134	union node *np;
135	int first;
136	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#ifdef __STDC__
302trace(const char *fmt, ...)
303#else
304trace(va_alist)
305	va_dcl
306#endif
307{
308	va_list va;
309#ifdef __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	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