【问题标题】:Cat command didn't work correctly with execvpCat 命令无法与 execvp 一起正常工作
【发布时间】:2017-11-18 05:56:17
【问题描述】:

1) 我不能在这段代码中使用一些命令,例如:cat somefile.txt > somefile2.txt 我也不能使用:cat somefile.txt | less

2) 当我使用( cd ../) (cd ./Desktop) 之类的命令,然后我想退出程序时,我需要多次执行退出命令:即“如果我使用 3 个 cd 命令,我将需要 3 个退出命令来结束程序”

#define MAX_ARGS 5

// Global Declarations

// Mini Functions

void remove_new_line_char(char line[])
{
    int i=0;
    while(line[i]!= '\n')
        i++;
    line[i] = '\0';
}

// Grand Functions

int read_line(char line[])
{
    fgets(line, 10000, stdin); // File Get String
    remove_new_line_char(line); // Remove New Line Charactere
    if (strlen(line) > 512)
    {
        fprintf(stderr,"The Command exceeded available line length\n");
        return 0;
    }
    if (strcmp(line, "exit") == 0)
        exit(0);
    return 1;
}

int parse_line(char* args[], char line[])
{
    int i=0;
    args[i] = strtok(line, " ");
    if(args[i] == NULL)
    {
        printf("Command Line is Empty!\n");
        return -1;
    }
    while (args[i] != NULL)
    {
        int flag = 0;
        if(strcmp(args[i],"&") == 0)
            flag = 1;
        i++;
        args[i] = strtok(NULL, " "); // NULL maintains a static pointer to the previously passed string.
        if (args[i] == NULL && flag == 1)
        {
            args[i-1] = NULL; // Remove & From Argument List and Set Background Flag.
            return 1;
        }
    }
    return 0;
}

// Main

int main()
{
    char* args[MAX_ARGS]; // Array of Strings
    char line[10000]; // String
    while(1)
    {
        printf("Shell> ");
        if(read_line(line) == 1) // No Errors
        {
            int background = parse_line(args, line);
            if(background != -1) // Command Line isn't Empty
            {
                // Fork and Execute
                pid_t child_pid = fork();
                if(child_pid == 0) // Child
                {
                    if (strcmp(args[0], "cd") == 0 && args[1]!= NULL && args[2] == NULL)  // Special Handling For CD
                    {
                        //printf("%s\n",args[2]);
                        int check = chdir(args[1]);
                        if(check == -1)
                            fprintf(stderr, "Invalid Directory\n");
                    }
                    // Handle if args[1]== NULL, Don't even execvp()
                    else   // Other Functions
                    {
                        execvp(args[0], args); // args[0] is actually the command.
                        fprintf(stderr,"an error occured in execution\n%s\n",strerror(errno));
                        //fprintf(stderr,"Invalid Instruction\n");
                    }
                }
                else // Parent
                {
                    if(background == 0)
                        waitpid(child_pid, 0);
                    wait(1000);
                }
            }
        }
    }
    return 0;
}

我怀疑我不能使用任何包含以下字符的命令:> < |
提前致谢

【问题讨论】:

  • 您的问题是否收到“代码过多”警告?您能否将您的示例缩减为最小的内容,以显示您尝试使用 cat 做什么以及为什么它在您的程序中不起作用?
  • while(line[i]!= '\n') i++ 会发生什么line[] 缺少'\n'
  • 不清楚你在问什么。你能修改这句话“..我应该写出与我之前使用的命令相同数量的退出命令”。另外,如前所述,这是一个 MVE:Minimum Complete, and Verifiable example?
  • @chux fgets 开始一个我不需要的新空行,所以我用这个循环删除它
  • @SherylHohman 当我尝试退出程序时,我应该多次编写退出命令“如果我使用 cd ../ 命令 3 次,我将使用退出命令 3 次来关闭终端” (因为我认为每个退出命令都会退出一个子进程)

标签: c ubuntu unix


【解决方案1】:

1) 我不能在这段代码中使用一些命令:cat somefile.txt > somefile2.txt 我也不能使用:cat somefile.txt |少

在标准 shell 中,>| 是操作符由 shell 解释,而不是命令的参数。因为在这种情况下,shell 就是您的程序本身,如果您必须支持这些运算符,那么您需要自己实现适当的重定向。请参考open()pipe()dup2(),对于管道案例,您还需要明智地应用close()

2)当我使用类似的命令:( cd ../) (cd ./Desktop) 然后我想退出程序时,我需要多次执行退出命令“如果我使用 3 cd 命令我将需要 3 个退出命令来结束程序”

cd 命令的特殊情况下,您在子进程中fork 然后更改目录,但子进程不会终止或执行另一个进程。这让你有两个运行的 shell 副本。您需要在控制返回到启动程序的任何进程之前退出两者。在这种情况下,您可能希望在不分叉(或等待孩子)的情况下执行 chdir

【讨论】:

  • exec 后是否有终止子进程的方法??
  • @MoustafaUsama,一般来说,shell 应该允许它启动的子进程正常终止,但您可以尝试通过kill() 函数向它们发送适当的信号来提前终止它们。请注意,这些都不适合您的cd 命令,但是,因为目录更改仅影响执行它的进程(代码中的 child 进程,如您提供的那样)。这就是为什么我建议在这种情况下不分叉执行chdir()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多