我正在使用C创建一个非常原始的shell。输入命令后,提示正确打印并正确打印命令输出。在执行“run”命令之后出现问题,该命令基本上在用户输入的可执行文件上调用execve。我做到了这样,如果用户按下Ctrl-C(SIGINT),父级将不会死,并且子级(运行execve'd程序的那个)被中断。这是有效的,并且控制权将返回给父级,但是提示的打印在它之后会中断。运行“ls”或任何其他execve系统调用时可以看到它。
DOGsh:-$ run /bin/cat
This is cat just repeating what I say.
This is cat just repeating what I say.
Okay, I will do Ctrl-C to send SIGINT to parent and child. Parent will doNothing and child will act normally.
Okay, I will do Ctrl-C to send SIGINT to parent and child. Parent will doNothing and child will act normally.
^C
DOGsh:-$ echo "Now watch what happens when I execve('/bin/ls')..."
Now watch what happens when I execve('/bin/ls')...
DOGsh:-$ run /bin/ls
commands.c commands.h commands.o help.txt main.c main.o makefile readinput.c readinput.h readinput.o task2 utils.c utils.h utils.o
DOGsh:-$
DOGsh:-$ run /bin/cat
This is cat just repeating what I say.
This is cat just repeating what I say.
Okay, I will do Ctrl-C to send SIGINT to parent and child. Parent will doNothing and child will act normally.
Okay, I will do Ctrl-C to send SIGINT to parent and child. Parent will doNothing and child will act normally.
^C
DOGsh:-$ echo "Now watch what happens when I execve('/bin/ls')..."
Now watch what happens when I execve('/bin/ls')...
DOGsh:-$ run /bin/ls
/* Note the gap here and the printing of the output after the shell prompt. */
DOGsh:-$ commands.c commands.h commands.o help.txt main.c main.o makefile readinput.c readinput.h readinput.o task2 utils.c utils.h utils.o
// Here it's waiting for my next command but the prompt is missing...
[-] Unknown command. // Entering an empty command comes up with this error message.
DOGsh:-$ // Oh great, it's back...
pid_t run_pid; // Global var of the child pid.
int run(CommandStruct *cmd_struct) {
char *arg_str = cmd_struct->arg_str; // The path of the executable
char *args[2] = {arg_str, NULL}; // *argv[] for the executable
signal(SIGINT, doNothing); // The parent should ignore the SIGINT.
run_pid = fork();
if (run_pid > 0) {
wait(NULL);
}
else {
execve(arg_str, args, NULL);
exit(1);
}
printf("\n");
signal(SIGINT, SIG_DFL); // Reset the handler for parent.
return 0;
}
void doNothing(int sig) {
return;
}
/* Only relevant parts included */
int main() {
char raw_cmd[BUF_SIZE];
char install_dir[BUF_SIZE];
CommandStruct *cmd_struct; // A struct with the command name and its args.
Commands cmd; // Enum with command names. Used for easier decision making.
// ...
while (1) {
printf("\033[1;31mDOG\033[1;30msh:-$\033[0;37m "); // Coloured prompt.
fgets(raw_cmd, BUF_SIZE, stdin);
cmd_struct = getCommandStruct(raw_cmd);
cmd = getCommandFromCommandStruct(cmd_struct);
switch (cmd) {
case CLEAR:
clear();
break;
// ...
case RUN:
run(cmd_struct); // Run function
break;
}
free((void*) cmd_struct);
}
return 0;
}
编辑:MCVE 我创建了类似的东西来重新创建我遇到的问题,当你遇到我放在循环中作为断点的getchar时,只需继续按Enter键。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 1024
typedef struct CommandStruct {
char cmd[BUF_SIZE];
char arg_str[BUF_SIZE];
} CommandStruct;
pid_t run_pid;
void doNothing(int sig) {
return;
}
int run(CommandStruct *cmd_struct) {
char *arg_str = cmd_struct->arg_str;
char *args[2] = {arg_str, NULL};
signal(SIGINT, doNothing);
run_pid = fork();
if (run_pid > 0) {
wait(NULL);
}
else {
execve(arg_str, args, NULL);
exit(1);
}
signal(SIGINT, SIG_DFL);
return 0;
}
int main() {
CommandStruct cmd_struct;
strcpy(cmd_struct.cmd, "run");
strcpy(cmd_struct.arg_str, "/bin/cat");
while (1) {
printf("\033[1;31mDOG\033[1;30msh:-$\033[0;37m ");
getchar(); // Waiting to continue.
run(&cmd_struct);
printf("\033[1;31mDOG\033[1;30msh:-$\033[0;37m ");
getchar(); // Waiting to continue.
strcpy(cmd_struct.arg_str, "/bin/ls");
run(&cmd_struct);
}
return 0;
}