/**********************************************************
 *  TSHELL.C - Demonstration tiny command interpreter     *
 *  Jim Kyle, July 10, 1990                               *
 *  revised 15 May 1991                                   *
 *                                                        *
 *  Intended only to show basic principles; not for use   *
 *  with DOS versions prior to 3.1 (EXEC function of such *
 *  versions does not preserve stack registers).          *
 *                                                        *
 *  For Turbo C only due to pseudovariable usage.         *
 *                                                        *
 *      tcc -mt -c tshell                                 *
 *      tlink /t /c c0t+tshell,tshell,,cs.lib             *
 *                                                        *    
 *  or (Borland C++ 2.0):                                 *
 *      bcc -mt -c tshell.c                               *
 *      tlink /t /c c0t+tshell,tshell,,cs.lib             *
 *                                                        *
 **********************************************************/
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <dir.h>

char cmdbuf[128];
char *cmdlst[] = {"DIR","RUN"};
int i;

void do_dir( void )     /* reports files in cur dir     */
{ struct ffblk wkarea;
  int endir;

  if (strlen(cmdbuf) < 5)       /* default to all files */
    strcpy( cmdbuf+4, "*.*" );
  puts("\n    Files and sizes\n");
  endir = findfirst( cmdbuf+4, &wkarea, 0 );
  while ( !endir )
    { printf("%-13s   %8ld\n",
             wkarea.ff_name, wkarea.ff_fsize );
      endir = findnext( &wkarea );
    }
  putchar( '\n' );
}

void do_run( void )     /* caution, safe only for DOS3+ */
{ struct {
    unsigned eseg, clo, cls;
    long     fcb1, fcb2;
  } parms;

#if 1
  /* THANKS, chappell@vax1.trincoll.edu */
  cmdbuf[0] = strlen(cmdbuf+1);
  cmdbuf[1] = '/';
  cmdbuf[2] = 'C';
  cmdbuf[3] = ' ';
  parms.eseg = 0;
  parms.clo = (unsigned) cmdbuf;
#else
  /* AS PUBLISHED IN BOOK: WRONG! */
  cmdbuf[1] = '/';
  cmdbuf[2] = 'C';
  cmdbuf[3] = ' ';
  parms.eseg = 0;
  parms.clo = (unsigned) cmdbuf+1;
#endif  
  parms.cls = _DS;
  parms.fcb1 = parms.fcb2 = 0L;
  _ES = _SS;
  _BX = (unsigned) &parms;
  _DX = (unsigned) "C:\\COMMAND.COM";
  _AX = 0x4B00;
  geninterrupt( 0x21 );
}

void main( void )
{ puts( "  TINY SHELL DEMONSTRATOR\n" );
  puts( "Copyright 1990  by Jim Kyle\n" );
  puts( "  Commands: DIR, RUN only\n" );
  for( ; ; )
    { printf("tinyshell> ");
      gets(cmdbuf);
      for(i=0; i<2; i++)
        if(strnicmp(cmdlst[i],cmdbuf,strlen(cmdlst[i]))==0)
          break;
      switch(i)
        { case 0: do_dir();
             break;
          case 1: do_run();
             break;
          default: puts("Unknown command!!!\n");
        }
    }
}
