- Timestamp:
- Sep 13, 2020, 1:17:09 PM (5 years ago)
- Location:
- trunk/src/kash
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kash/eval.c
r3440 r3449 41 41 #endif 42 42 43 #include <assert.h> 44 #include <stddef.h> 43 45 #include <stdlib.h> 44 46 #include <stdio.h> … … 103 105 STATIC void evalcase(shinstance *, union node *, int); 104 106 STATIC void evalsubshell(shinstance *, union node *, int); 105 STATIC void expredir(shinstance *, union node *); 106 STATIC void expredircleanup(shinstance *, union node *); 107 STATIC unsigned expredir(shinstance *, union node *); 107 108 STATIC void evalpipe(shinstance *, union node *); 108 109 STATIC void evalcommand(shinstance *, union node *, int, struct backcmd *); … … 247 248 evaltree(psh, n->nbinary.ch2, flags); 248 249 break; 249 case NREDIR: 250 expredir(psh, n->nredir.redirect);250 case NREDIR: { 251 unsigned const oldfnames = expredir(psh, n->nredir.redirect); 251 252 redirect(psh, n->nredir.redirect, REDIR_PUSH); 252 253 evaltree(psh, n->nredir.n, flags); 253 254 popredir(psh); 254 expredircleanup(psh, n->nredir.redirect);255 expredircleanup(psh, oldfnames); 255 256 break; 257 } 256 258 case NSUBSHELL: 257 259 evalsubshell(psh, n, flags); … … 450 452 struct job *jp; 451 453 int backgnd = (n->type == NBACKGND); 452 453 expredir(psh, n->nredir.redirect); 454 unsigned expfnamedepth; 455 456 expfnamedepth = expredir(psh, n->nredir.redirect); 454 457 INTOFF; 455 458 jp = makejob(psh, n, 1); … … 474 477 if (! backgnd) 475 478 psh->exitstatus = waitforjob(psh, jp); 479 expredircleanup(psh, expfnamedepth); 476 480 INTON; 477 expredircleanup(psh, n->nredir.redirect);478 481 } 479 482 … … 484 487 */ 485 488 486 STATIC void489 STATIC unsigned 487 490 expredir(shinstance *psh, union node *n) 488 491 { 489 492 union node *redir; 490 491 for (redir = n ; redir ; redir = redir->nfile.next) { 493 redirexpfnames *expfnames; 494 unsigned i; 495 496 /* We typically end up here w/o redirections. */ 497 if (!n) 498 return !(expfnames = psh->expfnames) ? 0 : expfnames->depth + 1; 499 500 /* Prepare a table for the expanded names. */ 501 i = 0; 502 for (redir = n; redir ; redir = redir->nfile.next) 503 i++; 504 expfnames = stalloc(psh, offsetof(redirexpfnames, names) + sizeof(expfnames->names[0]) * i); 505 expfnames->count = i; 506 TRACE2((psh, "expredir: %p: count=%u\n", expfnames, i)); 507 508 /* Do the expansion. */ 509 for (redir = n, i = 0 ; redir ; redir = redir->nfile.next, i++) { 492 510 struct arglist fn; 493 511 fn.lastp = &fn.list; … … 499 517 case NAPPEND: 500 518 expandarg(psh, redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 501 redir->nfile.expfname= fn.list->text;519 expfnames->names[i] = fn.list->text; 502 520 break; 503 521 case NFROMFD: … … 507 525 fixredir(psh, redir, fn.list->text, 1); 508 526 } 527 expfnames->names[i] = NULL; 509 528 break; 510 } 511 } 529 default: 530 assert(0); 531 expfnames->names[i] = NULL; 532 break; 533 } 534 } 535 assert(i == expfnames->count); 536 537 /* Do the linking at the end, as nesting happens when we expand backtick arguments. */ 538 expfnames->prev = psh->expfnames; 539 psh->expfnames = expfnames; 540 return expfnames->depth = psh->expfnames ? psh->expfnames->depth + 1 : 1; 512 541 } 513 542 514 543 STATIC void 515 expredircleanup(shinstance *psh, union node *n) 516 { 517 for (; n ; n = n->nfile.next) { 518 struct arglist fn; 519 fn.lastp = &fn.list; 520 switch (n->type) { 521 case NFROMTO: 522 case NFROM: 523 case NTO: 524 case NCLOBBER: 525 case NAPPEND: 526 n->nfile.expfname = NULL; 527 break; 528 } 529 } 544 expredircleanup(shinstance *psh, unsigned depth) 545 { 546 redirexpfnames *expfnames = psh->expfnames; 547 assert(expfnames == NULL ? depth == 0 : expfnames->depth == depth || expfnames->depth + 1 == depth); 548 while (expfnames && expfnames->depth >= depth) 549 expfnames = psh->expfnames = expfnames->prev; 530 550 } 531 551 … … 1111 1131 struct strlist *sp; 1112 1132 const char *path = pathval(psh); 1133 unsigned expfnamedepth; 1113 1134 1114 1135 /* First expand the arguments. */ … … 1134 1155 *arglist.lastp = NULL; 1135 1156 1136 exp redir(psh, cmd->ncmd.redirect);1157 expfnamedepth = expredir(psh, cmd->ncmd.redirect); 1137 1158 1138 1159 /* Now do the initial 'name=value' ones we skipped above */ … … 1254 1275 &args, sizeof(args), evalcommand_setup_child); 1255 1276 evalcommand_parent(psh, flags, args.lastarg, &args.smark, mode, jp, 1256 1277 args.pip, backcmd); 1257 1278 #else 1258 1279 if (forkshell(psh, jp, cmd, mode) != 0) { 1259 1280 evalcommand_parent(psh, flags, args.lastarg, &args.smark, mode, jp, 1260 1281 args.pip, backcmd); 1261 expredircleanup(psh, cmd->ncmd.redirect);1282 expredircleanup(psh, expfnamedepth); 1262 1283 return; /* at end of routine */ 1263 1284 } … … 1270 1291 evalcommand_doit(psh, cmd, &args); 1271 1292 } 1272 expredircleanup(psh, cmd->ncmd.redirect);1293 expredircleanup(psh, expfnamedepth); 1273 1294 } 1274 1295 -
trunk/src/kash/generated/nodes.c
r3443 r3449 276 276 new->nfile.fd = n->nfile.fd; 277 277 new->nfile.next = copynode(n->nfile.next); 278 new->nfile.expfname = NULL;279 278 break; 280 279 case NTOFD: -
trunk/src/kash/generated/nodes.h
r3437 r3449 105 105 union node *next; 106 106 union node *fname; 107 char *expfname;108 107 }; 109 108 -
trunk/src/kash/mknodes.sh
r3443 r3449 200 200 string ) fn="nodesavestr(";; 201 201 int ) fn=;; 202 temp ) echo " new->$f = 0;";;202 temp ) echo "unexpected 'temp' node type" >&2; exit 2;; 203 203 * ) continue;; 204 204 esac -
trunk/src/kash/nodetypes
r3437 r3449 45 45 # int - an integer 46 46 # other - any type that can be copied by assignment 47 # temp - a field that doesn't have to be copied when the node is copied48 47 # The last two types should be followed by the text of a C declaration for 49 48 # the field. … … 121 120 next nodeptr # next redirection in list (must match ndup) 122 121 fname nodeptr # file name, in a NARG node 123 expfname temp char *expfname # actual file name124 122 125 123 NTOFD ndup # fd<&dupfd -
trunk/src/kash/parser.c
r3440 r3449 1199 1199 union node *np; 1200 1200 char fd = *out; 1201 char dummy[ sizeof(struct n file) >= sizeof(struct ndup)1202 && sizeof(struct n file) >= sizeof(struct nhere) ? 1 : 0];1201 char dummy[ sizeof(struct ndup) >= sizeof(struct nfile) 1202 && sizeof(struct ndup) >= sizeof(struct nhere) ? 1 : 0]; 1203 1203 (void)dummy; 1204 1204 1205 np = (union node *)stalloc(psh, sizeof (struct nfile)); 1206 np->nfile.expfname = NULL; 1205 np = (union node *)stalloc(psh, sizeof (struct ndup)); 1207 1206 if (c == '>') { 1208 1207 np->nfile.fd = 1; … … 1899 1898 ret->nfile.next = copyparsetree(psh, src->nfile.next); 1900 1899 ret->nfile.fname = copyparsetree(psh, src->nfile.fname); 1901 /** @todo complicated, we should copy it in some contexts but no all. sigh. */1902 ret->nfile.expfname = stsavestr(psh, src->nfile.expfname);1903 1900 break; 1904 1901 -
trunk/src/kash/redir.c
r3445 r3449 43 43 #include <sys/types.h> 44 44 #include <limits.h> /* PIPE_BUF */ 45 #include <assert.h> 45 46 #include <string.h> 46 47 #include <errno.h> 48 #include <stddef.h> 47 49 #include <stdlib.h> 48 50 … … 88 90 //int fd0_redirected = 0; 89 91 90 STATIC void openredirect(shinstance *, union node *, char[10], int );92 STATIC void openredirect(shinstance *, union node *, char[10], int, const char *); 91 93 STATIC int openhere(shinstance *, union node *); 92 94 … … 114 116 psh->fd0_redirected = inherit->fd0_redirected; 115 117 } 118 119 /* Copy the expanded redirection filenames (stack), but only the last entry 120 as the subshell does not have the ability to unwind stack in the parent 121 and therefore cannot get to the earlier redirection stuff: */ 122 if (inherit->expfnames) 123 { 124 redirexpfnames * const expfnamesrc = inherit->expfnames; 125 unsigned i = expfnamesrc->count; 126 redirexpfnames *dst = stalloc(psh, offsetof(redirexpfnames, names) + sizeof(dst->names[0]) * i); 127 dst->count = i; 128 dst->depth = 1; 129 dst->prev = NULL; 130 while (i-- > 0) 131 dst->names[i] = stsavestr(psh, expfnamesrc->names[i]); 132 psh->expfnames = dst; 133 } 116 134 } 117 135 #endif /* !SH_FORKED_MODE */ … … 135 153 int try; 136 154 char memory[10]; /* file descriptors to write to memory */ 155 unsigned idxexpfname; 137 156 138 157 for (i = 10 ; --i >= 0 ; ) … … 146 165 psh->redirlist = sv; 147 166 } 148 for (n = redir ; n ; n = n->nfile.next) { 167 idxexpfname = 0; 168 for (n = redir, idxexpfname = 0 ; n ; n = n->nfile.next, idxexpfname++) { 169 assert(idxexpfname < psh->expfnames->count); 149 170 fd = n->nfile.fd; 150 171 try = 0; … … 160 181 case EBADF: 161 182 if (!try) { 162 openredirect(psh, n, memory, flags );183 openredirect(psh, n, memory, flags, psh->expfnames->names[idxexpfname]); 163 184 try++; 164 185 goto again; … … 182 203 psh->fd0_redirected++; 183 204 if (!try) 184 openredirect(psh, n, memory, flags); 185 } 205 openredirect(psh, n, memory, flags, psh->expfnames->names[idxexpfname]); 206 } 207 assert(!redir || idxexpfname == psh->expfnames->count); 186 208 if (memory[1]) 187 209 psh->out1 = &psh->memout; … … 192 214 193 215 STATIC void 194 openredirect(shinstance *psh, union node *redir, char memory[10], int flags )216 openredirect(shinstance *psh, union node *redir, char memory[10], int flags, const char *fname) 195 217 { 196 218 int fd = redir->nfile.fd; 197 char *fname;198 219 int f; 199 220 int oflags = O_WRONLY|O_CREAT|O_TRUNC; … … 208 229 switch (redir->nfile.type) { 209 230 case NFROM: 210 fname = redir->nfile.expfname;211 231 if ((f = shfile_open(&psh->fdtab, fname, O_RDONLY, 0)) < 0) 212 232 goto eopen; 213 233 break; 214 234 case NFROMTO: 215 fname = redir->nfile.expfname;216 235 if ((f = shfile_open(&psh->fdtab, fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) 217 236 goto ecreate; … … 222 241 /* FALLTHROUGH */ 223 242 case NCLOBBER: 224 fname = redir->nfile.expfname;225 243 if ((f = shfile_open(&psh->fdtab, fname, oflags, 0666)) < 0) 226 244 goto ecreate; 227 245 break; 228 246 case NAPPEND: 229 fname = redir->nfile.expfname;230 247 if ((f = shfile_open(&psh->fdtab, fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) 231 248 goto ecreate; -
trunk/src/kash/redir.h
r3442 r3449 46 46 void popredir(struct shinstance *); 47 47 int fd0_redirected_p(struct shinstance *); 48 struct redirexpfnames; 49 void expredircleanup(shinstance *, unsigned); 48 50 void clearredir(struct shinstance *); 49 51 int copyfd(struct shinstance *, int, int); -
trunk/src/kash/shinstance.c
r3447 r3449 437 437 struct redirtab *redirlist; 438 438 int fd0_redirected/* = 0*/; 439 439 #endif 440 psh->expfnames = NULL; /* stack alloc */ 441 442 #if 0 440 443 /* show.c */ 441 444 char tracebuf[1024]; -
trunk/src/kash/shinstance.h
r3447 r3449 131 131 int inquotes; /* search for nul bytes only */ 132 132 }; 133 134 /* redir.c / bird */ 135 /** 136 * This is a replacement for temporary node field nfile.expfname. 137 * Uses stack allocator, created by expredir(), duplicated by 138 * subshellinitredir() and popped (but not freed) by expredircleanup(). 139 */ 140 typedef struct redirexpfnames 141 { 142 struct redirexpfnames *prev; /**< Previous record. */ 143 unsigned depth; /**< Nesting depth. */ 144 unsigned count; /**< Number of expanded filenames in the array. */ 145 char *names[1]; /**< Variable size. */ 146 } redirexpfnames; 133 147 134 148 … … 311 325 struct redirtab *redirlist; 312 326 int fd0_redirected/* = 0*/; 327 redirexpfnames *expfnames; /**< Expanded filenames for current redirection setup. */ 313 328 314 329 /* show.c */
Note:
See TracChangeset
for help on using the changeset viewer.