home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 20 / ntshell / ntshell.c < prev    next >
Text File  |  1992-11-02  |  6KB  |  172 lines

  1. // NTSHELL.C    Simple extendable command interpreter 
  2. //              illustrating use of the WIN32 console API.
  3. //
  4. // Copyright 1992 Ray Duncan
  5. // PC Magazine * Ziff Davis Publishing
  6.  
  7. #include "windows.h"
  8. #include "stdio.h"
  9. #include "process.h"
  10. #include "stdlib.h"
  11. #include "string.h"
  12. #include "ntshell.h"
  13.  
  14. //
  15. // This table associates "intrinsic" commands with the 
  16. // routines that carry them out.
  17. //
  18. struct decodeCmd commands[] = {
  19.     "CLS",   doCls,
  20.     "DOS",   doDos,
  21.     "EXIT",  doExit, };
  22.  
  23. char comspec[MAXEXENAMESIZE];               // pathname of CMD.EXE
  24.  
  25. char msg1[] = "\nCan't run CMD.EXE.\n";     // misc. error messages
  26. char msg2[] = "\nCMD.EXE couldn't execute command.\n";  
  27. char msg3[] = "\nNo COMSPEC in environment.\n"; 
  28.  
  29. HANDLE hConIn;                              // console input handle
  30. HANDLE hConOut;                             // console output handle
  31.  
  32. VOID main(int argc, char *argv[])
  33. {
  34.     char buffer[INPUTSIZE];                 // keyboard input buffer
  35.  
  36.     FreeConsole();                          // discard inherited console
  37.     if(!AllocConsole())                     // and create a new one
  38.         exit(TRUE);                         // allocation failed, exit
  39.  
  40.     // open handles for console input and output
  41.     hConIn =  CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
  42.                          FILE_SHARE_READ | FILE_SHARE_WRITE, 
  43.                          NULL, OPEN_EXISTING, 0, NULL);
  44.     hConOut = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
  45.                          FILE_SHARE_READ | FILE_SHARE_WRITE, 
  46.                          NULL, OPEN_EXISTING, 0, NULL);
  47.  
  48.     // bail out if we can't get console I/O handles
  49.     if((hConIn == (HANDLE) -1) || (hConOut == (HANDLE) -1)) 
  50.         exit(TRUE);               
  51.  
  52.     getComspec(comspec);                    // get pathname for CMD.EXE
  53.  
  54.     while(TRUE)                             // main interpreter loop
  55.     {
  56.         getCommand(buffer);                 // get command from user
  57.         if(!intrinsic(buffer))              // if intrinsic, run worker
  58.            extrinsic(buffer);               // else pass to CMD.EXE
  59.     }
  60. }
  61.  
  62. //
  63. //  intrinsic() -- try and match user's command with intrinsic 
  64. //  command table.  If a match is found, run the associated routine
  65. //  and return TRUE, else return FALSE.
  66. //
  67. UINT intrinsic(char *input)
  68. {
  69.     int i;                                  // scratch variable
  70.     char token[64];                         // scratch buffer
  71.  
  72.     // discard leading blanks from user's input
  73.     while(*input == '\x20') input++ ;
  74.  
  75.     i = strcspn(input, " ;/,-");            // search for delimiter
  76.     memset(token, 0, sizeof(token));        // zero out token buffer
  77.     strncpy(token, input, i);               // copy first input token
  78.     strupr(token);                          // fold token to upper case
  79.  
  80.     for(i=0; i < dim(commands); i++)        // search command table
  81.     {
  82.         if(!strcmp(commands[i].name, token))
  83.         {
  84.             (*commands[i].fxn)(input);      // if match, run routine
  85.             return(TRUE);                   // and return true
  86.         }
  87.     }
  88.     return(FALSE);                          // no match, return false
  89. }
  90.  
  91. //
  92. //  extrinsic() -- process an unrecognized command by passing 
  93. //  it to a child instance of CMD.EXE.
  94. //
  95. VOID extrinsic(char *input)
  96. {
  97.     if(system(input))                       // run child CMD.EXE
  98.         putMsg(msg2);                       // error message if failed
  99. }
  100.  
  101. //
  102. //  getCommand() - issue prompt, get user's command from console,
  103. //  and make it ASCIIZ.
  104. //
  105. VOID getCommand(char *buffer)
  106. {
  107.     DWORD count;
  108.  
  109.     putMsg("\nntshell: ");                  // display prompt 
  110.     ReadFile(hConIn, buffer, INPUTSIZE, &count, NULL);
  111.     buffer[count-2] = 0;                    // clip off CR-LF
  112.     strupr(buffer);                         // fold to upper case 
  113. }
  114.  
  115. //
  116. //  getComspec() -- get the full pathname for CMD.EXE
  117. //  from the "COMSPEC=" variable in the environment.
  118. //
  119. VOID getComspec(char *buffer)
  120. {
  121.     strcpy(buffer, getenv("COMSPEC"));      // get COMSPEC variable
  122.                                             // from environment
  123.     if(!buffer[0])                      
  124.     {                                       // if no such variable,
  125.         putMsg(msg3);                       // display error message
  126.         exit(1);                            // and exit
  127.     }
  128. }
  129.  
  130. //
  131. // putMsg() -- display a string on the console.
  132. //
  133. VOID putMsg(char *string)
  134. {
  135.     DWORD count;
  136.  
  137.     WriteFile(hConOut, string, strlen(string), &count, NULL);
  138. }
  139.  
  140. //
  141. //  These are the subroutines for NTSHELL's intrinsic commands.
  142. //
  143.  
  144. VOID doCls(char *input)                     // CLS command = 
  145. {                                           // erase the window
  146.     DWORD count;
  147.     COORD coord;
  148.     CONSOLE_SCREEN_BUFFER_INFO si;
  149.  
  150.     GetConsoleScreenBufferInfo(hConOut, &si); // get screen dimensions
  151.  
  152.     coord.X = 0;                            // buffer coordinates for
  153.     coord.Y = 0;                            // start of blanking = (0,0)
  154.  
  155.     // fill screen with blanks, set cursor at upper left corner
  156.     FillConsoleOutputCharacter(hConOut, ' ', si.dwSize.X * si.dwSize.Y, 
  157.         coord, &count);
  158.     SetConsoleCursorPosition(hConOut, coord);
  159. }   
  160.  
  161. VOID doDos(char *input)                     // DOS command = start
  162. {                                           // child copy of CMD.EXE 
  163.     if(spawnlp(P_WAIT, comspec, comspec, NULL))
  164.         putMsg(msg1);                       // error message if failed
  165. }
  166.  
  167. VOID doExit(char *input)                    // EXIT command =
  168. {                                           // terminate NTSHELL
  169.     exit(FALSE);                            // with success status
  170. }
  171.  
  172.