/* envtrim.c
   Program to read and re-write environment variables for MS-DOS
   Written by H. D. Todd, Computing Center, Wesleyan University, 12/26/90,
   using prototypes written by Douglas Bigelow, same address.
   Contact: hdtodd@mockingbird.wesleyan.edu
   
   envtrim trims from the left or right ("l" or "r") to a specified
   count of characters ("nn") the value associated with environment
   variable  "var".   One or more environment variables can be truncated
   in a single  invocation of envtrim.  The environment variables in the
   PARENT process are  modified.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#define MAXSTRS 100		/* increase this if you have more env strings */

void main(int argc, char *argv[])

{
  int i, num, envsize, len, nstrs=0, nextra;
  unsigned far *x1, far *x2;
  char dowhat, varstg[100], *varval, far *envp, far *envptr;
  char *strptr[MAXSTRS];
  unsigned far *p_psp, far *p_env;
  struct {
         char link;
         unsigned int owner_psp;
         unsigned int blk_len;
         } far *envmcb;

  if (argc < 2) {
    fprintf(stderr, "Usage: envtrim -{lr}nn var [-{lr}nn var] ...\n");
    exit(1); }

/* Construct the PSP pointers -- first find the root PSP*/
  x1 = MK_FP(_psp,0x16);
  x2 = MK_FP(*x1,0x10);
/*  printf("x1=%Fp   x2=%Fp\n",x1,x2); */
  while (x1 != x2)
	 {x1 = x2;
	  x2 = MK_FP(*x1,0x10);
/*	  printf("x1=%Fp   x2=%Fp\n",x1,x2); */
	 }
/* We now have the pointer to the root COMMAND.COM PSP*/

  x1 = MK_FP(*x1,0x2c);  	/* pointer to root environment ptr */
  envptr = MK_FP(*x1,0x00);     /* pointer to root environment */
  envmcb = MK_FP((*x1)-1,0x00); /* pointer to root env MCB */
  envsize = (*envmcb).blk_len<<4;

/* copy strings from root environment (FAR) to local strings */
   envp = envptr;
   while (*envp) {      /* env strings terminated by second null */
         int len;
         char far *fp;
         char *lp;
         for (len=0, fp=envp; *fp; fp++) len++;
         lp = strptr[nstrs++] = malloc(len+1);
         for ( ; (*lp++=*envp++); );
         }

    while (--argc > 0 ) {
	  if ( ( (dowhat=(*++argv)[0])) != '-') {
	     fprintf(stderr, "envtrim: begin switches with '-', as in '-%c'\n", dowhat);
	     exit(1);
	  };
          dowhat = tolower(*++argv[0]);
	  if (dowhat!='l' && dowhat!='r') {
	     fprintf(stderr, "envtrim: invalid switch -%c\n", dowhat);
	     exit(1);
	  };
	  if ( ((i=sscanf(++argv[0],"%d",&num)) == EOF) || (i==0) ) {
             fprintf(stderr, "envtrim: can't scan number for arg -%c\n",dowhat);
             exit(1);
          };

/*  now look in the table of env strings to see if we match the one
    we're supposed to edit */

          ++argv; --argc;
          strcpy(varstg,argv[0]);
          strcat(varstg,"=");
          for (i=0; i<nstrs; i++)
              if (strnicmp(strptr[i],varstg,strlen(varstg))==0) break;
          if (i>=nstrs)
               fprintf(stderr, "envtrim: Can't find environment var '%s'\n", varstg);
            else {
                 varval = strdup(strptr[i]+strlen(varstg));
                 if (strlen(varval)>num) {
	                if (dowhat == 'l') varval[num] = 0;
    	            if (dowhat == 'r') varval += strlen(varval)-num;
                 };
                 strcpy(strptr[i]+strlen(varstg), varval);
            }
    }

    for (i=0, len=0; i<nstrs; i++) len += strlen(strptr[i]) + 1;
    if (len+1>envsize)  {
        fprintf(stderr,"envtrim: Env block too small to store updated environment strings\n");
        exit(1);
        }
      else {
        for (i=0; i<nstrs; i++) {
            for ( ; (*envptr++ = *strptr[i]++) ; ) ;
            *envptr = '\0';
        }
      }
}
