/*This line lets emacs recognize this as -*- C -*- Code
 *-----------------------------------------------------------------------------
 *
 * Project:	Tcl Modules
 * Created:	91/10/23
 * Author:	John L. Furlani<john.furlani@East.Sun.COM>
 *
 * Description:
 *      The initialization routines for Tcl Modules.  Primarily the setup of
 *  the different Tcl module commands and the global hash tables are
 *  initialized here.  The initial storage of the begining environment is here
 *  as well.
 *	
 * $Log: init.c,v $
 *
 *
 * Revision 1.3  1993/01/25  18:48:13  jlf
 * Changed the method for keeping and unwinding failed modulefiles.
 * The output returns to its optimized state where only the aggregate
 * changes to the environment are sent to the executing shell.
 *
 * Revision 1.2  1993/01/22  17:37:35  jlf
 * Added purge sub-command.
 *
 * Revision 1.1  1992/11/05  23:26:09  jlf
 * Initial revision
 *
 *---------------------------------------------------------------------------*/
static char Id[] =
    "$Id: init.c,v 2.0 1993/02/21 00:01:14 jlf Exp jlf $";

#include "global.h"

int
Module_Tcl_ExitCmd(ClientData client_data,
		   Tcl_Interp* interp,
		   int argc,
		   char* argv[])
{
  char *buffer = malloc(25);
  int  value;
  
  if ((argc != 1) && (argc != 2)) {
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		     " ?returnCode?\"", (char *) NULL);
    return TCL_ERROR;
  }

  if(argc == 1) {
    value = 0;
  } else if (Tcl_GetInt(interp, argv[1], &value) != TCL_OK) {
    return TCL_ERROR;
  }

  sprintf(buffer, "EXIT %d", value);
  Tcl_SetResult(interp, buffer, NULL);

  return TCL_ERROR;
}


int
Initialize_Tcl(Tcl_Interp** interp,
	       int         argc,
	       char*       argv[],
               char*       environ[])
{
    if(argc < 2) {
        fprintf(stderr, 
                "ERROR:  Not enough arguments -- expected '%s shellname'\n",
                argv[0]);
        exit(1);
    } else {
        strcpy(shell_name, argv[1]);
    
        if(set_derelict(argv[1]) == NULL) {
            fprintf(stderr, "ERROR:  %s is an unknown shell type\n",
                    argv[1]);
            exit(1);
        }
    }

  *interp = Tcl_CreateInterp();

    InitializeModuleCommands(*interp);

    addPtr    = regcomp("^ad|^lo");
    rmPtr     = regcomp("^rm|^de|^er|^rem|^unl");
    swPtr     = regcomp("^sw");
    dispPtr   = regcomp("^di|^sh");
    listPtr   = regcomp("^l");
    availPtr  = regcomp("^av");
    helpPtr   = regcomp("^he");
    initPtr   = regcomp("^i");
    usePtr    = regcomp("^use");
    unusePtr  = regcomp("^unu");
    updatePtr = regcomp("^up");
    purgePtr  = regcomp("^p");
    clearPtr  = regcomp("^cl");
  
    if(((setenvHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL) ||
       ((unsetenvHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL) ||
       ((aliasSetHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL) ||
       ((aliasUnsetHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL) ||
       ((markVariableHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL) ||
       ((markAliasHashTable = 
         (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable))) == NULL)) {
        fprintf(stderr, "Error allocating memory for hash tables in Initialize\n");
        exit(1);
    }

    Tcl_InitHashTable(setenvHashTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(unsetenvHashTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(aliasSetHashTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(aliasUnsetHashTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(markVariableHashTable, TCL_STRING_KEYS);
    Tcl_InitHashTable(markAliasHashTable, TCL_STRING_KEYS);

    /*
     *  What I'm going to do here is check for the existance of the
     *  environment variable "_MODULESBEGINENV_".  If it is set, then I will do
     *  nothing, otherwise, I will store every environment variable into
     *  ~/.modulesbeginenv.  This will be used to store the environment
     *  variables exactly as it was when Modules saw it for the very first
     *  time.
     *
     *  The update command will use this information to reinitialize the
     *  environment and then reload every modulefile that has been loaded
     *  since as stored in the LOADEDMODULES environment variable in order.
     */
    if(getenv("_MODULESBEGINENV_") == NULL) {
        char*  argv[3];
        FILE*  file;
        
        argv[1] = "~/.modulesbeginenv";
        argv[2] = NULL;

        if(Tcl_GlobCmd(0, *interp, 2, argv) == TCL_OK) {
            if((file = fopen((*interp)->result, "w+")) != NULL) {
                int i=0;
                while(environ[i]) {
                    fprintf(file, "%s\n", environ[i++]);
                }
                moduleSetenv(*interp, "_MODULESBEGINENV_", (*interp)->result, 1);
                fclose(file);
            }
        }
    }

    return 0;
}

void InitializeModuleCommands(Tcl_Interp* interp)
{
  Tcl_CreateCommand(interp, "exit", Module_Tcl_ExitCmd,
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);

  Tcl_CreateCommand(interp, "setenv", cmdSetEnv, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "unsetenv", cmdUnsetEnv, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  
  Tcl_CreateCommand(interp, "prepend-path", cmdSetPath, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "append-path", cmdSetPath, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "remove-path", cmdRemovePath, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);

  Tcl_CreateCommand(interp, "module-info", cmdModuleInfo, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "module", cmdModule, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  
  Tcl_CreateCommand(interp, "set-alias", cmdSetAlias, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "unset-alias", cmdSetAlias, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);

  Tcl_CreateCommand(interp, "conflict", cmdConflict, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "prereq", cmdPrereq, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);

  Tcl_CreateCommand(interp, "system", cmdSystem, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
  Tcl_CreateCommand(interp, "uname", cmdUname, 
		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);

  Tcl_CreateCommand(interp, "x-resource", cmdXResource,
 		    (ClientData) shell_derelict, (void (*)(ClientData)) NULL);
}

int
Setup_Environment(Tcl_Interp* interp)
{
  int   i, envsize = 0;
  char* eq;
 
  for(i = 0; environ[i]; i++) {
    envsize += strlen(environ[i]) + 1;
    eq = environ[i];
    while(*eq++ != '=' && *eq);  /* point to the equal sign */
    *(eq - 1)= '\0';
    if(Tcl_SetVar(interp, environ[i], eq, 0) == NULL) {
      Tcl_AppendResult(interp, "Tcl_SetVar couldn't set ",
                       environ[1], (char *) NULL);
      return TCL_ERROR;
    }
    *(eq - 1) = '=';
  }
 
  return 0;
}

int
TieStdout(void) {
  int save = dup(1);
  close(1);
  dup(2);
  return save;
}

int
UnTieStdout(int saved_stdout) {
  close(1);
  return dup(saved_stdout);
}
  

void SetStartupFiles(void)
{
    if((strcmp("csh", shell_name) == 0)) {
	shell_startups = (char**) malloc(4*sizeof(char*));
	shell_startups[0] = ".cshrc";
	shell_startups[1] = ".csh_variables";
	shell_startups[2] = ".login";
	shell_startups[3] = NULL;
    } else if((strcmp("tcsh", shell_name) == 0)) {
	shell_startups = (char**) malloc(4*sizeof(char*));
	shell_startups[0] = ".tcshrc";
	shell_startups[1] = ".cshrc";
	shell_startups[2] = ".csh_variables";
	shell_startups[3] = ".login";
	shell_startups[4] = NULL;
    } else if((strcmp("sh", shell_name) == 0) ||
	      (strcmp("ksh", shell_name) == 0)) {
	shell_startups = (char**) malloc(2*sizeof(char*));
	shell_startups[0] = ".profile";
	shell_startups[1] = NULL;
    } else if((strcmp("bash", shell_name) == 0)) { 
	shell_startups = (char**) malloc(4*sizeof(char*));
	shell_startups[0] = ".bashrc";
	shell_startups[1] = ".bash_env";
	shell_startups[2] = ".bash_profile";
	shell_startups[3] = NULL;
    } else if((strcmp("zsh", shell_name) == 0)) { 
	shell_startups = (char**) malloc(4*sizeof(char*));
	shell_startups[0] = ".zshrc";
	shell_startups[1] = ".zshenv";
	shell_startups[2] = ".zlogin";
	shell_startups[3] = NULL;
    } else {
	shell_startups = (char**) malloc(1*sizeof(char*));
	shell_startups[0] = NULL;
    }
}
