#include #include #include #define HISTSIZE 131072 #define SMBUF 256 char cursrv[SMBUF]; char shortname[SMBUF]; char shellctl; char hist[HISTSIZE]; int histlen; int fd[4]; int hubfdmap[3]; void iocat(int infd, int outfd); void fdzerocat(int infd, int outfd); /* ioshell is a front end client for iosrv that spider-walks acrss available pipe files */ /* traps certain user input as commands to be implemented via messages to Hub ctl/data file */ /* basic cat-style data transfer between file descriptors */ void iocat(int infd, int outfd) { char buf[8192]; long n; while((n=read(infd, buf, (long)sizeof(buf)))>0){ if(write(outfd, buf, n)!=n){ sysfatal("write error copying on fd %d\n", outfd); } sleep(0); if(shellctl == 'q'){ exits(nil); } } if(n == 0){ print("zero length read on fd %d\n", infd); } if(n < 0){ sysfatal("error reading fd %d\n", infd); } return; } /* the process handling user input parses it and helps send commands to the iosrv ctl */ /* this function is a bit monstrous in appearance, but most of the time it simply bucket brigades information */ /* the complex actions are taken in response to control messages specifying changing or creating input/output sources */ void fdzerocat(int infd, int outfd) { char buf[8192]; char fileinbuf[8192]; char numname[SMBUF]; int numfd; char tmpcmdname[SMBUF]; int tmpcmdfd; long n; int swtarg; int targouttag; int tmpnum; char cmdstr[SMBUF]; char newfd0[SMBUF]; char newfd1[SMBUF]; char newfd2[SMBUF]; char ctlfdname[SMBUF]; ulong datamode; ulong execmode; datamode = 0664L; execmode = 0777L; while(shellctl != 'q'){ while((n=read(infd, buf, (long)sizeof(buf)))>0){ /* remote # command creates and connects to a new rc running on the remote iosrv host */ if(strncmp(buf, "remote", 6) == 0){ if(isdigit(*(buf + 7))){ swtarg = atoi(buf +7); } else { print("ioshell err: new needs numeric argument\n"); continue; } targouttag = 0; for(int i=swtarg; i < swtarg+3; i++){ fprint(fd[3], "h%ds%d\n", i, targouttag); sleep(200); fprint(fd[3], "h%do%d\n", i, targouttag); sleep(200); } sprint(cmdstr, "rc -i <%s/H%dout%d/data1 >%s/H%din%d/data >[2]%s/H%din%d/data &\n", cursrv, swtarg, targouttag, cursrv, swtarg+1, targouttag, cursrv, swtarg+2, targouttag); if(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG) == 0){ sleep(400); write(outfd, "rfork\n", 6); sleep(400); write(outfd, cmdstr, strlen(cmdstr)); sleep(200); write(outfd, "rfork\n",6); exits(nil); } sleep(1500); sprint(numname, "%s/attach%d", cursrv, swtarg); numfd = create(numname, OWRITE, datamode); fprint(numfd, "%d", targouttag +1); close(numfd); sprint(numname, "%s/trihubs", cursrv); numfd = open(numname, OREAD); if(numfd < 0){ print("didnt find a trihubs value\n"); } read(numfd, fileinbuf, 8192); close(numfd); if(isdigit(*(fileinbuf))){ tmpnum = atoi(fileinbuf); numfd=create(numname, OWRITE, datamode); fprint(numfd, "%d\n", tmpnum +1); close(numfd); } else { print("couldnt read trihub value, automatic client adds may fail\n"); } sprint(newfd0, "%s/H%din%d/data", cursrv, swtarg, targouttag); sprint(newfd1, "%s/H%dout%d/data1", cursrv, swtarg+1, targouttag); sprint(newfd2, "%s/H%dout%d/data1", cursrv, swtarg+2, targouttag); sprint(ctlfdname, "%s/ctl/data", cursrv); shellctl = 'q'; write(outfd, "fortune\n", 8); rfork(RFNOWAIT|RFNOTEG); execl("/bin/ioshell", "ioshell", newfd0, newfd1, newfd2, ctlfdname, 0); exits(nil); } /* local # creates and connects to a new rc running on the local machine, and connects its file descriptors to pipes from iosrv */ if(strncmp(buf, "local", 5) == 0){ if(isdigit(*(buf + 6))){ swtarg = atoi(buf +6); } else { print("ioshell err: new needs numeric argument\n"); continue; } targouttag = 0; for(int i=swtarg; i < swtarg+3; i++){ fprint(fd[3], "h%ds%d\n", i, targouttag); sleep(200); fprint(fd[3], "h%do%d\n", i, targouttag); sleep(200); } sprint(cmdstr, "rc -i <%s/H%dout%d/data1 >%s/H%din%d/data >[2]%s/H%din%d/data\n", cursrv, swtarg, targouttag, cursrv, swtarg+1, targouttag, cursrv, swtarg+2, targouttag); sprint(tmpcmdname, "%s/tmpcmd", cursrv); tmpcmdfd=create(tmpcmdname, OWRITE, execmode); if(tmpcmdfd < 0){ print("couldnt create tmpcmd so rc will not be active\n"); } else { fprint(tmpcmdfd, "#!/bin/rc\n"); fprint(tmpcmdfd, cmdstr); close(tmpcmdfd); if(rfork(RFPROC|RFNAMEG|RFENVG|RFNOTEG) == 0){ execl(tmpcmdname, "rcstart", nil); print("rc started exiting\n"); exits(nil); } } sprint(numname, "%s/attach%d", cursrv, swtarg); numfd = create(numname, OWRITE, datamode); fprint(numfd, "%d", targouttag +1); close(numfd); sprint(numname, "%s/trihubs", cursrv); numfd = open(numname, ORDWR); if(numfd < 0){ print("didnt find a trihubs value\n"); } read(numfd, fileinbuf, 8192); close(numfd); if(isdigit(*(fileinbuf))){ tmpnum = atoi(fileinbuf); numfd=create(numname, OWRITE, datamode); fprint(numfd, "%d\n", tmpnum +1); close(numfd); } else { print("couldnt read trihub value, automatic client adds may fail\n"); } sprint(newfd0, "%s/H%din%d/data", cursrv, swtarg, targouttag); sprint(newfd1, "%s/H%dout%d/data1", cursrv, swtarg+1, targouttag); sprint(newfd2, "%s/H%dout%d/data1", cursrv, swtarg+2, targouttag); sprint(ctlfdname, "%s/ctl/data", cursrv); shellctl = 'q'; write(outfd, "fortune\n", 8); rfork(RFNOWAIT|RFNOTEG); execl("/bin/ioshell", "ioshell", newfd0, newfd1, newfd2, ctlfdname, 0); print("stdout ioshell complete, exiting\n"); exits(nil); } /* attach # moves the ioshell between hubs - actually by exiting the current and starting a new ioshell with the correct paramaters */ /* this same technique is also used for 'remote' and 'local' connections */ if(strncmp(buf, "attach", 6) == 0){ if(isdigit(*(buf + 7))){ swtarg = atoi(buf+7); } else { print("ioshell err: switch needs numeric argument\n"); continue; } sprint(numname, "%s/attach%d", cursrv, swtarg); numfd=open(numname, OREAD); if(numfd < 0){ print("couldnt find attach number, using arbitrary\n"); targouttag=swtarg*5; goto readfailed; } read(numfd, fileinbuf, 8192); if(isdigit(*(fileinbuf))){ targouttag = atoi(fileinbuf); close(numfd); numfd = create(numname, OWRITE, datamode); fprint(numfd, "%d", targouttag +1); close(numfd); } else { print("failed to read attach number using arbitrary \n"); close(numfd); targouttag=swtarg*4; } readfailed: fprint(fd[3], "h%di%d\n", swtarg, targouttag); sleep(200); for(int i=swtarg; i < swtarg+3; i++){ fprint(fd[3], "h%do%d\n", i, targouttag); sleep(200); } sprint(newfd0, "%s/H%din%d/data", cursrv, swtarg, targouttag); sprint(newfd1, "%s/H%dout%d/data1", cursrv, swtarg+1, targouttag); sprint(newfd2, "%s/H%dout%d/data1", cursrv, swtarg+2, targouttag); sprint(ctlfdname, "%s/ctl/data", cursrv); shellctl = 'q'; write(outfd, "fortune\n", 8); rfork(RFMEM|RFNOWAIT|RFNOTEG); execl("/bin/ioshell", "ioshell", newfd0, newfd1, newfd2, ctlfdname, 0); print("stdout ioshell complete, exiting\n"); exits(nil); } if(strncmp(buf, "clear", 5) == 0){ fprint(fd[3], "h0c\n"); sleep(200); fprint(fd[3], "h1c\n"); sleep(200); fprint(fd[3], "h2c\n"); print("server buffer cleared\n"); print("ioshell: "); continue; } /* hub cmdstr sends a message to the parsecmd routine in the iosrv ctlsrv - see control.c */ if(strncmp(buf, "hub", 3) == 0){ memset(cmdstr, 0, SMBUF); strncpy(cmdstr, buf+4, SMBUF); print("transmitting command to ctl\n"); fprint(fd[3], "%s", cmdstr); print("ioshell: "); continue; } if(strncmp(buf, "hist\n", 5) == 0){ write(1, hist, histlen); print("ioshell: "); continue; } if(strncmp(buf, "detach", 6) == 0){ print("ioshell detaching\n"); shellctl = 'q'; write(outfd, "fortune\n", 8); exits(nil); } if(histlen > (HISTSIZE - 16385)){ memset(hist, 0, HISTSIZE); histlen = 0; } strncat(hist, buf, n); histlen += n; if(write(outfd, buf, n)!=n){ sysfatal("write error copying on fd %d", outfd); } sleep(0); } if(n == 0){ print("zero length read on fd %d\n", infd); } if(n < 0){ sysfatal("error reading on fd %d\n", infd); } } return; } /* fork off procs to transfer data between the given files and /fd/0,1,2 */ void main(int argc, char *argv[]) { if(argc != 5){ sysfatal("USAGE: ioshell filefromfd0 filetofd1 filetofd2 ctlfile"); } strncat(cursrv, argv[4], (strlen(argv[4]) -9)); strcat(shortname, cursrv+3); memset(hist, 0, HISTSIZE); fd[3] = open(argv[4], OWRITE); if(fd[4] < 0){ sysfatal("cant open ctl file %s\n", argv[4]); } fd[0] = open(argv[1], OWRITE); if(fd[0] < 0){ sysfatal("cant redirect stdout to %s\n", argv[1]); } for(int i=1; i < 3; i++){ if(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG)==0){ sleep(200); fd[i] = open(argv[i+1], OREAD); if(fd[i] < 0){ sysfatal("cant open %s\n", argv[i+1]); } iocat(fd[i], i); print("iocat on fd %d ended\n", fd[i]); exits(nil); } } rfork(RFMEM|RFNOWAIT|RFNOTEG); print("attaching ioshell user input to %s fd %d\n", argv[1], fd[0]); fdzerocat(0, fd[0]); print("iocat of user input on fd %d ended\n", fd[0]); return; }