home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advmsdos / chap12 / shell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-01  |  4.1 KB  |  176 lines

  1. /*
  2.     SHELL.C        Simple extendable command interpreter
  3.                 for MS-DOS version 2.0 and later
  4.  
  5.     Copyright 1988 Ray Duncan
  6.  
  7.     Compile:    C>CL SHELL.C
  8.  
  9.     Usage:        C>SHELL
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <process.h>
  14. #include <stdlib.h>
  15. #include <signal.h>
  16.  
  17.                                     /* macro to return number of
  18.                                        elements in a structure */
  19. #define dim(x) (sizeof(x) / sizeof(x[0]))
  20.  
  21. unsigned intrinsic(char *);            /* function prototypes */
  22. void extrinsic(char *);
  23. void get_cmd(char *);
  24. void get_comspec(char *);
  25. void break_handler(void);
  26. void cls_cmd(void);
  27. void dos_cmd(void);
  28. void exit_cmd(void);
  29.  
  30. struct cmd_table {                    /* intrinsic commands table */
  31.                    char *cmd_name;
  32.                       int  (*cmd_fxn)(); 
  33.                  }   commands[] =
  34.  
  35.                     { "CLS",   cls_cmd,
  36.                    "DOS",   dos_cmd,
  37.                    "EXIT",  exit_cmd, };
  38.  
  39. static char com_spec[64];            /* COMMAND.COM filespec */
  40.  
  41.  
  42. main(int argc, char *argv[])
  43. {   
  44.     char inp_buf[80];                 /* keyboard input buffer */
  45.  
  46.     get_comspec(com_spec);            /* get COMMAND.COM filespec */
  47.  
  48.                                     /* register new handler
  49.                                         for Ctrl-C interrupts */
  50.     if(signal(SIGINT, break_handler) == (int(*)()) -1)
  51.     {    
  52.         fputs("Can't capture Control-C Interrupt", stderr);
  53.         exit(1); 
  54.     }
  55.  
  56.     while(1)                           /* main interpreter loop */
  57.     {    
  58.         get_cmd(inp_buf);           /* get a command */
  59.         if (! intrinsic(inp_buf) )    /* if it's intrinsic,
  60.                                        run its subroutine */
  61.            extrinsic(inp_buf);        /* else pass to COMMAND.COM */
  62.         }
  63. }
  64.  
  65.  
  66. /*      
  67.     Try and match user's command with intrinsic command 
  68.     table.  If a match is found, run the associated routine 
  69.     and return true, else return false.
  70. */
  71.  
  72. unsigned intrinsic(char *input_string)
  73. {   
  74.     int i, j;                        /* some scratch variables */
  75.  
  76.                                     /* scan off leading blanks */
  77.     while(*input_string == '\x20') input_string++ ;
  78.  
  79.                                     /* search command table */
  80.     for(i=0; i < dim(commands); i++)
  81.     {    
  82.         j = strcmp(commands[i].cmd_name, input_string);
  83.  
  84.         if(j == 0)                     /* if match, run routine */
  85.         { 
  86.             (*commands[i].cmd_fxn)();  
  87.             return(1);                /* and return true */
  88.         }
  89.     }
  90.     return(0);                        /* no match, return false */
  91. }
  92.  
  93.  
  94. /* 
  95.     Process an extrinsic command by passing it
  96.     to an EXEC'd copy of COMMAND.COM.
  97. */
  98.  
  99. void extrinsic(char *input_string)
  100. {   
  101.     int status;                        
  102.  
  103.     status = system(input_string);    /* call EXEC function */
  104.  
  105.     if(status)                         /* if failed, display
  106.                                        error message */
  107.         fputs("\nEXEC of COMMAND.COM failed\n", stderr);
  108. }
  109.  
  110.  
  111. /* 
  112.     Issue prompt, get user's command from standard input,
  113.     fold it to upper case.
  114. */
  115.  
  116. void get_cmd(char *buffer)
  117. {   
  118.     printf("\nsh: ");                   /* display prompt */
  119.     gets(buffer);                       /* get keyboard entry */
  120.     strupr(buffer);                     /* fold to upper case */
  121. }       
  122.  
  123.  
  124. /*    
  125.     Get the full path and file specification for COMMAND.COM
  126.     from the "COMSPEC=" variable in the environment.
  127. */
  128.  
  129. void get_comspec(char *buffer)
  130. {   
  131.     strcpy(buffer, getenv("COMSPEC"));
  132.  
  133.     if(buffer[0] == NULL)        
  134.     {   
  135.         fputs("\nNo COMSPEC in environment\n", stderr);
  136.          exit(1);
  137.     }
  138. }
  139.  
  140.  
  141. /*
  142.     This Ctrl-C handler keeps SHELL from losing control.
  143.     It just re-issues the prompt and returns.
  144. */
  145.  
  146. void break_handler(void)
  147. {   
  148.     signal(SIGINT, break_handler);        /* reset handler */
  149.     printf("\nsh: ");                   /* display prompt */
  150. }    
  151.  
  152.  
  153. /*      
  154.     These are the subroutines for the intrinsic commands.
  155. */
  156.  
  157. void cls_cmd(void)                         /* CLS command */
  158. {   
  159.     printf("\033[2J");                  /* ANSI escape sequence */
  160. }                                        /* to clear screen */
  161.  
  162. void dos_cmd(void)                         /* DOS command */
  163. {   
  164.     int status;
  165.                                         /* run COMMAND.COM */
  166.     status = spawnlp(P_WAIT, com_spec, com_spec, NULL);
  167.  
  168.     if (status)    
  169.         fputs("\nEXEC of COMMAND.COM failed\n",stderr); 
  170. }
  171.  
  172. void exit_cmd(void)                        /* EXIT command */
  173. {   
  174.     exit(0);                            /* terminate SHELL */
  175. }
  176.