#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, Аллен И Голуб».