rc

[fork] interactive rc shell
git clone https://hhvn.uk/rc
git clone git://hhvn.uk/rc
Log | Files | Refs | README | LICENSE

redir.c (2097B)


      1 /* redir.c: code for opening files and piping heredocs after fork but before exec. */
      2 
      3 #include "rc.h"
      4 
      5 /*
      6    Walk the redirection queue, and open files and dup2 to them. Also,
      7    here-documents are treated here by dumping them down a pipe. (this
      8    should make here-documents fast on systems with lots of memory which
      9    do pipes right. Under sh, a file is copied to /tmp, and then read
     10    out of /tmp again. I'm interested in knowing how much faster, say,
     11    shar runs when unpacking when invoked with rc instead of sh. On my
     12    sun4/280, it runs in about 60-75% of the time of sh for unpacking
     13    the rc source distribution.)
     14 */
     15 
     16 extern void doredirs() {
     17 	List *fname;
     18 	int fd, p[2];
     19 	Rq *r;
     20 	for (r = redirq; r != NULL; r = r->n) {
     21 		switch(r->r->type) {
     22 		default:
     23 			panic("unexpected node in doredirs");
     24 			/* NOTREACHED */
     25 		case nRedir:
     26 			if (r->r->u[0].i == rHerestring) {
     27 				fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */
     28 				if (pipe(p) < 0) {
     29 					uerror("pipe");
     30 					rc_error(NULL);
     31 				}
     32 				if (rc_fork() == 0) { /* child writes to pipe */
     33 					setsigdefaults(FALSE);
     34 					close(p[0]);
     35 					if (fname != NULL)
     36 						writeall(p[1], fname->w, strlen(fname->w));
     37 					exit(0);
     38 				} else {
     39 					close(p[1]);
     40 					if (mvfd(p[0], r->r->u[1].i) < 0)
     41 						rc_error(NULL);
     42 				}
     43 			} else {
     44 				fname = glob(glom(r->r->u[2].p));
     45 				if (fname == NULL)
     46 					rc_error("null filename in redirection");
     47 				if (fname->n != NULL)
     48 					rc_error("multi-word filename in redirection");
     49 				switch (r->r->u[0].i) {
     50 				default:
     51 					panic("unexpected node in doredirs");
     52 					/* NOTREACHED */
     53 				case rCreate: case rAppend: case rFrom:
     54 					fd = rc_open(fname->w, r->r->u[0].i);
     55 					break;
     56 				}
     57 				if (fd < 0) {
     58 					uerror(fname->w);
     59 					rc_error(NULL);
     60 				}
     61 				if (mvfd(fd, r->r->u[1].i) < 0)
     62 					rc_error(NULL);
     63 			}
     64 			break;
     65 		case nDup:
     66 			if (r->r->u[2].i == -1)
     67 				close(r->r->u[1].i);
     68 			else if (r->r->u[2].i != r->r->u[1].i) {
     69 				if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) {
     70 					uerror("dup2");
     71 					rc_error(NULL);
     72 				}
     73 			}
     74 		}
     75 	}
     76 	redirq = NULL;
     77 }