/*This line lets emacs recognize this as -*- C -*- Code
 *-----------------------------------------------------------------------------
 *
 * Project:	Tcl Modules
 * Created:	92/06/20
 * Author:	John L. Furlani<john.furlani@East.Sun.COM>
 *
 * Description:
 *      Routines that act on a user's "dot" startup files to add, remove, and
 *  list modulefiles to/from/in their startup files.
 *	
 * $Log: ModuleCmd_Init.c,v $
 *
 *
 * Revision 1.1  1992/11/05  23:49:14  jlf
 * Initial revision
 *
 *---------------------------------------------------------------------------*/
static char Id[] =
    "$Id: ModuleCmd_Init.c,v 2.0 1993/02/21 00:00:03 jlf Exp jlf $";

#include "global.h"
#include <regexp.h>

int
ModuleCmd_Init(Tcl_Interp*    interp,
	       int            argc,
	       char*          argv[])
{
  static char home_pathname[1064];  /* 1024 + 40 */
  static char home_pathname2[1064];  /* 1024 + 40 */
  regexp*     cookiePtr = regcomp("^[ \t]*module load .*\n$");
  regexp*     modcmdPtr = regcomp("^[ \t]*module load ");
  regexp*     modlstPtr = regcomp("^[^#^\n]*");
  char**      modlist;
  char*       home, *p;
  char*       buffer;
  char        ch, rch;
  FILE*       fileptr, *newfileptr;
  int         i, j;
  int         found_module_command = 0;
  int         found_modload_flag = 0;
  int         matched_module = 0;
  int         shell_num = 0;
  int         nummods, bufsiz = 8192;
  int         home_end, path_end;
  int         sw_found = 0, rm_found = 0;

  if(argc < 1 && !(flags & (M_DISPLAY | M_CLEAR)))
    return TCL_OK;
  
  if(flags & M_SWITCH) {
    argc--;
    if(argc != 1) {
      Tcl_AppendResult(interp,
		       "Wrong number of arguments:  usage is ", 
		       "'initswitch oldmodule newmodule'", NULL);
      return TCL_ERROR;
    }
  }
  
  if((buffer = (char*) malloc(bufsiz * sizeof(char))) == NULL) {
    Tcl_AppendResult(interp, "malloc() failed in Init_Modules()", NULL);
    return TCL_ERROR;
  }
  
  home = getenv("HOME");
  
  if(home) home_end = strlen(home);
  else {
    Tcl_AppendResult(interp, "HOME Environment variable is not set", NULL);
    return TCL_ERROR;
  }
  
  /*
    Put HOME into a buffer and store 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';
  
  SetStartupFiles();
  
  while(shell_startups[shell_num]) {
    strcpy(&home_pathname[home_end], shell_startups[shell_num]);
    if((fileptr = fopen(home_pathname, "r")) == NULL) 
      {
	shell_num++;
	continue;
      }
    
    path_end = (home_end + strlen(shell_startups[shell_num]));
    strcpy(&home_pathname[path_end], "-NEW");
    
    if((newfileptr = fopen(home_pathname, "w")) == NULL) {
      shell_num++;
      continue;
    }
    
    shell_num++;

    while(fgets(buffer, bufsiz, fileptr)) {
      if(regexec(cookiePtr, buffer)) {
	found_modload_flag = 1;
	break;
      }
      fputs(buffer, newfileptr);
    }

    /* If not found... */
    if(! found_modload_flag) {
      close(fileptr);
      close(newfileptr);
      unlink(home_pathname);
      continue;  /* ... do the next startup file again */
    }
    
    found_module_command = 1;
    found_modload_flag = 0;

    regexec(modcmdPtr, buffer);
    regexec(modlstPtr, modcmdPtr->endp[0]);
    
    if(!(flags & M_LOAD) || (flags & M_PREPEND)) {
      rch = *modcmdPtr->endp[0];
      *modcmdPtr->endp[0] = '\0';
    }
    
    ch = *modlstPtr->endp[0];
    *modlstPtr->endp[0] = '\0';
    
    fputs(buffer, newfileptr);  /* Write beginning of module load 
				   to end of module load */
    if(flags & M_CLEAR)
      goto complete_output;
    
    if(!(flags & M_LOAD) || (flags & M_PREPEND))
      *modcmdPtr->endp[0] = rch;
    
    modlist = SplitIntoList(interp, modlstPtr->startp[0], &nummods);

    if(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], 
		modlstPtr->startp[0]);
      }
      FreeList(modlist, nummods);

      unlink(home_pathname);  /* Remove ~/.startup-NEW */

      continue;
    }
    
    for(i = 0; i < argc; i++) {
      matched_module = 0;

      /* 
	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) && !matched_module; j++) {
	if(! strcmp(modlist[j], argv[i])) {  /* is this the one we want? */
	  if(flags & M_REMOVE) {
	    /* If removing it, NULL it off the list. */
	    fprintf(stderr, "Removed %s\n", modlist[j]);
	    free(modlist[j]);
	    modlist[j] = NULL;
	    rm_found = 1;
	  } else if(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]);
	  }
	  matched_module = 1;
	}
      }
      
      if(!(flags & M_LOAD))
	continue;
      
      /* If adding, don't put it in there if it is already there... */
      if(!matched_module)
	fprintf(newfileptr, " %s", argv[i]);
    }
    
    /*
      Ok, if we're removing it, prepending it, or switching it, 
      the modlist contains what needs to be put where...
      */
    if(!(flags & M_LOAD) || (flags & M_PREPEND))
      for(j = 0; j < nummods; j++) {
	if(modlist[j])
	  fprintf(newfileptr, " %s", modlist[j]);
      }
    
    FreeList(modlist, nummods);
    
  complete_output:
    *modlstPtr->endp[0] = ch;
    
    /* Restore any comments at the end of the line... */
    fputs(modlstPtr->endp[0], newfileptr);

    /* Complete copying the rest of the file... */
    while(fgets(buffer, bufsiz, fileptr))
      fputs(buffer, newfileptr);

    /* Don't need these any more */
    close(fileptr);
    close(newfileptr);

    /* Truncate -NEW from home_pathname */
    home_pathname[path_end] = '\0';

    /* Create a -OLD name */
    sprintf(home_pathname2, "%s-OLD", home_pathname);

    /* Move ~/.startup to ~/.startup-OLD */
    if(rename(home_pathname, home_pathname2) < 0) {
      Tcl_AppendResult(interp, "Couldn't rename ", home_pathname, " to ",
		       home_pathname2, NULL);
      return TCL_ERROR;
    }

    /* Create a -NEW name */
    sprintf(home_pathname2, "%s-NEW", home_pathname);

    /* Move ~/.startup-NEW to ~/.startup */
    if(rename(home_pathname2, home_pathname) < 0) {
      Tcl_AppendResult(interp, "Couldn't rename ", home_pathname2, " to ",
		       home_pathname, NULL);
      
      /* Put the -OLD one back if I can't rename it */
      sprintf(home_pathname2, "%s-OLD", home_pathname);
      
      if(rename(home_pathname2, home_pathname) < 0) {
	Tcl_AppendResult(interp, "Couldn't rename ", home_pathname2, " to ",
			 home_pathname, NULL);
      }
      
      return TCL_ERROR;
    }
  }
  
  /* Create a -NEW name */
  sprintf(home_pathname2, "%s-NEW", home_pathname);

  if((flags & M_SWITCH) && !sw_found) {
    Tcl_AppendResult(interp, "Unable to locate ", argv[0], 
		     " to switch with ", argv[1], ".");
    unlink(home_pathname2);
    return TCL_ERROR;
  }
    
  if((flags & M_REMOVE) && !rm_found) {
    Tcl_AppendResult(interp, 
		     "Unable to locate any of the given", 
		     " module(s) for removal.", NULL);
    unlink(home_pathname2);
    return TCL_ERROR;
  }
    
  if(! found_module_command) {
      Tcl_AppendResult(interp, "Can't locate 'module load' string in ",
		       "any of these \n\t\t", shell_name, 
		       " shell startup files:\n\n", NULL);

      i = 0;
      shell_num= 0;
      while(shell_startups[shell_num])
          Tcl_AppendResult(interp, "\t\t\t+ ", shell_startups[shell_num++], 
                           "\n", NULL);

      return TCL_ERROR;
  }

  return TCL_OK;
}
