Plan 9 from Bell Labs’s /usr/web/sources/contrib/mycroftiv/root/sys/src/cmd/hubfs/hubshell.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ctype.h>

#define SMBUF 777

/* hubshell is the client for hubfs, usually started by the hub wrapper script */

typedef struct Shell	Shell;

struct Shell {
	int fd[3];
	int fdzerodelay;
	int fdonedelay;
	int fdtwodelay;
	char basename[SMBUF];
	char *fdname[3];
	char shellctl;
	char cmdresult;
};

char initname[SMBUF];
char srvname[SMBUF];

Shell* setupshell(char *name);
void startshell(Shell *s);
void fdzerocat(int infd, int outfd, Shell *s);
void fdonecat(int infd, int outfd, Shell *s);
void fdtwocat(int infd, int outfd, Shell *s);
int touch(char *name);
void closefds(Shell *s);
void parsebuf(Shell *s, char *buf, int outfd);

Shell*
setupshell(char *name)
{
	Shell *s;

	s = (Shell*)malloc(sizeof(Shell));
	memset(s, 0, sizeof(Shell));
	strncat(s->basename, name, SMBUF);
	for(int i = 1; i < 3; i++){
		s->fdname[i] = (char*)malloc((strlen(s->basename)+1));
		sprint(s->fdname[i], "%s%d", s->basename, i);
		if((s->fd[i] = open(s->fdname[i], OREAD)) < 0){
			fprint(2, "hubshell: giving up on task - cant open %s\n", s->fdname[i]);
			return(nil);
		};
	}
	s->fdname[0] =  (char*)malloc((strlen(s->basename)+1));
	sprint(s->fdname[0], "%s%d", s->basename, 0);
	if((s->fd[0] = open(s->fdname[0], OWRITE)) < 0){
		fprint(2, "hubshell: giving up on task - cant open %s\n", s->fdname[0]);
		return(nil);
	}
	s->fdzerodelay = 0;
	s->fdonedelay = 0;
	s->fdtwodelay = 30;
	s->cmdresult = 'a';
	return s;
}

void
startshell(Shell *s)
{
	if(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG)==0){
		fdonecat(s->fd[1], 1, s);
		exits(nil);
	}
	if(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG)==0){
		fdtwocat(s->fd[2], 2, s);
		exits(nil);
	}
	fdzerocat(0, s->fd[0], s);
	exits(nil);
}

void
fdonecat(int infd, int outfd, Shell *s)
{
	char buf[8192];
	long n;

	while((n=read(infd, buf, (long)sizeof(buf)))>0){
		sleep(s->fdonedelay);
		if(write(outfd, buf, n)!=n){
			fprint(2, "hubshell: write error copying on fd %d\n", outfd);
		}
		if(s->shellctl == 'q'){
			exits(nil);
		}
	}
	if(n == 0){
		fprint(2, "hubshell: zero length read on fd %d\n", infd);
	}
	if(n < 0){
		fprint(2, "hubshell: error reading fd %d\n", infd);
	}
}

void
fdtwocat(int infd, int outfd, Shell *s)
{
	char buf[8192];
	long n;

	while((n=read(infd, buf, (long)sizeof(buf)))>0){
		sleep(s->fdtwodelay);
		if(write(outfd, buf, n)!=n){
			fprint(2, "hubshell: write error copying on fd %d\n", outfd);
		}
		if(s->shellctl == 'q'){
			exits(nil);
		}
	}
	if(n == 0){
		fprint(2, "hubshell: zero length read on fd %d\n", infd);
	}
	if(n < 0){
		fprint(2, "hubshell: error reading fd %d\n", infd);
	}
}

void
fdzerocat(int infd, int outfd, Shell *s)
{
	char buf[8192];
	long n;

	while((n=read(infd, buf, (long)sizeof(buf)))>0){
		if((strncmp(buf, "%", 1)) == 0){
			s->cmdresult = 'p';
			parsebuf(s, buf + 1, outfd);
			if(s->cmdresult != 'x'){
				memset(buf, 0, 8192);
				continue;
			}
		}
		sleep(s->fdzerodelay);
		if(write(outfd, buf, n)!=n){
			fprint(2, "hubshell: write error copying on fd %d\n", outfd);
		}
		if(s->shellctl == 'q'){
			exits(nil);
		}
	}
	if(n == 0){
		fprint(2, "hubshell: zero length read on fd %d\n", infd);
	}
	if(n < 0){
		fprint(2, "hubshell: error reading fd %d\n", infd);
	}
}

int
touch(char *name)
{
	int fd;

	if((fd = create(name, OREAD|OEXCL, 0666)) < 0){
		fprint(2, "hubshell: %s: cannot create: %r\n", name);
		return 1;
	}
	close(fd);
	return 0;
}

void
closefds(Shell *s)
{
	for(int i = 0; i < 3; i++){
		close(s->fd[i]);
	}
}

void
parsebuf(Shell *s, char *buf, int outfd)
{
	char tmpstr[SMBUF];
	char tmpname[SMBUF];
	Shell *newshell;
	char *fi[3];
	memset(tmpstr, 0, SMBUF);
	memset(tmpname, 0, SMBUF);

	if(strncmp(buf, "detach", 6) == 0){
		fprint(2, "hubshell detaching\n");
		s->shellctl = 'q';
		write(outfd, "fortune\n", 8);
		sleep(1000);
		closefds(s);
		exits(nil);
	}
	if(strncmp(buf, "remote", 6) == 0){
		if(isalpha(*(buf + 7)) == 0){
			fprint(2, "remote needs a name parameter to create new hubs\n:io ");
			return;
		}
		strncat(tmpname, buf + 7, strcspn(buf + 7, "\n"));
		fprint(2, "creating new shell %s %s on remote host\n", srvname, tmpname);
		for(int i = 0; i < 3; i++){
			snprint(tmpstr, SMBUF, "/n/%s/%s%d", srvname, tmpname, i);
			if(touch(tmpstr) !=0){
				fprint(2, "cant create new hubs to remote to!\nio: ");
				return;
			}
			fi[i] = strdup(tmpstr);		
		}
		snprint(tmpstr, SMBUF, "rc -i <%s >%s >[2]%s &\n", fi[0], fi[1], fi[2]);
		write(outfd, tmpstr, strlen(tmpstr));
		sleep(700);
		snprint(tmpstr, SMBUF, "echo 'prompt=%s%%'' '' ' >>%s\n", tmpname, fi[0]);
		write(outfd, tmpstr, strlen(tmpstr));
		sleep(200);
		snprint(tmpstr, SMBUF, "/n/%s/%s", srvname, tmpname);
		newshell = setupshell(tmpstr);
		if(newshell == nil){
			fprint(2, "failed to setup up client shell, maybe problems on remote end\nio: ");
			return;
		}
		s->shellctl = 'q';
		write(outfd, "fortune\n", 8);
		sleep(700);
		closefds(s);
		startshell(newshell);
		exits(nil);
	}
	if(strncmp(buf, "local", 5) == 0){
		if(isalpha(*(buf + 6)) == 0){
			fprint(2, "local needs a name parameter to create new hubs\nio: ");
			return;
		}
		strncpy(tmpstr, buf + 6, strcspn(buf + 6, "\n"));
		fprint(2, "creating new local shell using hub %s %s\n", srvname, tmpstr);
		s->shellctl = 'q';
		write(outfd, "fortune\n", 8);
		sleep(1000);
		closefds(s);
		execl("/bin/hub", "hub", srvname, tmpstr, 0);
		exits(nil);
	}
	if(strncmp(buf, "attach", 6) == 0){
		if(isalpha(*(buf + 7)) == 0){
			fprint(2, "attach needs a name parameter to know what hubs to use, try %%list\nio: ");
			return;
		}
		strncat(tmpname, buf + 7, strcspn(buf + 7, "\n"));
		fprint(2, "attaching to  shell %s %s\n", srvname, tmpname);
		snprint(tmpstr, SMBUF, "/n/%s/%s", srvname, tmpname);
		newshell = setupshell(tmpstr);
		if(newshell == nil){
			fprint(2, "failed to setup up client shell - do you need to create it with remote NAME?\nio: ");
			return;
		}
		s->shellctl = 'q';
		write(outfd, "fortune\n", 8);
		sleep(1000);
		closefds(s);
		startshell(newshell);
		exits(nil);
	}
	if(strncmp(buf, "status", 6) == 0){
		print("\tHubshell status: attached to mounted %s of /srv/%s\n", s->basename, srvname);
		print("\tfdzero delay: %d  fdone delay: %d  fdtwo delay: %d\n", s->fdzerodelay, s->fdonedelay, s->fdtwodelay);
		fprint(2, "io: ");
		return;
	}
	if(strncmp(buf, "list", 4) == 0){
		sprint(tmpstr, "/n/%s", srvname);
		print("listing mounted hubfs at /n/%s\n", srvname);
		if(rfork(RFPROC|RFNOTEG|RFNOWAIT) == 0){
			execl("/bin/lc", "lc", tmpstr, 0);
			exits(nil);
		}
		sleep(1500);
		fprint(2, "io: ");
		return;
	}
	if(strncmp(buf, "err", 3) == 0){
		if(isdigit(*(buf + 4)) == 0){
			fprint(2, "err hub delay setting requires numeric delay\nio: ");
			return;
		}
		s->fdtwodelay = atoi(buf + 4);
		fprint(2, "err hub delay set to %d\nio: ", atoi(buf +4));
		return;
	}
	if(strncmp(buf, "in", 2) == 0){
		if(isdigit(*(buf + 3)) == 0){
			fprint(2, "in hub delay setting requires numeric delay\nio: ");
			return;
		}
		s->fdzerodelay = atoi(buf + 3);
		fprint(2, "in hub delay set to %d\nio: ", atoi(buf +3));
		return;
	}
	if(strncmp(buf, "out", 3) == 0){
		if(isdigit(*(buf + 4)) == 0){
			fprint(2, "out hub delay setting requires numeric delay\nio: ");
			return;
		}
		s->fdonedelay = atoi(buf + 4);
		print("out hub delay set to %d\nio: ", atoi(buf +4));
		return;
	}
	fprint(2, "hubshell %% commands: \n\tdetach, remote NAME, local NAME, attach NAME \n\tstatus, list, err TIME, in TIME, out TIME\n");
	s->cmdresult = 'x';
}

void
main(int argc, char *argv[])
{
	Shell *s;

	if(argc != 2){
		fprint(2, "usage: hubshell hubsname - and probably you want the hub wrapper script instead");
		exits(nil);
	}
	strncpy(initname, argv[1], SMBUF);
	strncat(srvname, initname+3, SMBUF);
	sprint(srvname + strcspn(srvname, "/"), "\0");

	s = setupshell(initname);
	if(s == nil){
		sysfatal("couldnt setup shell, bailing out\n");
	}
	startshell(s);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.