Я пытаюсь создать базовую оболочку для Linux с помощью C. Я заставил ее работать, пока не попытался выполнить перенаправление вывода, и она просто все уничтожила. Когда я запускаю этот код, он переходит прямо к случаю fork() по умолчанию. Понятия не имею почему. Если я избавлюсь от цикла for в дочернем процессе, он сработает, но даже с циклом for я не понимаю, почему дочерний процесс даже не запускается. Если я помещу оператор печати вверху дочернего процесса, он не будет напечатан.
Когда я запускаю это в командной строке, я получаю подсказку и набираю что-то вроде «ls», что работало до того, как я добавил цикл for, но теперь я просто получаю «% я здесь», и если я нажимаю ввод, он просто продолжает выдавать мне та самая линия. Моя цель - набрать «ls > output» и заставить его работать. Я думаю, что перенаправление ввода работает, но, честно говоря, я даже особо не играл с ним, потому что совершенно не понимаю, что происходит с перенаправлением вывода. Буду очень признателен за любую помощь, я потратил 4 часа на то же самое, что и 15 строк, пытаясь заставить это работать.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#define HISTORY_COUNT 20
char *prompt = "% ";
int
main()
{
int pid;
//int child_pid;
char line[81];
char *token;
char *separator = " \t\n";
char **args;
char **args2;
char **args3;
char cmd[100];
char *hp;
char *cp;
char *ifile;
char *ofile;
int check;
int pfds[2];
int i;
int j;
int current = 0;
int p = 0;
//int check;
char *hist[HISTORY_COUNT];
//char history[90];
//typedef void (*sighandler_t) (int);
args = malloc(80 * sizeof(char *));
args2 = malloc(80 * sizeof(char *));
signal(SIGINT, SIG_IGN);
while (1) {
fprintf(stderr, "%s", prompt);
fflush(stderr);
if (fgets(line, 80, stdin) == NULL)
break;
// split up the line
i = 0;
while (1) {
token = strtok((i == 0) ? line : NULL, separator);
if (token == NULL)
break;
args[i++] = token;
/* build command array */
}
args[i] = NULL;
if (i == 0){
continue;
}
// assume no redirections
ofile = NULL;
ifile = NULL;
// split off the redirections
j = 0;
i = 0;
while (1) { //stackoverflow.com/questions/35569673
cp = args[i++];
if (cp == NULL)
break;
switch (*cp) {
case '<':
if (cp[1] == 0)
cp = args[i++];
else
++cp;
ifile = cp;
break;
case '>':
if (cp[1] == 0)
cp = args[i++];
else
++cp;
ofile = cp;
break;
case '|':
if(cp[1] ==0){
cp = args[i++];
if(pipe(pfds) == -1){
perror("Broken Pipe");
exit(1);
}
p = 1;
}
else{
++cp;
}
break;
default:
args2[j++] = cp;
args3[cp++] = cp
break;
}
}
args2[j] = NULL;
if (j == 0)
continue;
switch (pid = fork()) {
case 0:
// open stdin
if (ifile != NULL) {
int fd = open(ifile, O_RDONLY);
if (dup2(fd, STDIN_FILENO) == -1) {
fprintf(stderr, "dup2 failed");
}
close(fd);
}
// open stdout
if (ofile != NULL) {
// args[1] = NULL;
int fd2;
if ((fd2 = open(ofile, O_WRONLY | O_CREAT, 0644)) < 0) {
perror("couldn't open output file.");
exit(0);
}
// args+=2;
printf("okay");
dup2(fd2, STDOUT_FILENO);
close(fd2);
}
if(p == 1){ //from stackoverflow.com/questions/2784500
close(1);
dup(pfds[1]);
close(pfds[0]);
execvp(args2[0], args2);
break;
}
if(strcmp(args2[0], "cd") == 0){ //cd command
if(args2[1] == NULL){
fprintf(stderr, "Expected argument");
}
else{
check = chdir(args2[1]);
if(check != 0){
fprintf(stderr,"%s",prompt);
}
}
break;
}
execvp(args2[0], args2); /* child */
signal(SIGINT, SIG_DFL);
fprintf(stderr, "ERROR %s no such program\n", line);
exit(1);
break;
case -1:
/* unlikely but possible if hit a limit */
fprintf(stderr, "ERROR can't create child process!\n");
break;
default:
//printf("am I here");
if(p==1){
close(0);
dup(pfds[0]);
close(pfds[1]);
//execvp();
}
wait(NULL);
//waitpid(pid, 0, 0);
}
}
exit(0);
}
indent
] и упрощения, когда/где это необходимо, я пытался сохранить как можно больше исходного кода и стиля, чтобы он не выглядел для вас совершенно чуждым. 23.02.2016