xref: /freebsd/bin/sh/show.c (revision 417ed37975261df51f61d13e179ad04d8f4839c7)
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
40 static 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
51 static shtree(), shcmd(), sharg(), indent();
52 
53 
54 showtree(n)
55 	union node *n;
56 	{
57 	trputs("showtree called\n");
58 	shtree(n, 1, NULL, stdout);
59 }
60 
61 
62 static
63 shtree(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 = " || ";
81 binop:
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 
113 static
114 shcmd(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 
154 static
155 sharg(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 
220 static
221 indent(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 
242 FILE *tracefile;
243 
244 #if DEBUG == 2
245 int debug = 1;
246 #else
247 int debug = 0;
248 #endif
249 
250 
251 trputc(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 
262 trace(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 
275 trputs(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 
288 trstring(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;
310 backslash:	  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 
330 trargs(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 
348 opentrace() {
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