How do I make a background process block for input a la the shell's `bg` command?

烂漫一生 提交于 2021-01-28 08:15:23

问题


I am implementing my own fragment of code for a security control purpose. It normally runs in the background but on a timeout needs to take over the current terminal, display a message, collect user input, and react to the user input.

Waiting for the timeout is easy. Collecting user input while sleep is the active program is easy. Preventing the shell from stealing the user input I just tried to collect is not so easy.

I am reasonably convinced that "What if two programs did this?" doesn't apply. If another program triggered while we were waiting for input, it's not too bad. If the user wants to interfere with the security check, there are easier ways than this.


回答1:


Need process group control. This is not so easy to find if you don't know that job control is implemented using process group control. The shell starts background processes in their own process groups and the bg and fg commands toggle which process group is allowed to read from the terminal. All other processes block reading from the terminal.

#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);
        }
    }


来源:https://stackoverflow.com/questions/51697742/how-do-i-make-a-background-process-block-for-input-a-la-the-shells-bg-command

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!