/*
* LoaderUtilsImpl.c
* bj, August 4, 1989 9:12:48 pm PDT
* eduardo, November 20, 1989 10:29:52 am PST
* cc -c -g -I/jaune/xrhome/INSTALLED/INCLUDE/ LoaderUtilsImpl.c
*/
#include <xr/ThreadsMsg.h>
#define stdout XR←MSG←STDOUT
/* #include <ctype.h> */
#define ←U 01
#define ←L 02
#define ←N 04
#define ←S 010
#define ←P 020
#define 𡤌 040
#define ←X 0100
#define 𡤋 0200
static char 𡤌type←[] = { 0,
/*  0  1  2  3  4  5  6  7 */
/* 0*/ 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌,
/* 10*/ 𡤌, ←S|𡤌, ←S|𡤌, ←S|𡤌, ←S|𡤌, ←S|𡤌, 𡤌, 𡤌,
/* 20*/ 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌,
/* 30*/ 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌, 𡤌,
/* 40*/ ←S|𡤋, ←P, ←P, ←P, ←P, ←P, ←P, ←P,
/* 50*/ ←P, ←P, ←P, ←P, ←P, ←P, ←P, ←P,
/* 60*/ ←N|←X, ←N|←X, ←N|←X, ←N|←X, ←N|←X, ←N|←X, ←N|←X, ←N|←X,
/* 70*/ ←N|←X, ←N|←X, ←P, ←P, ←P, ←P, ←P, ←P,
/*100*/ ←P, ←U|←X, ←U|←X, ←U|←X, ←U|←X, ←U|←X, ←U|←X, ←U,
/*110*/ ←U, ←U, ←U, ←U, ←U, ←U, ←U, ←U,
/*120*/ ←U, ←U, ←U, ←U, ←U, ←U, ←U, ←U,
/*130*/ ←U, ←U, ←U, ←P, ←P, ←P, ←P, ←P,
/*140*/ ←P, ←L|←X, ←L|←X, ←L|←X, ←L|←X, ←L|←X, ←L|←X, ←L,
/*150*/ ←L, ←L, ←L, ←L, ←L, ←L, ←L, ←L,
/*160*/ ←L, ←L, ←L, ←L, ←L, ←L, ←L, ←L,
/*170*/ ←L, ←L, ←L, ←P, ←P, ←P, ←P, 𡤌,
/*200*/  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0
};
#defineisupper(c) ((𡤌type←+1)[c]&←U)
#define tolower(c) ((c)-'A'+'a')
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <dirent.h>
#include <xr/UIO.h>
#include <xr/Errno.h>
#include "XREnviron.h"
#include "LoaderUtils.h"
/* missing interface declarations */
externchar *XR←malloc();
externchar *XR←SPrintF();
typedef (*procpointer)();
static (*lrh𡤌ommand←ptr)() = (procpointer)XR←lrh𡤌ommand;
static (*Comment←ptr)() = (procpointer)XR𡤌omment𡤌ommand;
static (*RequireFrom←ptr)() = (procpointer)XR←RequireFrom𡤌ommand;
static (*ORequireFrom←ptr)() = (procpointer)XR←ORequireFrom𡤌ommand;
static (*DRequireFrom←ptr)() = (procpointer)XR𡤍RequireFrom𡤌ommand;
static (*LoadFrom←ptr)() = (procpointer)XR←LoadFrom𡤌ommand;
static (*RunFrom←ptr)() = (procpointer)XR←RunFrom𡤌ommand;
static (*ReleaseLocation←ptr)() = (procpointer)XR←ReleaseLocation𡤌ommand;
/* fatal error */
static int FatalVersionError(s) char *s; {
(void)XR𡤏PrintF(stdout, "Error - all UNames must have a %s.\n", s);
exit(1);
}
/* string utilities */
static char *LowerCase(s) char *s; {
int length = strlen(s);
char *scratch = (char *)XR←malloc((unsigned)(length+1));
int i; int c;
scratch[length] = NULL;
for ( i = 0; i < length; i++ ) { c = s[i]; scratch[i] = isupper(c) ? tolower(c) : c; };
return(scratch);
};
static char *LowerCaseAndDot(s) char *s; {
int length = strlen(s);
char *scratch = (char *)XR←malloc((unsigned)(length+1));
int i; int c;
scratch[length] = NULL;
for ( i = 0; i < length; i++ ) {
c = s[i];
c = isupper(c) ? tolower(c) : c;
scratch[i] = (c == CHDOT) ? CHUNDERSCORE : c;
};
return(scratch);
};
static void StripCR(s) char *s; {
int last = strlen(s) - 1;
if ( last < 0) { return; };
if ( s[last] == CHCR ) { s[last] = NULL; };
}
static void StripSlash(s) char *s; {
int last = strlen(s) - 1;
if ( last < 0) { return; };
if ( s[last] == CHSLASH ) { s[last] = NULL; };
}
/* stuff */
static int ParseBaseAndVersion(base) char *base; {
int version; /* result */
char *temp = strchr(base, CHTILDE);
if (temp == NULL)
{ /* NO version */
version = 0;
}
else { /* version exists */
char *versionPlus = temp+1;
temp = temp - 1;
if ( temp[0] != CHDOT ) { FatalVersionError("version"); };
temp[0] = NULL; /* delete the ".~" */
temp[1] = NULL;
temp = strchr(versionPlus, CHTILDE);
if ( temp == NULL ) { FatalVersionError("version"); };
temp[0] = NULL;
version = atoi(versionPlus);
if ( version == 0 ) { FatalVersionError("non-zero version"); };
}
return(version);
}
static int ParseUName(name, pathPrefix, base) char *name, *pathPrefix, *base; {
int version; /* result */
char pattern[1024];
char *temp, *basePlus;
(void)strcpy(pattern, name);
/* first get the path prefix */
if ( pattern[0] != CHSLASH ) { FatalVersionError("leading slash(/)"); };
temp = strrchr(pattern, CHSLASH);
if ( temp == NULL ) { FatalVersionError("directory part"); };
basePlus = temp + 1;
temp[0] = NULL;
(void)strcpy(pathPrefix, pattern);
/* next get base */
(void)strcpy(base, basePlus);
version = ParseBaseAndVersion(base);
return(version);
}
static void GetPattern(pattern, pathPrefix, base) char *pattern, *pathPrefix, *base; {
(void)strcpy(pattern, pathPrefix);
(void)strcat(pattern, STRSLASH);
(void)strcat(pattern, base);
}
static void ParseDirectoryAndFileName(directory, fileNamePrefix, pattern)
char *directory, *fileNamePrefix, *pattern; {
char *temp;
(void)strcpy(directory, pattern);
temp = strrchr(directory, CHSLASH);
(void)strcpy(fileNamePrefix, temp+1);
temp[0] = NULL;
}
static int GetVersionFromName(name) char *name; {
int version; /* result */
char buf[1024];
(void)strcpy(buf, name);
version = ParseBaseAndVersion(buf);
return(version);
}
/* File System & Directory access */
DIR *OpenDir(name) char *name; {
register DIR *dirp; /* result */
register int fd;
struct stat sb;
if ( ( fd = XR←Open(name, 0) ) == -1 ) { return(NULL); };
if ( XR𡤏Stat(fd, &sb) == -1 ) { (void) XR𡤌lose(fd); return(NULL); }
if ( ( sb.st←mode & S←IFMT ) != S←IFDIR )
{ XR←SetErrno(ENOTDIR); (void) XR𡤌lose(fd); return(NULL); }
if ( ((dirp = (DIR *)XR←malloc(sizeof(DIR))) == NULL )
|| ((dirp->dd𡤋uf =XR←malloc((unsigned)sb.st𡤋lksize)) == NULL)) {
if (dirp) free((char *)dirp);
(void) XR𡤌lose(fd);
return(NULL);
}
dirp->dd� = fd;
dirp->dd←loc = 0;
dirp->dd←size = 0;
dirp->dd𡤋size = sb.st𡤋lksize;
dirp->dd←off = 0;
return(dirp);
}
int CloseDir(dirp) DIR *dirp; {
int fd;
fd = dirp->dd�
dirp->dd� = -1;
dirp->dd←loc = 0;
(void)free(dirp->dd𡤋uf);
(void)free((char *)dirp);
return(XR𡤌lose(fd));
}
struct dirent *ReadDir(dirp) DIR *dirp; {
struct dirent *dp;
int saveloc = 0;
next:
if (dirp->dd←size != 0) {
dp = (struct dirent *)&dirp->dd𡤋uf[dirp->dd←loc];
saveloc = dirp->dd←loc; /* save for possible EOF */
dirp->dd←loc += dp->d←reclen;
}
if (dirp->dd←loc >= dirp->dd←size) dirp->dd←loc = dirp->dd←size = 0;
if ( dirp->dd←size == 0 /* refill buffer */ && ( (dirp->dd←size = XR←GetDEnts(dirp->dd�, dirp->dd𡤋uf, dirp->dd𡤋size)) <= 0 ) ) {
if ( dirp->dd←size == 0 )
{ dirp->dd←loc = saveloc; }; /* This means EOF, so save for telldir */
return(NULL); /* error or EOF */
}
dp = (struct dirent *)&dirp->dd𡤋uf[dirp->dd←loc];
if ( dp->d←reclen <= 0 ) { return(NULL); };
if ( dp->d𡤏ileno == 0 ) { goto next; };
dirp->dd←off = dp->d←off;
return(dp);
}
/* more stuff */
static int GetHighestVersion(pattern) char *pattern; {
int highestVersion = -1; /* result */
char directory[1024];
char fileNamePrefix[100];
int len;
int version = -1;
DIR *dirp;
struct dirent *dp;
ParseDirectoryAndFileName(directory, fileNamePrefix, pattern);
dirp = OpenDir(directory);
if (dirp == NULL) return(highestVersion);
len = strlen(fileNamePrefix);
for (dp = ReadDir(dirp); dp != NULL; dp = ReadDir(dirp)) {
if ( ! strncmp(dp->d←name, fileNamePrefix, len) ) {
version = GetVersionFromName(dp->d←name);
if ( version > highestVersion ) { highestVersion = version; };
};
};
(void)CloseDir (dirp);
return(highestVersion);
}
static void MakeUName(pattern, pathPrefix, base, version)
char *pattern, *pathPrefix, *base; int version; {
char buf[10];
(void)strcpy(pattern, pathPrefix);
(void)strcat(pattern, STRSLASH);
(void)strcat(pattern, base);
(void)strcat(pattern, STRDOTTILDE);
(void)XR←SPrintF(buf, "%d", version);
(void)strcat(pattern, buf);
(void)strcat(pattern, STRTILDE);
}
static void ExpandFileVersion(oldfile, newfile) char *oldfile, *newfile; {
char pathPrefix[1024];
char base[255];
int version;
(void)ParseUName(oldfile, pathPrefix, base);
GetPattern(newfile, pathPrefix, base);
version = GetHighestVersion(newfile);
MakeUName(newfile, pathPrefix, base, version);
}
extern void getnewfile(oldfile, newfile) char *oldfile, *newfile; { /* backward compat */
ExpandFileVersion(oldfile, newfile);
};
void XR𡤌omment𡤌ommand(command) char *command; {
};
void XR←RequireFrom𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *pkg; char *module;
char *path; char *directory; char *file; char *cmd; char *fullname;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
pkg = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
module = strtok((char *)NULL, STRPUNCTUATION);
file = LowerCase(module);
directory = XR←getenv(releasevar); StripSlash(directory);
path = (char *)XR←malloc((unsigned)(strlen(directory) + strlen(pkg) + strlen(file) + 20));
(void)XR←SPrintF(path, "%s/%s/sun4/%s.c2c.o", directory, pkg, file);
fullname = (char *)XR←malloc((unsigned)(strlen(path) + 20));
ExpandFileVersion(path, fullname);
cmd = (char *)XR←malloc((unsigned)(strlen(fullname) + strlen(module) + 20));
(void)XR←SPrintF(cmd, "LoadAndRun %s %s \n", fullname, module);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, pkg: {%s} module: {%s}]\n",
releasename, pkg, module);
(void)XR𡤏PrintF(stdout, " %s", cmd);
XR←SetCurrentCommand(cmd);
XR←loadAndRun𡤌ommand(cmd);
(void)free(scratch);
};
void XR𡤍RequireFrom𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *pkg; char *module;
char *path; char *directory; char *file; char *cmd; char *fullname;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
pkg = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
module = strtok((char *)NULL, STRPUNCTUATION);
file = LowerCase(module);
directory = XR←getenv(releasevar); StripSlash(directory);
path = (char *)XR←malloc((unsigned)(strlen(directory) + strlen(pkg) + strlen(file) + 20));
(void)XR←SPrintF(path, "%s/%s/sun4/%s.c2c.o", directory, pkg, file);
fullname = (char *)XR←malloc((unsigned)(strlen(path) + 20));
ExpandFileVersion(path, fullname);
cmd = (char *)XR←malloc((unsigned)(strlen(fullname) + strlen(module) + 20));
(void)XR←SPrintF(cmd, "LoadAndRun %s %s -d \n", fullname, module);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, pkg: {%s} module: {%s}]\n",
releasename, pkg, module);
(void)XR𡤏PrintF(stdout, " %s", cmd);
XR←SetCurrentCommand(cmd);
XR←loadAndRun𡤌ommand(cmd);
(void)free(scratch);
};
void XR←ORequireFrom𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *pkg; char *module;
char *path; char *directory; char *file; char *cmd; char *fullname;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
pkg = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
module = strtok((char *)NULL, STRPUNCTUATION);
file = LowerCase(module);
directory = XR←getenv(releasevar); StripSlash(directory);
path = (char *)XR←malloc((unsigned)(strlen(directory) + strlen(pkg) + strlen(file) + 20));
(void)XR←SPrintF(path, "%s/%s/sun4-o3/%s.c2c.o", directory, pkg, file);
fullname = (char *)XR←malloc((unsigned)(strlen(path) + 20));
ExpandFileVersion(path, fullname);
cmd = (char *)XR←malloc((unsigned)(strlen(fullname) + strlen(module) + 20));
(void)XR←SPrintF(cmd, "LoadAndRun %s %s -d \n", fullname, module);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, pkg: {%s} module: {%s}]\n",
releasename, pkg, module);
(void)XR𡤏PrintF(stdout, " %s", cmd);
XR←SetCurrentCommand(cmd);
XR←loadAndRun𡤌ommand(cmd);
(void)free(scratch);
};
void XR←LoadFrom𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *pkg; char *module;
char *path; char *directory; char *file; char *cmd; char *fullname;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
pkg = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
module = strtok((char *)NULL, STRPUNCTUATION);
file = LowerCase(module);
directory = XR←getenv(releasevar); StripSlash(directory);
path = (char *)XR←malloc((unsigned)(strlen(directory) + strlen(pkg) + strlen(file) + 20));
(void)XR←SPrintF(path, "%s/%s/sun4/%s.c2c.o", directory, pkg, file);
fullname = (char *)XR←malloc((unsigned)(strlen(path) + 20));
ExpandFileVersion(path, fullname);
cmd = (char *)XR←malloc((unsigned)(strlen(fullname) + strlen(module) + 20));
(void)XR←SPrintF(cmd, "Load %s %s \n", fullname, module);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, pkg: {%s} module: {%s}]\n",
releasename, pkg, module);
(void)XR𡤏PrintF(stdout, " %s", cmd);
XR←SetCurrentCommand(cmd);
XR←load𡤌ommand(cmd);
(void)free(scratch);
};
void XR←RunFrom𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *pkg; char *module;
char *path; char *directory; char *file; char *cmd; char *fullname;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
pkg = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
module = strtok((char *)NULL, STRPUNCTUATION);
file = LowerCase(module);
directory = XR←getenv(releasevar); StripSlash(directory);
path = (char *)XR←malloc((unsigned)(strlen(directory) + strlen(pkg) + strlen(file) + 20));
(void)XR←SPrintF(path, "%s/%s/sun4/%s.c2c.o", directory, pkg, file);
fullname = (char *)XR←malloc((unsigned)(strlen(path) + 20));
ExpandFileVersion(path, fullname);
cmd = (char *)XR←malloc((unsigned)(strlen(fullname) + strlen(module) + 20));
(void)XR←SPrintF(cmd, "Run %s %s \n", fullname, module);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, pkg: {%s} module: {%s}]\n",
releasename, pkg, module);
(void)XR𡤏PrintF(stdout, " %s", cmd);
XR←SetCurrentCommand(cmd);
XR←run𡤌ommand(cmd);
(void)free(scratch);
};
void XR←ReleaseLocation𡤌ommand(command) char *command; {
char *releasename; char *releasevar; char *directory;
char *scratch = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(scratch, command);
(void)strtok(scratch, STRPUNCTUATION); /* skip the command name */
releasename = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
releasevar = LowerCaseAndDot(releasename);
directory = LowerCase(strtok((char *)NULL, STRPUNCTUATION));
XR←setenv(releasevar, directory, 1);
if ( 0 == 1 ) (void)XR𡤏PrintF(stdout, "[release: {%s}, directory: {%s}]\n", releasename, directory);
(void)free(scratch);
};
void XR←lrh𡤌ommand(command) char *command; {
char *cmd←rememberer;
char *rest, *oldfile;
char *new = (char *)XR←malloc((unsigned)(strlen(command) + 100));
char *newcommand = (char *)XR←malloc((unsigned)(strlen(command) + 100));
(void)strcpy(new, command);
/* discard the lrh */
(void)strtok(new, STRWHITESPACE);
oldfile = strtok((char *)NULL, STRWHITESPACE);
rest = strtok((char *)NULL, STRNULL);
StripCR(oldfile);
ExpandFileVersion(oldfile, new);
(void)strcpy(newcommand, "lr ");
(void)strcat(newcommand, new);
(void)strcat(newcommand, STRBLANK);
if ( rest != NULL ) {
(void)strcat(newcommand, STRBLANK);
(void)strcat(newcommand, rest);
}
cmd←rememberer = (char *)XR←malloc((unsigned)(strlen(newcommand) + 1));
(void)strcpy(cmd←rememberer, newcommand);
if ( XR←load𡤌ommand(newcommand) ) { XR←run𡤌ommand(cmd←rememberer); };
(void)free(new);
}
void XR←install←LoaderUtilsImpl() { /* PRE-start trap */
};
void XR←run←LoaderUtilsImpl() { /* start trap */
RequireFrom PCedar1.1 SunPMap SunPMapClientStub
ReleaseLocation PCedar1.1 /pixel2/pcedar1.1/
XR←register("lrh", &lrh𡤌ommand←ptr, "Like lr, but use !h", 0);
XR←register("#", &Comment←ptr, "the obvious noop", 0);
XR←register("--", &Comment←ptr, "the obvious noop", 0);
XR←register("Comment", &Comment←ptr, "the obvious noop", 0);
XR←register("RequireFrom", &RequireFrom←ptr, "LoadAndRun(release, pkg, module)", 0);
XR←register("DRequireFrom", &DRequireFrom←ptr, "LoadAndRun(release, pkg, module) -d", 0);
XR←register("ORequireFrom", &ORequireFrom←ptr, "LoadAndRunOptimizedVersion(release, pkg, module) -d", 0);
XR←register("LoadFrom", &LoadFrom←ptr, "Load(release, pkg, module)", 0);
XR←register("RunFrom", &RunFrom←ptr, "Run(release, pkg, module)", 0);
XR←register("ReleaseLocation", &ReleaseLocation←ptr,
"setenv ReleaseLocation (release)", 0);
}
/* eof */