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