Hi stackoverflow family,
I'm doing a uni task to make a linux program to read a password and secure it and "re-read" the password again if the user interrupts it during.
Here's my code for catching handler.
void catch_suspend(int sig_num)
{
printf("\nSuspending execution...\n");
fflush(stdout);
echo_on(YES); // re-enable echo mode
raise(SIGSTOP); // stop self
// we'll get back here when the process is resumed
printf("Resuming execution...\n");
echo_on(NO); // disable echo mode again
printf("Password: "); // reproduce the prompt
fflush(stdout);
}
and here is the main program
int main(int argc, char *argv[])
{
#define MAX_SIZE 30
char user[MAX_SIZE]; // user name supplied by the user
char passwd[MAX_SIZE]; // password supplied by the user
sigset_t sigs;
struct sigaction sa_new;
memset(&sa_new, 0, sizeof(sa_new)); // initialization to zeros
sa_new.sa_handler = catch_suspend; // set handler
sigemptyset(&sa_new.sa_mask); // mask: empty set
sigaddset(&sa_new.sa_mask, SIGINT); // mask: add SIGINT
sigaddset(&sa_new.sa_mask, SIGQUIT); // mask: add SIGQUIT
sa_new.sa_flags = 0; // no flags
printf("Username: "); // prompt the user for a user name
fflush(stdout);
fgets(user, MAX_SIZE, stdin); // wait for input
sigaction(SIGTSTP, &sa_new, &sa_old); // set the handler for SIGTSTP and get old handler setting
printf("Password: "); // prompt the user for a password
fflush(stdout);
echo_on(NO); // set input to no-echo mode
fgets(passwd, MAX_SIZE, stdin); // get the user input
echo_on(YES); // re-enable echo on input
printf("\n"); // the Enter pressed by the user was not echoed
fflush(stdout);
// verify the password (\n is stored, don't compare it)
etc...
return 0;
I should also block all signals except SIGINT and SIGQUIT, not sure if I've done it right with the mask. The problem I've encountered now is this: after interrupting during the password reading, process is stopped. That's ok. But after I use "fg" command to continue, my handler only writes the output and the program ends, but I need it to run fgets(passwd, MAX_SIZE, stdin) (where it was stopped) again.
I guess that I'm probably not setting the old_action correctly, but the manuals I've read didn't really make it more clear to me. Anyone who can lend a helping hand?
Okay, I've finally figured it out and I'm gonna leave it here for anyone having the same issues.
I didn't set the sigaction flag as followed:
sa_new.sa_flags = SA_RESTART;
This flag controls what happens when a signal is delivered during certain primitives (such as open, read or write), and the signal handler returns normally. There are two alternatives: the library function can resume, or it can return failure with error code EINTR.
The choice is controlled by the SA_RESTART flag for the particular kind of signal that was delivered. If the flag is set, returning from a handler resumes the library function. If the flag is clear, returning from a handler makes the function fail