/// puzzlebox.c: Inputs are read from a file on the command line. The
/// inputs are modified in various ways to checked to match specific
/// patterns associated with “phases”. Each set of correct inputs
/// “passes” a phase and scores points.
///
/// USING THE DEBUGGER is almost essential to understand what is
/// happening in the source code. Compile with debug flags and run in
/// the gdb debugger as in
///
/// > gcc -g -o puzzlebox puzzlebox.c
/// > gdb -tui ./puzzlebox
///
/// is a good policy.
///
/// Original DebugMe.java version and rhymes by
/// C Port/Adaptation by
#include
#include
#include
#include
#include
#define BUFSIZE 128
#define NSTAGES 10
int points[NSTAGES+1] = {
0,
8,
8,
8,
8,
5,
5,
4,
4,
5,
5,
};
int score = 0;
int max_score = 50;
char *userID = NULL;
int hash = 0;
void setup(); void end_now();
void phase01(); void phase02(); void phase03(); void phase04(); void phase05();
void phase06(); void phase07(); void phase08(); void phase09(); void phase10();
int main(int argc, char *argv[]){
printf(“========================================\n”);
printf(“PROBLEM 2: Puzzlebox\n”);
if(sizeof(int)!=4 || sizeof(long)!=8){
printf(“Unexpected byte sizes of int or long\n”);
printf(” %5s %5s\n”,”EXPECT”,”ACTUAL”);
printf(” int: %5d %5lu\n”,4,sizeof(int));
printf(“long: %5d %5lu\n”,8,sizeof(long));
printf(“\n”);
printf(“puzzlebox must be run on a 64-bit architecture. Bailing out\n”);
return 1;
}
if(argc < 2){
printf("usage: %s
printf(” Provide a text file to read from on the command line\n”);
printf(” The first token in the input file is your Internet ID like kauf0095\n”);
printf(” Bailing out.\n”);
return 1;
}
setup(argv[1]);
printf(“PHASE 1: A puzzle you say? Challenge accepted!\n”);
phase01();
score += points[1];
printf(“PHASE 2: That was cake by the ocean! Wait: the cake is a lie!\n”);
phase02();
score+=points[2];
printf(“PHASE 3: Warm-up is over. This $#!^ just go real.\n”);
phase03();
score+=points[3];
printf(“PHASE 4: Tired yet? Nope? There’s more in phase four.\n”);
phase04();
score+=points[4];
printf(“PHASE 5: You’re doing well. But can you break through this secret technique of darkness?\n”);
phase05();
score+=points[5];
printf(“PHASE 6: Watch out, here comes a wall of bricks! It’s time for you to solve phase six.\n”);
phase06();
score+=points[6];
printf(“PHASE 7: Next it’s phase eleven! oops, seven. (off-by-4 errors don’t lose credit, right?)\n”);
phase07();
score+=points[7];
printf(“PHASE 8: You’re doing great, now try phase 1000!\n”);
phase08();
score+=points[8];
printf(“PHASE 9: Finally, the finish line; Can you solve phase nine?\n”);
phase09();
score+=points[9];
printf(“PHASE 10: Rule #1: The doctor lies. Next time a message mentions ‘finish line,’ check the source code.\n”);
phase10();
score+=points[10];
printf(“***Achievement Unlocked***\n”);
printf(“gdb? Yeah you know me!\n”);
end_now();
return 0;
}
void setup_signal_handlers();
void failure(char *msg);
void end_now();
void setup_input(char *fname);
void close_input();
char *next_input();
void setup(char *infile_name){
setup_signal_handlers();
setup_input(infile_name);
userID = next_input();
int len = strlen(userID);
if(len != 8){
printf(“‘%s’ is a userID and must be 8 characters\n”,
userID);
exit(1);
}
hash = 0;
int *hash1 = (int *) (userID);
int *hash2 = (int *) (userID+4);
hash = (*hash1) ^ (*hash2);
if(hash < 0){
hash = -hash;
}
printf("UserID '%s' accepted: hash value = %d\n",userID,hash);
}
#define NSIGNALS 35
char *signal_names[NSIGNALS] = {
"",
"SIGHUP", /// 1 Hangup
"SIGINT", /// 2 Interrupt
"SIGQUIT", /// 3 Quit
"SIGILL", /// 4 Illegal Instruction
"SIGTRAP", /// 5 Trace/Breakpoint Trap
"SIGABRT", /// 6 Abort
"SIGEMT", /// 7 Emulation Trap
"SIGFPE (usually divide by 0)", /// 8 Arithmetic Exception
"SIGKILL", /// 9 Killed
"SIGBUS", /// 10 Bus Error
"SIGSEGV (out of bounds memory)", /// 11 Segmentation Fault
"SIGSYS", /// 12 Bad System Call
"SIGPIPE", /// 13 Broken Pipe
"SIGALRM", /// 14 Alarm Clock
"SIGTERM", /// 15 Terminated
"SIGUSR1", /// 16 User Signal 1
"SIGUSR2", /// 17 User Signal 2
"SIGCHLD", /// 18 Child Status
"SIGPWR", /// 19 Power Fail/Restart
"SIGWINCH", /// 20 Window Size Change
"SIGURG", /// 21 Urgent Socket Condition
"SIGPOLL", /// 22 Socket I/O Possible
"SIGSTOP", /// 23 Stopped (signal)
"SIGTSTP", /// 24 Stopped (user)
"SIGCONT", /// 25 Continued
"SIGTTIN", /// 26 Stopped (tty input)
"SIGTTOU", /// 27 Stopped (tty output)
"SIGVTALRM", /// 28 Virtual Timer Expired
"SIGPROF", /// 29 Profiling Timer Expired
"SIGXCPU", /// 30 CPU time limit exceeded
"SIGXFSZ", /// 31 File size limit exceeded
"SIGWAITING", /// 32 All LWPs blocked
"SIGLWP", /// 33 Virtual Interprocessor Interrupt for Threads Library
"SIGAIO", /// 34 Asynchronous I/O
};
void handle_signals(int signum){
char msg[BUFSIZE];
snprintf(msg,BUFSIZE,"Fatal signal %d (%s) received",
signum,signal_names[signum]);
failure(msg);
}
void setup_signal_handlers(){
for(int i=1; i
if(n & 1){
n = (n<<2) - n + 1;
}
else {
n = n >> 1;
}
if(s == t && m == t){
return;
}
s++;
}
failure(“Seems you forgatz the essence of Collatz”);
}
void phase06(){
int a = atoi(next_input());
int b = atoi(next_input());
int c = atoi(next_input());
int d = atoi(next_input());
char expect[BUFSIZE] =
“There are 10 kinds of people in the world: those who understand binary and those who don’t”;
char actual[BUFSIZE] = {};
strcpy(actual,expect);
int slen = strlen(expect);
int ilen = slen / sizeof(int) – 1;
int location1 = (hash % 211) % ilen;
int location2 = (hash % 311) % ilen;
((int *)actual)[location1] = 0x58585858;
((int *)actual)[location2] = 0x59595959;
*(((int *)actual) + a) = b;
*(((int *)actual) + c) = d;
if(strncmp(expect,actual,BUFSIZE) == 0){
return;
}
failure(“Here are hints:\n- use two ints with 4 bytes to make the message right\n- beware of endian ordering angst\n”);
}
void phase07(){
float a = atof(next_input());
union {
char c[9];
float f;
} flar;
strcpy(flar.c, userID);
if( fabs(a-flar.f) < 1e-8 ){
return;
}
char *msg =
"Ugly cousin to the struct: if you don't know unions, then on this phase you're ...\n"
"stuck.\n"
"What did you think was going to rhyme with 'struct'? A curseword?\n"
"Keep it PG: there are little bits 'n bytes with ears around here.\n"
;
failure(msg);
}
void phase08() {
int n = atoi(next_input());
int m = atoi(next_input());
int t = (hash % 83) + 21;
int s = 0;
char *msg =
"Do you like spaghetti? Try some spaghetti! It's good, right?\n"
"What, you prefer structured loops? How mundane.\n";
goto LTOP;
LEND:
failure(msg);
LOM1:
n = (n<<2) - n + 1;
LCHK:
if(s == t && m == t){
goto LAFT;
}
s++;
goto LTOP;
LOC1:
if(n & 1){
goto LOM1;
}
goto LEM1;
LTOP:
if(!(n>1)){
goto LEND;
}
goto LOC1;
LEM1:
n = n >> 1;
goto LCHK;
LAFT:
return;
}
unsigned long state = 1;
unsigned int pb_rand() {
state = state * 1103515245 + 12345;
return (unsigned int)(state/65536) % 32768;
}
void pb_srand(unsigned long seed){
state = seed;
}
void scramble(char *str, int rounds){
int len = strlen(str);
for(int i=0; i
char *msg =
“\”My, what big ints you have, Granny!\” ”
“\”All the better to overflow your buffers my dear\”\n”;
failure(msg);
}
}
long seed = (((long) hash) << 32) + ~hash;
pb_srand(seed);
scramble(letters, 100);
char buf[BUFSIZE] = {};
for(int i=0; i<5; i++){
buf[i] = letters[idxs[i]];
}
union{
long l;
char s[8];
} chong;
chong.l = 478426194263;
if(strcmp(buf,chong.s)==0){
return;
}
char *msg =
"Where's that stripey hipster with the lame hat and cane?\n"
"He's all spread around in there. Find him.";
failure(msg);
}
void phase10(){
long a = atol(next_input());
char ans[] = " ";
for(int i=0; i<8; i++){
ans[i] = (char) (a >> (7*i) & 0x7F);
}
char *accept = userID;
if(strcmp(ans,accept)==0){
printf(“OMG %s, the answers were inside you the the whole time!\n”,accept);
return;
}
char msg[BUFSIZE] = {};
snprintf(msg, BUFSIZE,
“‘%s’??? Not quite, try a little closer to home…\n”,
ans);
failure(msg);
}