Beispiel #1
0
/* since when does 'main()' take three arguments? */
int	main(int argc, char *argv[], char *environ[]) {

    Tcl_Interp	*interp;
    int          return_val = 0;
    char	*rc_name;
    char	*rc_path;

#if WITH_DEBUGGING
    ErrorLogger(NO_ERR_START, LOC, _proc_main, NULL);
#endif /* WITH_DEBUGGING */
    /**
     ** check if first argument is --version or -V then output the
     ** version to stdout.  This is a special circumstance handled
     ** by the regular options.
     **/
    if ((argc > 1) && (*argv[1] == '-')) {
        if ((!strcmp("-V", argv[1])) || (!strcmp("--version", argv[1]))) {
			version(stdout);
			return 0;
        }
    }
    /**
     **  Initialization.
     **  Check the command line syntax. There will be no return from the
     **  initialization function in case of invalid command line arguments.
     **/

    if (TCL_OK != Initialize_Tcl(&interp, argc, argv, environ)) {
		goto unwind0;
	}

    if (TCL_OK != Setup_Environment(interp)) {
		goto unwind0;
	}

    /**
     **  Check for command line switches
     **/

    if (TCL_OK != Check_Switches(&argc, argv)) {
		goto unwind0;
	}

    /**
     **  Figure out, which global RC file to use. This depends on the environ-
     **  ment variable 'MODULERCFILE', which can be set to one of the following:
     **
     **		<filename>	-->	PREFIX/etc/<filename>
     **		<dir>/		-->	<dir>/RC_FILE
     **		<dir>/<file>	-->	<dir>/<file>
     **  Use xgetenv to expand 1 level of env.vars.
     **/

    if ((rc_name = xgetenv("MODULERCFILE"))) {
		/* found something in MODULERCFILE */
		if ((char *)NULL == (rc_path = stringer(NULL, 0, rc_name, NULL))) {
			if (OK != ErrorLogger(ERR_STRING, LOC, NULL)) {
				goto unwind1;
			} else {
				null_free((void *)&rc_name);
			}
		} else {
			null_free((void *)&rc_name);
			if ((char *)NULL == (rc_name = strrchr(rc_path, '/'))) {
				rc_name = rc_path;
				rc_path = instpath;
			} else {
				*rc_name++ = '\0';
			}
			if (!*rc_name) {
				rc_name = rc_file;
			}
		}
    } else {
		rc_path = instpath;
		null_free((void *)&rc_name);
		rc_name = rc_file;
    }

    /**
     **  Finally we have to change PREFIX -> PREFIX/etc
     **/
    if (rc_path == instpath) {
		if ((char *)NULL == (rc_path = stringer(NULL, 0, instpath,
												"/etc", NULL))) {
			if (OK != ErrorLogger(ERR_ALLOC, LOC, NULL)) {
				goto unwind1;
			} else {
				rc_path = NULL;
			}
		}
    }

    /**
     **  Source the global and the user defined RC file
     **/

    g_current_module = (char *)NULL;

    if ((TCL_ERROR == SourceRC(interp, rc_path, rc_name)) ||
		(TCL_ERROR == SourceRC(interp, getenv("HOME"), modulerc_file))) {
		exit(1);
	}

    if (rc_path) {
		null_free((void *)&rc_path);
	}

    /**
     **  Invocation of the module command as specified in the command line
     **/

    g_flags = 0;
    return_val = cmdModule((ClientData)0, interp, (argc - 1),
						   (CONST84 char **)(argv + 1));

    /**
     **  If we were doing some operation that has already flushed its output,
     **  then we do NOT need to re-flush the output here.
     **
     **  Also, if we have had an error here, then the whole modulecmd failed
     **  and not just the values for a single modulefile.  So, we shall pass in
     **  a NULL here to indicate that any error message should say that
     **  absolutely NO changes were made to the environment.
     **/
    if (TCL_OK == return_val) {
		Output_Modulefile_Changes(interp);
#ifdef HAS_X11LIBS
		xresourceFinish(1);
#endif /* HAS_X11LIBS */
    } else {
		Unwind_Modulefile_Changes(interp, NULL);
#ifdef HAS_X11LIBS
		xresourceFinish(0);
#endif /* HAS_X11LIBS */
    }

    /**
     **  Finally clean up. Delete the required hash tables and conditionally
     **  allocated areas.
     **/

    Delete_Global_Hash_Tables();

    if (line) {
		null_free((void *)&line);
	}
    if (error_line) {
		null_free((void *)&error_line);
	}

    /**
     **  This return value may be evaluated by the calling shell:
     **/
#if WITH_DEBUGGING
    ErrorLogger(NO_ERR_END, LOC, _proc_main, NULL);
#endif /* WITH_DEBUGGING */

    OutputExit();
    return (return_val ? return_val : g_retval);

unwind2:
    null_free((void *)&rc_path);
unwind1:
    null_free((void *)&rc_name);
unwind0:

    /* an error occurred of some type */
    g_retval = (g_retval ? g_retval : 1);
    OutputExit();
    return (g_retval);

} /** End of 'main' **/
Beispiel #2
0
int main(
	int argc,
	char *argv[],
	char *environ[]
) {

	Tcl_Interp     *interp;
	int             return_val = 0;
	char           *rc_name;
	char           *rc_path;
	Tcl_Obj       **objv;		/** Tcl Object vector **/
	int             objc;		/** Tcl Object vector count **/

#ifdef HAVE_SETLOCALE
	/* set local via LC_ALL */
	setlocale(LC_ALL, "");
#endif

#if ENABLE_NLS
	/* the text message domain. */
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
#endif
    /**
     ** check if first argument is --version or -V then output the
     ** version to stdout.  This is a special circumstance handled
     ** by the regular options.
     **/
	if (argc > 1 && *argv[1] == '-') {
		if (!strcmp("-V", argv[1]) || !strcmp("--version", argv[1])) {
			version(stdout);
			return 0;
		}
	}
    /**
     **  Initialization. 
     **/
	if (!(ModulePathVec = ModulePathList())) {
		ModulePath = NULL;
		/* goto unwind0; */
	} else {
		ModulePath = uvec_vector(ModulePathVec);
	}

    /**
     **  Check the command line syntax. There will be no return from the
     **  initialization function in case of invalid command line arguments.
     **/
	if (TCL_OK != Initialize_Module(&interp, argc, argv, environ))
		goto unwind1;

	if (TCL_OK != Setup_Environment(interp))
		goto unwind1;

    /**
     **  Check for command line switches
     **/
	if (TCL_OK != Check_Switches(&argc, argv))
		goto unwind1;
    /**
     **  Figure out, which global RC file to use. This depends on the environ-
     **  ment variable 'MODULERCFILE', which can be set to one of the following:
     **
     **		<filename>	-->	SYSCONFDIR/<filename>
     **		<dir>/		-->	<dir>/RC_FILE
     **		<dir>/<file>	-->	<dir>/<file>
     **  Use xgetenv to expand 1 level of env.vars.
     **/
	if ((rc_name = xgetenv("MODULERCFILE"))) {
		/* found something in MODULERCFILE */
		if (!(rc_path = stringer(NULL, 0, rc_name, NULL))) {
			if (OK != ErrorLogger(ERR_STRING, LOC, NULL))
				goto unwind2;
			else
				null_free((void *)&rc_name);
		} else {
			null_free((void *)&rc_name);
			if (!(rc_name = strrchr(rc_path, *psep))) {
				rc_name = rc_path;
				rc_path = etcpath;
			} else
				*rc_name++ = '\0';
			if (!*rc_name) {
				rc_name = rc_file;
			}
		}
	} else {
		rc_path = stringer(NULL,0, etcpath, NULL);
		null_free((void *)&rc_name);
		rc_name = rc_file;
	}
    /**
     **  Source the global and the user defined RC file
     **/
	g_current_module = (char *)NULL;

	if (TCL_ERROR == SourceRC(interp, rc_path, rc_name, Mod_Load) ||
	    TCL_ERROR == SourceRC(interp,getenv("HOME"),modulerc_file,Mod_Load))
		exit(1);

	if (rc_path)
		null_free((void *)&rc_path);
    /**
     **  Invocation of the module command as specified in the command line
     **/
	g_flags = 0;
	Tcl_ArgvToObjv(&objc, &objv, argc - 1, argv + 1);
	return_val = cmdModule((ClientData) 0, interp, objc, objv);
    /**
     **  If we were doing some operation that has already flushed its output,
     **  then we don't need to re-flush the output here.
     **
     **  Also, if we've had an error here, then the whole modulecmd failed
     **  and not just the values for a single modulefile.  So, we'll pass in
     **  a NULL here to indicate that any error message should say that
     **  absolutely NO changes were made to the environment.
     **/
	if (TCL_OK == return_val) {
		Output_Modulefile_Changes(interp);
#ifdef HAS_X11LIBS
		xresourceFinish(1);
#endif
	} else {
		Unwind_Modulefile_Changes(interp, NULL);
#ifdef HAS_X11LIBS
		xresourceFinish(0);
#endif
	}
    /**
     **  Finally clean up. Delete the required hash tables and conditionally
     **  allocated areas.
     **/
	Global_Hash_Tables(GHashDelete, NULL);

	if (line)
		null_free((void *)&line);
	if (error_line)
		null_free((void *)&error_line);
    /**
     **  This return value may be evaluated by the calling shell
     **/
	OutputExit();
	return (return_val ? return_val : g_retval);

/* unwind3:
    null_free((void *) &rc_path); */
unwind2:
	null_free((void *)&rc_name);
unwind1:
	FreeList(&ModulePathVec);
unwind0:
	/* and error occurred of some type */
	g_retval = (g_retval ? g_retval : 1);
	OutputExit();
	return (g_retval);

} /** End of 'main' **/
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' **/