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