You don't specify what OS you are using but this is simple on POSIX systems. I can't speak to Windows.
The call you want is sigwaitinfo.
You need to block all signals and then use sigwaitinfo
to process any received signals synchronously. Sigwaitinfo's return code is the signal received and when you pass a non-null siginfo_t struct as the second parameter you get the same information you would get from a signal handler returning a siginfo_t structure, including the pid of the sending process. Take the received signal and pid and use kill
to send the signal back to the originating process. Make sure you aren't sending the signal to yourself before calling kill
lest you end up in a loop of sending and receiving a signal to yourself.
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#define errExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while (0)
int main(int argc, char *argv[])
{
siginfo_t signalInfo;
sigset_t allSignals;
printf("echo pid = %d\n", getpid());
// block every signal but SIGKILL & SIGSTOP which can't be blocked
sigfillset(&allSignals);
if (sigprocmask(SIG_SETMASK, &allSignals, NULL) == -1)
errExit("sigprocmask");
while(1)
{
// accept signals until SIGTERM delivered
int sig = sigwaitinfo(&allSignals, &signalInfo);
if (sig == -1)
errExit("sigwaitinfo");
if (sig == SIGTERM)
{
printf("buh-bye\n");
exit(EXIT_SUCCESS);
}
printf("echo received signal %s (%d) from pid = %d\n", strsignal(sig), sig, signalInfo.si_pid);
/*** NOT doing this for testing because it will kill the sending shell
// echo signal back to sender but not to yourself
// which would be stupid and lead to an endless loop
if (signalInfo.si_pid != getpid())
kill(signalInfo.si_pid, sig);
***/
}
}
TEST
--- terminal 1 ---
//current shell's pid
> echo $$
7646
//send signals after starting echo pgm in another terminal
> kill -SIGUSR1 7754
> kill -SIGUSR2 7754
> kill -SIGTERM 7754
--- terminal 2 ---
> echosig
echo pid = 7754
echo received signal User defined signal 1 (10) from pid = 7646
echo received signal User defined signal 2 (12) from pid = 7646
buh-bye