home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 21 / CD_ASCQ_21_040595.iso / dos / prg / c / freedos3 / source / com020 / command.c < prev    next >
C/C++ Source or Header  |  1995-01-15  |  7KB  |  316 lines

  1. /* COMMAND.C
  2.  * command-line interface
  3.  * Tim Norman
  4.  * Started: 8-17-94
  5.  * v 0.02
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <process.h>
  14. #include <time.h>
  15. #include <errno.h>
  16. #include <dir.h>
  17.  
  18. long history_size = 256;   /* make this configurable later */
  19.  
  20. #include "history.h"
  21. #include "cmdinput.h"
  22.  
  23. #define ENV_SIZE 256
  24. #define MAX_ENV_VARS 32
  25.  
  26. /* The first unused pointer in env_vars points to the next empty spot */
  27. /* That is:  env_vars[num_environment_variables] ==
  28.    env_vars[num_environment_variables - 1] +
  29.    strlen (env_vars[num_environment_variables - 1]) + 1
  30. */
  31.  
  32. char *environment;
  33. char **env_vars;
  34. int num_environment_variables = 0;
  35. char env_temp[128];
  36.  
  37. #include "internal.h"            /* internal functions */
  38.  
  39. char exitflag = 0;    /* indicates EXIT was typed */
  40. char canexit = 1;     /* exitable shell? */
  41.  
  42. void fatal_error (char *s)
  43. {
  44.    puts (s);
  45.    exit (100);
  46. }
  47.  
  48. #include "prompt.h"
  49.  
  50. /* is character a delimeter when used on first word? */
  51. char is_delim (char c)
  52. {
  53.    return (c == '/' || c == '=');
  54. }
  55.  
  56. /* strip the extra spaces between parameters on command-line.  quotation */
  57. /* mark aware */
  58. int strip (char *command)
  59. {
  60.    char temp[128] = "", foundspace = 0;
  61.    unsigned char place = 0, tempplace = 0, firstword = 1, inquote = 0;
  62.  
  63.    while (isspace (command[place]))
  64.       place++;
  65.  
  66.    while (command[place])
  67.    {
  68.       if (foundspace && !isspace (command[place]))
  69.       {
  70.      temp[tempplace++] = ' ';
  71.      foundspace = 0;
  72.       }
  73.  
  74.       if (isspace (command[place]) && !inquote)
  75.       {
  76.      foundspace = 1;
  77.      firstword = 0;
  78.       }
  79.       else if (is_delim (command[place]) && firstword)
  80.       {
  81.      temp[tempplace++] = ' ';
  82.      temp[tempplace++] = command[place];
  83.       }
  84.       else if (command[place] == '"')
  85.       {
  86.      if (!inquote && place > 0 && !isspace (command[place - 1]))
  87.         temp[tempplace++] = ' ';
  88.  
  89.      temp[tempplace++] = '"';
  90.  
  91.      inquote = !inquote;
  92.  
  93.      if (!inquote && !isspace (command[place + 1]))
  94.         temp[tempplace++] = ' ';
  95.       }
  96.       else
  97.      temp[tempplace++] = command[place];
  98.  
  99.       place++;
  100.    }
  101.  
  102.    temp[tempplace] = 0;
  103.    strcpy (command, temp);
  104.  
  105.    if (inquote)
  106.       return 0;
  107.    else
  108.       return 1;  /* true on success */
  109. }
  110.  
  111. /* split the command-line into parameters.  Works with quotation marks */
  112. unsigned char split (char *command, char *p[128])
  113. {
  114.    unsigned char count, place = 1, len, inquote = 0;
  115.  
  116.    p[0] = command;
  117.  
  118.    len = strlen (command);
  119.  
  120.    for (count = 0; count < len; count++)
  121.       if (command[count] == '"')
  122.      inquote = !inquote;
  123.       else if (command[count] == ' ' && !inquote)
  124.       {
  125.      command[count] = 0;
  126.      p[place++] = &command[count + 1];
  127.       }
  128.  
  129.    p[place] = NULL;
  130.  
  131.    return place;
  132. }
  133.  
  134. /* returns TRUE if the char is a delimiter char (i.e. can't be in a filename) */
  135. char is_special (char ch)
  136. {
  137.    return (ch == '<' || ch == '>' || ch == '=' || ch == ',' || ch == ';' ||
  138.        ch == ':' || ch == '*' || ch == '?' || ch == '[' || ch == ']' ||
  139.        ch == '/' || ch == '\\'|| ch == '+' || ch == '"' || ch <= ' ');
  140. }
  141.  
  142. /* splits up command-line and figures out what to call */
  143. void parsecommandline (char *command)
  144. {
  145.    char *p[128];        /* array of char pointers for splitting up command */
  146.    unsigned char args;  /* number of words on command line */
  147.    char origcommand[1024], tempcommand[1024];
  148.  
  149.    strcpy (origcommand, command);
  150.  
  151.    /* get rid of places with more than one space & beginning and ending space */
  152.    if (!strip (command))
  153.    {
  154.       puts ("Syntax error.");  /* unmatched quote */
  155.       return;
  156.    }
  157.  
  158.    /* replace spaces with null's and place in p */
  159.    args = split (command, p);
  160.  
  161.    /* parse first word for known commands */
  162.    if (p[0][0] && p[0][1] == ':' && p[0][2] == 0)  /* change drives */
  163.    {
  164.       if (isalpha (p[0][0]))
  165.      setdisk (toupper (p[0][0]) - 'A');
  166.  
  167.       if (getdisk () != toupper (p[0][0]) - 'A')
  168.      puts ("Invalid drive specification");
  169.    }
  170.    else if (strcmpi (p[0], "SET") == 0) /* List */
  171.    {
  172.       if (p[1])
  173.      SET (origcommand);
  174.       else
  175.      show_environment ();
  176.    }
  177.    else if (strcmpi (p[0], "PROMPT") == 0)
  178.    {
  179.       char *from, *to;
  180.  
  181.       from = origcommand;
  182.       to = tempcommand + 11;
  183.  
  184.       strcpy (tempcommand, "SET PROMPT=");
  185.  
  186.       while (isspace (*from))
  187.      from++;
  188.  
  189.       from += 6;
  190.  
  191.       while (isspace (*from))
  192.      from++;
  193.  
  194.       if (*from == '=')
  195.      {
  196.         from++;
  197.  
  198.         while (isspace (*from))
  199.            from++;
  200.      }
  201.  
  202.       strcpy (to, from);
  203.  
  204.       SET (tempcommand);
  205.    }
  206.    else if (strcmpi (p[0], "EXIT") == 0)
  207.       exitflag = 1;
  208.    else if (strncmpi (p[0], "CD", 2) == 0 &&
  209.         (p[0][2] == 0 || p[0][2] == '\\' || p[0][2] == '.'))
  210.       CD (origcommand, p, args);
  211.    else if (strcmpi (p[0], "DOSKEY") == 0)
  212.    {
  213.       puts ("DOSKEY features are already available to the DOS shell.");
  214.       puts ("To create an alias, use the ALIAS command.");
  215.    }
  216.    else if (strcmpi (p[0], "REM") == 0)
  217.       ;         /* don't do anything */
  218.    else if (!p[0][0])  /* nothing typed */
  219.       ;
  220.    else
  221.    {
  222.       int count;
  223.       char *temp;
  224.  
  225. /*
  226.       printf ("p[0]=%s\n", p[0]);
  227.       for (count = 0; p[count]; count++)
  228.      printf ("%d: %s\n", count, p[count]);
  229.       getch ();
  230. */
  231.  
  232.       temp = env_vars[num_environment_variables];
  233.       env_vars[num_environment_variables] = NULL;
  234.  
  235.       if (spawnvpe (P_WAIT, p[0], p, env_vars) == -1)
  236.       {
  237.      /* call internal DIR if external one not found or error */
  238.      if (strcmpi (p[0], "DIR") == 0)
  239.         DIR (&p[1], args - 1);
  240.      else switch (errno)
  241.      {
  242.         case E2BIG:
  243.            puts ("Command line too long.");
  244.            break;
  245.  
  246.         case EINVAL:
  247.            puts ("Invalid argument.");
  248.            break;
  249.  
  250.         case ENOENT:
  251.            puts ("Bad command or filename.");
  252.            break;
  253.  
  254.         case ENOEXEC:
  255.            puts ("Exec format error.");
  256.            break;
  257.  
  258.         case ENOMEM:
  259.            puts ("Insufficient memory.");
  260.            break;
  261.  
  262.         default:
  263.            printf ("Unknown error %d.  Contact the author!\n", errno);
  264.      }
  265.       }
  266.  
  267.       env_vars[num_environment_variables] = temp;
  268.    }
  269. }
  270.  
  271. int process_input ()
  272. {
  273.    char commandline[1024];
  274.  
  275.    do
  276.    {
  277.       puts ("");
  278.       printprompt ();
  279.       readcommand (commandline, 128);
  280.       parsecommandline (commandline);
  281.    }
  282.    while (!canexit || !exitflag);
  283.  
  284.    return 0;
  285. }
  286.  
  287. int c_brk (void)  /* ctrl-break handler */
  288. {
  289.    return 1;    /* continue execution */
  290. }
  291.  
  292. void initialize (int argc, char *argv[], char *env[])
  293. {
  294.    ctrlbrk (c_brk);
  295.  
  296.    puts ("FreeDOS Alpha COMMAND.COM\n");
  297.  
  298.    environment = malloc (ENV_SIZE);
  299.  
  300.    /* allocate space for environment variable pointers into environment */
  301.    env_vars = malloc (MAX_ENV_VARS * sizeof (char *));
  302.    env_vars[0] = environment;
  303.  
  304.    /* make it inherit the environment if run from another process */
  305.    /* not implemented */
  306. }
  307.  
  308. int main (int argc, char *argv[], char *env[])
  309. {
  310.    /* check switches on command-line */
  311.  
  312.    initialize (argc, argv, env);
  313.  
  314.    return process_input ();     /* call prompt routine */
  315. }
  316.