如何为 shell 的 `bg` 命令的输入创建后台进程块?
How do I make a background process block for input a la the shell's `bg` command?
出于安全控制的目的,我正在实现自己的代码片段。它通常在后台运行,但在超时时需要接管当前终端、显示消息、收集用户输入并对用户输入做出反应。
等待超时很容易。在 sleep
是活动程序时收集用户输入很容易。防止 shell 窃取我刚刚尝试收集的用户输入并不是那么容易。
我有理由相信 "What if two programs did this?" 不适用。如果在我们等待输入时触发了另一个程序,那还不错。如果用户想干扰安全检查,还有比这更简单的方法。
需要进程组控制。如果你不知道作业控制是使用进程组控制实现的,这就不太容易找到了。 shell 在它们自己的进程组中启动后台进程,bg
和 fg
命令切换允许哪个进程组从终端读取。所有其他进程阻止从终端读取。
#include <unistd.h>
sleep(600); /* triggering condition goes here */
pid_t pgid = tcgetpgrp(0);
pid_t pid;
if ((pid = fork()) == 0) { /* Need to fork to safely create a new process group to bind to the terminal -- otherwise we might be in the same process group as we started in */
pid_t npid = getpid();
setpgid(npid, npid); /* create new process group and put us in it */
pid_t pid2;
if ((pid2 = fork() == 0) { /* what? another process */
setpgid(getpid(), pgid);
tcsetpgid(0, getpid()); /* set active process group */
_exit(0);
}
if (pid2 > 0) {
int junk;
waitpid(pid2, &junk, 0);
}
struct termios savedattr;
struct termios newattr;
tcgetattr(0, &savedattr);
newattr = savedattr;
newattr.c_lflag |= ICANON | ECHO;
tcsetattr(0, TCSANOW, &newattr); /* set sane terminal state */
printf("\nHi there. I'm the background process and I want some input:");
char buf[80];
fgets(buf, 80, stdin);
/* Do something with user input here */
tcsetattr(0, TCSANOW, &savedattr); /* restore terminal state */
tcsetpgrp(0, pgid); /* restore terminal owner -- only possible if the existing owner is a live process */
} else {
if (pid > 0) {
int junk;
waitpid(pid, &junk, 0);
}
}
出于安全控制的目的,我正在实现自己的代码片段。它通常在后台运行,但在超时时需要接管当前终端、显示消息、收集用户输入并对用户输入做出反应。
等待超时很容易。在 sleep
是活动程序时收集用户输入很容易。防止 shell 窃取我刚刚尝试收集的用户输入并不是那么容易。
我有理由相信 "What if two programs did this?" 不适用。如果在我们等待输入时触发了另一个程序,那还不错。如果用户想干扰安全检查,还有比这更简单的方法。
需要进程组控制。如果你不知道作业控制是使用进程组控制实现的,这就不太容易找到了。 shell 在它们自己的进程组中启动后台进程,bg
和 fg
命令切换允许哪个进程组从终端读取。所有其他进程阻止从终端读取。
#include <unistd.h>
sleep(600); /* triggering condition goes here */
pid_t pgid = tcgetpgrp(0);
pid_t pid;
if ((pid = fork()) == 0) { /* Need to fork to safely create a new process group to bind to the terminal -- otherwise we might be in the same process group as we started in */
pid_t npid = getpid();
setpgid(npid, npid); /* create new process group and put us in it */
pid_t pid2;
if ((pid2 = fork() == 0) { /* what? another process */
setpgid(getpid(), pgid);
tcsetpgid(0, getpid()); /* set active process group */
_exit(0);
}
if (pid2 > 0) {
int junk;
waitpid(pid2, &junk, 0);
}
struct termios savedattr;
struct termios newattr;
tcgetattr(0, &savedattr);
newattr = savedattr;
newattr.c_lflag |= ICANON | ECHO;
tcsetattr(0, TCSANOW, &newattr); /* set sane terminal state */
printf("\nHi there. I'm the background process and I want some input:");
char buf[80];
fgets(buf, 80, stdin);
/* Do something with user input here */
tcsetattr(0, TCSANOW, &savedattr); /* restore terminal state */
tcsetpgrp(0, pgid); /* restore terminal owner -- only possible if the existing owner is a live process */
} else {
if (pid > 0) {
int junk;
waitpid(pid, &junk, 0);
}
}