C Shell Открыть файл и вернуться в командную строку - PullRequest
1 голос
/ 25 февраля 2011

Я пытаюсь реализовать команду UNIX cat ">", чтобы выполнить file1.txt > foo.txt из моей оболочки UNIX.

Я хочу взять обычные команды UNIX из пользовательского ввода и выполнить их через execvp (что я сейчас делаю просто отлично).

Я хочу добавить ">" в мой поток оболочки , но у меня проблемы с закрытием файла после записи в него И возвращением делегирования в командную строку для постоянного пользователяinput. Может ли кто-нибудь объяснить мне, где я делаю что-то глупое?

Я понимаю, что для записи в файл мне нужно закрыть стандарт, открыть новый стандарт, написатьфайл, а затем каким-то образом закройте стандартный вывод файла и снова включите стандартный вывод клавиатуры, чтобы иметь возможность снова принимать пользовательские команды ..

Моя основная функция, просто чтобы дать вам представление:

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;    
}

Это основа моей функции получения пользовательского ввода.Если он находит «>» в ​​массиве 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;
        }        
    }

Код из execute_command, управляющий выводомфункциональность Обратите внимание, я получил здесь MSG.Кажется, это где он умирает :

   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;
    }

И 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;
    }
}

1 Ответ

1 голос
/ 25 февраля 2011

Вы ошибаетесь. Вы не хотите связываться с файловыми дескрипторами родительского процесса на всех , и вы не хотите использовать stdio C - вы должны использовать низкоуровневые вызовы файлового дескриптора для этой работы.

После fork() в дочернем процессе вы должны выполнить:

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

Нет необходимости в очистке в родительском элементе, поскольку открытые файлы родительского элемента остаются одни.

...