/* hacked up cat ... */
/* so the lucent public license applies to this file. */
/* ron minnich rminnich@lanl.gov */
#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");
}
|