Search code examples
clinuxunixsignalssleep

determine what secret handshake causes them to print the given lines ONE TIME ONLY


So I need to find what causes this program to print out "I'm unlocked!" But when I run this algorithm, it prints out nothing.

I tried removing lines of code or adding sleep but no matter what I do it just prints out blank.

I am expected to print "I'm unlocked!"

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

volatile int locked, t, c;

static void handler(int signo);

int main(int argc, char * argv[])
{
  locked = 1;
  t = c = 0;

  char * knock = getenv("KNOCK");
  if(knock == NULL || strcmp(knock, "KNOCK"))
  {
    return 1;
  }

  if(signal(SIGUSR1, handler) == SIG_ERR ||
     signal(SIGUSR2, handler) == SIG_ERR ||
     signal(SIGALRM, handler) == SIG_ERR)
  {
    fprintf(stderr, "%s: cannot register signal handlers\n", argv[0]);
    return 2;
  }

  while(locked)
  {
    pause();
  }

  puts("I'm unlocked!");

  return 0;
}

static void handler(int signo)
{
  switch(signo)
  {
    case SIGUSR1:
      if(c == 2)
      {
        t = alarm(3);
      }
      break;
    case SIGUSR2:
      c++;
      if(t == 1)
      {
        locked = 0;
      }
      break;
    case SIGALRM:
      t = 0;
      break;
  }
}

Solution

  • The pause() function suspends the calling thread and returns when a signal that has a registered handler is invoked.

    The loop then terminates when pause() returns and the locked == 0.

    So the following signal sequence and timing will unlock:

    SIGUSR2  // c = 1
    SIGUSR2  // c = 2
    SIGUSR1  // t = 0 (no scheduled alarm)
    Delay two seconds
    SIGUSR1  // t = 1 (alarm seconds remaining)
    SIGUSR2  // locked = 0 (because t == 1)
    

    The signals can be issued from a separate thread or process using the kill() function or from a shell script using the kill command.