/* 
 * File:   DontEverDoThis.c
 * Author: J Dean Brock <brock@unca.edu>
 */

/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
    This is actually a useless program, but it might teach you something
    Unix processes.
 */

#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>

int crashAndBurnChild(int*, int*, int, int, int) ;

void handle_signal(int signal);

unsigned int oopsCause[5] = {0, 0, 0, 0, 0} ;
unsigned int callNum = 0 ; 


int main(void) {
    int X[6] = {3, 1, 4, 1, 5, 9} ;
    
    callNum = 0 ;
    oopsCause[callNum] = crashAndBurnChild(X, &X[3], 1, 4, 1) ;
    ++callNum ;
        
    oopsCause[callNum] = crashAndBurnChild(X, (int *) 31416, 1, 4, 1) ;
    ++callNum ;
        
    oopsCause[callNum] = crashAndBurnChild(X, &X[3], 31416, 4, 1) ;
    ++callNum ;
        
    oopsCause[callNum] = crashAndBurnChild(X, &X[3], 1, 7, 1) ;
    ++callNum ;
        
    oopsCause[callNum] = crashAndBurnChild(X, &X[3], 1, 4, 0) ;
    ++callNum ;
    
    for (int i=0; i<callNum; ++i) {
        printf("Return is %4d\n", oopsCause[i]) ;
    }
    
    return (EXIT_SUCCESS) ;
}

void crashAndBurn(
        int *V,
        int *mustBeValidAddr,
        int mustBeWithinArray,
        int mustBeVisibleBy4,
        int mustBeNonZero) {
    *mustBeValidAddr = 255 ;
    V[mustBeWithinArray] = 320 ;
    *(int *) &(((char *)V)[mustBeVisibleBy4]) = 202 ;
    *V = 1000/mustBeNonZero ;
}

int crashAndBurnChild(
        int *V,
        int *mustBeValidAddr,
        int mustBeWithinArray,
        int mustBeVisibleBy4,
        int mustBeNonZero) {
    int childPid = fork() ;
    if (childPid==0) {
        crashAndBurn(
            V,
            mustBeValidAddr,
            mustBeWithinArray,
            mustBeVisibleBy4,
            mustBeNonZero) ;
        exit(0) ;
    } else {
        int childStatus ;
        (void) waitpid(childPid, &childStatus, 0) ;
        return childStatus ;
    }
}
