While I agree with the comments saying that you should generally trust the users, this tries to answer the question as I've come to understand it from reading the comments ("If my program runs in the background, the command terminal is usable and operational, but the output of the program obscures user input and displaces the prompt").
This will not prevent the program from running, but streaming to std::cout
will be discarded so the program can run without disturbing the user. Redirecting the output to a file or a pipe will still work.
#define _POSIX_SOURCE
#include <iostream>
#include <stdexcept>
#include <stdio.h> // fileno
#include <unistd.h> // isatty
#include <signal.h> // signal
#include <fcntl.h> // fcntl
#include <termios.h> // tcgetattr/tcsetattr
void handle_input(int /*sig*/) {
signal(SIGTTIN, SIG_IGN);
std::cin.setstate(std::ios::failbit);
}
void handle_output(int /*sig*/) {
signal(SIGTTOU, SIG_IGN);
std::cout.setstate(std::ios::failbit);
}
class TCAttr {
int m_fd;
termios m_attr;
public:
TCAttr(int fd) : m_fd(fd), m_attr() {
// get input, output and local attributes
if(tcgetattr(m_fd, &m_attr) != 0)
m_fd = -1;
}
TCAttr(FILE* fp) : TCAttr(fileno(fp)) {}
TCAttr() : m_fd(-1), m_attr() {}
~TCAttr() {
// restore original input, output and local attributes
if(m_fd>=0)
tcsetattr(m_fd, TCSADRAIN, &m_attr);
}
//
bool set_lmode(tcflag_t flag) {
termios tmp;
if(tcgetattr(m_fd, &tmp)!=0) return false;
tmp.c_lflag = flag;
return tcsetattr(m_fd, TCSADRAIN, &tmp)==0;
}
bool add_lmode(tcflag_t flag) {
termios tmp;
if(tcgetattr(m_fd, &tmp)!=0) return false;
tmp.c_lflag |= flag;
return tcsetattr(m_fd, TCSADRAIN, &tmp)==0;
}
bool remove_lmode(tcflag_t flag) {
termios tmp;
if(tcgetattr(m_fd, &tmp)!=0) return false;
tmp.c_lflag &= ~flag;
return tcsetattr(m_fd, TCSADRAIN, &tmp)==0;
}
};
int main() {
TCAttr tca(stdout);
if(isatty(fileno(stdin))) {
// if tty input is requested in background mode
// SIGTTIN will be sent
signal(SIGTTIN, handle_input);
}
if(isatty(fileno(stdout))) {
// if tty output is requested in background mode
// SIGTTOU will be sent
signal(SIGTTOU, handle_output);
tca.add_lmode(TOSTOP);
}
std::cout << "Thanks for not streaming to a tty in background mode\n";
std::string name;
std::cin >> name;
std::cout << name << "\n";
}