]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/dash/contrib/src/show.c
Update
[l4.git] / l4 / pkg / dash / contrib / src / show.c
1 /*-
2  * Copyright (c) 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1997-2005
5  *      Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Kenneth Almquist.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <stdio.h>
36 #include <stdarg.h>
37
38 #include "shell.h"
39 #include "parser.h"
40 #include "nodes.h"
41 #include "mystring.h"
42 #include "show.h"
43 #include "options.h"
44
45
46 #ifdef DEBUG
47 static void shtree(union node *, int, char *, FILE*);
48 static void shcmd(union node *, FILE *);
49 static void sharg(union node *, FILE *);
50 static void indent(int, char *, FILE *);
51 static void trstring(char *);
52
53
54 void
55 showtree(union node *n)
56 {
57         trputs("showtree called\n");
58         shtree(n, 1, NULL, stdout);
59 }
60
61
62 static void
63 shtree(union node *n, int ind, char *pfx, FILE *fp)
64 {
65         struct nodelist *lp;
66         const char *s;
67
68         if (n == NULL)
69                 return;
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 void
114 shcmd(union node *cmd, FILE *fp)
115 {
116         union node *np;
117         int first;
118         const char *s;
119         int dftfd;
120
121         first = 1;
122         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
123                 if (! first)
124                         putchar(' ');
125                 sharg(np, fp);
126                 first = 0;
127         }
128         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
129                 if (! first)
130                         putchar(' ');
131                 switch (np->nfile.type) {
132                         case NTO:       s = ">";  dftfd = 1; break;
133                         case NCLOBBER:  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                         case NFROMTO:   s = "<>"; dftfd = 0; break;
139                         default:        s = "*error*"; dftfd = 0; break;
140                 }
141                 if (np->nfile.fd != dftfd)
142                         fprintf(fp, "%d", np->nfile.fd);
143                 fputs(s, fp);
144                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
145                         fprintf(fp, "%d", np->ndup.dupfd);
146                 } else {
147                         sharg(np->nfile.fname, fp);
148                 }
149                 first = 0;
150         }
151 }
152
153
154
155 static void
156 sharg(union node *arg, 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                 abort();
165         }
166         bqlist = arg->narg.backquote;
167         for (p = arg->narg.text ; *p ; p++) {
168                 switch ((signed char)*p) {
169                 case CTLESC:
170                         putc(*++p, fp);
171                         break;
172                 case CTLVAR:
173                         putc('$', fp);
174                         putc('{', fp);
175                         subtype = *++p;
176                         if (subtype == VSLENGTH)
177                                 putc('#', fp);
178
179                         while (*p != '=')
180                                 putc(*p++, fp);
181
182                         if (subtype & VSNUL)
183                                 putc(':', fp);
184
185                         switch (subtype & VSTYPE) {
186                         case VSNORMAL:
187                                 putc('}', fp);
188                                 break;
189                         case VSMINUS:
190                                 putc('-', fp);
191                                 break;
192                         case VSPLUS:
193                                 putc('+', fp);
194                                 break;
195                         case VSQUESTION:
196                                 putc('?', fp);
197                                 break;
198                         case VSASSIGN:
199                                 putc('=', fp);
200                                 break;
201                         case VSTRIMLEFT:
202                                 putc('#', fp);
203                                 break;
204                         case VSTRIMLEFTMAX:
205                                 putc('#', fp);
206                                 putc('#', fp);
207                                 break;
208                         case VSTRIMRIGHT:
209                                 putc('%', fp);
210                                 break;
211                         case VSTRIMRIGHTMAX:
212                                 putc('%', fp);
213                                 putc('%', fp);
214                                 break;
215                         case VSLENGTH:
216                                 break;
217                         default:
218                                 printf("<subtype %d>", subtype);
219                         }
220                         break;
221                 case CTLENDVAR:
222                      putc('}', fp);
223                      break;
224                 case CTLBACKQ:
225                         putc('$', fp);
226                         putc('(', fp);
227                         shtree(bqlist->n, -1, NULL, fp);
228                         putc(')', fp);
229                         break;
230                 default:
231                         putc(*p, fp);
232                         break;
233                 }
234         }
235 }
236
237
238 static void
239 indent(int amount, char *pfx, FILE *fp)
240 {
241         int i;
242
243         for (i = 0 ; i < amount ; i++) {
244                 if (pfx && i == amount - 1)
245                         fputs(pfx, fp);
246                 putc('\t', fp);
247         }
248 }
249
250
251
252 /*
253  * Debugging stuff.
254  */
255
256
257 FILE *tracefile;
258
259
260 void
261 trputc(int c)
262 {
263         if (debug != 1)
264                 return;
265         putc(c, tracefile);
266 }
267
268 void
269 trace(const char *fmt, ...)
270 {
271         va_list va;
272
273         if (debug != 1)
274                 return;
275         va_start(va, fmt);
276         (void) vfprintf(tracefile, fmt, va);
277         va_end(va);
278 }
279
280 void
281 tracev(const char *fmt, va_list va)
282 {
283         if (debug != 1)
284                 return;
285         (void) vfprintf(tracefile, fmt, va);
286 }
287
288
289 void
290 trputs(const char *s)
291 {
292         if (debug != 1)
293                 return;
294         fputs(s, tracefile);
295 }
296
297
298 static void
299 trstring(char *s)
300 {
301         char *p;
302         char c;
303
304         if (debug != 1)
305                 return;
306         putc('"', tracefile);
307         for (p = s ; *p ; p++) {
308                 switch ((signed char)*p) {
309                 case '\n':  c = 'n';  goto backslash;
310                 case '\t':  c = 't';  goto backslash;
311                 case '\r':  c = 'r';  goto backslash;
312                 case '"':  c = '"';  goto backslash;
313                 case '\\':  c = '\\';  goto backslash;
314                 case CTLESC:  c = 'e';  goto backslash;
315                 case CTLVAR:  c = 'v';  goto backslash;
316                 case CTLBACKQ:  c = 'q';  goto backslash;
317 backslash:        putc('\\', tracefile);
318                         putc(c, tracefile);
319                         break;
320                 default:
321                         if (*p >= ' ' && *p <= '~')
322                                 putc(*p, tracefile);
323                         else {
324                                 putc('\\', tracefile);
325                                 putc(*p >> 6 & 03, tracefile);
326                                 putc(*p >> 3 & 07, tracefile);
327                                 putc(*p & 07, tracefile);
328                         }
329                         break;
330                 }
331         }
332         putc('"', tracefile);
333 }
334
335
336 void
337 trargs(char **ap)
338 {
339         if (debug != 1)
340                 return;
341         while (*ap) {
342                 trstring(*ap++);
343                 if (*ap)
344                         putc(' ', tracefile);
345                 else
346                         putc('\n', tracefile);
347         }
348 }
349
350
351 void
352 opentrace(void)
353 {
354         char s[100];
355 #ifdef O_APPEND
356         int flags;
357 #endif
358
359         if (debug != 1) {
360                 if (tracefile)
361                         fflush(tracefile);
362                 /* leave open because libedit might be using it */
363                 return;
364         }
365 #ifdef not_this_way
366         {
367                 char *p;
368                 if ((p = getenv(homestr)) == NULL) {
369                         if (geteuid() == 0)
370                                 p = "/";
371                         else
372                                 p = "/tmp";
373                 }
374                 scopy(p, s);
375                 strcat(s, "/trace");
376         }
377 #else
378         scopy("./trace", s);
379 #endif /* not_this_way */
380         if (tracefile) {
381 #ifndef __KLIBC__
382                 if (!freopen(s, "a", tracefile)) {
383 #else
384                 if (!(!fclose(tracefile) && (tracefile = fopen(s, "a")))) {
385 #endif /* __KLIBC__ */
386                         fprintf(stderr, "Can't re-open %s\n", s);
387                         debug = 0;
388                         return;
389                 }
390         } else {
391                 if ((tracefile = fopen(s, "a")) == NULL) {
392                         fprintf(stderr, "Can't open %s\n", s);
393                         debug = 0;
394                         return;
395                 }
396         }
397 #ifdef O_APPEND
398         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
399                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
400 #endif
401 #ifndef __KLIBC__
402         setlinebuf(tracefile);
403 #endif /* __KLIBC__ */
404         fputs("\nTracing started.\n", tracefile);
405 }
406 #endif /* DEBUG */