Пользовательская оболочка в C: перенаправление ввода-вывода

#c #shell #redirect #io

#c #оболочка #перенаправление #io

Вопрос:

В настоящее время я пытаюсь создать свою собственную (простую) оболочку на языке C, но мне трудно с перенаправлением ввода-вывода.

Я компилирую и запускаю в VMware (gcc, и если я хочу выполнить команду: $ cat < file_in.txt > file_out.txt Я получаю :

Ошибка файла cat: ‘<‘: нет такого файла или каталога cat: file_in.txt : Нет такого файла или каталога

Функция в заголовочном файле:

      void fileRedirect(char **args, int k, int ioMode)
{
pid_t pid, wpid;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd, status = 0;

pid = fork();
if (pid == 0) {
    // Child process
    if(ioMode == 0)   // Input mode
        fd = open(args[k 1], O_RDONLY, mode);
    else              // Output mode
        fd = open(args[k 1], O_WRONLY|O_CREAT|O_TRUNC, mode);
    if(fd < 0)
        fprintf(stderr, "File error");
    else {
    
        dup2(fd, ioMode);   // Redirect input or output according to ioMode
        close(fd);          // Close the corresponding pointer so child process can use it
        args[k] = NULL;
        args[k 1] = NULL;

        if (execvp(args[0], args) == -1) {
            perror("SHELL");
        }
        exit(EXIT_FAILURE);
    }
}
else if (pid < 0) { // Error forking process
    perror("SHELL");
} 
else {
    // Parent process. Wait till it finishes execution
    do {
        wpid = waitpid(pid, amp;status, WUNTRACED);
    } 
    while (!WIFEXITED(status) amp;amp; !WIFSIGNALED(status));
}        
 

}

И .c-код :

    #include <unistd.h>
   #include <sys/wait.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <fcntl.h>
   #include "functions.h"

   #define BUFSIZE 64     // Size of a single token
   #define TOKEN_DELIM " trna"  // Token Delimiters

   void main(){
char *command = NULL, cwd[1024], *pwd;
char **args, *options[4] = {"<", ">"};
int k = 0, option, found;

pwd = NULL;
pwd = getenv("HOME");
do
{
    ssize_t bsize = 0;
    found = 0;
    printf("$");
    if(getcwd(cwd, sizeof(cwd)) != NULL)
    {
        printf("%s$", cwd);
    }
    getline(amp;command, amp;bsize, stdin);
    if(endOfFile(command) == 0)
    {
        printf("n");
        break;
    }
    if(charLimit(command) == 0)
    {
        printf("n");
        break;
    }
    args = splitTokens(command);
    if(args[0] == NULL)
        {
            free(command);
            free(args);
            continue;
        }
    if(strcmp(args[0],"exit") == 0)
    {
        break;
    }
    else if(strcmp(args[0], "cd") == 0)
    {
        if(args[1] == NULL)
        {
            if(pwd[0] != 0)
            {
                chdir(pwd);
            }
        }
        else
        {
            chdir(args[1]);
        }  
    }
    else
    {
        k = 1;
        while(args[k] != NULL) {           // Check for any of the redirect or process operators <,<,|,amp;
            for(option = 0; option < 2; option  ) {
                if(strcmp(args[k],options[option]) == 0) 
                    break;
            }
            if(option < 2) {
                found = 1;
                if(args[k 1] == NULL) {   // For IORedirect and Pipe, argument is necessary
                    fprintf(stderr, "SHELL: parameter missingn"); 
                    break;
                }
                fileRedirect(args, k, option);
            }

            k  ;
        }
        if(found == 0)
            execute(args, 0);                      // Start a foreground process or command
    }
    free(command);
    free(args);
} while(1);
 

}

Я видел много ответов на подобный вопрос, но они меня еще больше смутили.

Заранее благодарю вас.

Комментарии:

1. Не помещайте определения функций в заголовочные файлы.

2. Вы разветвляетесь один раз для каждого перенаправления. Вы должны разветвляться только один раз. Убедитесь, что оба fd 0 и 1 были скопированы, и что аргументы execvp только {"cat", NULL}

3. Есть старая, но хорошая книга на эту тему: «По команде: написание Unix-подобной оболочки для MS-DOS, 1987, Аллен И Голуб».