/*
* 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.
*/