/* set.c
 * v0.91
 * 
 * Holger Danielsson
 * (dani@lara.prima.ruhr.de)
 * 6.9.1996
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> 
#include <malloc.h>


/* Expandierung des SET-Befehls:
 *
 * Vorbereitung:
 * Der übergebene Token-String 'token' wird zunächst im Environment-Puffer
 * 'e' gesichert. Wenn keine zwei Prozent-Zeichen vorkommen, muß keine
 * Environment-Variable expandiert werden.
 *
 * Schleife:
 * Sonst wird der aktuelle Token-String in einer Schleife immer
 * weiter expandiert, wobei das aktuelle Zwischenergebnis immer
 * im Environment-Puffer 'e' gespeichert ist. Bei jedem Durchgang
 * wird dieser in drei Teile aufgeteilt:
 *
 *    d:/work;%TEXINPUT%;d:/emtex/work
 *    ^       ^        ^
 *    e       p1       p2
 *
 * Nun werden die Prozentzeichen durch die End-Of-String-Kennung
 * ersetzt, so dass drei Teilstrings entstehen. Die Environment-Variable 
 * an der Position p1+1 wird mit 'getenv' expandiert, wobei 'envar' 
 * auf das Ergebnis zeigt. Danach kann der expandierte String in 
 * einem temporären Pueffer zusammengesetz werden:
 * 
 * 1) String ab der Position 'e' (wenn überhaupt vorhanden)
 * 2) expandierte Environment-Variable aus 'envar'
 * 3) String ab Position 'p2+1' (wenn überhaupt vorhanden)
 *
 * Abschliessend wird dieser String in den aktuellen Exvironment-Puffer
 * umkopiert und der temporäre Speicher freigegeben.
 * 
 * Abschluss:
 * Der Puffer ist jetzt vollständig expandiert und der SET-Befehl
 * kann mit 'putenv' ausgeführt werden.
 */
 
static int expand_set_command(const char *token)
{ 
   char *p1,                /* erstes Vorkommen von '%'         */
        *p2,                /* zweites Vorkommen von '%'        */
        *temp,              /* temporaerer Puffer               */
        *e,                 /* Environment-Puffer               */
        *envar;             /* expandierte Environment-Variable */
   
   if (!token) return 0;
   
   if ( (p1=strchr(token,'=')) == NULL) {
      puts("No environment-variable in SET command");
      return 0;
   }
   
   e = strdup(token) ;                 /* Puffer initialisieren */
   
   p1 = e;                       /* Variablen nur in Upper-Case */
   while ( *p1 != '=' ) {
      *p1 = toupper(*p1);
      p1++;
   }
   
   while ( ((p1=strchr(e,'%')) != NULL) &&        /* Schleife ? */
           ((p2=strchr(p1+1,'%')) != NULL) ) {
      *p1 = '\0';                      /* Puffer auftrennen     */
      *p2 = '\0';
      envar = getenv( strupr(p1+1) );  /* Variable expandieren  */
      if (!envar) goto expand_error;
                                           /* Puffer anfordern  */
      temp = malloc( strlen(e)+strlen(envar)+strlen(p2+1) +2 );
      if (!temp) goto expand_error; 
      sprintf(temp,"%s%s%s",e,envar,p2+1); /* Puffer belegen    */
      free(e);                             
      e = strdup(temp);                    /* Puffer umkopieren */
      free(temp);                          /* Puffer freigeben  */
      continue;                   /* wieder zum Schleifenanfang */
      
      expand_error:               /* wenn ein Fehler auftritt:  */ 
         free(e);
         puts("Unable to expand SET command");
         return 0;
   }  
   
   if (putenv(e)) {
      puts("Bad environment");
      free(e);
   }
   
   return 0;
}

/* SET-Befehl mit Expandierung:
 *
 *  1) mit Parameter wird eine Environment-Variable neu
 *     gesetzt oder verändert
 *  2) ohne Parameter werden die aktuellen Werte ausgegeben
 *
 * Syntax: SET
 *         SET var=text
 * argv[]:        0     
 *
 */
 
int execute_set(char *argv[])
{
   int i;
   if ( argv[0] )                 /* mit Parameter */ 
      expand_set_command( argv[0] );  
   else {                         /* ohne Parameter */
      for (i=0; environ[i] != NULL; i++)
         puts(environ[i]);
      }
   return 0;
}
