关闭外部进程

时间:2016-03-09 21:20:03

标签: c shell fork exec

我正在为C中的赋值编写一个shell。我现在唯一的问题是,当我使用execvp()调用外部程序然后关闭使用CTRL + C时,我发送的任何其他命令都会在提示符后打印出来不是在它之前。我做了一个虚拟程序,只是一个无限循环来测试它。

关闭此程序后,如果我尝试运行一个不存在的程序,它将打印出来 MINISHELL(cwd)$:然后是一个空白行 然后它将打印我的错误消息,说我已经输入了一个不存在的程序,然后它不会打印提示,因为它已经有了。所以它以一个空的新行结束,看起来该程序还没有结束但实际上已经结束了。

仅在用CTRL + C关闭非终止程序后才执行此操作。否则它可以正常执行程序。我是不是在某处使用close()来关闭文件描述符?我不确定。任何帮助表示赞赏。谢谢。

#include "minishell.h"


void intHandler(int sig)
{
    my_char('\n');
}

int main(int argc, char **argv)
{
    int n;
    int pid = 0;
    char* s = (char*)malloc(256*sizeof(char));
    char cwd[1024];
    char** input;

    while (1)
    {
        signal(SIGINT, intHandler);

        my_str("MINISHELL:");

        if (getcwd(cwd, sizeof(cwd)) != NULL)
            my_str(cwd);

        else
        {
            my_str("Error in current directory");
            return -1;
        }

        my_str(" $: ");
        n = read(0, s, 256);
        s[n] = '\0';

        if (n > 1)
        {
            input = my_str2vect(s);
            if (my_strcmp(input[0], "cd") == 0)
            {
                /*CHANGE DIRECTORY*/
                if (input[1] != '\0')
                {
                    if (chdir(input[1]) < 0)
                        my_str("MINISHELL: Error in path. Make sure the directory exists.\n");
                }

                else
                    my_str("MINISHELL: Error. No directory specified.\n");
            }

            else if (my_strcmp(input[0], "help") == 0)
            {
                /*HELP*/
                my_str("\nMINISHELL COMMANDS:\n\ncd *directory\nChanges the current working directory to *directory\n\nexit\nExits the minishell\n\nhelp\nPrints a help message listing the built in commands\n\n");
            }

            else if (my_strcmp(input[0], "exit") == 0)
            {
                /*EXIT*/
                my_str("Thank you for using MINISHELL\n");
                exit(0);
            }

            else if (input[0] != NULL)
            {
                /*EXECUTE AN EXTERNAL PROGRAM*/
                if ((pid = fork()) < 0)
                    my_str("MINISHELL: Error forking\n");

                else if (pid > 0)
                {
                    wait(NULL);
                }

                else
                {
                    if (execvp(input[0], input) < 0)
                    {
                        my_str("MINISHELL: Error. Program does not exist in current directory.\n");
                    }

                    else
                    {
                        exit(0);
                        close(0);   
                    }
                }
            }

            else
            {
                my_str("MINISHELL: Error reading command. Type help to see available commands.");
            }
        }
    }

    return 0;
}

1 个答案:

答案 0 :(得分:0)

您不能指望在提示之前始终会打印错误消息。分叉进程与主程序并行运行。从两个程序输出到stdout的顺序取决于OS调度程序如何运行进程。

我认为像bash这样的大多数真正的shell实际上会在执行fork()之前检查主进程中存在的文件。或者,您可以使用pipe()并手动重定向输出。然后,您可以在执行提示之前强制刷新整个内容。