#include <u.h>
#include <libc.h>
#include <ctype.h>
#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;
}
|