/*****
** ** Module Header ******************************************************* **
** **
** Modules Revision 3.0 **
** Providing a flexible user environment **
** **
** File: ModuleCmd_Init.c **
** First Edition: 91/10/23 **
** **
** Authors: John Furlan, jlf@behere.com **
** Jens Hamisch, jens@Strawberry.COM **
** **
** Description: Routines that act on a user's "dot" startup files to **
** add, remove, and list modulefiles to/from/in their **
** startup files. **
** **
** Exports: ModuleCmd_Init **
** **
** Notes: **
** **
** ************************************************************************ **
****/
/** ** Copyright *********************************************************** **
** **
** Copyright 1991-1994 by John L. Furlan. **
** see LICENSE.GPL, which must be provided, for details **
** **
** ************************************************************************ **/
static char Id[] = "@(#)$Id: ModuleCmd_Init.c,v 1.2 2001/06/09 09:48:46 rkowen Exp $";
static void *UseId[] = { &UseId, Id };
/** ************************************************************************ **/
/** HEADERS **/
/** ************************************************************************ **/
#include "modules_def.h"
/** ************************************************************************ **/
/** LOCAL DATATYPES **/
/** ************************************************************************ **/
/** not applicable **/
/** ************************************************************************ **/
/** CONSTANTS **/
/** ************************************************************************ **/
/** not applicable **/
/** ************************************************************************ **/
/** MACROS **/
/** ************************************************************************ **/
/** not applicable **/
/** ************************************************************************ **/
/** LOCAL DATA **/
/** ************************************************************************ **/
static char module_name[] = "ModuleCmd_Init.c"; /** File name of this module **/
#if WITH_DEBUGGING_MODULECMD
static char _proc_ModuleCmd_Init[] = "ModuleCmd_Init";
#endif
/** ************************************************************************ **/
/** PROTOTYPES **/
/** ************************************************************************ **/
/** not applicable **/
/** ************************************************************************ **/
/** STATIC FUNCTIONS **/
/** ************************************************************************ **/
/* Handles the output of a substring where the start & ending positions
* are given - if either is NULL then just do nothing and return -1
* all other cases it returns 0
*/
static int out_substr(FILE *stream, char *start, char *end) {
char save;
if (!start || !end) return -1;
save = *end;
*end = '\0';
fputs(start, stream);
*end = save;
return 0;
}
/*++++
** ** Function-Header ***************************************************** **
** **
** Function: ModuleCmd_Init **
** **
** Description: Execution of the module-command 'init' **
** **
** First Edition: 91/10/23 **
** **
** Parameters: Tcl_Interp *interp Attached Tcl Interp. **
** int argc Number of arguments **
** char *argv[] Argument list **
** **
** Result: int TCL_ERROR Failure **
** TCL_OK Successfull operation **
** **
** Attached Globals: g_flags These are set up accordingly before **
** this function is called in order to **
** control everything **
** **
** ************************************************************************ **
++++*/
int ModuleCmd_Init( Tcl_Interp *interp,
int argc,
char *argv[])
{
static char home_pathname[ MOD_BUFSIZE + 40];
static char home_pathname2[ MOD_BUFSIZE + 40];
Tcl_RegExp modcmdPtr = Tcl_RegExpCompile(interp,
"^([ \t]*module[ \t]+)(load|add)[ \t]+([^#\n]*)([#.\n]*)");
char **modlist;
char *home;
char *buffer;
char ch;
char *startp, *endp;
FILE *fileptr, *newfileptr;
int i, j;
int found_module_command = 0;
int found_modload_flag = 0;
int shell_num = 0;
int nummods, bufsiz = 8192;
int home_end, path_end;
int sw_found = 0, rm_found = 0;
#if WITH_DEBUGGING_MODULECMD
ErrorLogger( NO_ERR_START, LOC, _proc_ModuleCmd_Init, NULL);
#endif
/**
** If called with no arguments and the flags don't say that there's some-
** thing to do - exit now!
**/
if( argc < 1 && !(g_flags & (M_DISPLAY | M_CLEAR)))
return( TCL_OK); /** -------- EXIT (SUCCESS) -------> **/
/**
** Parameter check for the initswitch command
**/
if(g_flags & M_SWITCH) {
argc--;
if(argc != 1) {
if( OK != ErrorLogger( ERR_USAGE, LOC, "initswitch oldmodule newmodule",
NULL))
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
}
/**
** Allocate a buffer for fgets ...
**/
if( NULL == (buffer = (char*) malloc( bufsiz * sizeof(char)))) {
if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
/**
** Where's my HOME?
**/
if( NULL == (home = (char *) getenv("HOME")))
if( OK != ErrorLogger( ERR_HOME, LOC, NULL)) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
home_end = strlen( home);
/**
** Put HOME into a buffer and store a slash where the end of HOME is
** for quick contatination of the shell startup files.
**/
strcpy( home_pathname, home);
home_pathname[ home_end++] = '/';
home_pathname[ home_end] = '\0';
/**
** Scan all startup files related to the current invoking shell
**/
if( TCL_OK != SetStartupFiles()) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
while( shell_startups[ shell_num]) {
strcpy( &home_pathname[ home_end], shell_startups[ shell_num]);
if( NULL == (fileptr = fopen(home_pathname, "r"))) {
shell_num++;
continue; /** while( shell_startups) ... **/
}
/**
** ... when the startup file exists ...
** open a new startupfile with the extension -NEW for output
**/
path_end = home_end + strlen( shell_startups[ shell_num]);
strcpy( &home_pathname[ path_end], "-NEW");
shell_num++;
if( !(g_flags & M_DISPLAY) &&
NULL == (newfileptr = fopen( home_pathname, "w"))) {
(void) ErrorLogger(ERR_OPEN,LOC,home_pathname,"init",NULL);
continue; /** while( shell_startups) ... **/
}
/**
** Seek for a modules load|add command within the shell startup file
** Copy the shell input file to the new one until the magic cookie
** is found.
**/
while( fgets( buffer, bufsiz, fileptr)) {
if( Tcl_RegExpExec(interp, modcmdPtr, buffer, buffer)) {
found_modload_flag = 1;
break;
}
if (!(g_flags & M_DISPLAY)) fputs( buffer, newfileptr);
}
/**
** If not found...
**/
if( !found_modload_flag) {
if( EOF == fclose( fileptr))
if( OK != ErrorLogger( ERR_CLOSE, LOC, home_pathname, NULL)) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
if (!(g_flags & M_DISPLAY)) {
if( EOF == fclose( newfileptr))
if( OK != ErrorLogger(ERR_CLOSE,LOC,home_pathname,NULL)) {
free( buffer);
return( TCL_ERROR); /** ---- EXIT (FAILURE) ---> **/
}
if( -1 == unlink( home_pathname))
if( OK != ErrorLogger(ERR_UNLINK,LOC,home_pathname,NULL)) {
free( buffer);
return( TCL_ERROR); /** ---- EXIT (FAILURE) ---> **/
}
}
continue; /** while( shell_startups) ... **/
}
/**
** ... module load|add found ...
**/
found_module_command = 1;
found_modload_flag = 0;
/* print out the "module" part */
(void) Tcl_RegExpRange(modcmdPtr, 1, &startp, &endp);
if (!(g_flags & M_DISPLAY)) (void) out_substr(newfileptr, startp, endp);
/* print out the "add/load" part */
(void) Tcl_RegExpRange(modcmdPtr, 2, &startp, &endp);
if (!(g_flags & M_DISPLAY)) (void) out_substr(newfileptr, startp, endp);
if( !(g_flags & M_CLEAR)) {
/* look at the "module list" part */
(void) Tcl_RegExpRange(modcmdPtr, 3, &startp, &endp);
/* save the end character & set to 0 */
if(endp) {
ch = *endp;
*endp = '\0';
}
if( !( modlist = SplitIntoList( interp, startp, &nummods)))
continue;
/* restore the list end character */
if(endp) {
*endp = ch;
}
if( g_flags & M_DISPLAY) {
if( modlist[0] == NULL) {
fprintf( stderr,
"\nNo modules are loaded in %s's initialization file "
"$HOME/%s\n\n",shell_name,shell_startups[shell_num-1]);
} else {
fprintf( stderr,
"\n%s initialization file $HOME/%s loads modules:\n\t%s\n\n",
shell_name, shell_startups[shell_num - 1], startp);
}
FreeList( modlist, nummods);
continue;
}
for(i = 0; i < argc; i++) {
/**
** Search through the modlist of modules that are currently
** in the ~/.startup. If one is found, it handles removing
** it, switching it, etc.
**/
for( j=0; j < nummods; j++) {
if( !strcmp( modlist[j], argv[i])) {
if( g_flags & (M_LOAD | M_PREPEND | M_REMOVE)) {
/**
** If removing, adding, prepending it,
** NULL it off the list.
**/
if ( g_flags & M_REMOVE )
fprintf( stderr, "Removed %s\n", modlist[j]);
else if ( (g_flags & M_LOAD)
&& !(g_flags & M_PREPEND))
fprintf(stderr,"Moving %s to end\n",modlist[j]);
else if ( g_flags & M_PREPEND )
fprintf(stderr,"Moving %s to beginning\n",
modlist[j]);
free( modlist[j]);
modlist[j] = NULL;
rm_found = 1;
} else if( g_flags & M_SWITCH) {
/**
** If switching it, swap the old string with
** the new string in the list.
**/
fprintf( stderr, "Switching %s to %s\n", modlist[j],
argv[i+1]);
sw_found = 1;
free( modlist[j]);
modlist[j] = strdup( argv[i+1]);
}
} /** if **/
} /** for(j) **/
} /** for(i) **/
/**
** Ok, if we're removing it, prepending it, or switching it,
** the modlist contains what needs to be put where...
**/
if( g_flags & M_PREPEND) {
/**
** PREPENDING
**/
for(i = 0; i < argc; i++)
fprintf( newfileptr, " %s", argv[i]);
}
if( (g_flags & (M_LOAD | M_PREPEND | M_REMOVE | M_SWITCH )) )
/**
** DUMP LIST
**/
for(j = 0; j < nummods; j++) {
if( modlist[j])
fprintf( newfileptr, " %s", modlist[j]);
}
if( (g_flags & M_LOAD) && !(g_flags & M_PREPEND)) {
/**
** ADDING
**/
for(i = 0; i < argc; i++)
fprintf( newfileptr, " %s", argv[i]);
}
FreeList( modlist, nummods);
} else { /** if( M_CLEAR) **/
/**
** Clear out the list, but leave a "null"
**/
fprintf( newfileptr, " %s", "null");
}
/**
** Restore any comments at the end of the line...
**/
(void) Tcl_RegExpRange(modcmdPtr, 4, &startp, &endp);
(void) out_substr(newfileptr, startp, endp);
/**
** Complete copying the rest of the file...
**/
while( fgets( buffer, bufsiz, fileptr))
fputs( buffer, newfileptr);
/**
** Don't need these any more
**/
if( EOF == fclose( fileptr))
if( OK != ErrorLogger( ERR_CLOSE, LOC, home_pathname, NULL)) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
if( EOF == fclose( newfileptr))
if( OK != ErrorLogger( ERR_CLOSE, LOC, home_pathname, NULL)) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
/**
** Truncate -NEW from home_pathname and Create a -OLD name
** Move ~/.startup to ~/.startup-OLD
**/
home_pathname[ path_end] = '\0';
/* sprintf( home_pathname2, "%s-OLD", home_pathname); */
strcpy( home_pathname2, home_pathname);
strcat( home_pathname2, "-OLD");
if( 0 > rename( home_pathname, home_pathname2)) {
if( OK != ErrorLogger(ERR_RENAME,LOC,home_pathname,home_pathname2,
NULL)) {
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
}
/**
** Create a -NEW name
** Move ~/.startup-NEW to ~/.startup
**/
/* sprintf( home_pathname2, "%s-NEW", home_pathname); */
strcpy( home_pathname2, home_pathname);
strcat( home_pathname2, "-NEW");
if( 0 > rename( home_pathname2, home_pathname)) {
if( OK != ErrorLogger(ERR_RENAME,LOC,home_pathname2,home_pathname,
NULL)) {
/**
** Put the -OLD one back if I can't rename it
**/
/* sprintf( home_pathname2, "%s-OLD", home_pathname); */
strcpy( home_pathname2, home_pathname);
strcat( home_pathname2, "-OLD");
if( 0 > rename( home_pathname2, home_pathname))
ErrorLogger(ERR_RENAME,LOC,home_pathname2,home_pathname,
NULL);
free( buffer);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
}
} /** while( shell_startups) **/
/**
** Free up internal buffers
**/
free( buffer);
/**
** Create a -NEW name. This may conditionally be used for removing the
** new files if the operation hasn't had success
** Check the SWITCH command
**/
/* sprintf( home_pathname2, "%s-NEW", home_pathname); */
strcpy( home_pathname2, home_pathname);
strcat( home_pathname2, "-NEW");
if((g_flags & M_SWITCH) && !sw_found) {
if( OK != ErrorLogger( ERR_LOCATE, LOC, argv[0], NULL)) {
if( -1 == unlink( home_pathname2))
ErrorLogger( ERR_UNLINK, LOC, home_pathname2, NULL);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
}
/**
** Check the REMOVE command
**/
if((g_flags & M_REMOVE) && !rm_found) {
if( OK != ErrorLogger( ERR_LOCATE, LOC, NULL)) {
if( -1 == unlink( home_pathname2))
ErrorLogger( ERR_UNLINK, LOC, home_pathname2, NULL);
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
}
if( !found_module_command) {
if( OK != ErrorLogger( ERR_INIT_STUP, LOC, shell_name, NULL))
return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/
}
#if WITH_DEBUGGING_MODULECMD
ErrorLogger( NO_ERR_END, LOC, _proc_ModuleCmd_Init, NULL);
#endif
return( TCL_OK);
} /** end of 'ModuleCmd_Init' **/
syntax highlighted by Code2HTML, v. 0.9.1