show.c revision 127958
1302327Sngie/*- 2302327Sngie * Copyright (c) 1991, 1993 3302327Sngie * The Regents of the University of California. All rights reserved. 4302327Sngie * 5302327Sngie * This code is derived from software contributed to Berkeley by 6302327Sngie * Kenneth Almquist. 7302327Sngie * 8302327Sngie * Redistribution and use in source and binary forms, with or without 9302327Sngie * modification, are permitted provided that the following conditions 10302327Sngie * are met: 11302327Sngie * 1. Redistributions of source code must retain the above copyright 12302327Sngie * notice, this list of conditions and the following disclaimer. 13302327Sngie * 2. Redistributions in binary form must reproduce the above copyright 14302327Sngie * notice, this list of conditions and the following disclaimer in the 15302327Sngie * documentation and/or other materials provided with the distribution. 16302327Sngie * 4. Neither the name of the University nor the names of its contributors 17302327Sngie * may be used to endorse or promote products derived from this software 18302327Sngie * without specific prior written permission. 19302327Sngie * 20302327Sngie * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21302327Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22302327Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23302327Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24302327Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25302327Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26302327Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27302327Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28302327Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#ifndef lint 34#if 0 35static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; 36#endif 37#endif /* not lint */ 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/bin/sh/show.c 127958 2004-04-06 20:06:54Z markm $"); 40 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 55static void shtree(union node *, int, char *, FILE*); 56static void shcmd(union node *, FILE *); 57static void sharg(union node *, FILE *); 58static void indent(int, char *, FILE *); 59static void trstring(char *); 60 61 62void 63showtree(union node *n) 64{ 65 trputs("showtree called\n"); 66 shtree(n, 1, NULL, stdout); 67} 68 69 70static void 71shtree(union node *n, int ind, char *pfx, FILE *fp) 72{ 73 struct nodelist *lp; 74 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 = " || "; 89binop: 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 121static void 122shcmd(union node *cmd, FILE *fp) 123{ 124 union node *np; 125 int first; 126 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 default: s = "*error*"; dftfd = 0; break; 148 } 149 if (np->nfile.fd != dftfd) 150 fprintf(fp, "%d", np->nfile.fd); 151 fputs(s, fp); 152 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { 153 if (np->ndup.dupfd >= 0) 154 fprintf(fp, "%d", np->ndup.dupfd); 155 else 156 fprintf(fp, "-"); 157 } else { 158 sharg(np->nfile.fname, fp); 159 } 160 first = 0; 161 } 162} 163 164 165 166static void 167sharg(union node *arg, FILE *fp) 168{ 169 char *p; 170 struct nodelist *bqlist; 171 int subtype; 172 173 if (arg->type != NARG) { 174 printf("<node type %d>\n", arg->type); 175 fflush(stdout); 176 abort(); 177 } 178 bqlist = arg->narg.backquote; 179 for (p = arg->narg.text ; *p ; p++) { 180 switch (*p) { 181 case CTLESC: 182 putc(*++p, fp); 183 break; 184 case CTLVAR: 185 putc('$', fp); 186 putc('{', fp); 187 subtype = *++p; 188 if (subtype == VSLENGTH) 189 putc('#', fp); 190 191 while (*p != '=') 192 putc(*p++, fp); 193 194 if (subtype & VSNUL) 195 putc(':', fp); 196 197 switch (subtype & VSTYPE) { 198 case VSNORMAL: 199 putc('}', fp); 200 break; 201 case VSMINUS: 202 putc('-', fp); 203 break; 204 case VSPLUS: 205 putc('+', fp); 206 break; 207 case VSQUESTION: 208 putc('?', fp); 209 break; 210 case VSASSIGN: 211 putc('=', fp); 212 break; 213 case VSTRIMLEFT: 214 putc('#', fp); 215 break; 216 case VSTRIMLEFTMAX: 217 putc('#', fp); 218 putc('#', fp); 219 break; 220 case VSTRIMRIGHT: 221 putc('%', fp); 222 break; 223 case VSTRIMRIGHTMAX: 224 putc('%', fp); 225 putc('%', fp); 226 break; 227 case VSLENGTH: 228 break; 229 default: 230 printf("<subtype %d>", subtype); 231 } 232 break; 233 case CTLENDVAR: 234 putc('}', fp); 235 break; 236 case CTLBACKQ: 237 case CTLBACKQ|CTLQUOTE: 238 putc('$', fp); 239 putc('(', fp); 240 shtree(bqlist->n, -1, NULL, fp); 241 putc(')', fp); 242 break; 243 default: 244 putc(*p, fp); 245 break; 246 } 247 } 248} 249 250 251static void 252indent(int amount, char *pfx, FILE *fp) 253{ 254 int i; 255 256 for (i = 0 ; i < amount ; i++) { 257 if (pfx && i == amount - 1) 258 fputs(pfx, fp); 259 putc('\t', fp); 260 } 261} 262 263 264/* 265 * Debugging stuff. 266 */ 267 268 269FILE *tracefile; 270 271#if DEBUG == 2 272int debug = 1; 273#else 274int debug = 0; 275#endif 276 277 278void 279trputc(int c) 280{ 281 if (tracefile == NULL) 282 return; 283 putc(c, tracefile); 284 if (c == '\n') 285 fflush(tracefile); 286} 287 288 289void 290sh_trace(const char *fmt, ...) 291{ 292 va_list va; 293 va_start(va, fmt); 294 if (tracefile != NULL) { 295 (void) vfprintf(tracefile, fmt, va); 296 if (strchr(fmt, '\n')) 297 (void) fflush(tracefile); 298 } 299 va_end(va); 300} 301 302 303void 304trputs(char *s) 305{ 306 if (tracefile == NULL) 307 return; 308 fputs(s, tracefile); 309 if (strchr(s, '\n')) 310 fflush(tracefile); 311} 312 313 314static void 315trstring(char *s) 316{ 317 char *p; 318 char c; 319 320 if (tracefile == NULL) 321 return; 322 putc('"', tracefile); 323 for (p = s ; *p ; p++) { 324 switch (*p) { 325 case '\n': c = 'n'; goto backslash; 326 case '\t': c = 't'; goto backslash; 327 case '\r': c = 'r'; goto backslash; 328 case '"': c = '"'; goto backslash; 329 case '\\': c = '\\'; goto backslash; 330 case CTLESC: c = 'e'; goto backslash; 331 case CTLVAR: c = 'v'; goto backslash; 332 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 333 case CTLBACKQ: c = 'q'; goto backslash; 334 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 335backslash: putc('\\', tracefile); 336 putc(c, tracefile); 337 break; 338 default: 339 if (*p >= ' ' && *p <= '~') 340 putc(*p, tracefile); 341 else { 342 putc('\\', tracefile); 343 putc(*p >> 6 & 03, tracefile); 344 putc(*p >> 3 & 07, tracefile); 345 putc(*p & 07, tracefile); 346 } 347 break; 348 } 349 } 350 putc('"', tracefile); 351} 352 353 354void 355trargs(char **ap) 356{ 357 if (tracefile == NULL) 358 return; 359 while (*ap) { 360 trstring(*ap++); 361 if (*ap) 362 putc(' ', tracefile); 363 else 364 putc('\n', tracefile); 365 } 366 fflush(tracefile); 367} 368 369 370void 371opentrace(void) 372{ 373 char s[100]; 374 char *getenv(); 375 int flags; 376 377 if (!debug) 378 return; 379#ifdef not_this_way 380 { 381 char *p; 382 if ((p = getenv("HOME")) == NULL) { 383 if (geteuid() == 0) 384 p = "/"; 385 else 386 p = "/tmp"; 387 } 388 scopy(p, s); 389 strcat(s, "/trace"); 390 } 391#else 392 scopy("./trace", s); 393#endif /* not_this_way */ 394 if ((tracefile = fopen(s, "a")) == NULL) { 395 fprintf(stderr, "Can't open %s: %s\n", s, strerror(errno)); 396 return; 397 } 398 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) 399 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 400 fputs("\nTracing started.\n", tracefile); 401 fflush(tracefile); 402} 403#endif /* DEBUG */ 404