Plan 9 from Bell Labs’s /usr/web/sources/9grid/xsh.c

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


/* hacked up cat ... */
/* so the lucent public license applies to this file. */
/* ron minnich  [email protected] */

#include <u.h>
#include <libc.h>
int nodeno = 0;
char **dirno = nil;
int totalenvsize = 32; /* leave some headroom */
int debugfd = 2;
char *base = 0;
int debuglevel = 0;

void
debug(int level, char *fmt, ...)
{
	va_list arg;

	if (debuglevel < level)
		return;
	va_start(arg, fmt);
	vfprint(2, fmt, arg);
	va_end(arg);
}

int
copy(int fromfd, int tofd) {
	int amtread, amtwrite;
	static char buf[8192];
	while ((amtread = read(fromfd, buf, sizeof(buf))) > 0) {
		amtwrite = write(tofd, buf, amtread);
		if (amtwrite < amtread)
			return -1;
	}
	return 0;
}

void
copybinary(char *dirnames[], int numdirs, char *execname){
	char *name;
	int i;
	int rfd, wfd;

	rfd = open(execname, OREAD);
	if (rfd < 0) {
		perror(execname);
		exits(execname);
	}

	for(i = 0; i < numdirs; i++) {
		name = smprint("%s/exec", dirnames[i]);
		wfd = open(name, OWRITE);
		if (wfd < 0) {
			perror(name);
			exits(name);
		}
		free(name);
		copy(rfd, wfd);
		close(wfd);
	}
}

void
catfile(char *dirnames[], int numdirs, char *filename, int wfd){
	char *name;
	int i;
	int rfd;

	for(i = 0; i < numdirs; i++) {
		name = smprint("%s/%s", dirnames[i], filename);

		rfd = open(name, OREAD);
		if (rfd < 0) {
			perror(name);
			exits(name);
		}
		debug(2, "catfile: copy %s(%d) to %d\n", name, rfd, wfd);
		free(name);
		copy(rfd, wfd);
	}
}

void
writestring(char *dirnames[], int numdirs, char *file, char *string) {
	int wfd;
	int slen = strlen(string);
	int i;
	int amt;

	for(i = 0; i < numdirs; i++) {
		char *name;
		name = smprint("%s/%s", dirnames[i], file);
		wfd = open(name, OWRITE);
		if (wfd < 0) {
			perror(name);
			exits(name);
		}
		debug(2, "Write %s to %s\n", string, name);

		amt = write(wfd, string, slen);
		if (amt < slen)
			perror(name);
		free(name);
		close(wfd);
	}
}

void
openfiles(int f, char *s)
{
	char buf[8192];
	long n;
	memset(buf, 0, sizeof(buf));
	n=read(f, buf, (long)sizeof buf);
	write(1, buf, n);
	debug(3,"now strdup the thing\n");
	/* force it to be rooted ... */
	dirno[nodeno++] = smprint("/%s/%s/xcpu/%s", base, s, buf);
	totalenvsize += strlen(buf) + 1; 
	debug(3,"totales now %d\n", totalenvsize);
	
}

void
main(int argc, char *argv[])
{
	void shell(void);
	int f, i;
	struct Waitmsg *m;
	char *envvar, *argvar;
	char *me = argv[0];
	int nodecount = 0, arg_start = 0;
	int totalargsize;
	char *binary;

	if(argc == 1)
		exits("at least one");

	base = getenv("XCPUBASE");
	if (! base)
		base = "/mnt/xcpu";

	/* we actually allocate too many, but who cares? */
	dirno = malloc(argc * sizeof(char *));
	if (! dirno)
		exits("dirno malloc failed");

	/* format is nodes "--" argv */
	else for(i=1; i<argc; i++){
		char *name;
		if (! strcmp(argv[i], "--")){
			arg_start = i + 1;
			break;
		}
		debug(2, "Open %s\n", argv[i]);
		name = smprint("/%s/%s/xcpu/clone", base, argv[i]);
		f = open(name, OREAD);
		if(f < 0)
			sysfatal("%s:can't open %s: %r", argv[i], name);
		else{
			openfiles(f, argv[i]);
		}
		free(name);
		nodecount = i;
		/* cover the case of no "--" */
		arg_start = nodecount + 1;
	}

	envvar = mallocz(totalenvsize, 1);
	if (! envvar)
		exits("envvar malloc failed");

	strcpy(envvar, "");

	for(i = 0; i < nodecount; i++){
		debug(3,"i %d dirno[i] %p\n", i, dirno[i]);
		strcat(envvar, dirno[i]);
		if (i < nodecount-2)
			strcat(envvar," ");
		else
			strcat(envvar, "");
		debug(3,"done %d\n", i);
	}

	for(i = arg_start, totalargsize = 0; i < argc; i++){
		totalargsize += strlen(argv[i]) + 2;
	}

	argvar = mallocz(totalargsize, 1);

	print("arg_start %d, argc %d, totalargsize %d\n", 
	      arg_start, argc, totalargsize);

	binary = argv[arg_start];

	for(i = arg_start; i < argc; i++){
		debug(3,"i %d dirno[i] %p\n", i, dirno[i]);
		strcat(argvar, argv[i]);
		if (i < argc-1)
			strcat(argvar," ");
		else
			strcat(argvar, "");
		debug(3,"done %d\n", i);
	}
	debug(3,"time to fork\n");

	if (fork()) {
		m = wait();
		debug(2, "%s: child exits, we exit too\n", me);
		exits(0);
	}
	putenv("XCPUNODES", envvar);
	putenv("XCPUARGS", argvar);
	/* copy the binary out */
	copybinary(dirno, nodecount, binary);
	debug(2, "copied binary\n");
	//shell();

	/* echo the argv out */
	writestring(dirno, nodecount, "argv", argvar);
	debug(2, "wrote argv\n");
	/* read all of stdouts */
	if (fork() == 0) {
	  catfile(dirno, nodecount, "stdout", 1);
	   exits(0);
	}
	/* read all of stderr */
	if (fork() == 0) {
	  catfile(dirno, nodecount, "stderr", 2);
	  exits(0);
	}
	/* exec it */
	writestring(dirno, nodecount, "ctl", "exec\n");
	debug(2, "wrote exec\n");

	/* for now, send eof */
//	writestring(dirno, nodecount, "ctl", "eof");
	/* now the files are open. exec window -m and all should be fine. */
//	shell();
	debug(2, "Exec failed: %r\n");

}



Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].