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