diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/rslm/rslm.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/sdktools/rslm/rslm.c')
-rw-r--r-- | private/sdktools/rslm/rslm.c | 1111 |
1 files changed, 1111 insertions, 0 deletions
diff --git a/private/sdktools/rslm/rslm.c b/private/sdktools/rslm/rslm.c new file mode 100644 index 000000000..7872bea60 --- /dev/null +++ b/private/sdktools/rslm/rslm.c @@ -0,0 +1,1111 @@ +// +// RSLM.C +// +// rslm - a huge multi-project tool +// + +#include <stdlib.h> +#include <ctype.h> +#include <process.h> +#include <io.h> +#include <stdio.h> +#include <string.h> +#include <direct.h> +#include <windows.h> + +/* + * Globals + */ +char szParentProject[32] = ""; +char szParentServer[MAX_PATH] = ""; +char szInfoFileName[MAX_PATH] = "rslm.ini"; +char szDefInfoFileName[] = "rslm.ini"; +char szSlmFileName[] = "slm.ini"; +char szNoLock[] = "NoLock"; +char szLocalMetaRoot[MAX_PATH] = ""; +BOOL fAsync = FALSE; +BOOL fRecurse = FALSE; +BOOL fBuildFiles = FALSE; +BOOL fDebug = FALSE; +BOOL fBatch = FALSE; +BOOL fKeep = FALSE; +BOOL fMinimized = FALSE; +BOOL fValidate = FALSE; +int iOutputFile = 0; +WIN32_FIND_DATA wfd; + +/* + * Prototypes + */ +BOOL SpawnEnlistCmd(char **argv, char *pszServer, char *pszProject); +BOOL SpawnSlmckCmd( char **argv, char *pszServer, char *pszProject); +BOOL SpawnOtherCmd( char **argv, char *pszServer, char *pszProject); +BOOL Noop( char **argv, char *pszServer, char *pszProject); +BOOL GrabReadLock( char **argv, char *pszServer, char *pszProject); +BOOL GrabWriteLock( char **argv, char *pszServer, char *pszProject); +BOOL ReleaseLock( char **argv, char *pszServer, char *pszProject); +BOOL CallRslm( char **argv, char *pszServer, char *pszProject); + +/* + * structures + */ +typedef struct tagSPAWNINFO { + char *pszCmd; + BOOL (*pfnSpawn)(char **, char*, char*); +} SPAWNINFO, *PSPAWNINFO; + +SPAWNINFO aLockCmdData[] = { + { "ssync", GrabReadLock }, + { "in", GrabWriteLock }, + { NULL, Noop } +}; + +SPAWNINFO aPreCmdData[] = { + { "enlist", SpawnEnlistCmd }, + { "slmck", SpawnSlmckCmd }, + { "defect", Noop }, + { "sadmin", SpawnSlmckCmd }, + { NULL, SpawnOtherCmd } +}; + +SPAWNINFO aPostCmdData[] = { + { "defect", SpawnOtherCmd }, + { NULL, Noop } +}; + +SPAWNINFO aUnlockCmdData[] = { + { "ssync", ReleaseLock }, + { "in", ReleaseLock }, + { NULL, Noop } +}; + + +LPSTR *ParseCmdLine( +LPSTR *parg) +{ + LPSTR arg; + + ++parg; // skip name of us + +nextArg: + + arg = *parg; + + if (arg == NULL || (*arg != '-' && *arg != '/')) { + return(parg); // last arg + } + + parg++; // parg points to next arg + + while (TRUE) { + arg++; // skip switch char + switch (toupper(*arg)) { + case '\0': + case ' ': + goto nextArg; + + case 'A': + fAsync = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -a\n"); + } + break; + + case 'B': + fBuildFiles = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -b\n"); + } + break; + + case 'C': + fBatch = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -c\n"); + } + break; + + case 'D': + fDebug = TRUE; + fprintf(stderr, "PARAM: -d\n"); + break; + + case 'F': + if (*parg == NULL) { + goto usage; + } + strcpy(szInfoFileName, *parg++); + if (fDebug) { + fprintf(stderr, "PARAM: -f %s\n", szInfoFileName); + } + goto nextArg; + + case 'K': + fKeep = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -k\n"); + } + break; + + case 'L': + if (*parg == NULL) { + goto usage; + } + strcpy(szLocalMetaRoot, *parg++); + if (fDebug) { + fprintf(stderr, "PARAM: -l %s\n", szLocalMetaRoot); + } + goto nextArg; + + case 'M': + fMinimized = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -m\n"); + } + break; + + case 'P': + if (*parg == NULL) { + goto usage; + } + strcpy(szParentProject, *parg++); + if (fDebug) { + fprintf(stderr, "PARAM: -p %s\n", szParentProject); + } + goto nextArg; + + case 'R': + fRecurse = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -r\n"); + } + break; + + case 'S': + if (*parg == NULL) { + goto usage; + } + strcpy(szParentServer, *parg++); + if (fDebug) { + fprintf(stderr, "PARAM: -s %s\n", szParentServer); + } + goto nextArg; + + case 'V': + fValidate = TRUE; + if (fDebug) { + fprintf(stderr, "PARAM: -v\n"); + } + break; + + default: +usage: + fprintf(stderr, "usage: rslm [options] <command line>\n"); + fprintf(stderr, " -a (async spawn)\n"); + fprintf(stderr, " -b (build infofiles)\n"); + fprintf(stderr, " -c (emit batch file to std out - no spawn)\n"); + fprintf(stderr, " -d (debug mode)\n"); + fprintf(stderr, " -f rslmfile (default=\"rslm.ini\")\n"); + fprintf(stderr, " -k (keep async spawn windows around)\n"); + fprintf(stderr, " -l lockdir (\"NoLock\" turns off meta locking)\n"); + fprintf(stderr, " -m (async spawn windows minmimzed)\n"); + fprintf(stderr, " -p project (defaults to slm.ini project)\n"); + fprintf(stderr, " -r (do command on all dirs w/infofile.)\n"); + fprintf(stderr, " -s slm_server (defaults to slm.ini server root)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "set RSLM_OPTS environent variable for new defaults.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "<command line> may contain the following substitute patterns:\n"); + fprintf(stderr, " %%CUR_PATH%% => full path of Current Directory at spawn time.\n"); + fprintf(stderr, " %%CUR_DIR%% => name of current directory at spawn time.\n"); + _exit(1); + } + } + + return(parg); +} + + + +VOID mystrrpl( +char *psz, +char cFind, +char cReplace) +{ + while (*psz != '\0') { + if (*psz == cFind) { + *psz = cReplace; + } + psz++; + } +} + + +/* + * Open file named pszSlmFileName and fill pszProject and pszServer from + * that file. (buffers are assumed large enough) Returns fSuccess. + */ +BOOL ExtractSlmIniInfo( +char *pszSlmFileName, +char *pszProject, +char *pszServer) +{ + static char szProjectKey[] = "project = "; + static char szServerKey[] = "slm root = "; + static char szSlmFileLine[MAX_PATH]; + FILE *hFile; + char *psz, *psz2; + + hFile = fopen(pszSlmFileName, "r"); + if (hFile == NULL) { + return(FALSE); + } + fgets(szSlmFileLine, MAX_PATH, hFile); // line 1 + + psz = strstr(szSlmFileLine, szProjectKey); + if (psz == NULL) { + fclose(hFile); + return(FALSE); + } + strcpy(pszProject, psz + strlen(szProjectKey)); + pszProject[strlen(pszProject) - 1] = '\0'; // remove \n + + fgets(szSlmFileLine, MAX_PATH, hFile); // line 2 + + psz = strstr(szSlmFileLine, szServerKey); + if (psz == NULL) { + fclose(hFile); + return(FALSE); + } + psz += strlen(szServerKey); + if (psz[3] == ':') { + // Its a local slm project, clean up the string + psz += 2; // skip '//' + psz2 = strchr(psz, '/'); + *--psz2 = ':'; + *--psz2 = *psz; + psz = psz2; + } + strcpy(pszServer, psz); + pszServer[strlen(pszServer) - 1] = '\0'; // remove \n + mystrrpl(pszServer, '/', '\\'); + + fclose(hFile); + return(TRUE); +} + + +/* + * Reads next line of hRslmFile and fills pszProject and pszServer with + * apropriate info from that line. Returns fSuccess. + */ +BOOL ExtractRslmLine( +FILE *hRslmFile, +LPSTR pszProject, +LPSTR pszServer) +{ + char szBuf[100]; + LPSTR psz; + + if (fgets(szBuf, 100, hRslmFile) == NULL) { + return(FALSE); + } + psz = strchr(szBuf, ' '); + if (psz == NULL) { + return(FALSE); + } + *psz++ = '\0'; + while (isspace(*psz)) { + psz++; + } + psz[strlen(psz) - 1] = '\0'; // remove \n + strcpy(pszServer, psz); + strcpy(pszProject, szBuf); + return(pszServer[0] && pszProject[0]); +} + + +/* + * Recurse from current directory depth first on all directories containing + * szSlmFileName files. Create szInfoFileName files at + * nodes where any descendant directories have projects differing from + * the parent directory's project. + * + * Returns fInfoFileCreated. Emits a message if directory structure is + * not ok. (ie, no rslm.ini file (except the root) should exist without + * its parent directory having an rslm.ini file too. + */ +BOOL BuildFiles( +LPSTR pszCurProj) +{ + HANDLE hFF; + char szProject[32]; + char szServer[MAX_PATH]; + FILE *hInfoFile, *hFile; + char szCurPath[MAX_PATH]; + BOOL fSlmOk; + BOOL fInfoFileCreated = FALSE; + BOOL fChildInfoFileCreated = FALSE; + + GetCurrentDirectory(MAX_PATH, szCurPath); + + // + // delete any existing rslm.ini file + // + hFile = fopen(szInfoFileName, "r"); + if (hFile != NULL) { + fclose(hFile); + if (remove(szInfoFileName) == -1) { + fprintf(stderr, "RSLM: Could not delete %s\\%s\n", szCurPath, + szInfoFileName); + return(FALSE); + } + } + + // + // for each subdirectory... + // + hFF = FindFirstFile("*.*", &wfd); + while (hFF) { + if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + goto nextFile; + } + + if (!strcmp(wfd.cFileName, "..") || !strcmp(wfd.cFileName, ".")) { + goto nextFile; + } + + if (!SetCurrentDirectory(wfd.cFileName)) { + goto nextFile; + } + /* + * if this sub-directory doesn't have an slm.ini file, skip it. + */ + hFile = fopen(szSlmFileName, "r"); + if (hFile == NULL) { + SetCurrentDirectory(".."); + goto nextFile; + } + fclose(hFile); + + fSlmOk = ExtractSlmIniInfo(szSlmFileName, szProject, szServer); + + if (fSlmOk) { + fChildInfoFileCreated |= BuildFiles(szProject); + } + + SetCurrentDirectory(".."); + + if (!fSlmOk) { + fprintf(stderr, "\nRSLM: Can't parse %s\\%s\\%s\n", szCurPath, wfd.cFileName, szSlmFileName); + } else { + /* + * Append child project info if its not part of the current proj. + */ + if (_stricmp(szProject, pszCurProj)) { + hInfoFile = fopen(szInfoFileName, "a"); + if (hInfoFile == NULL) { + fprintf(stderr, "RSLM: Couldn't append to %s.\n", szInfoFileName); + return(FALSE); + } + fprintf(hInfoFile, "%s %s\n", szProject, szServer); + fclose(hInfoFile); + fprintf(stdout, "%s\\%s << %s %s\n", szCurPath, szInfoFileName, szProject, szServer); + fInfoFileCreated = TRUE; + } + } + +nextFile: + if (!FindNextFile(hFF, &wfd)) { + FindClose(hFF); + break; + } + } + if (fDebug) { + fprintf(stderr, "RSLM: %d->%d at %s\n", fInfoFileCreated, fChildInfoFileCreated, szCurPath); + } + if (fChildInfoFileCreated && !fInfoFileCreated) { + fprintf(stderr, "RSLM: Invalid project structure at %s.\n", szCurPath); + } + return(fInfoFileCreated); +} + + +/* + * This routine validates an RSLM metaproject by ssyncing all rslm.ini files + * and making sure the directory structure reflects what the rslm.ini file + * says it should be. + * + * 1) reconcile szInfoFileName file (if not rslm.ini) to new rslm.ini file. + * a) If the new rslm.ini file contains a project that is not in the + * szInfoFIleName file, add it to the szInfoFIleName File. + * b) If the new rslm.ini file server is different from the + * szInforFIleName file server name, fix the szInfoFileName server + * name. Add an entry to the global changed file. + * c) If the new rslm.ini file does not contain projects that are in + * the szInfoFileName file, comment out entry from the szInfoFileName + * file. + * + * 2) for each subdirectory that has an slm.ini file with a project + * different from the current project name: + * a) if it is NOT in the szInfoFIleName file, add entry to global + * remove project file. + * + * 3) recurse on all directories with an rslm.ini file. + * + * 4) for each non-comment entry in the szInfoFileName file: + * a) if no directory exists with the project name: + * 1) if project exists in removed global list, mv removed project + * to current directory and remove entry from global removed list. + * 2) otherwise, enlist in the new project. + * + * 5) for each project in the global removed list, defect from that node. + * + * 6) for each project in the global changed list, slmck that node. + */ +BOOL Validate( +LPSTR pszCurProj) +{ +#if 0 + char szCurDir[MAX_PATH]; + FILE *hInfoFile; + + static char *ssyncArgs[] = { "ssync", "rslm.ini", NULL }; + + if (fBatch) { + fprintf(stderr, "RSLM: Can't validate in batch mode.\n"); + return(FALSE); + } + + if (fAsync) { + fprintf(stderr, "RSLM: Can't validate in assync mode.\n"); + return(FALSE); + } + + if (fRecurse) { + fprintf(stderr, "RSLM: Can't validate in recurse mode.\n"); + return(FALSE); + } + + GetCurrentDirectory(MAX_PATH, szCurDir); + + MySpawn(P_WAIT, ssyncArgs, NULL, 0); + if (_stricmp(szInfoFileName, szDefInfoFileName)) { + ReconcileInfoFile(); + } + + hInfoFile = fopen(szInfoFileName, "r"); + if (hInfoFile == NULL) { + hInfoFile = fopen(szDefInfoFileName, "r"); + if (hInfoFile == NULL) { + return(FALSE); + } + } + + // + // for each subdirectory... + // + hFF = FindFirstFile("*.*", &wfd); + while (hFF) { + if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + goto nextFile; + } + + if (!strcmp(wfd.cFileName, "..") || !strcmp(wfd.cFileName, ".")) { + goto nextFile; + } + + if (!SetCurrentDirectory(wfd.cFileName)) { + goto nextFile; + } + /* + * if this sub-directory doesn't have an slm.ini file, skip it. + */ + hFile = fopen(szSlmFileName, "r"); + if (hFile == NULL) { + SetCurrentDirectory(".."); + goto nextFile; + } + fclose(hFile); + + fSlmOk = ExtractSlmIniInfo(szSlmFileName, szDirProject, szDirServer); + + SetCurrentDirectory(".."); + + if (!fSlmOk) { + goto nextFile; + } + + /* + * searsh rslm.ini file for szThisProject + */ + rewind(hInfoFile); + while (ExtractRslmLine(hInfoFile, szThisProject, szThisServer)) { + if (!_stricmp(szThisProject, szDirProject) { + if (_stricmp(szThisServer, szDirServer)) { + goto nextFile; // cool, no problems + } else { + Append(pszChanged, szThisProject, szThisServer, szCurDir); + goto nextFile; + } + } + } + /* + * Getting here means we did not find an rslm.ini line to account + * for szThisProject. We need to remove it. + */ + Append(pszRemoved, szThisProject, szThisServer, szCurDir); + +nextFile: + if (!FindNextFile(hFF, &wfd)) { + FindClose(hFF); + break; + } + } + + fclose(hInfoFile); +#endif + return(TRUE); +} + + +char *Substitute( +char *pszIn) +{ + static char szCurDir[MAX_PATH]; + char *pszOut, *pszOut2; + + if (!_stricmp(pszIn, "%%CUR_PATH%%") || + !strcmp(pszIn, "%%CUR_DIR%%")) { + GetCurrentDirectory(MAX_PATH, szCurDir); + pszOut = szCurDir; + if (!_stricmp(pszIn, "%%CUR_DIR%%")) { + pszOut = strrchr(szCurDir, '\\'); + if (pszOut == NULL) { + pszOut = szCurDir; + } else { + pszOut++; + } + } + return(pszOut); + } + return(pszIn); +} + +/* + * spawns the command in argv using the mode form. If argInsert is provided, + * those params are inserted into the argv params at param offset + * cCommandsBeforeInsert. If fRelease is set, the -r switch is propigated + * on spawns if "rslm" is an arguement. + * + * stdout is flushed after each spawn. + */ +int MySpawn( +int mode, +char *argv[], +char *argInsert[], +int cCommandsBeforeInsert) +{ + char *modarg[32]; + int iMod, iRet, j, k, iArg, iAdded; + char szFullPath[MAX_PATH]; + char szCurDir[MAX_PATH]; + char *pszFilePart; + DWORD dw; + + iMod = 0; + iArg = 0; + iAdded = 0; + if (fAsync) { + modarg[iMod++] = "start"; + iAdded++; + if (fMinimized) { + modarg[iMod++] = "/MIN"; + iAdded++; + } + if (fKeep) { + modarg[iMod++] = "cmd"; + iAdded++; + modarg[iMod++] = "/K"; + iAdded++; + } + } + while (iMod < cCommandsBeforeInsert + iAdded && argv[iArg] != NULL) { + modarg[iMod++] = Substitute(argv[iArg++]); + } + j = iMod; + while (argInsert != NULL && argInsert[iMod - j] != NULL) { + modarg[iMod] = Substitute(argInsert[iMod - j]); + iMod++; + } + while (argv[iArg] != NULL) { + modarg[iMod++] = Substitute(argv[iArg++]); + } + modarg[iMod] = NULL; + +searchIt: + + if (!SearchPath(NULL, modarg[0], ".com", MAX_PATH, szFullPath, &pszFilePart)) + if (!SearchPath(NULL, modarg[0], ".exe", MAX_PATH, szFullPath, &pszFilePart)) + if (!SearchPath(NULL, modarg[0], ".cmd", MAX_PATH, szFullPath, &pszFilePart)) + if (!SearchPath(NULL, modarg[0], ".bat", MAX_PATH, szFullPath, &pszFilePart)) { + /* + * assume its an internal command + */ + for (iMod = 30; iMod; iMod--) { + modarg[iMod] = modarg[iMod - 2]; + } + modarg[0] = "cmd"; + modarg[1] = "/c"; + goto searchIt; + } + + if (fDebug) { + fprintf(stderr, "RSLM: spawning: "); + for (iMod = 0; modarg[iMod] != NULL; iMod++) { + fprintf(stderr, "%s ", modarg[iMod]); + } + fprintf(stderr, "\n"); + } + + if (fBatch) { + GetCurrentDirectory(MAX_PATH, szCurDir); + fprintf(stdout, "cd %s\n", szCurDir); + for (iMod = 0; modarg[iMod] != NULL; iMod++) { + fprintf(stdout, "%s ", modarg[iMod]); + } + fprintf(stdout, "\n"); + iRet = 0; + } else { + modarg[0] = szFullPath; + iRet = spawnv(mode, modarg[0], modarg); + } + fflush(stdout); + + return(iRet); +} + + +BOOL GrabReadLock( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + static char *readlockargs[] = { + "cookie", "-r", "-c", "\"Autolock - (RSLM)\"", NULL + }; + char szCurDir[MAX_PATH]; + int iRet; + + if (!_stricmp(szLocalMetaRoot, szNoLock)) { + return(TRUE); // skip locks + } + + /* + * cd to local dir with meta-project locks + */ + GetCurrentDirectory(MAX_PATH, szCurDir); + if (!SetCurrentDirectory(szLocalMetaRoot)) { + fprintf(stderr, "RSLM: Bad or unspecified rslm lock directory [%s].\n", + szLocalMetaRoot); + return(FALSE); + } + /* + * Get the cookie! + */ + iRet = MySpawn(P_WAIT, readlockargs, NULL, 0); + if (fBatch) { + fprintf(stdout, "if ERRORLEVEL==1 goto end\n"); + } + SetCurrentDirectory(szCurDir); + if (iRet) { + fprintf(stderr, "RSLM: Unable to obtain root lock.\n"); + return(FALSE); + } + return(TRUE); +} + + +BOOL GrabWriteLock( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + static char *readlockargs[] = { + "cookie", "-w", "-c", "\"Autolock - (RSLM)\"", NULL + }; + char szCurDir[MAX_PATH]; + int iRet; + + if (!_stricmp(szLocalMetaRoot, szNoLock)) { + return(TRUE); // skip locks + } + + /* + * cd to local dir with meta-project locks + */ + GetCurrentDirectory(MAX_PATH, szCurDir); + if (!SetCurrentDirectory(szLocalMetaRoot)) { + fprintf(stderr, "RSLM: Bad or unspecified rslm lock directory [%s].\n", + szLocalMetaRoot); + return(FALSE); + } + /* + * Get the cookie! + */ + iRet = MySpawn(P_WAIT, readlockargs, NULL, 0); + SetCurrentDirectory(szCurDir); + if (iRet) { + fprintf(stderr, "RSLM: Unable to obtain root lock.\n"); + return(FALSE); + } + return(TRUE); +} + + +BOOL ReleaseLock( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + static char *freelockargs[] = { + "cookie", "-f", NULL + }; + char szCurDir[MAX_PATH]; + int iRet; + + if (!_stricmp(szLocalMetaRoot, szNoLock)) { + return(TRUE); // skip locks + } + + /* + * cd to local dir with meta-project locks + */ + GetCurrentDirectory(MAX_PATH, szCurDir); + if (!SetCurrentDirectory(szLocalMetaRoot)) { + fprintf(stderr, "RSLM: Bad or unspecified rslm lock directory.\n"); + fprintf(stderr, "RSLM: Use -l parameter or set RSLM_LOCK_DIR variable.\n"); + return(FALSE); + } + /* + * Release the cookie! + */ + iRet = MySpawn(P_WAIT, freelockargs, NULL, 0); + if (fBatch) { + fprintf(stdout, ":end\n"); + } + SetCurrentDirectory(szCurDir); + if (iRet) { + return(FALSE); + } + return(TRUE); +} + + +BOOL SpawnEnlistCmd( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + int i; + static char*ssyncargs[] = { + "ssync", "-u", "rslm.ini", NULL + }; + char *parentArgs[] = { "-s", pszParentServer, "-p", pszParentProject, NULL }; + + /* + * enlist requires p and s flags to be specified + */ + if (!*pszParentProject || !*pszParentServer) { + fprintf(stderr, "RSLM: -p and/or -s parameter to rslm is missing.\n"); + return(FALSE); + } + /* + * find out where to insert -p and -s parameters + */ + for (i = 1; argv[i] != NULL && (*argv[i] == '-' || *argv[i] == '/'); i++) { + } + /* + * run enlist cmd + */ + if (MySpawn(P_WAIT, argv, parentArgs, i)) { + return(FALSE); + } + /* + * ssync to rslm.ini file so we can continue recursing + */ + if (MySpawn(P_WAIT, ssyncargs, NULL, 0)) { + return(FALSE); + } + return(TRUE); +} + + + +BOOL SpawnSlmckCmd( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + int i; + char *parentArgs[] = { "-s", pszParentServer, "-p", pszParentProject, NULL }; + + /* + * slmck requires p and s flags to be specified + */ + if (!*pszParentProject || !*pszParentServer) { + fprintf(stderr, "RSLM: -p and/or -s parameter to rslm is missing.\n"); + return(FALSE); + } + /* + * find out where to insert -p and -s parameters + */ + for (i = 1; argv[i] != NULL && (*argv[i] == '-' || *argv[i] == '/'); i++) { + } + /* + * run slmck-like cmd + */ + if (MySpawn(P_WAIT, argv, parentArgs, i)) { + return(FALSE); + } + /* + * correct project and server names if they are wrong or not supplied. + */ + return(ExtractSlmIniInfo(szSlmFileName, pszParentProject, pszParentServer)); +} + + + +BOOL SpawnOtherCmd( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + pszParentServer; + pszParentProject; + + return(!MySpawn(P_WAIT, argv, NULL, 0)); +} + + +BOOL Noop( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + argv; + pszParentServer; + pszParentProject; + + return(TRUE); +} + + +BOOL SpawnCommand( +char **argv, +char *pszParentServer, +char *pszParentProject, +PSPAWNINFO psi) +{ + int i; + + for (i = 0; TRUE; i++) { + if (psi[i].pszCmd == NULL || + !_stricmp(argv[0], psi[i].pszCmd)) { + return(psi[i].pfnSpawn(argv, pszParentServer, pszParentProject)); + } + } +} + + +BOOL CallRslm( +char **argv, +char *pszParentServer, +char *pszParentProject) +{ + static int cIndent = 0; + int i; + HANDLE hFF; + FILE *hOutputFile, *hInfoFile; + char szSpawnProject[32]; + char szSpawnServer[MAX_PATH]; + + if (fDebug) { + for (i = 0; i < cIndent; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, "\\\n"); + for (i = 0; i < cIndent; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, " \\\n"); + cIndent++; + } + + SpawnCommand(argv, pszParentServer, pszParentProject, aPreCmdData); + + /* + * Now spawn child projects as specified by the rslm.ini file. + * + * Spawn propigates proper -p and -s parameters to rslm. + */ + hInfoFile = fopen(szInfoFileName, "r"); + if (hInfoFile == NULL) { + /* + * szInfoFileName may be a custom file name, try for the default name + */ + hInfoFile = fopen(szDefInfoFileName, "r"); + } + if (hInfoFile != NULL) { + while (ExtractRslmLine(hInfoFile, szSpawnProject, szSpawnServer)) { + if (!SetCurrentDirectory(szSpawnProject)) { + fprintf(stderr, "RSLM: Creating %s directory\n", szSpawnProject); + _mkdir(szSpawnProject); + if (!SetCurrentDirectory(szSpawnProject)) { + fprintf(stderr, "RSLM: Could not create %s directory\n", szSpawnProject); + goto leave; + } + } + + CallRslm(argv, szSpawnServer, szSpawnProject); + + SetCurrentDirectory(".."); + } + fclose(hInfoFile); + } + + SpawnCommand(argv, pszParentServer, pszParentProject, aPostCmdData); + + /* + * Now, if fRecurse is indicated, spawn all child directories w/o an + * rslm.ini file. This spawn propigates -p and -s parameters to rslm. + */ + if (fRecurse) { + hFF = FindFirstFile("*.*", &wfd); + while (hFF) { + if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + goto nextFile; + } + + if (!strcmp(wfd.cFileName, "..") || !strcmp(wfd.cFileName, ".")) { + goto nextFile; + } + + if (!SetCurrentDirectory(wfd.cFileName)) { + goto nextFile; + } + if (!ExtractSlmIniInfo(szSlmFileName, szSpawnProject, szSpawnServer)) { + goto nextFile2; + } + /* + * If the project key in the slmini file != the parent project, + * skip this directory. + */ + if (_stricmp(szSpawnProject, pszParentProject)) { + if (fDebug) { + fprintf(stderr, "RSLM: %s != %s\n", szSpawnProject, pszParentProject); + } + goto nextFile2; + } + + CallRslm(argv, szSpawnServer, szSpawnProject); + +nextFile2: + SetCurrentDirectory(".."); + +nextFile: + if (!FindNextFile(hFF, &wfd)) { + FindClose(hFF); + break; + } + } + } + +leave: + + if (fDebug) { + cIndent--; + for (i = 0; i < cIndent; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, " /\n"); + for (i = 0; i < cIndent; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, "/\n"); + } + return(0); +} + + + +main (argc, argv) + int argc; + char *argv[]; +{ + int defargc; + char *buf[25]; + char **defargv = buf; + LPSTR psz; + char szDefParams[MAX_PATH] = ""; + char szDefParamsEnv[] = "RSLM_OPTS"; + + /* + * First get default args from environment and parse them. + */ + GetEnvironmentVariable(szDefParamsEnv, szDefParams, MAX_PATH); + + psz = szDefParams; + defargv[0] = ""; + defargc = 1; + while (*psz != '\0') { + while (*psz == ' ') { // scan to next token + *psz++; + } + if (*psz == '\0') { // quit if at NULL + break; + } + defargv[defargc++] = psz++; // mark start of token + while (*psz != ' ' && *psz != '\0') { // scan over token + *psz++; + } + if (*psz == ' ') { // terminate token + *psz++ = '\0'; + } + } + defargv[defargc] = NULL; + ParseCmdLine(defargv); + + /* + * Now parse the main command line. + */ + argv = ParseCmdLine(argv); + + if (fBuildFiles) { + char szCurProj[MAX_PATH]; + + GetCurrentDirectory(sizeof(szCurProj), szCurProj); + BuildFiles(strrchr(szCurProj, '\\') + 1); + fprintf(stderr, "RSLM: %s files are built.\n", szInfoFileName); + } + + if (fValidate) { + char szCurProj[MAX_PATH]; + + GetCurrentDirectory(sizeof(szCurProj), szCurProj); + Validate(strrchr(szCurProj, '\\') + 1); + fprintf(stderr, "RSLM: metaproject is validated.\n", szInfoFileName); + } + + if (*argv) { + if (!SpawnCommand(argv, szParentServer, szParentProject, aLockCmdData)) { + return(0); + } + + CallRslm(argv, szParentServer, szParentProject); + + SpawnCommand(argv, szParentServer, szParentProject, aUnlockCmdData); + } + + return(0); +} |