Я реализую простую оболочку в C. RunCommand отлично работает для всех остальных процессов, но когда я запускаю программу, используя & (фоновый процесс). Подсказка командной строки застревает и больше не выдается, пока я снова не нажму клавишу ввода или другой ввод с клавиатуры.
Я не уверен, что именно вызывает эту проблему. Я реализовал грипп sh, чтобы очистить стандартный вывод, но ошибка все та же.
Основная функция драйвера. Запускается в al oop, чтобы продолжать запрашивать пользователя после каждого выполнения команды.
/* Simple Shell implementation. Prompts until exit received from user or any other errors */
int eggShell()
{
char *lineRead;
char **command;
char *commandsPathFull = getenv("PATH"); //Get the $PATH in the environment
while (1)
{
fflush(stdout);
signal(SIGCHLD, sigchld_handler);
lineRead = readline("esh> ");
command = parseCommand(lineRead, " ");
int backgroundTask = 0;
if (command[0] != NULL)
{
if (strcmp(command[0], "exit") == 0)
{
free(command);
free(lineRead);
return 1;
}
if (command[1] != NULL)
{
for (size_t i = 1; command[i] != (char *)NULL; i++)
{
if (strcmp(command[i], "&") == 0)
{
backgroundTask = 1;
}
}
}
if ((validCommand(command[0], commandsPathFull)) == 1)
{
printf("Running Command\n");
runCommand(command, backgroundTask);
free(command);
free(lineRead);
}
}
fflush(stdout);
}
free(lineRead);
free(command);
return 1;
}
Команда Run запускает новый процесс для каждой команды. Если команда не является фоновой, команда parent не ожидает завершения дочернего процесса sh.
/* Receives a command and runs it using fork
returns 1 on successfull execution.*/
int runCommand(char **command, int bckTask)
{
pid_t pid, wpid;
int status;
pid = fork();
// Child process
if (pid == 0)
{
//Execute the command
if (execvp(command[0], command) == -1)
{
perror("esh Exec:");
}
exit(EXIT_FAILURE);
}
// Error forking
else if (pid < 0)
{
perror("esh fork error:");
}
// Parent process
else
{
// wait until either the processes are exited or killed
// If not a background task
if (bckTask != 1)
{
// {
do
{
wpid = waitpid(pid, &status, WUNTRACED);
if (wpid == -1)
{
perror("Esh Wait PID:");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
//printf("Foreground Task\n");
//waitpid(pid, &status, 0);
}
else if (bckTask == 1)
{
printf("Command %s | Background PID: %d\n", command[0], pid);
return 1;
// do
// {
// wpid = waitpid(-1, &status, WNOHANG);
// printf("Background pid: %d\n", pid);
// if (wpid > 0)
// {
// printf("Completed Background pid: %d\n", wpid);
// }
// } while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
}
return 1;
}
Текущий вывод:
esh> ls
Running Command
esh esh.c Makefile README.md
esh> echo "Hello World"
Running Command
"Hello World"
esh> echo "Hello 2" &
Running Command
Command echo | Background PID: 16618
esh> "Hello 2" &
(At this point the cursor is stuck. I need to press enter again to get the prompt)
esh>