show.c revision 1557
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
37#ifndef lint
38static char sccsid[] = "@(#)show.c	8.1 (Berkeley) 5/31/93";
39#endif /* not lint */
40
41#include <stdio.h>
42#include "shell.h"
43#include "parser.h"
44#include "nodes.h"
45#include "mystring.h"
46
47
48#ifdef DEBUG
49static shtree(), shcmd(), sharg(), indent();
50
51
52showtree(n)
53	union node *n;
54	{
55	trputs("showtree called\n");
56	shtree(n, 1, NULL, stdout);
57}
58
59
60static
61shtree(n, ind, pfx, fp)
62	union node *n;
63	char *pfx;
64	FILE *fp;
65	{
66	struct nodelist *lp;
67	char *s;
68
69	indent(ind, pfx, fp);
70	switch(n->type) {
71	case NSEMI:
72		s = "; ";
73		goto binop;
74	case NAND:
75		s = " && ";
76		goto binop;
77	case NOR:
78		s = " || ";
79binop:
80		shtree(n->nbinary.ch1, ind, NULL, fp);
81	   /*    if (ind < 0) */
82			fputs(s, fp);
83		shtree(n->nbinary.ch2, ind, NULL, fp);
84		break;
85	case NCMD:
86		shcmd(n, fp);
87		if (ind >= 0)
88			putc('\n', fp);
89		break;
90	case NPIPE:
91		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
92			shcmd(lp->n, fp);
93			if (lp->next)
94				fputs(" | ", fp);
95		}
96		if (n->npipe.backgnd)
97			fputs(" &", fp);
98		if (ind >= 0)
99			putc('\n', fp);
100		break;
101	default:
102		fprintf(fp, "<node type %d>", n->type);
103		if (ind >= 0)
104			putc('\n', fp);
105		break;
106	}
107}
108
109
110
111static
112shcmd(cmd, fp)
113	union node *cmd;
114	FILE *fp;
115	{
116	union node *np;
117	int first;
118	char *s;
119	int dftfd;
120
121	first = 1;
122	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
123		if (! first)
124			putchar(' ');
125		sharg(np, fp);
126		first = 0;
127	}
128	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
129		if (! first)
130			putchar(' ');
131		switch (np->nfile.type) {
132			case NTO:	s = ">";  dftfd = 1; break;
133			case NAPPEND:	s = ">>"; dftfd = 1; break;
134			case NTOFD:	s = ">&"; dftfd = 1; break;
135			case NFROM:	s = "<";  dftfd = 0; break;
136			case NFROMFD:	s = "<&"; dftfd = 0; break;
137		}
138		if (np->nfile.fd != dftfd)
139			fprintf(fp, "%d", np->nfile.fd);
140		fputs(s, fp);
141		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
142			fprintf(fp, "%d", np->ndup.dupfd);
143		} else {
144			sharg(np->nfile.fname, fp);
145		}
146		first = 0;
147	}
148}
149
150
151
152static
153sharg(arg, fp)
154	union node *arg;
155	FILE *fp;
156	{
157	char *p;
158	struct nodelist *bqlist;
159	int subtype;
160
161	if (arg->type != NARG) {
162		printf("<node type %d>\n", arg->type);
163		fflush(stdout);
164		abort();
165	}
166	bqlist = arg->narg.backquote;
167	for (p = arg->narg.text ; *p ; p++) {
168		switch (*p) {
169		case CTLESC:
170			putc(*++p, fp);
171			break;
172		case CTLVAR:
173			putc('$', fp);
174			putc('{', fp);
175			subtype = *++p;
176			while (*p != '=')
177				putc(*p++, fp);
178			if (subtype & VSNUL)
179				putc(':', fp);
180			switch (subtype & VSTYPE) {
181			case VSNORMAL:
182				putc('}', fp);
183				break;
184			case VSMINUS:
185				putc('-', fp);
186				break;
187			case VSPLUS:
188				putc('+', fp);
189				break;
190			case VSQUESTION:
191				putc('?', fp);
192				break;
193			case VSASSIGN:
194				putc('=', fp);
195				break;
196			default:
197				printf("<subtype %d>", subtype);
198			}
199			break;
200		case CTLENDVAR:
201		     putc('}', fp);
202		     break;
203		case CTLBACKQ:
204		case CTLBACKQ|CTLQUOTE:
205			putc('$', fp);
206			putc('(', fp);
207			shtree(bqlist->n, -1, NULL, fp);
208			putc(')', fp);
209			break;
210		default:
211			putc(*p, fp);
212			break;
213		}
214	}
215}
216
217
218static
219indent(amount, pfx, fp)
220	char *pfx;
221	FILE *fp;
222	{
223	int i;
224
225	for (i = 0 ; i < amount ; i++) {
226		if (pfx && i == amount - 1)
227			fputs(pfx, fp);
228		putc('\t', fp);
229	}
230}
231#endif
232
233
234
235/*
236 * Debugging stuff.
237 */
238
239
240FILE *tracefile;
241
242#if DEBUG == 2
243int debug = 1;
244#else
245int debug = 0;
246#endif
247
248
249trputc(c) {
250#ifdef DEBUG
251	if (tracefile == NULL)
252		return;
253	putc(c, tracefile);
254	if (c == '\n')
255		fflush(tracefile);
256#endif
257}
258
259
260trace(fmt, a1, a2, a3, a4, a5, a6, a7, a8)
261	char *fmt;
262	{
263#ifdef DEBUG
264	if (tracefile == NULL)
265		return;
266	fprintf(tracefile, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
267	if (strchr(fmt, '\n'))
268		fflush(tracefile);
269#endif
270}
271
272
273trputs(s)
274	char *s;
275	{
276#ifdef DEBUG
277	if (tracefile == NULL)
278		return;
279	fputs(s, tracefile);
280	if (strchr(s, '\n'))
281		fflush(tracefile);
282#endif
283}
284
285
286trstring(s)
287	char *s;
288	{
289	register char *p;
290	char c;
291
292#ifdef DEBUG
293	if (tracefile == NULL)
294		return;
295	putc('"', tracefile);
296	for (p = s ; *p ; p++) {
297		switch (*p) {
298		case '\n':  c = 'n';  goto backslash;
299		case '\t':  c = 't';  goto backslash;
300		case '\r':  c = 'r';  goto backslash;
301		case '"':  c = '"';  goto backslash;
302		case '\\':  c = '\\';  goto backslash;
303		case CTLESC:  c = 'e';  goto backslash;
304		case CTLVAR:  c = 'v';  goto backslash;
305		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
306		case CTLBACKQ:  c = 'q';  goto backslash;
307		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
308backslash:	  putc('\\', tracefile);
309			putc(c, tracefile);
310			break;
311		default:
312			if (*p >= ' ' && *p <= '~')
313				putc(*p, tracefile);
314			else {
315				putc('\\', tracefile);
316				putc(*p >> 6 & 03, tracefile);
317				putc(*p >> 3 & 07, tracefile);
318				putc(*p & 07, tracefile);
319			}
320			break;
321		}
322	}
323	putc('"', tracefile);
324#endif
325}
326
327
328trargs(ap)
329	char **ap;
330	{
331#ifdef DEBUG
332	if (tracefile == NULL)
333		return;
334	while (*ap) {
335		trstring(*ap++);
336		if (*ap)
337			putc(' ', tracefile);
338		else
339			putc('\n', tracefile);
340	}
341	fflush(tracefile);
342#endif
343}
344
345
346opentrace() {
347	char s[100];
348	char *p;
349	char *getenv();
350	int flags;
351
352#ifdef DEBUG
353	if (!debug)
354		return;
355#ifdef not_this_way
356	if ((p = getenv("HOME")) == NULL) {
357		if (geteuid() == 0)
358			p = "/";
359		else
360			p = "/tmp";
361	}
362	scopy(p, s);
363	strcat(s, "/trace");
364#else
365	scopy("./trace", s);
366#endif /* not_this_way */
367	if ((tracefile = fopen(s, "a")) == NULL) {
368		fprintf(stderr, "Can't open %s\n", s);
369		return;
370	}
371#ifdef O_APPEND
372	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
373		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
374#endif
375	fputs("\nTracing started.\n", tracefile);
376	fflush(tracefile);
377#endif /* DEBUG */
378}
379