Search code examples
c++clinuxtty

How to output to the currently visible terminal


I want to output some text as response to the signal SIGUSR1

I.e. a user sends kill -USR1 <pid> to a process started in background or in another terminal.

I would like to get some output in the terminal where kill was invoked.

How can I achieve this?


Solution

  • The comment of @BoBTFish is working. A possible pseudo C++ implementation:

    // somewhere in code:
    std::memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_sigaction = sh_dump;
    sa.sa_flags = static_cast<int>(SA_SIGINFO); // <- important, else you'll get an invalid siginfo_t pointer
    sigaction(SIGUSR1, &sa, NULL);
    
    void sh_dump(int, siginfo_t *info, void *) {
    
        if(info) {
    
            // do some locking of your choice
    
            char *p = NULL;
            char sp[PATH_MAX] = "";
    
            std::snprintf(sp, PATH_MAX, "/proc/%d/stat", info->si_pid);
    
            int tty_nr = 0;
            FILE *spf;
    
            if((spf = std::fopen(sp, "r"))) {
    
                int iDummy;
                char cDummy, *sDummy;
    
                // proc(5)
                if(std::fscanf(spf, "%d %ms %c %d %d %d %d", &iDummy, &sDummy, &cDummy, &iDummy, &iDummy, &iDummy, &tty_nr)) {}
    
                free(sDummy);
                std::fclose(spf);
            }
    
            // see http://goo.gl/L0pGK1 for an implementation
            if(!(p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev/pts"))) {
                p = ttynameCheckDir(static_cast<dev_t>(tty_nr), "/dev");
            }
    
            std::ofstream out(p ? p : "/dev/null");
    
            free(p);
    
            if(out.is_open()) out << "HELLO" << std::endl;
    
            // do some unlocking of your choice
        }
    }
    

    prints HELLO on the terminal invoking kill -USR1 <pid>

    EDIT: Using /proc/#/stat (Linux only)