VirtualBox

source: kBuild/trunk/src/kash/show.c@ 3569

最後變更 在這個檔案從3569是 3477,由 bird 提交於 4 年 前

kash: Use kHlpAssert instead of assert.h (debugger stops on the assertion rather than at exit process code).

  • 屬性 svn:eol-style 設為 LF
  • 屬性 svn:keywords 設為 Id
檔案大小: 11.1 KB
 
1/* $NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $ */
2
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#if 0
36#ifndef lint
37static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
38#else
39__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
40#endif /* not lint */
41#endif
42
43#include <stdio.h>
44#include <stdarg.h>
45#include <stdlib.h>
46
47#include "shell.h"
48#include "parser.h"
49#include "nodes.h"
50#include "mystring.h"
51#include "show.h"
52#include "options.h"
53#include "shinstance.h"
54
55
56#ifdef DEBUG
57static void shtree(union node *, int, char *, FILE*);
58static void shcmd(union node *, FILE *);
59static void sharg(union node *, FILE *);
60static void indent(int, char *, FILE *);
61static void trstring(shinstance *, char *);
62
63
64void
65showtree(shinstance *psh, union node *n)
66{
67 trputs(psh, "showtree called\n");
68 shtree(n, 1, NULL, stdout);
69}
70
71
72static void
73shtree(union node *n, int ind, char *pfx, FILE *fp)
74{
75 struct nodelist *lp;
76 const char *s;
77
78 if (n == NULL)
79 return;
80
81 indent(ind, pfx, fp);
82 switch(n->type) {
83 case NSEMI:
84 s = "; ";
85 goto binop;
86 case NAND:
87 s = " && ";
88 goto binop;
89 case NOR:
90 s = " || ";
91binop:
92 shtree(n->nbinary.ch1, ind, NULL, fp);
93 /* if (ind < 0) */
94 fputs(s, fp);
95 shtree(n->nbinary.ch2, ind, NULL, fp);
96 break;
97 case NCMD:
98 shcmd(n, fp);
99 if (ind >= 0)
100 putc('\n', fp);
101 break;
102 case NPIPE:
103 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
104 shcmd(lp->n, fp);
105 if (lp->next)
106 fputs(" | ", fp);
107 }
108 if (n->npipe.backgnd)
109 fputs(" &", fp);
110 if (ind >= 0)
111 putc('\n', fp);
112 break;
113 default:
114 fprintf(fp, "<node type %d>", n->type);
115 if (ind >= 0)
116 putc('\n', fp);
117 break;
118 }
119}
120
121
122
123static void
124shcmd(union node *cmd, FILE *fp)
125{
126 union node *np;
127 int first;
128 const char *s;
129 int dftfd;
130
131 first = 1;
132 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
133 if (! first)
134 putchar(' ');
135 sharg(np, fp);
136 first = 0;
137 }
138 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
139 if (! first)
140 putchar(' ');
141 switch (np->nfile.type) {
142 case NTO: s = ">"; dftfd = 1; break;
143 case NCLOBBER: s = ">|"; dftfd = 1; break;
144 case NAPPEND: s = ">>"; dftfd = 1; break;
145 case NTOFD: s = ">&"; dftfd = 1; break;
146 case NFROM: s = "<"; dftfd = 0; break;
147 case NFROMFD: s = "<&"; dftfd = 0; break;
148 case NFROMTO: 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 fprintf(fp, "%d", np->ndup.dupfd);
156 } else {
157 sharg(np->nfile.fname, fp);
158 }
159 first = 0;
160 }
161}
162
163
164
165static void
166sharg(union node *arg, FILE *fp)
167{
168 char *p;
169 struct nodelist *bqlist;
170 int subtype;
171
172 if (arg->type != NARG) {
173 printf("<node type %d>\n", arg->type);
174 abort();
175 }
176 bqlist = arg->narg.backquote;
177 for (p = arg->narg.text ; *p ; p++) {
178 switch (*p) {
179 case CTLESC:
180 putc(*++p, fp);
181 break;
182 case CTLVAR:
183 putc('$', fp);
184 putc('{', fp);
185 subtype = *++p;
186 if (subtype == VSLENGTH)
187 putc('#', fp);
188
189 while (*p != '=')
190 putc(*p++, fp);
191
192 if (subtype & VSNUL)
193 putc(':', fp);
194
195 switch (subtype & VSTYPE) {
196 case VSNORMAL:
197 putc('}', fp);
198 break;
199 case VSMINUS:
200 putc('-', fp);
201 break;
202 case VSPLUS:
203 putc('+', fp);
204 break;
205 case VSQUESTION:
206 putc('?', fp);
207 break;
208 case VSASSIGN:
209 putc('=', fp);
210 break;
211 case VSTRIMLEFT:
212 putc('#', fp);
213 break;
214 case VSTRIMLEFTMAX:
215 putc('#', fp);
216 putc('#', fp);
217 break;
218 case VSTRIMRIGHT:
219 putc('%', fp);
220 break;
221 case VSTRIMRIGHTMAX:
222 putc('%', fp);
223 putc('%', fp);
224 break;
225 case VSLENGTH:
226 break;
227 default:
228 printf("<subtype %d>", subtype);
229 }
230 break;
231 case CTLENDVAR:
232 putc('}', fp);
233 break;
234 case CTLBACKQ:
235 case CTLBACKQ|CTLQUOTE:
236 putc('$', fp);
237 putc('(', fp);
238 shtree(bqlist->n, -1, NULL, fp);
239 putc(')', fp);
240 break;
241 default:
242 putc(*p, fp);
243 break;
244 }
245 }
246}
247
248
249static void
250indent(int amount, char *pfx, FILE *fp)
251{
252 int i;
253
254 for (i = 0 ; i < amount ; i++) {
255 if (pfx && i == amount - 1)
256 fputs(pfx, fp);
257 putc('\t', fp);
258 }
259}
260#endif
261
262
263
264#ifdef DEBUG
265/*
266 * Debugging stuff.
267 */
268
269/** @def TRY_GET_PSH_OR_RETURN
270 * Make sure @a psh is valid, trying to fetch it from TLS
271 * if it's NULL and returning (void) if that fails. */
272# define TRY_GET_PSH_OR_RETURN(psh) \
273 if (!(psh)) { \
274 (psh) = shthread_get_shell(); \
275 if (!(psh)) \
276 return; \
277 } else do { } while (0)
278
279/** @def RETURN_IF_NOT_TRACING
280 * Return if we're not tracing. */
281# define RETURN_IF_NOT_TRACING(psh) \
282 if (debug(psh) != 1 || psh->tracefd == -1) \
283 return; \
284 else do {} while (0)
285
286/* Flushes the tracebuf. */
287static void
288trace_flush(shinstance *psh)
289{
290 size_t pos = psh->tracepos;
291
292 if (pos > sizeof(psh->tracebuf)) {
293 char *end;
294 kHlpAssert(0);
295 end = memchr(psh->tracebuf, '\0', sizeof(psh->tracebuf));
296 pos = end ? end - &psh->tracebuf[0] : 0;
297 }
298
299 if (pos) {
300 int s = errno;
301 char prefix[40];
302 size_t len;
303
304#ifdef SH_FORKED_MODE
305 len = sprintf(prefix, "[%" SHPID_PRI "] ", sh_getpid(psh));
306#else
307 shpid pid = sh_getpid(psh);
308 len = sprintf(prefix, "[%d/%d] ", SHPID_GET_PID(pid), SHPID_GET_TID(pid));
309#endif
310 shfile_write(&psh->fdtab, psh->tracefd, prefix, len);
311 shfile_write(&psh->fdtab, psh->tracefd, psh->tracebuf, pos);
312
313 psh->tracepos = 0;
314 psh->tracebuf[0] = '\0';
315
316 errno = s;
317 }
318}
319
320/* Adds a char to the trace buffer. */
321static void
322trace_char(shinstance *psh, int c)
323{
324 size_t pos = psh->tracepos;
325 if (pos >= sizeof(psh->tracebuf) - 1) {
326 trace_flush(psh);
327 pos = psh->tracepos;
328 }
329 psh->tracebuf[pos] = c;
330 psh->tracepos = pos + 1;
331 if (c == '\n')
332 trace_flush(psh);
333 else
334 psh->tracebuf[pos + 1] = '\0';
335}
336
337/* Add a string to the trace buffer. */
338static void
339trace_string(shinstance *psh, const char *str)
340{
341 /* push it out line by line. */
342 while (*str) {
343 /* find line/string length. */
344 size_t pos;
345 size_t len;
346 const char *end = str;
347 int flush_it = 0;
348 while (*end) {
349 if (*end++ == '\n') {
350 flush_it = 1;
351 break;
352 }
353 }
354 len = end - str;
355
356 /* copy to the buffer */
357 pos = psh->tracepos;
358 if (pos + len <= sizeof(psh->tracebuf)) {
359 memcpy(&psh->tracebuf[pos], str, len);
360 psh->tracepos = pos + len;
361 if (flush_it)
362 trace_flush(psh);
363 } else {
364 /* it's too big for some reason... */
365 int s = errno;
366 trace_flush(psh);
367 shfile_write(&psh->fdtab, psh->tracefd, str, len);
368 if (!flush_it)
369 shfile_write(&psh->fdtab, psh->tracefd, "[too long]\n", sizeof( "[too long]\n") - 1);
370 errno = s;
371 }
372
373 /* advance */
374 str = end;
375 }
376}
377
378void
379trputc(shinstance *psh, int c)
380{
381 TRY_GET_PSH_OR_RETURN(psh);
382 RETURN_IF_NOT_TRACING(psh);
383
384 trace_char(psh, c);
385}
386
387void
388trace(shinstance *psh, const char *fmt, ...)
389{
390 va_list va;
391 char buf[2048];
392
393 TRY_GET_PSH_OR_RETURN(psh);
394 RETURN_IF_NOT_TRACING(psh);
395
396 va_start(va, fmt);
397# ifdef _MSC_VER
398 _vsnprintf(buf, sizeof(buf), fmt, va);
399# else
400 vsnprintf(buf, sizeof(buf), fmt, va);
401# endif
402 va_end(va);
403 trace_string(psh, buf);
404}
405
406void
407tracev(shinstance *psh, const char *fmt, va_list va)
408{
409 char buf[2048];
410
411 TRY_GET_PSH_OR_RETURN(psh);
412 RETURN_IF_NOT_TRACING(psh);
413
414# ifdef _MSC_VER
415 _vsnprintf(buf, sizeof(buf), fmt, va);
416# else
417 vsnprintf(buf, sizeof(buf), fmt, va);
418# endif
419 trace_string(psh, buf);
420}
421
422void
423trputs(shinstance *psh, const char *s)
424{
425 TRY_GET_PSH_OR_RETURN(psh);
426 RETURN_IF_NOT_TRACING(psh);
427
428 trace_string(psh, s);
429 trace_char(psh, '\n');
430}
431
432
433static void
434trstring(shinstance *psh, char *s)
435{
436 char *p;
437 char c;
438
439 TRY_GET_PSH_OR_RETURN(psh);
440 RETURN_IF_NOT_TRACING(psh);
441
442 trace_char(psh, '"');
443 for (p = s ; *p ; p++) {
444 switch (*p) {
445 case '\n': c = 'n'; goto backslash;
446 case '\t': c = 't'; goto backslash;
447 case '\r': c = 'r'; goto backslash;
448 case '"': c = '"'; goto backslash;
449 case '\\': c = '\\'; goto backslash;
450 case CTLESC: c = 'e'; goto backslash;
451 case CTLVAR: c = 'v'; goto backslash;
452 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
453 case CTLBACKQ: c = 'q'; goto backslash;
454 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
455backslash: trace_char(psh, '\\');
456 trace_char(psh, c);
457 break;
458 default:
459 if (*p >= ' ' && *p <= '~')
460 trace_char(psh, *p);
461 else {
462 trace_char(psh, '\\');
463 trace_char(psh, *p >> 6 & 03);
464 trace_char(psh, *p >> 3 & 07);
465 trace_char(psh, *p & 07);
466 }
467 break;
468 }
469 }
470 trace_char(psh, '"');
471}
472
473void
474trargs(shinstance *psh, char **ap)
475{
476 TRY_GET_PSH_OR_RETURN(psh);
477 RETURN_IF_NOT_TRACING(psh);
478
479 while (*ap) {
480 trstring(psh, *ap++);
481 if (*ap)
482 trace_char(psh, ' ');
483 else
484 trace_char(psh, '\n');
485 }
486}
487
488void
489opentrace(shinstance *psh)
490{
491 static const char s[] = "./trace";
492
493 TRY_GET_PSH_OR_RETURN(psh);
494 if (debug(psh) != 1) {
495 /* disabled */
496 if (psh->tracefd != -1) {
497 trace_flush(psh);
498 shfile_close(&psh->fdtab, psh->tracefd);
499 psh->tracefd = -1;
500 }
501 return;
502 }
503 /* else: (re-)enabled */
504
505 if (psh->tracefd != -1)
506 return;
507
508 psh->tracefd = shfile_open(&psh->fdtab, s, O_APPEND | O_RDWR | O_CREAT, 0600);
509 if (psh->tracefd != -1) {
510 /* relocate it */
511 int want_fd = 199;
512 while (want_fd > 10)
513 {
514 int fd2 = shfile_fcntl(&psh->fdtab, psh->tracefd, F_DUPFD, want_fd);
515 if (fd2 != -1) {
516 shfile_close(&psh->fdtab, psh->tracefd);
517 psh->tracefd = fd2;
518 break;
519 }
520 want_fd = ((want_fd + 1) / 2) - 1;
521 }
522 shfile_cloexec(&psh->fdtab, psh->tracefd, 1 /* close it */);
523 shfile_set_trace(&psh->fdtab, psh->tracefd);
524 }
525 if (psh->tracefd == -1) {
526 fprintf(stderr, "Can't open %s\n", s);
527 debug(psh) = 0;
528 return;
529 }
530 trace_string(psh, "Tracing started.\n");
531}
532
533#endif /* DEBUG */
534
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette