// // RSLM.C // // rslm - a huge multi-project tool // #include #include #include #include #include #include #include #include /* * 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] \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, " 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); }