我有以下代码:

#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”的内容时,它会重新显示“execvp echoué”,因为代码删除了空格。我该怎么做才能让它接受带有ps-f等选项的Comands?

最佳答案

您应该使用fgets()而不是scanf()。因为fgets不会从输入中删除空格。scanf函数只消耗输入直到空格。例如,如果输入“ps-f”,scanf会将此输入用作“ps”。如果您直接将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 */
     }
}

c - C Shell执行命令-LMLPHP

关于c - C Shell执行命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40272013/

10-14 22:09