#ifndef lint
static char *RCSid = "$Id: envir.c,v 1.2 1993/05/10 05:52:45 anders Exp anders $";
#endif

/*
 *  The Regina Rexx Interpreter
 *  Copyright (C) 1993-1994  Anders Christensen <anders@pvv.unit.no>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
    This code modified for Win32 port by Ataman Software, Inc. June 29, 1995.
*/

#include "rexx.h"
#include <string.h>


#if defined(VMS)
# define fork() vfork()
# define posix_do_command vms_do_command
#endif

#if defined(DOS)
# define posix_do_command dos_do_command
#endif

#if defined(WIN32)
# define posix_do_command dos_do_command
#endif
 
static streng var_rc = {2,2,"RC"} ;


struct envir 
{
   streng *name ;
   int type ;
   int subtype ;
   struct envir *next, *prev ;
} *firstenvir=NULL ;


void add_envir( streng *name, int type, int subtype ) 
{
   struct envir *ptr ;

   ptr = Malloc( sizeof(struct envir)) ;
   ptr->name = name ;
   ptr->type = type ;
   ptr->subtype = subtype ;
   ptr->prev = firstenvir ;
   ptr->next = NULL ;
   firstenvir = ptr ;
   if (ptr->prev)
      ptr->prev->next = ptr ;
}


#ifdef TRACEMEM
void markenvir( void ) 
{
   struct envir *eptr ;

   eptr = firstenvir ;
   for (; eptr; eptr=eptr->prev )
   {
      markmemory( eptr, TRC_ENVIRBOX ) ;
      markmemory( eptr->name, TRC_ENVIRNAME ) ;
   }
}
#endif /* TRACEMEM */


static struct envir *find_envir( streng *name ) 
{
   struct envir *ptr ;

   for (ptr=firstenvir; ptr; ptr=ptr->prev)
      if (!Str_cmp(ptr->name, name))
         return ptr ;

   return NULL ;
}


void del_envir( streng *name ) 
{
   struct envir *ptr ;
   
   ptr = find_envir( name ) ;
   if (ptr)
   {
      if (ptr->prev)
         ptr->prev->next = ptr->next ;
      if (ptr->next)
         ptr->next->prev = ptr->prev ;
      if (firstenvir==ptr)
         firstenvir = ptr->prev ;
   }
}


void init_envir( void )
{
   add_envir( Str_cre("COMMAND"), ENVIR_SHELL, SUBENVIR_COMMAND ) ;
   add_envir( Str_cre("SYSTEM"), ENVIR_SHELL, SUBENVIR_SYSTEM ) ;   
   add_envir( Str_cre("PATH"), ENVIR_SHELL, SUBENVIR_PATH ) ;

#ifdef TRACEMEM
   regmarker( markenvir ) ;
#endif
}


int get_io_flag( streng *command )
{
   int length, i ;
   int flag ;

   flag = REDIR_NONE ;
   if ((length=Str_len(command))>5) 
   {
      if ((!memcmp(command->value,"lifo>",5)) || 
          (!memcmp(command->value,"LIFO>",5)))
               flag |= REDIR_INPUT ;

      if ((!memcmp(command->value+length-5,">lifo",5)) ||
          (!memcmp(command->value+length-5,">LIFO",5)))
               flag |= REDIR_OUTLIFO ;

      if ((!memcmp(command->value+length-5,">fifo",5)) ||
          (!memcmp(command->value+length-5,">FIFO",5)))
               flag |= REDIR_OUTFIFO ;
   }

   if (flag & REDIR_OUTPUT) 
      command->len -= 5 ;

   if (flag & REDIR_INPUT)
   {
      for(i=5; i<=Str_len(command); i++ )
         command->value[i-5]=command->value[i] ;
       command->len -= 5 ;
   }

   return flag ;
}


streng *perform( streng *command, streng *envir, nodeptr this )
{
   int rc, io_flag ;
   extern proclevel currlevel ;
   struct envir *eptr ;
   streng *retstr ;

#ifdef lint
   retstr = NULL ;
#endif

   eptr = find_envir( envir ) ;
   io_flag = get_io_flag( command=Str_dup(command)) ;

   if (eptr)
   {
      switch (eptr->type)
      {
         case ENVIR_PIPE:
            retstr = SubCom( command, envir, &rc ) ;
            break ;

         case ENVIR_SHELL:
            rc = posix_do_command( command, io_flag, eptr->subtype ) ;
            retstr = int_to_streng( rc ) ;
            break ;

         default:
            exiterror( ERR_INTERPRETER_FAILURE ) ;
      }
   }
   else
   {
      rc = -3 ;
      retstr = nullstringptr() ;
   }

   setvalue(&var_rc,Str_dup(retstr)) ;

   if (rc && this)
   {
      trap *traps ;
      int type ; 

      traceerror( this, rc ) ;
      traps = gettraps( currlevel ) ;
      type = (rc>0) ? SIGNAL_ERROR : SIGNAL_FAILURE ;

      if ((type==SIGNAL_FAILURE) && (traps[type].on_off))
         condition_hook( type, rc, this->lineno, Str_dup(command) ) ;
      else if (traps[SIGNAL_ERROR].on_off)
         condition_hook( SIGNAL_ERROR, rc, this->lineno, Str_dup(command) ) ;
   }
   
   Free( command ) ;
   return retstr ;
}




