From mboxrd@z Thu Jan 1 00:00:00 1970 Message-Id: <200007301954.PAA29225@cse.psu.edu> Subject: [9fans] pipefile From: "rob pike" Date: Sun, 30 Jul 2000 15:54:30 -0400 To: 9fans@cse.psu.edu MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Topicbox-Message-UUID: ee3de09a-eac8-11e9-9e20-41e7f4b1d025 I had an idea while trying to kill groundhogs today. The command is called pipefile; it interposes a command between you and the named file. Options -r and -w specify a command to interpose when reading or writing; -b does both, but in that case the command must handle bidirectional input; most standard commands such as cat won't work. Try this: pipefile -w 'tr a-z A-Z' /dev/cons rc -i < /dev/cons > /dev/cons >[2] /dev/cons for a shell reminiscent of olden times. The origin of the idea was a way to support Asian input. Consider pipefile -r 'tr a-z A-Z' /dev/cons rio < /dev/cons > /dev/cons >[2] /dev/cons I leave the rest to the interested Asian reader. The command leaves the file in an odd state, and can only work well on continuous files such as devices or with very special commands interposed, but I offer it as an interesting idea. -rob #include #include #define TEMP "/n/temp" void usage(void) { fprint(2, "usage: pipefile [-r command] [-w command] [-b command] file\n"); exits("usage"); } void connect(char *cmd, int fd0, int fd1) { switch(rfork(RFPROC|RFFDG|RFREND|RFNOWAIT)){ case -1: sysfatal("fork %s: %r", cmd); break; default: return; case 0: if(fd0 != 0) dup(fd0, 0); if(fd1 != 1) dup(fd1, 1); execl("/bin/rc", "rc", "-c", cmd, nil); sysfatal("exec %s: %r", cmd); break; } } void main(int argc, char *argv[]) { char *file; char *rcmd, *wcmd, *bcmd; int fd0, fd1; rcmd = wcmd = bcmd = nil; ARGBEGIN{ case 'r': if(bcmd != nil) usage(); rcmd = EARGF(usage()); break; case 'w': if(bcmd != nil) usage(); wcmd = EARGF(usage()); break; case 'b': if(rcmd!=nil || wcmd!=nil) usage(); bcmd = EARGF(usage()); break; default: usage(); }ARGEND if(argc!=1 || (rcmd==nil && wcmd==nil && bcmd==nil)) usage(); if(rcmd==nil && wcmd!=nil) rcmd = "/bin/cat"; if(wcmd==nil && rcmd!=nil) wcmd = "/bin/cat"; file = argv[0]; if(bind("#|", TEMP, MREPL) < 0) sysfatal("bind pipe %s: %r", TEMP); if(bind(TEMP "/data", file, MREPL) < 0) sysfatal("bind %s %s: %r", TEMP "/data", file); if(bcmd != nil){ fd0 = open(TEMP "/data1", ORDWR); if(fd0 < 0) sysfatal("open %s: %r", TEMP "/data1"); connect(bcmd, fd0, fd0); close(fd0); }else{ fd0 = open(TEMP "/data1", OREAD); if(fd0 < 0) sysfatal("open %s: %r", TEMP "/data1"); connect(wcmd, fd0, 1); fd1 = open(TEMP "/data1", OWRITE); if(fd1 < 0) sysfatal("open %s: %r", TEMP "/data1"); connect(rcmd, 0, fd1); close(fd0); close(fd1); } unmount(nil, TEMP); exits(nil); }