Я почти закончил практическую реализацию оболочки Unix, за исключением того, что у меня возникла проблема с реализацией cat
, когда ее вывод в файл;IE: cat foo.txt > bar.txt
- вывод содержимого foo
в bar
.
Давайте начнем с основной функции , а затем я определю подметоды:
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;
}
handle_user_input
просто заполняет массив cmd_argv
для выполнения user_input
, удаляет >
и устанавливает флаг output
, если пользователь желает вывести нафайл.Это основа этого метода:
while (buffer_pointer != NULL) {
cmd_argv[cmd_argc] = buffer_pointer;
buffer_pointer = strtok(NULL, " ");
if(strcmp(cmd_argv[cmd_argc], ">") == 0){
printf("\nThere was a '>' in %s @ index: %d for buffer_pointer: %s \n", *cmd_argv,cmd_argc,buffer_pointer);
cmd_argv[cmd_argc] = strtok(NULL, " ");
output = 1;
}
cmd_argc++;
if(output){
filename = buffer_pointer;
printf("The return of handling input for filename %s = %s + %s \n", buffer_pointer, cmd_argv[0], cmd_argv[1]);
return;
}
}
execute_command
затем вызывается, интерпретируя теперь заполненный cmd_argv
.Просто чтобы дать вам представление о большой картине.Очевидно, что ни один из этих случаев не совпадает, и метод create_process
вызывается:
int execute_command()
{
if (strcmp("pwd", cmd_argv[0]) == 0){
printf("%s\n",getenv("PATH"));
return 1;
}
else if(strcmp("cd", cmd_argv[0]) == 0){
change_directory();
return 1;
}
else if (strcmp("jobs", cmd_argv[0]) == 0){
display_job_list();
return 1;
}
else if (strcmp("kill", cmd_argv[0]) == 0){
kill_job();
}
else if (strcmp("EOT", cmd_argv[0]) == 0){
exit(1);
}
else if (strcmp("exit", cmd_argv[0]) == 0){
exit(-1);
}
else{
create_process();
return;
}
}
Довольно прямо, верно?
create_process
- вот где у меня возникают проблемы.
void create_process()
{
status = 0;
int pid = fork();
background = 0;
if (pid == 0) {
// child process
if(output){
printf("Output set in create process to %d\n",output);
output = 0;
int output_fd = open(filename, O_RDONLY);
printf("Output desc = %d\n",output_fd);
if (output_fd > -1) {
dup2(output_fd, STDOUT_FILENO);
close(output_fd);
} else {
perror("open");
}
}
printf("Executing command, but STDOUT writing to COMMAND PROMPT instead of FILE - as I get the 'open' error above \n");
execvp(*cmd_argv,cmd_argv);
// If an error occurs, print error and exit
fprintf (stderr, "unknown command: %s\n", cmd_argv[0]);
exit(0);
} else {
// parent process, waiting on child process
waitpid(pid, &status, 0);
if (status != 0)
fprintf (stderr, "error: %s exited with status code %d\n", cmd_argv[0], status);
}
return;
}
Мой напечатанный output_fd = -1
, и мне удается получить perror("open")
внутри остального, заявив: open: No such file or directory
.Затем он печатает, что это "writing to COMMAND PROMPT instead of FILE"
, как я отображаю на консоли.Затем выполняет execvp
, который обрабатывает cat foo.txt
, но выводит его на консоль вместо файла.
Я понимаю, что это не должно быть в данный момент, так как наличие output_fd = -1
нежелательно и должно возвращать другое значение;но я не могу понять, как правильно использовать файловые дескрипторы, чтобы открыть новый / существующий файл с cat foo.txt > bar.txt
и записать в него, как WELL AS GET BACK на стандартный ввод командной строки.
Мне удалось вывести в файл, но потом я потерял вернувшийся правильный stdin.Может ли кто-нибудь, пожалуйста, направить меня сюда?Я чувствую, что иду по кругу из-за чего-то глупого, я делаю что-то не так или оглядываюсь.
Любая помощь очень ценится.