简体   繁体   English

C Shell打开文件并返回命令提示符

[英]C Shell Open File And Back to Command Prompt

I'm trying to implement the UNIX cat ">" command, to perform file1.txt > foo.txt from within my UNIX shell. 我正在尝试实现UNIX cat“>”命令,以从我的UNIX shell中执行file1.txt > foo.txt

I want to take normal UNIX commands from user input and execute them via execvp (which I'm currently doing just fine). 我想从用户输入中获取普通的UNIX命令,并通过execvp执行它们(我目前做的很好)。

I want to add ">" into my shell flow , but am having issues with closing the file after writing to it AND giving delegation back to the command line for continual user input. 我想将“>”添加到我的shell流中 ,但是在写入文件后将文件关闭并且将委派返回命令行以进行连续的用户输入时遇到了问题。 Can someone explain to me where I'm doing something silly? 有人可以向我解释我在做什么傻事吗?

I realize that in order to write to a file, I have to close standard in, open a new standard out, write the file, and then somehow close the file's stdout and re-enable the keyboard's stdout to be able to accept user commands again.. 我意识到,要写入文件,我必须先关闭标准,打开新标准,写入文件,然后以某种方式关闭文件的标准输出,然后重新启用键盘的标准输出,才能再次接受用户命令..

My main function, just to give you an idea: 我的主要功能,只是给您一个想法:

int main(int argc, char **argv)
{           
    printf("[MYSHELL] $ ");

    while (TRUE) {
        user_input = getchar();
        switch (user_input) {
            case EOF:
                exit(-1);

            case '\n':
                printf("[MYSHELL] $ ");
                break;

            default:
                // parse input into cmd_argv - store # commands in cmd_argc
                handle_user_input();

                //determine input and execute foreground/background process
                execute_command();
        }
        background = 0;
    }
    printf("\n[MYSHELL] $ ");
    return 0;    
}

This is the basic of my function getting user input. 这是我获得用户输入的功能的基础。 If it finds a ">" in the cmd_argv array, it sets the output flag = 1 and removes it from the desired executable command: 如果在cmd_argv数组中找到一个“>”,它将设置输出标志= 1并将其从所需的可执行命令中删除:

// get command line input
    while ((user_input != '\n') && (buffer_characters < 50)) {
        buffer[buffer_characters++] = user_input;
        user_input = getchar();
    }

    // clear buffer
    buffer[buffer_characters] = 0x00;

    // populate cmd_argv - array of commands
    char *buffer_pointer;
    buffer_pointer = strtok(buffer, " ");

    while (buffer_pointer != NULL) { 
        cmd_argv[cmd_argc] = buffer_pointer;
        buffer_pointer = strtok(NULL, " ");

        if(strcmp(cmd_argv[cmd_argc], ">") == 0){
            cmd_argv[cmd_argc] = strtok(NULL, " ");
            output = 1;
        }

        cmd_argc++;

        if(output){
            filename = buffer_pointer; //name of file that we're going to write to.
            return;
        }        
    }

The code from execute_command driving the output functionality NOTICE THE I GOT HERE MSG. 来自execute_command的代码驱动了输出功能,请注意,这里是MSG。 This seems to be where it's dying : 这似乎快要死了

   if (output == 1){
            close(1);
            file = fopen(filename, "w");
            create_process();
            output = 0;
            printf("IT GOT HERE!!!\n");
            fclose(file);
            fopen("/dev/null", "r"); // open a new stdin that is always empty
            return 1;
        }else{
        create_process();
        return;
    }

And create_process to handle foreground and background processes 和create_process来处理前台和后台进程

void create_process()
{
    status = 0;
    int pid = fork();
    background = 0;

    if (pid == 0) {
        // child process
        if(background) {
            printf("no background");
            fclose(stdin); // close child's stdin
            fopen("/dev/null", "r"); // open a new stdin that is always empty
            execvp(*cmd_argv,cmd_argv);

            // If an error occurs, print error and exit
            fprintf (stderr, "unknown command: %s\n", cmd_argv[0]);
            exit(1);

        }else if(output == 1){
            execvp(*cmd_argv,cmd_argv);
        } 
        else {
            execvp(*cmd_argv,cmd_argv);
            // If an error occurs, print error and exit
            fprintf (stderr, "unknown command: %s\n", cmd_argv[0]);
            exit(1);
        }
    } else {
        // parent process, waiting on child process
        if (background) {
            printf("starting background job %d\n", pid);
            jobs_list[jobs_list_size] = pid;
            jobs_list_size++;

        } else { 
            waitpid(pid, &status, 0);
        } 

        if (status != 0)
            fprintf  (stderr, "error: %s exited with status code %d\n", cmd_argv[0], status);

        return;
    }
}

You're approaching it wrong. 您正在错误地处理它。 You don't want to mess with the parent process's file descriptors at all , and you don't want to use C's stdio - you should be using the low-level file-descriptor based calls for this work. 您根本不想弄混父进程的文件描述符也不想使用C的stdio-为此工作应使用基于低级文件描述符的调用。

After the fork() , in the child process, you should execute: fork() ,在子进程中,您应该执行:

int output_fd = open(filename, O_RDONLY);
if (output_fd > -1) {
    dup2(output_fd, STDOUT_FILENO);
    close(output_fd);
} else {
    perror("open");
}

There's no need for any cleanup in the parent, since the parent's open files are left alone. 无需对父级进行任何清理,因为父级的打开文件被保留了下来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM