/* * compServerUtils.c - utilities for the mimosa and cinder stubs */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/param.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/time.h> #include <signal.h> #ifdef sun #include <mntent.h> #elif ←IBMR2 /* * for compatability with SunOS */ #include <fstab.h> #define MOUNTED "" /* bogus value for compatability purposes only */ struct mntent { char *mnt←dir; }; static FILE *setmntent(); static struct mntent *getmntent(); #endif #include "compServer.h" #include "compServerDefs.h" /* maximum number of machines of each architecture type for use * as cross-compile servers */ #define MAXNUMMACH 5 /* * the automount map prefix for referring to machines on the net */ #define NET←AUTOMOUNT←PREFIX "/net" #define AUTOMOUNT←PREFIX "/tmp←mnt" #define MIMOSA←SERVER "MIMOSA←SERVER" static char *getRandomMach(); static char *getMachInner(); extern char *getwd(); extern char **environ; char *archNames[] = { "unknown", "sun4", "rs6000", "dec" }; extern JobStatus JobStatusFromStatus(sstatus) int sstatus; { return (JobStatus)sstatus; } extern void ExitSuccessfully() { exit(0); /*NOTREACHED*/ } /* command line switches/args routines */ extern void setSwitch(h, sw) Handle h; Switches sw; { h->job.switches[(int)sw - 'a'] = TRUE; } extern void resetSwitch(h, sw) Handle h; Switches sw; { h->job.switches[(int)sw - 'a'] = FALSE; } extern int isSwitchSet(h, sw) Handle h; Switches sw; { return h->job.switches[(int)sw - 'a']; } /* process/command execution routines */ extern int CallSys(h, fileArg, argVector) Handle h; char *fileArg, **argVector; { #ifdef ←POSIX←SOURCE int status; #elif sun union wait status; #else --->> status declaration <<--- #endif int pid, i; for (i = 0; argVector[i]; i++) { Verbose(h, argVector[i]); Verbose(h, " "); } Verbose(h, "\n"); /* if dryrun, don't actually do the op */ if (isSwitchSet(h, (Switches)'d')) return 0; switch (pid = fork()) { case -1: Fatal(h, "No more processes\n"); break; case 0: (void)execv(fileArg, argVector); Fatal2(h, "Couldn't exec \n", fileArg); break; } while (pid != wait(&status)) ; #ifdef ←POSIX←SOURCE if ((pid = (status & 0377)) != 0) #elif sun if ((pid = (status.w←status & 0377)) != 0) #else ---->> status use <<----- #endif Fatal2(h, "Fatal error in ", fileArg); #ifdef ←POSIX←SOURCE return (status >> 8) & 0377; #elif sun return (status.w←status>>8) & 0377; #else ---->> status return <<----- #endif } extern int csh←system(s) char *s; { int status; pid←t pid, w; register void (*istat)(), (*qstat)(); if ((pid = fork() ) == 0) { (void)execle("/bin/csh", "csh", "-f -c", s, (char *)0, environ); ←exit(127); } istat = signal(SIGINT, SIG←IGN); qstat = signal(SIGQUIT, SIG←IGN); w = waitpid(pid, &status, 0); (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); return ((w == -1) ? -1: status); } extern int rsh←system(h, shell) Handle h; char *shell; { char *shellStr; int w; shellStr = malloc((unsigned) MAXCOMMANDSTRINGSIZE); (void)strcpy(shellStr, " "); /* so we can use strcat from here on out */ if (getArch() != h->archtype) { char *mach = getMach(h, h->archtype); (void)strcpy(shellStr, "rsh "); (void)strcat(shellStr, mach); (void)strcat(shellStr, " \"cd "); (void)strcat(shellStr, getwd←wo←automount(".")); (void)strcat(shellStr, "; "); } (void)strcat(shellStr, shell); w = csh←system(shellStr) >> 8; free(shellStr); return w; } extern int systeme(h, shell, commander, fileToWorkOn, archType, defSuccess) Handle h; char *shell; char *commander; char *fileToWorkOn; arch archType; int defSuccess; { int w; char *commanderStr, *shellStr; char *shmtype; char statusFile[25]; commanderStr = malloc((unsigned) MAXCOMMANDSTRINGSIZE); shellStr = malloc((unsigned) MAXCOMMANDSTRINGSIZE); (void)strcpy(commanderStr, "COMMANDER←INITIAL←COMMAND="); (void)strcat(commanderStr, commander); (void)strcat(commanderStr, " "); (void)strcat(commanderStr, fileToWorkOn); Verbose(h, commanderStr); Verbose(h, "\n"); (void)strcpy(shellStr, " "); /* so we can use strcat from here on out */ /* if (getArch() != archType) { char *mach = getMach(h, archType); (void)strcpy(shellStr, "rsh "); (void)strcat(shellStr, mach); (void)strcat(shellStr, " 'cd "); (void)strcat(shellStr, getwd←wo←automount(fileToWorkOn)); (void)strcat(shellStr, "; setenv COMMANDER←INITIAL←COMMAND \""); (void)strcat(shellStr, commander); (void)strcat(shellStr, " "); (void)strcat(shellStr, fileToWorkOn); (void)strcat(shellStr, "\"; "); } */ if (getArch() != archType) { char *mach = getMach(h, archType); (void)strcpy(shellStr, "rsh "); (void)strcat(shellStr, mach); (void)strcat(shellStr, " 'cd "); (void)strcat(shellStr, getwd←wo←automount(fileToWorkOn)); (void)strcat(shellStr, "; setenv COMMANDER←INITIAL←COMMAND \""); (void)strcat(shellStr, "cdf "); (void)strcat(shellStr, getwd←wo←automount(fileToWorkOn)); (void)strcat(shellStr, "; "); (void)strcat(shellStr, commander); (void)strcat(shellStr, " "); (void)strcat(shellStr, fileToWorkOn); (void)strcat(shellStr, "\"; "); } else if (getArch() == RS6000) { (void)strcat(shellStr, "setenv COMMANDER←INITIAL←COMMAND \""); (void)strcat(shellStr, "cdf "); (void)strcat(shellStr, getwd←wo←automount(fileToWorkOn)); (void)strcat(shellStr, "; "); (void)strcat(shellStr, commander); (void)strcat(shellStr, " "); (void)strcat(shellStr, fileToWorkOn); (void)strcat(shellStr, "\"; "); } (void)strcat(shellStr, shell); (void)strcat(shellStr, "-"); (void)strcat(shellStr, stringFromArch(archType)); if (getArch() != archType) { (void)strcat(shellStr, "; echo $status > "); (void)sprintf(statusFile, "%s%d", ".mimstat", getpid()); (void)strcat(shellStr, statusFile); /* (void)unlink(statusFile); */ } if (getArch() == archType) { /* only if you are compiling locally can you hope to check for /pcrswap */ shmtype = getenv("TOOLS←SHMTYPE"); if (shmtype && !strcmp("mmap", shmtype)) { if (access("/pcrswap", F←OK|W←OK)) Fatal(h, "Error: TOOLS←SHMTYPE mmap requires writable /pcrswap directory\n"); (void)strcat(shellStr, " -shmtype mmap "); } } if (getArch() != archType) { (void)strcat(shellStr, "'"); } if (!getenv("MIMOSA←NO←NULL")) { (void)strcat(shellStr, " > /dev/null "); } Verbose(h, shellStr); Verbose(h, "\n"); if (isSwitchSet(h, (Switches)'d')) return defSuccess; if (putenv(commanderStr) != 0) { /* set env variable */ (void)free(commanderStr); (void)free(shellStr); Fatal(h, "Unable to set environment variable \"COMMANDER←INITIAL←COMMAND\"\n"); } w = csh←system(shellStr) >> 8; if (getArch() != archType) { FILE *f = fopen(statusFile, "r"); if (f == 0) { Fatal(h, "Couldn't read status file\n"); } (void)fscanf(f, "%d", &w); (void)fclose(f); (void)unlink(statusFile); } if (putenv("COMMANDER←INITIAL←COMMAND=") != 0) { /* unset env. variable */ (void)free(commanderStr); (void)free(shellStr); Fatal(h, "Unable to unset environment variable \"COMMANDER←INITIAL←COMMAND\"\n"); } (void)free(commanderStr); (void)free(shellStr); return w; } /* IO routines */ extern void PutLong(arg) long arg; { (void)printf("%ld", arg); } extern void PutC(ch) char ch; { (void)fputc(ch, stdout); } extern void PutS(arg) char *arg; { (void)fputs(arg, stdout); (void)fflush(stdout); } extern void echoArgs(h) Handle h; { Switches s; for (s = a; s <= Q; s++) { if (isSwitchSet(h, s)) { PutC('-'); PutC((char)s); PutC(' '); } } } extern void Verbose(h, s) Handle h; char *s; { if (isSwitchSet(h, (Switches)'v') || isSwitchSet(h, (Switches)'d')) { PutS(s); } } /*ARGSUSED*/ extern void echoCmd(h, cmd, filename) Handle h; char *cmd; char *filename; { PutS(cmd); PutC(' '); PutS(filename); PutC('\n'); } extern void Fatal(h, string1) Handle h; char *string1; { if (string1) (void)fputs(string1, stderr); (void)fputc('\n', stderr); if (h) FreeHandle(h); exit(88); /*NOTREACHED*/ } extern void Fatal2(h, string1, string2) Handle h; char *string1, *string2; { if (string1) (void)fputs(string1, stderr); Fatal(h, string2); } extern void Warning(h, arg) Handle h; char *arg; { if (!h || !isSwitchSet(h, (Switches)'w')) { (void)fputs(arg, stderr); (void)fflush(stderr); } } /* C compiling */ extern void DoCCompile(h, suffix, cswitch) Handle h; char *suffix; int cswitch; { char *fileNameBase = h->job.shortFileName; char stringBody[MAXNAMLEN+3]; char shellStr[MAXCOMMANDSTRINGSIZE]; char *cFileName = stringBody; char outBody[MAXNAMLEN+3]; char *outFileName = outBody; char *outFileExtension = ".o"; (void)strcpy(cFileName, fileNameBase); (void)strcat(cFileName, suffix); (void)strcpy(outFileName, fileNameBase); if ((h->job.jobKind==compile || h->job.jobKind == ms) && isSwitchSet(h,(Switches)'l')) { outFileExtension = ".c2c.o"; } if (h->job.jobKind == cind && isSwitchSet(h, (Switches)'m')) { outFileExtension = ".c2c.o"; } (void)strcat(outFileName, outFileExtension); (void)strcpy(shellStr, ""); if (getArch() != h->archtype) { (void)strcpy(shellStr, "rsh "); (void)strcat(shellStr, getMach(h, h->archtype)); (void)strcat(shellStr, " \"cd "); (void)strcat(shellStr, getwd←wo←automount(cFileName)); (void)strcat(shellStr, "; "); } (void)strcat(shellStr, "/bin/cc "); if (cswitch) (void)strcat(shellStr, "-c "); if (isSwitchSet(h, (Switches)'a')) { (void)strcat(shellStr,"-a "); /* coverage testing code */ } if (!isSwitchSet(h, (Switches)'g')) (void)strcat(shellStr, "-g "); if (isSwitchSet(h, (Switches)'o')) { if (isSun4Target(h)) { char s[3]; (void)strcat(shellStr, "-O"); s[0] = h->optLevel + '0'; s[1] = ' '; s[2] = '\0'; (void)strcat(shellStr, s); } else /* !isSun4Target() */ { (void)strcat(shellStr, "-O "); } } if (isSwitchSet(h, (Switches)'p')) (void)strcat(shellStr,"-p "); if (isSwitchSet(h, (Switches)'q')) (void)strcat(shellStr,"-pic "); if (isSwitchSet(h, Q)) (void)strcat(shellStr,"-PIC "); if (isSwitchSet(h, (Switches)'s')) { if (isSun4Target(h) || isDecTarget(h)) { (void)strcat(shellStr,"-S "); } else /* isRS6000Target() */ { (void)strcat(shellStr,"-qlst "); } } if (isSwitchSet(h, (Switches)'w')) (void)strcat(shellStr, "-w "); (void)strcat(shellStr,cFileName); (void)strcat(shellStr," "); if (!isSwitchSet(h, (Switches)'s') && !isRS6000Target(h)) { /* * -o doesn't work on AIX except for non-executable files */ (void)strcat(shellStr, "-o "); (void)strcat(shellStr, outFileName); } if (getArch() != h->archtype) { (void)strcat(shellStr, "\""); } (void)strcat(shellStr,"\n"); PutC('C'); Verbose(h, shellStr); if (!isSwitchSet(h, (Switches)'d')) { if (system(shellStr)) Fatal2(h, "cc failed for: ", fileNameBase); } } extern void DeleteFile(h, fileName) Handle h; char *fileName; { /* just do your best to delete the file - don't worry if you can't do it */ Verbose(h, "/bin/rm -f "); Verbose(h, fileName); Verbose(h, "\n"); if (!isSwitchSet(h, (Switches)'d')) (void)unlink(fileName); } extern void AppendFileName(base, s1, s2) char *base, *s1, *s2; { (void)strcpy(base, s1); (void)strcat(base, s2); } extern int validArch(archtype) char *archtype; { int i; for (i = 0; i <= MAXARCH; i++) { if (!strcmp(archtype, archNames[i])) return 1; } return 0; } /*ARGSUSED*/ extern int checkHostType(s, t) char *s; arch t; { return 1; } extern int isSun4Target(h) Handle h; { return h->archtype == SUN4; } extern int isDecTarget(h) Handle h; { return h->archtype == DEC; } extern int isRS6000Target(h) Handle h; { return h->archtype == RS6000; } extern arch getArch() { #ifdef sun return SUN4; #elif AIX return RS6000; #elif ←←mips←← return DEC; #else return UNKNOWN; #endif } extern char *stringFromArch(archtype) arch archtype; { return archNames[(int)archtype]; } extern arch archFromString(s) char *s; { arch i; for (i = UNKNOWN; i <= MAXARCH; i++) { if (!strcmp(s, archNames[(int)i])) { return i; } } return UNKNOWN; } extern char *getwd←wo←automount(s) char *s; { char cwd[MAXPATHLEN], *wd; wd = getwd(cwd); if (wd == NULL) Fatal((Handle)0, "Couldn't determine working directory\n"); if (strstr(wd, AUTOMOUNT←PREFIX) != NULL) { /* must be automounted dir. */ wd += strlen(AUTOMOUNT←PREFIX); return wd; } else { /* local filesytem -- convert its name to net based view */ char hostname[MAXHOSTNAMELEN]; char rcwd[MAXPATHLEN]; char *common←prefix; struct stat filestat, dirstat; struct mntent *mnt; FILE *mnttbl; if (stat(s, &filestat) == -1 && stat(".", &filestat)) { Fatal((Handle)0, "Couldn't stat file"); } if ((mnttbl = setmntent(MOUNTED, "r")) == 0) { Fatal((Handle)0, "setmntent failed"); } while ((mnt = getmntent(mnttbl)) != 0) { if (stat(mnt->mnt←dir, &dirstat) == -1) { Fatal((Handle)0, "stat on dir failed"); } if (dirstat.st←dev == filestat.st←dev) { break; } } if (mnt == 0) { Fatal((Handle)0, "mount point not found"); } (void)endmntent(mnttbl); (void)gethostname(hostname, MAXHOSTNAMELEN); (void)sprintf(rcwd, "%s/%s%s", NET←AUTOMOUNT←PREFIX, hostname, mnt->mnt←dir); if (common←prefix = strstr(cwd, mnt->mnt←dir)) { (void)strcat(rcwd, cwd + strlen(mnt->mnt←dir)); } else { (void)strcat(rcwd, s); } return rcwd; } } extern char *getMach(h, archType) Handle h; arch archType; { /* * algorithm: 1. check MIMOSA←SERVER←arch environment variable * 2. check MIMOSA←SERVER environment variable * 3. generate random machine */ char env[21]; /* strlen("MIMOSA←SERVER←") + max arch string + 1 */ char *archString = stringFromArch(archType); char *mimServ; /* machine to rsh to */ sprintf(env, "%s←%s", MIMOSA←SERVER, archString); /* form environ var */ mimServ = getenv(env); /* step 1 */ if (mimServ) { return getMachInner(mimServ, archType); } else { mimServ = getenv(MIMOSA←SERVER); if (mimServ) { /* step 2 */ return getMachInner(mimServ, archType); } return getRandomMach(h); /* step 3 */ } } static char *getMachInner(host, archType) char *host; arch archType; { if (!checkHostType(host, archType)) { Warning((Handle)0, host); Warning((Handle)0, "not a "); Warning((Handle)0, stringFromArch(archType)); Warning((Handle)0, " architecture machine\n"); } return host; } static char *getRandomMach(h) Handle h; { extern long random(); extern int srandom(); char *s = stringFromArch(h->archtype); char *randomMachName; randomMachName = (char *)malloc(strlen(s) + 8); /* 8 == "host" + XXX + '\0' */ srandom(time((time←t *)0)); (void)sprintf(randomMachName, "%shost%03d", s, random() % MAXNUMMACH); return randomMachName; } /* Handle routines */ extern void FreeHandle(h) Handle h; { int temp = 0; (void)free(h->job.shortFileName); /* (void)free(h->job.workingDirectory); (void)free(h->job.userName); (void)free(h->job.userPassword); (void)free(h->job.nfsHostName); (void)free(h->serverName); */ /* for each source file, free the jobList entry */ for (temp=0; temp < h->nJobs; temp++) { (void)free(h->jobList[temp]); } (void)free((char *)h->jobList); (void)free((char *)h); } extern Handle NewHandle(argc, argv) int argc; char **argv; { Handle h; /*char *defaultServer = "hindenburg";*/ /*char *envServer;*/ int temp; /* allocate object */ h = (Handle) malloc(sizeof(Object)); h->job.userPassword = NULL; /* calloc(MAXNAMLEN, sizeof(char)); */ h->serverName = NULL; /* calloc(MAXNAMLEN, sizeof(char)); */ /* initialize object */ /* most default false */ for (temp = 0; temp < 26; temp++) h->job.switches[temp] = FALSE; /* envServer = getenv("MIMOSASERVER"); if (envServer) (void)strcpy(h->serverName, envServer); else (void)strcpy(h->serverName, defaultServer); */ h->optLevel = 3; h->jobID = 0; h->argv = argv; h->argc = argc; h->jobList = (char **)calloc((unsigned)argc, sizeof(char **)); h->nJobs = 0; /* h->client = NULL; */ h->inlineFile = NULL; h->archtype = UNKNOWN; return (h); } #ifdef ←IBMR2 /* * get/setmntent compatibility stuff -- AIX doesn't have these * routines so, emulate them with setfsent and getfsent. */ static FILE *setmntent(filep, type) char *filep; char *type; { setfsent(); return (FILE *)1; /* return bogus value -- only valid in call to getmntent() */ } static struct mntent *getmntent(f) FILE *f; { static struct mntent m; struct fstab *fs; if ((fs = getfsent()) == 0) return 0; m.mnt←dir = fs->fs←file; return &m; } static int endmntent(f) FILE *f; { endfsent(); return 1; } #endif /* Revision History * [lah 03-Nov-88] Add -x option. * [mna 24-Mar-91] * Massive changes made. Re-wrote large portions and deleted mimosa Server * stuff for now. */