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