C Shell执行命令

时间:2016-10-26 20:59:31

标签: c linux

我有以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

void  passe(char *ligne, char **argv)
{
     while (*ligne != '\0')
     {
          while (*ligne == ' ' || *ligne == '\t' || *ligne == '\n')
               *ligne++ = '\0';
          *argv++ = ligne;
          while (*ligne != '\0' && *ligne != ' ' &&  *ligne != '\t' && *ligne != '\n') 
               ligne++;   
     }
     *argv = '\0';
}

void  executer(char **argv)
{
     pid_t  pid;
     int    status;

     if ((pid=fork()) == 0)
     {
          if (execvp(*argv, argv) < 0) 
          {
               printf("*** ERREUR: exec echoué\n");
               exit(1);
          }
     }
     wait(&status);
}

int  main(void)
{
     char  ligne[1024];
     char  *argv[64];

     while (1)
     {
          printf("Shell -> ");
          scanf("%s",ligne);
          printf("\n");
          passe(ligne, argv);
          if (strcmp(argv[0], "exit") == 0)
               exit(0);
          executer(argv);
     }
     return 0;
}

程序工作正常,但是当我解析类似“ps -f”之类的东西时,它会重新调整“execvpechué”,因为代码会删除空格。我应该做些什么来使它接受与ps -f?

等选项的命令

1 个答案:

答案 0 :(得分:2)

您应该使用fgets()而不是scanf()。因为fgets不会从输入中删除空格。 scanf函数只消耗输入直到空格。例如,如果输入&#34; ps -f&#34; scanf将此输入消耗为&#34; ps&#34;。如果你直接将ps写入shell终端,你可能面临同样的异常,那就是你的程序异常。您可以将fgets用作流读取器,可以是文件流或标准输入流(stdin)。我编写的代码可以解决您的问题。您可以查看如何使用。

/* ----------------------------------------------------------------- */
/* PROGRAM  shell.c                                                  */
/*    This program reads in an input line, parses the input line     */
/* into tokens, and use execvp() to execute the command.             */
/* ----------------------------------------------------------------- */

#include  <stdio.h>
#include  <sys/types.h>

/* ----------------------------------------------------------------- */
/* FUNCTION  parse:                                                  */
/*    This function takes an input line and parse it into tokens.    */
/* It first replaces all white spaces with zeros until it hits a     */
/* non-white space character which indicates the beginning of an     */
/* argument.  It saves the address to argv[], and then skips all     */
/* non-white spaces which constitute the argument.                   */
/* ----------------------------------------------------------------- */

void  parse(char *line, char **argv)
{
     while (*line != '\0') {       /* if not the end of line ....... */ 
          while (*line == ' ' || *line == '\t' || *line == '\n')
               *line++ = '\0';     /* replace white spaces with 0    */
          *argv++ = line;          /* save the argument position     */
          while (*line != '\0' && *line != ' ' && 
                 *line != '\t' && *line != '\n') 
               line++;             /* skip the argument until ...    */
     }
     *argv = '\0';                 /* mark the end of argument list  */
}

/* ----------------------------------------------------------------- */
/* FUNCTION execute:                                                 */
/*    This function receives a commend line argument list with the   */
/* first one being a file name followed by its arguments.  Then,     */
/* this function forks a child process to execute the command using  */
/* system call execvp().                                             */
/* ----------------------------------------------------------------- */

void  execute(char **argv)
{
     pid_t  pid;
     int    status;

     if ((pid = fork()) < 0) {     /* fork a child process           */
          printf("*** ERROR: forking child process failed\n");
          exit(1);
     }
     else if (pid == 0) {          /* for the child process:         */
          if (execvp(*argv, argv) < 0) {     /* execute the command  */
               printf("*** ERROR: exec failed\n");
               exit(1);
          }
     }
     else {                                  /* for the parent:      */
          while (wait(&status) != pid)       /* wait for completion  */
               ;
     }
}

/* ----------------------------------------------------------------- */
/*                  The main program starts here                     */
/* ----------------------------------------------------------------- */

void  main(void)
{
     char  line[1024];             /* the input line                 */
     char  *argv[64];              /* the command line argument      */

     while (1) {                   /* repeat until done ....         */
          printf("Shell -> ");     /*   display a prompt             */
          fgets(line,1024,stdin);  /*   read in the command line     */
          int i = strlen(line)-1;
          if( line[ i ] == '\n') 
              line[i] = '\0';
          parse(line, argv);       /*   parse the line               */
          if (strcmp(argv[0], "exit") == 0)  /* is it an "exit"?     */
               exit(0);            /*   exit if it is                */
          execute(argv);           /* otherwise, execute the command */
     }
}

output