/* redir.c: code for opening files and piping heredocs after fork but before exec. */ #include "rc.h" #include "lex.h" #include "glom.h" #include "glob.h" #include "open.h" #include "exec.h" #include "utils.h" #include "redir.h" #include "hash.h" /* Walk the redirection queue, and open files and dup2 to them. Also, here-documents are treated here by dumping them down a pipe. (this should make here-documents fast on systems with lots of memory which do pipes right. Under sh, a file is copied to /tmp, and then read out of /tmp again. I'm interested in knowing how much faster, say, shar runs when unpacking when invoked with rc instead of sh. On my sun4/280, it runs in about 60-75% of the time of sh for unpacking the rc source distribution.) */ void doredirs() { List *fname; int fd, p[2]; Rq *r; for (r = redirq; r != NULL; r = r->n) { switch(r->r->type) { default: fprint(2,"%d: bad node in doredirs\n", r->r->type); exit(1); /* NOTREACHED */ case rREDIR: if (r->r->u[0].i == HERESTRING) { fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */ if (fname == NULL) { close(r->r->u[1].i); /* feature? */ break; } if (pipe(p) < 0) { uerror("pipe"); exit(1); } switch (fork()) { case -1: uerror("fork"); exit(1); /* NOTREACHED */ case 0: /* child writes to pipe */ setsigdefaults(); close(p[0]); writeall(p[1], fname->w, strlen(fname->w)); exit(0); /* NOTREACHED */ default: close(p[1]); if (dup2(p[0], r->r->u[1].i) < 0) { uerror("dup"); exit(1); } close(p[0]); } } else { fname = glob(glom(r->r->u[2].p)); if (fname == NULL) { fprint(2,"null filename in redirection\n"); exit(1); } if (fname->n != NULL) { fprint(2,"multi-word filename in redirection\n"); exit(1); } switch (r->r->u[0].i) { default: fprint(2,"doredirs: this can't happen\n"); exit(1); /* NOTREACHED */ case CREATE: case APPEND: case FROM: fd = rc_open(fname->w, r->r->u[0].i); break; } if (fd < 0) { uerror(fname->w); exit(1); } if (dup2(fd, r->r->u[1].i) < 0) { uerror("dup"); exit(1); } close(fd); } break; case rDUP: if (r->r->u[2].i == -1) close(r->r->u[1].i); else if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) { uerror("dup"); exit(1); } } } redirq = NULL; }