/* envinit --- intialize the environment */

/*
** Initialize the environment a la Unix.
** Set up a bunch of strings of the form
** name=value
** sorted on name. The names and values
** are the user's shell variables.
** Make everything available through the
** variable environ and the getenv() routine.
**
** For use under bare primos, getenv returns NULL, and
** environ is set to NULL.  This is conditionally compiled in,
** and handled by the build procedures.
*/

/* maximum length of the name and value of a variable */
/* maximum number of variables we'll allow */

#define MAXVAR          50
#define MAXVAL          250
#define MAXENV          256
#define MAXBUF          1024

char **environ = NULL;  /* available for the outside world */

#ifndef STAND_ALONE     /* to run under bare primos (shudder!) */

static char env[MAXBUF];        /* holds the strings */
static char *envptr[MAXENV+1];  /* points to them, sort this array */

static int no_vars;     /* keep count */

/* The static functions must come first to avoid a bogus error form c1 */

#define swap(x,y) (temp = x, x = y, y = temp)

static int compare(s1,s2)
char *s1,*s2;
{
        int i;

        for(i = 0; s1[i] == s2[i]; i++)
                if(s1[i] == '\0')
                        return(0);      /* strings are equal */
        else if(s1[i] == '=' || s2[i] == '=')
                return((unsigned) s1[i-1] - (unsigned) s2[i-1]);

        /* loop broken. either chars equal or not */
        return((unsigned) s1[i] - (unsigned) s2[i]);
        /* <0 if s1 < s2, >0 if s1 > s2 */
}

static sort()
{
        char *temp;
        int i,j;
        int incr;
        int n;

        /* shell sort */

        n = no_vars;
        incr = n / 2;
        while(incr > 0)
        {
                for (i = incr + 1; i <= n; i++)
                {
                        j = i - incr;
                        while(j > 0)
                        {
                                if(compare(envptr[j-1], envptr[j+incr-1])       > 0)
                                {
                                        swap(envptr[j-1], envptr[j+incr-1]);
                                        j -= incr;
                                }
                                else
                                        break;
                        }       /* end while */
                }       /* end for */
                incr /= 2;
        }       /* end while */
}
#endif

/* envinit --- initialize the environment */

envinit()
{
#ifndef STAND_ALONE
        int i, j, k, l;
        char value[MAXVAL+1];
        int svscan(), svget();  /* get variables and values respectively */
        static int first = TRUE;
        static int status[3] = { 0, 0, 0 };

        if(first)
                first = FALSE;
        else
                return; /* initialize the environment only once */

        /* string the name=value groups end to end */
        for(i = j = 0; i < MAXBUF && j <= MAXENV
                && (k = svscan(&env[i], MAXVAR, status)) != EOF; j++)
        {
                l = svget(&env[i], &env[i+k+1], MAXVAL);
                env[i+k] = '=';
                envptr[j] = & env[i];
                i += k + l + 1 + 1; /* leave room for the EOS */
        }

        envptr[j] = NULL;

        no_vars = i;

        if(i >= MAXENV)
        {
                fprintf(stderr,"envinit(): too many variable in environment, ");
                fprintf(stderr,"using only the first %d variables\n",MAXENV);
        }

        if(j >= MAXBUF)
        {
                fprintf(stderr, "envinit(): too many characters in environment, ");
                fprintf(stderr, "using only the first %d characters\n", MAXBUF);
        }

        no_vars = j;

        sort();         /* sort the little devils */

        environ = envptr;
#endif
}

/* getenv --- return value of name=value pair from environment */

char *getenv (var)
char *var;
{
#ifndef STAND_ALONE
        static int first = TRUE;
        int i,j;
        int low, mid, high, val;

        if(first)
        {
                first = FALSE;
                if(environ == NULL)
                        envinit();
        }

        /* use binary search */
        i = val = 0;
        j = strlen(var);

        low = 0;
        high = no_vars - 1;
        mid = (high + low) / 2;
        while(low < high)
        {
                val = strncmp(var, environ[mid], j);
                if(val == 0) /* found */
                        break;
                else if(val < 0) /* var < environ[i] */
                        high = mid - 1;
                else /* var > environ[i] */
                        low = mid + 1;
                mid = (high + low) / 2;
        }

        if(strncmp(var, environ[mid], j) == 0) /* found */
                i = mid;
        else /* not found */
                return(NULL);

        if(environ[i] != NULL)           /* got it */
        {
                for(j = 0; environ[i][j] != '='; j++)
                        ;       /* skip over name */
                j++;            /* skip over '=' */
                return(&environ[i][j]);
        }
        else
                return(NULL);
#else
        return (NULL);
#endif
}
