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