代码之家  ›  专栏  ›  技术社区  ›  Peter

为什么在C中执行多个命令时execvp()失败?

  •  0
  • Peter  · 技术社区  · 2 年前

    我正在编写一个程序,从一个文件名cmdfile中读取命令列表。并在终端中执行它们。

    cmdfile。txt包含:

    whoami
    cal 4 2020
    echo The time is:
    date
    

    我面临的问题是,当文件只包含一个命令行时,程序工作正常。但是,当文件包含超过1个命令行时,该命令无法执行或生成未知命令。 以下是我的工作代码:

    #include  <stdio.h>
    #include  <sys/types.h>
    #include  <unistd.h>
    #include  <stdlib.h>
    #include  <sys/types.h>
    #include  <sys/wait.h>
    #include  <stdbool.h>
    #include  <string.h>
    
    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  */
    }
    
    void execute(char **argv)
    {
         pid_t  pid;
         int    status;
         pid = fork();
         if (pid < 0) {     /* fork a child process           */
              perror("The error for fork() is: ");
              exit(1);
         }
         else if (pid == 0) {          /* for the child process:         */
              if (execvp(*argv, argv) < 0) {     /* execute the command  */
                   perror("The error is: ");
                   exit(1);
              }
         }
         else {                                  /* for the parent:      */
              while (wait(&status) != pid)       /* wait for completion  */
                   ;
         }
    }
    
    void  main(void)
    {
         char  line[1024];             /* the input line                 */
         char  *argv[64];              /* the command line argument      */
         bool running = 1;
    
         FILE *fp = fopen("cmdfile.txt", "r");
         if(fp == NULL)
         {
              perror("Unable to open file!");
              exit(1);
         }
    
         while (fgets(line, 1024, fp)) {                   /* repeat until done ....         */      
              strtok(line, "\n");
              parse(line, argv);       
              execute(argv);
         }
    }
    

    我的第一个猜测是因为FGET没有像我预期的那样,因为新线的分离?我试着把线路打印到终端以追踪错误,但我不知道程序出了什么问题。谁能帮我指出我犯的错误吗?

    The error is: : No such file or directory
    cal: not a valid year 2020
    The time is:
    The error is: : No such file or directory
    The time is:
    The error is: : No such file or directory
    The error is: : No such file or directory
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Jonathan Leffler Toon Krijthe    2 年前

    这个 cmdfile.txt 该文件来自Windows计算机,并被复制到Linux计算机,而无需翻译行尾。因此,每一行都以CRLF结尾 "\r\n" .你的代码小心地将 '\n' 有一个空字节,但这会留下 '\r' 在绳子上。当你经过的时候 "whoami\r" execvp() ,它找不到命令;它会发现 "whoami" 但不是另一个。看来 cal 不喜欢以 \r 任何一个等等(小标题) echo 司令部并不担心这个问题 “\r” .)

    有很多方法可以解决这个问题。在代码的上下文中,最简单的方法是更改 strtok() 循环中的行 main() 阅读:

    strtok(line, "\r\n");
    

    字符串中字符的顺序无关紧要。