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