static char *GetModuleName(Tcl_Interp *interp, char *path, char *prefix, char *modulename) { struct stat stats; /** Buffer for the stat() systemcall **/ char *fullpath = NULL; /** Buffer for creating path names **/ char *Result = NULL; /** Our return value **/ char **filelist = NULL; /** Buffer for a list of possible ** module files **/ int numlist; /** Size of this list **/ int i, slen, is_def; char *s, *t; /** Private string buffer **/ char *mod, *ver; /** Pointer to module and version **/ char *mod1, *ver1; /** Temp pointer **/ #if WITH_DEBUGGING_LOCATE_1 ErrorLogger(NO_ERR_START, LOC, _proc_GetModuleName, NULL); #endif /* WITH_DEBUGGING_LOCATE_1 */ /** ** Split the modulename into module and version. Use a private buffer ** for this **/ if ((char *)NULL == (s = stringer(NULL, 0, modulename, NULL))) { ErrorLogger(ERR_ALLOC, LOC, NULL); goto unwind0; } slen = (int)(strlen(s) + 1); mod = s; /* assume that the '=' here is correct, because otherwise 'ver' would not * be initialized here yet (I think): */ if ((ver = strrchr(mod, '/'))) { *ver++ = '\0'; } /** ** Allocate a buffer for full pathname building: **/ if ((char *)NULL == (fullpath = stringer(NULL, MOD_BUFSIZE, NULL))) { if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) { goto unwind1; } } /** ** Check whether $path/$prefix/$modulename is a directory. **/ if (prefix) { if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", prefix, "/", modulename, NULL)) { goto unwind1; } } else { if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", modulename, NULL)) { goto unwind1; } } if (!stat(fullpath, &stats) && S_ISDIR(stats.st_mode)) { /** ** So the full modulename is $modulename/default. Recurse on that. **/ if ((char *)NULL == (t = stringer(NULL, 0, modulename, "/", _default, NULL))) { goto unwind1; } Result = GetModuleName(interp, path, prefix, t); null_free((void *)&t); null_free((void *)&fullpath); null_free((void *)&s); return (Result); } /** ** Check whether $path/$prefix/$mod is a directory: **/ if (prefix) { if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", prefix, "/", mod, NULL)) { goto unwind1; } } else { if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", mod, NULL)) { goto unwind1; } } is_def = !strcmp(mod, _default); if (is_def || !stat(fullpath, &stats)) { /** ** If it is a directory, then do this: **/ if (!is_def && S_ISDIR( stats.st_mode)) { /** ** Source the ".modulerc" file if it exists. ** For compatibility source the .version file, too. **/ if (prefix) { if ((char *)NULL == stringer(modfil_buf, MOD_BUFSIZE, prefix, "/", mod, NULL)) { goto unwind2; } } else { if ((char *)NULL == stringer(modfil_buf, MOD_BUFSIZE, mod, NULL)) { goto unwind2; } } if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", modfil_buf, NULL)) { goto unwind2; } g_current_module = modfil_buf; if ((TCL_ERROR == SourceRC(interp, fullpath, modulerc_file)) || (TCL_ERROR == SourceVers(interp, fullpath, modfil_buf))) { /* flags = save_flags; */ goto unwind2; } /** ** After sourcing the RC files, we have to look up the ** versions again: **/ if (VersionLookup(modulename, &mod1, &ver1)) { int len = (int)(strlen(mod1) + strlen(ver1) + 2); /** ** Maybe we have to enlarge s: **/ if (len > slen) { null_free((void *)&s); if((char *)NULL == (s = stringer( NULL, len, NULL))) { ErrorLogger( ERR_STRING, LOC, NULL); goto unwind2; } slen = len; /* dummy condition to use 'slen': */ if (slen == 0) { ; } } /** ** Print the new module/version in the buffer: **/ if ((char *)NULL == stringer(s, len, mod1, "/", ver1, NULL)) { ErrorLogger(ERR_STRING, LOC, NULL); goto unwind2; } mod = s; if (ver = strchr(s, (int)'/')) { *ver++ = '\0'; } } /** ** recursively delve into subdirectories (until ver == NULL). **/ if (ver) { int len; len = (int)(strlen(mod) + 1); if (prefix) { len += (strlen(prefix) + 1); } /** ** Build the new prefix **/ if((char *) NULL == (t = stringer(NULL, len, NULL))) { ErrorLogger( ERR_STRING, LOC, NULL); goto unwind2; } if( prefix) { if((char *) NULL == stringer(t, len, prefix,"/",mod, NULL)){ ErrorLogger( ERR_STRING, LOC, NULL); goto unwindt; } } else { if((char *) NULL == stringer(t, len, mod, NULL)){ ErrorLogger( ERR_STRING, LOC, NULL); goto unwindt; } } /** ** This is the recursion **/ Result = GetModuleName( interp, path, t, ver); /** ** Free our temporary prefix buffer **/ null_free((void *) &t); if (0) { /* an error occurred */ unwindt: null_free((void *) &t); goto unwind2; } } } else { /** if ($path/$prefix/$mod is a directory) **/ /** ** Now 'mod' should be either a file or the word 'default' ** In case of default get the file with the highest version number ** in the current directory **/ if( is_def) { if( !prefix) prefix = "."; if( NULL == (filelist = SortedDirList( interp, path, prefix, &numlist))) goto unwind1; prefix = (char *)NULL; /** ** Select the first one on the list which is either a ** modulefile or another directory. We start at the highest ** lexicographical name in the directory since the filelist ** is reverse sorted. ** If it is a directory, then we delve into it. **/ for( i=0; i<numlist && Result==NULL; i++) { /** ** Build the full path name and check if it is a ** directory. If it is, recursively try to find there what ** we are/were seeking for **/ if ((char *)NULL == stringer(fullpath, MOD_BUFSIZE, path, "/", filelist[i], NULL)) goto unwind2; if( !stat( fullpath, &stats) && S_ISDIR( stats.st_mode)) { Result = GetModuleName( interp, path, prefix, filelist[ i]); } else { /** ** Otherwise check the file for a magic cookie ... **/ if( check_magic( fullpath, MODULES_MAGIC_COOKIE, MODULES_MAGIC_COOKIE_LENGTH)) Result = filelist[ i]; } /** end "if (!stat)" **/ } /** end for-loop **/ } else { /** default **/ /** ** If mod names a file, we have to check wheter it exists and ** is a valid module file **/ if( check_magic( fullpath, MODULES_MAGIC_COOKIE, MODULES_MAGIC_COOKIE_LENGTH)) Result = mod; else { ErrorLogger( ERR_MAGIC, LOC, fullpath, NULL); Result = NULL; } } /** if( mod is a filename) **/ /** ** Build the full filename (using prefix and Result) if ** Result is defined **/ if (Result) { int len; len = (int)(strlen(Result) + 1); if (prefix) { len += (strlen(prefix) + 1); } if((char *) NULL == (t = stringer(NULL, len, NULL))) { ErrorLogger( ERR_STRING, LOC, NULL); goto unwind2; } if( prefix) { if((char *) NULL == stringer(t,len, prefix,"/",Result,NULL)) goto unwindt2; } else { if((char *) NULL == stringer(t,len, Result,NULL)) goto unwindt2; } Result = t; if (0) { /* an error occurred */ unwindt2: null_free((void *) &t); goto unwind2; } } } /** mod is a file **/ } /** mod exists **/ /** ** Free up temporary values and return what we've found **/ null_free((void*) &fullpath); null_free((void*) &s); FreeList(filelist, numlist); #if WITH_DEBUGGING_LOCATE_1 ErrorLogger(NO_ERR_END, LOC, _proc_GetModuleName, NULL); #endif /* WITH_DEBUGGING_LOCATE_1 */ return (Result); /** -------- EXIT (SUCCESS) -------> **/ unwind2: null_free((void *)&fullpath); unwind1: null_free((void *)&s); unwind0: return(NULL); /** -------- EXIT (FAILURE) -------> **/ } /** End of 'GetModuleName' (that was a lengthy function...) **/
int ModuleCmd_List( Tcl_Interp *interp, int argc, char *argv[]) { /** ** Get the list of loaded modules at first **/ char *loaded, *lmfiles; int i, count1, count2; char *list[ MOD_BUFSIZE]; char *files[ MOD_BUFSIZE]; char *tmplist[ MOD_BUFSIZE], *s; int len; #if WITH_DEBUGGING_MODULECMD ErrorLogger( NO_ERR_START, LOC, _proc_ModuleCmd_List, NULL); #endif lmfiles = getLMFILES( interp); loaded = getenv( "LOADEDMODULES"); if( !loaded || !*loaded) { if( sw_format & (SW_TERSE | SW_LONG | SW_HUMAN) ) fprintf(stderr, "No Modulefiles Currently Loaded.\n"); } else { /** ** Now tokenize it, form a list and print it out. **/ if( sw_format & SW_LONG ) { fprintf( stderr, long_header); } if( sw_format & (SW_TERSE | SW_LONG | SW_HUMAN) ) fprintf( stderr, "Currently Loaded Modulefiles:\n"); /** ** LOADEDMODULES and _LMFILES_ should provide a list of loaded ** modules and assigned files in the SAME ORDER ** but double check, because if they aren't you will get a crash. **/ count1 = 1; for( list[ 0] = xstrtok( loaded, ":"); list[ count1] = xstrtok( NULL, ":"); count1++ ); count2 = 1; for( files[ 0] = xstrtok( lmfiles, ":"); files[ count2] = xstrtok( NULL, ":"); count2++ ); if (count1 != count2) { ErrorLogger( ERR_ENVVAR, LOC, NULL); } /** ** We have to build a single list of files for each loaded entry ** in order to be able to figure out the length of the directory ** part **/ for( i=0; i<count1; i++) { len = strlen( files[i]) - strlen( list[i]); tmplist[i] = files[i]; /** ** We have to source all relevant .modulerc and .version files ** on the path **/ s = files[i] + len; while( s) { if( s = strchr( s, '/')) *s = '\0'; SourceRC( interp, files[i], modulerc_file); SourceVers( interp, files[i], list[i]); if( s) *s++ = '/'; } /** ** Print this guy **/ } print_aligned_files( interp, NULL, NULL, tmplist, count1, 1); } /** ** Return on success **/ #if WITH_DEBUGGING_MODULECMD ErrorLogger( NO_ERR_END, LOC, _proc_ModuleCmd_List, NULL); #endif return( TCL_OK); } /** End of 'ModuleCmd_List' **/