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