Esempio n. 1
0
void check_no_worker_running(char* worker_logfile) {
    char cmd[150];
    char *result, *error;
    int rrc;

    // ensure no worker are running anymore
    char *username=getenv("USER");
    snprintf(cmd, 150, "ps -efl 2>/dev/null | grep -v grep | grep '%s' | grep mod_gearman_worker", username);
    rrc = real_exit_code(run_check(cmd, &result, &error));
    ok(rrc == 1, "no worker running anymore");
    like(result, "^\\s*$", "ps output should be empty");
    like(error, "^\\s*$", "ps error output should be empty");
    if(rrc != 1) {
        check_logfile(worker_logfile, 3);
    }
    return;
}
Esempio n. 2
0
int main (int argc, char **argv, char **env) {
    argc = argc; argv = argv; env  = env;
#ifndef EMBEDDEDPERL
    plan(1);
    ok(1, "skipped epn tests");
    return exit_status();
#endif
#ifdef EMBEDDEDPERL
    int rc, rrc;
    char *result, *error;
    char cmd[120];

    plan(21);

    /* create options structure and set debug level */
    mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
    set_default_options(mod_gm_opt);
    char cmds[150];
    strcpy(cmds, "--p1_file=worker/mod_gearman2_p1.pl");
    parse_args_line(mod_gm_opt, cmds, 0);
    strcpy(cmds, "--enable_embedded_perl=on");
    parse_args_line(mod_gm_opt, cmds, 0);
    strcpy(cmds, "--use_embedded_perl_implicitly=on");
    parse_args_line(mod_gm_opt, cmds, 0);
    /*
     * mod_gm_opt->debug_level=4;
     * dumpconfig(mod_gm_opt, GM_WORKER_MODE);
     */
    ok(p1_file != NULL, "p1_file: %s", p1_file);

    /*****************************************
     * send_gearman
     */
    init_embedded_perl(env);

    rc=file_uses_embedded_perl("t/ok.pl");
    cmp_ok(rc, "==", TRUE, "ok.pl: file_uses_embedded_perl returned rc %d", rc);

    rc=file_uses_embedded_perl("t/noepn.pl");
    cmp_ok(rc, "==", FALSE, "noepn.pl: file_uses_embedded_perl returned rc %d", rc);

    strcpy(cmd, "./t/fail.pl");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "ePN failed to compile", "returned result string");
    like(error, "^$", "returned error string");
    free(result);
    free(error);

    strcpy(cmd, "./t/ok.pl");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "test plugin OK", "returned result string");
    unlike(result, "plugin did not call exit", "returned result string");
    like(error, "^$", "returned error string");
    free(result);
    free(error);

    strcpy(cmd, "./t/crit.pl");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 2, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "test plugin CRITICAL", "returned result string");
    like(error, "some errors on stderr", "returned error string");
    free(result);
    free(error);

    strcpy(cmd, "./t/noexit.pl");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "sample output but no exit", "returned result string");
    like(result, "plugin did not call exit", "returned result string");
    like(error, "^$", "returned error string");
    free(result);
    free(error);

    /* test mini epn */
    strcpy(cmd, "./mod_gearman2_mini_epn ./t/ok.pl");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "plugin return code: 0", "contains return code");
    like(result, "perl plugin output: 'test plugin OK", "contains plugin output");
    like(error, "^$", "returned error string");
    free(result);
    free(error);


    /*****************************************
     * clean up
     */
    mod_gm_free_opt(mod_gm_opt);
    deinit_embedded_perl(0);

    return exit_status();
#endif
}
Esempio n. 3
0
/* execute this command with given timeout */
int execute_safe_command(gm_job_t * exec_job, int fork_exec, char * identifier) {
    int pipe_stdout[2] , pipe_stderr[2];
    int return_code;
    int pclose_result;
    char *plugin_output, *plugin_error;
    char *bufdup;
    char buffer[GM_BUFFERSIZE], buf_error[GM_BUFFERSIZE];
    struct timeval start_time,end_time;
    pid_t pid    = 0;
    buffer[0]    = '\x0';
    buf_error[0] = '\x0';

    gm_log( GM_LOG_TRACE, "execute_safe_command()\n" );

    // mark all filehandles to close on exec
    int x;
    for(x = 0; x<=64; x++)
        fcntl(x, F_SETFD, FD_CLOEXEC);

    signal(SIGTERM, SIG_DFL);
    signal(SIGINT, SIG_DFL);

    if(exec_job->start_time.tv_sec == 0) {
        gettimeofday(&start_time,NULL);
        exec_job->start_time = start_time;
    }

    /* fork a child process */
    if(fork_exec == GM_ENABLED) {
        if(pipe(pipe_stdout) != 0)
            perror("pipe stdout");
        if(pipe(pipe_stderr) != 0)
            perror("pipe stderr");

        pid=fork();

        /*fork error */
        if( pid == -1 ) {
            exec_job->output      = strdup("(Error On Fork)");
            exec_job->return_code = 3;
            return(GM_ERROR);
        }
    }

    /* we are in the child process */
    if( fork_exec == GM_DISABLED || pid == 0 ) {

        /* become the process group leader */
        setpgid(0,0);
        pid = getpid();

        if( fork_exec == GM_ENABLED ) {
            close(pipe_stdout[0]);
            close(pipe_stderr[0]);
        }
        signal(SIGALRM, check_alarm_handler);
        alarm(exec_job->timeout);

        /* run the plugin check command */
        pclose_result = run_check(exec_job->command_line, &plugin_output, &plugin_error);
        return_code   = pclose_result;

        if(fork_exec == GM_ENABLED) {
            if(write(pipe_stdout[1], plugin_output, strlen(plugin_output)+1) <= 0)
                perror("write stdout");
            if(write(pipe_stderr[1], plugin_error, strlen(plugin_error)+1) <= 0)
                perror("write");

            if(pclose_result == -1) {
                char error[GM_BUFFERSIZE];
                snprintf(error, sizeof(error), "error on %s: %s", identifier, strerror(errno));
                if(write(pipe_stdout[1], error, strlen(error)+1) <= 0)
                    perror("write");
            }

            return_code = real_exit_code(pclose_result);
            free(plugin_output);
            free(plugin_error);
            _exit(return_code);
        }
        else {
            snprintf( buffer,    sizeof( buffer )-1,    "%s", plugin_output );
            snprintf( buf_error, sizeof( buf_error )-1, "%s", plugin_error  );
            free(plugin_output);
            free(plugin_error);
        }
    }

    /* we are the parent */
    if( fork_exec == GM_DISABLED || pid > 0 ){

        if( fork_exec == GM_ENABLED) {
            gm_log( GM_LOG_TRACE, "started check with pid: %d\n", pid);

            close(pipe_stdout[1]);
            close(pipe_stderr[1]);

            waitpid(pid, &return_code, 0);
            gm_log( GM_LOG_TRACE, "finished check from pid: %d with status: %d\n", pid, return_code);
            /* get all lines of plugin output */
            if(read(pipe_stdout[0], buffer, sizeof(buffer)-1) < 0)
                perror("read");
            if(read(pipe_stderr[0], buf_error, sizeof(buf_error)-1) < 0)
                perror("read");
        }
        return_code = real_exit_code(return_code);

        /* file not executable? */
        if(return_code == 126) {
            return_code = STATE_CRITICAL;
            snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 126 is out of bounds. Make sure the plugin you're trying to run is executable. (worker: %s)", identifier);
        }
        /* file not found errors? */
        else if(return_code == 127) {
            return_code = STATE_CRITICAL;
            snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. (worker: %s)", identifier);
        }
        /* signaled */
        else if(return_code >= 128 && return_code < 144) {
            char * signame = nr2signal((int)(return_code-128));
            bufdup = strdup(buffer);
            snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. Plugin exited by signal %s. (worker: %s)\\n%s", (int)(return_code), signame, identifier, bufdup);
            return_code = STATE_CRITICAL;
            free(bufdup);
            free(signame);
        }
        /* other error codes > 3 */
        else if(return_code > 3) {
            gm_log( GM_LOG_DEBUG, "check exited with exit code > 3. Exit: %d\n", (int)(return_code));
            gm_log( GM_LOG_DEBUG, "stdout: %s\n", buffer);
            bufdup = strdup(buffer);
            snprintf( buffer, sizeof( buffer )-1, "CRITICAL: Return code of %d is out of bounds. (worker: %s)\\n%s", (int)(return_code), identifier, bufdup);
            free(bufdup);
            if(return_code != 25 && mod_gm_opt->workaround_rc_25 == GM_DISABLED) {
                return_code = STATE_CRITICAL;
            }
        }

        exec_job->output      = strdup(buffer);
        exec_job->error       = strdup(buf_error);
        exec_job->return_code = return_code;
        if( fork_exec == GM_ENABLED) {
            close(pipe_stdout[0]);
            close(pipe_stderr[0]);
        }
    }
    alarm(0);
    current_child_pid = 0;
    pid               = 0;

    /* record check result info */
    gettimeofday(&end_time, NULL);
    exec_job->finish_time = end_time;

    /* did we have a timeout? */
    if(exec_job->timeout < ((int)end_time.tv_sec - (int)exec_job->start_time.tv_sec)) {
        exec_job->return_code   = 2;
        exec_job->early_timeout = 1;
        if ( !strcmp( exec_job->type, "service" ) )
            snprintf( buffer, sizeof( buffer ) -1, "(Service Check Timed Out On Worker: %s)", identifier);
        if ( !strcmp( exec_job->type, "host" ) )
            snprintf( buffer, sizeof( buffer ) -1, "(Host Check Timed Out On Worker: %s)", identifier);
        free(exec_job->output);
        exec_job->output = strdup( buffer );
    }

    return(GM_OK);
}
Esempio n. 4
0
/* main tests */
int main (int argc, char **argv, char **env) {
    argc = argc; argv = argv; env  = env;
    int status, chld, rc;
    int tests = 125;
    int rrc;
    char cmd[150];
    char *result, *error, *message, *output;
    plan(tests);

    mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
    set_default_options(mod_gm_opt);

#ifdef EMBEDDEDPERL
    char p1[150];
    snprintf(p1, 150, "--p1_file=worker/mod_gearman_p1.pl");
    parse_args_line(mod_gm_opt, p1, 0);
    init_embedded_perl(env);
#endif

    char options[150];
    snprintf(options, 150, "--server=127.0.0.1:%d", GEARMAND_TEST_PORT);
    ok(parse_args_line(mod_gm_opt, options, 0) == 0, "parse_args_line()");
    mod_gm_opt->debug_level = GM_LOG_ERROR;

    worker_logfile = my_tmpfile();
    if(!ok(worker_logfile != NULL, "created temp logile: %s", worker_logfile)) {
        diag("could not create temp logfile");
        exit( EXIT_FAILURE );
    }

    /* first fire up a gearmand server and one worker */
    start_gearmand((void*)NULL);
    sleep(2);
    start_worker((void*)NULL);
    sleep(2);

    /* wait one second and catch died procs */
    while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) {
        diag( "waitpid() %d exited with %d\n", chld, status);
        status = 0;
    }

    if(!ok(gearmand_pid > 0, "'gearmand started with port %d and pid: %d", GEARMAND_TEST_PORT, gearmand_pid)) {
        diag("make sure gearmand is in your PATH. Common locations are /usr/sbin or /usr/local/sbin");
        exit( EXIT_FAILURE );
    }
    if(!ok(pid_alive(gearmand_pid) == TRUE, "gearmand alive")) {
        check_logfile("/tmp/gearmand.log", 3);
        kill(gearmand_pid, SIGTERM);
        kill(worker_pid, SIGTERM);
        exit( EXIT_FAILURE );
    }
    if(!ok(worker_pid > 0, "worker started with pid: %d", worker_pid))
        diag("could not start worker");
    if(!ok(pid_alive(worker_pid) == TRUE, "worker alive")) {
        check_logfile(worker_logfile, 3);
        kill(gearmand_pid, SIGTERM);
        kill(worker_pid, SIGTERM);
        exit( EXIT_FAILURE );
    }

    skip(gearmand_pid <= 0 || worker_pid <= 0,
               tests-3,             /* Number of tests to skip */
               "Skipping all tests, no need to go on without gearmand or worker");

    /* create server / clients */
    mod_gm_opt->transportmode = GM_ENCODE_ONLY;
    create_modules();

    /* send big job */
    send_big_jobs(GM_ENCODE_ONLY);
    //diag_queues();
    wait_for_empty_queue("eventhandler", 20);
    wait_for_empty_queue("service", 20);
    //diag_queues();
    do_result_work(1);
    //diag_queues();
    wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5);

    /*****************************************
     * test check
     */
    //diag_queues();
    test_servicecheck(GM_ENCODE_ONLY, "./t/crit.pl");
    //diag_queues();
    wait_for_empty_queue("eventhandler", 20);
    wait_for_empty_queue("service", 5);
    //diag_queues();
    do_result_work(1);
    //diag_queues();
    wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5);
    //diag_queues();
    like(last_result, "test plugin CRITICAL", "stdout output from ./t/crit.pl");
    like(last_result, "some errors on stderr", "stderr output from ./t/crit.pl");

    /*****************************************
     * test check2
     */
    //diag_queues();
    test_servicecheck(GM_ENCODE_ONLY, "./t/both");
    //diag_queues();
    wait_for_empty_queue("eventhandler", 20);
    wait_for_empty_queue("service", 5);
    //diag_queues();
    do_result_work(1);
    //diag_queues();
    wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5);
    like(last_result, "stdout output", "stdout output from ./t/both");
    like(last_result, "stderr output", "stderr output from ./t/both");

    /* try to send some data with base64 only */
    //diag_queues();
    test_eventhandler(GM_ENCODE_ONLY);
    //diag_queues();
    test_servicecheck(GM_ENCODE_ONLY, NULL);
    //diag_queues();
    wait_for_empty_queue("eventhandler", 20);
    wait_for_empty_queue("service", 5);
    //diag_queues();
    do_result_work(1);
    //diag_queues();
    wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5);
    sleep(1);
    kill(worker_pid, SIGTERM);
    waitpid(worker_pid, &status, 0);
    ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status));
    status = 0;
    check_no_worker_running(worker_logfile);
    check_logfile(worker_logfile, 0);

    char * test_keys[] = {
        "12345",
        "test",
        "test key 123",
        "me make you loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong key"
    };

    /* ignore some signals for now */
    signal(SIGTERM, SIG_IGN);

    int i;
    for(i=0;i<4;i++) {
        mod_gm_opt->transportmode = GM_ENCODE_AND_ENCRYPT;
        start_worker((void *)test_keys[i]);

        mod_gm_crypt_init( test_keys[i] );
        ok(1, "initialized with key: %s", test_keys[i]);

        test_eventhandler(GM_ENCODE_AND_ENCRYPT);
        test_servicecheck(GM_ENCODE_AND_ENCRYPT, NULL);
        wait_for_empty_queue("eventhandler", 20);
        wait_for_empty_queue("service", 5);
        do_result_work(1);
        wait_for_empty_queue(GM_DEFAULT_RESULT_QUEUE, 5);
        sleep(1);

        kill(worker_pid, SIGTERM);
        waitpid(worker_pid, &status, 0);
        ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status));
        status = 0;
        check_no_worker_running(worker_logfile);
        check_logfile(worker_logfile, 0);
    }

    /*****************************************
     * send_gearman
     */
    snprintf(cmd, 150, "./send_gearman --server=127.0.0.1:%d --key=testtest --host=test --service=test --message=test --returncode=0", GEARMAND_TEST_PORT);
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "^\\s*$", "output from ./send_gearman");
    free(result);
    free(error);

    /*****************************************
     * send_multi
     */
    snprintf(cmd, 150, "./send_multi --server=127.0.0.1:%d --host=blah < t/data/send_multi.txt", GEARMAND_TEST_PORT);
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "send_multi OK: 2 check_multi child checks submitted", "output from ./send_multi");
    free(result);
    free(error);

    /*****************************************
     * check_gearman
     */
    snprintf(cmd, 150, "./check_gearman -H 127.0.0.1:%d -s check -a -q worker_test", GEARMAND_TEST_PORT);
    rrc = real_exit_code(run_check(cmd, &result, &error));
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "check_gearman OK - sending background job succeded", "output from ./check_gearman");

    /* cleanup */
    free(result);
    free(error);
    free_client(&client);
    free_worker(&worker);

    /* shutdown gearmand */
    rc = send2gearmandadmin("shutdown\n", "127.0.0.1", GEARMAND_TEST_PORT, &output, &message);
    ok(rc == 0, "rc of send2gearmandadmin %d", rc);
    like(output, "OK", "output contains OK");
    free(message);
    free(output);

    /* wait 5 seconds to shutdown */
    for(i=0;i<=5;i++) {
        waitpid(gearmand_pid, &status, WNOHANG);
        if(pid_alive(gearmand_pid) == FALSE) {
            todo();
            ok(status == 0, "gearmand (%d) exited with: %d", gearmand_pid, real_exit_code(status));
            endtodo;
            break;
        }
        sleep(1);
    }

    if(pid_alive(gearmand_pid) == TRUE) {
        /* kill it the hard way */
        kill(gearmand_pid, SIGTERM);
        waitpid(gearmand_pid, &status, 0);
        ok(status == 0, "gearmand (%d) exited with exit code %d", gearmand_pid, real_exit_code(status));
        status = 0;
        ok(false, "gearmand had to be killed!");
    }
    todo();
    check_logfile("/tmp/gearmand.log", status != 0 ? 2 : 0);
    endtodo;
    status = 0;

    kill(worker_pid, SIGTERM);
    waitpid(worker_pid, &status, 0);
    ok(status == 0, "worker (%d) exited with exit code %d", worker_pid, real_exit_code(status));
    check_no_worker_running(worker_logfile);
    status = 0;

#ifdef EMBEDDEDPERL
    deinit_embedded_perl(0);
#endif

    free(last_result);
    free(worker_logfile);
    endskip;
    mod_gm_free_opt(mod_gm_opt);
    return exit_status();
}
Esempio n. 5
0
int main(void) {
    int rc, rrc;
    char *result, *error;
    char cmd[120];
    char hostname[GM_BUFFERSIZE];

    plan(54);

    /* set hostname */
    gethostname(hostname, GM_BUFFERSIZE-1);

    /* create options structure and set debug level */
    mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
    set_default_options(mod_gm_opt);
    mod_gm_opt->debug_level = 0;

    /*****************************************
     * arg parsing test 1
     */
    char *argv[MAX_CMD_ARGS];
    strcpy(cmd, "/bin/true");
    parse_command_line(cmd, argv);
    like(argv[0], cmd, "parsing args cmd 1");

    /*****************************************
     * arg parsing test 2
     */
    strcpy(cmd, "/bin/cmd blah blub   foo");
    parse_command_line(cmd,argv);
    like(argv[0], "/bin/cmd", "parsing args cmd 2");
    like(argv[1], "blah", "parsing args cmd 2");
    like(argv[2], "blub", "parsing args cmd 2");
    like(argv[3], "foo", "parsing args cmd 2");

    /*****************************************
     * send_gearman
     */
    strcpy(cmd, "./send_gearman --server=blah --key=testtest --host=test --service=test --message=test --returncode=0");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    diag(result);
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * send_gearman
     */
    //mod_gm_opt->debug_level = 4;
    strcpy(cmd, "./send_multi --server=blah --host=blah < t/data/send_multi.txt");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    diag(result);
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 1
     */
    strcpy(cmd, "/bin/true");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 2
     */
    strcpy(cmd, "/bin/true 2>&1");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 3
     */
    strcpy(cmd, "/usr/lib/nagios/plugins/check_icmp -H 127.0.0.1");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 4
     */
    strcpy(cmd, "echo -n 'test'; exit 2");
    rc  = run_check(cmd, &result, &error);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 2, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "test", "returned result string");
    free(result);
    free(error);

    gm_job_t * exec_job;
    exec_job = ( gm_job_t * )malloc( sizeof *exec_job );
    set_default_job(exec_job, mod_gm_opt);



    /*****************************************
     * non existing command 1
     */
    exec_job->command_line = strdup("/bin/doesntexist");
    exec_job->type         = strdup("service");
    exec_job->timeout      = 10;
    int fork_on_exec       = 0;

    execute_safe_command(exec_job, fork_on_exec, hostname);
    cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
    like(exec_job->output, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. \\(worker:", "returned result string");
    free(exec_job->output);
    free(exec_job->error);

    fork_on_exec = 1;
    lives_ok({execute_safe_command(exec_job, fork_on_exec, hostname);}, "executing command using fork on exec");
Esempio n. 6
0
int main (int argc, char **argv, char **env) {
    argc = argc; argv = argv; env  = env;
    int rc, rrc;
    char *result, *error;
    char cmd[120];
    char hostname[GM_BUFFERSIZE];

    plan(56);

    /* set hostname */
    gethostname(hostname, GM_BUFFERSIZE-1);

    /* create options structure and set debug level */
    mod_gm_opt = malloc(sizeof(mod_gm_opt_t));
    set_default_options(mod_gm_opt);
    mod_gm_opt->debug_level = 0;

#ifdef EMBEDDEDPERL
    char p1[150];
    snprintf(p1, 150, "--p1_file=worker/mod_gearman_p1.pl");
    parse_args_line(mod_gm_opt, p1, 0);
    init_embedded_perl(env);
#endif

    /*****************************************
     * arg parsing test 1
     */
    char *args[MAX_CMD_ARGS];
    strcpy(cmd, "/bin/hostname");
    parse_command_line(cmd, args);
    like(args[0], cmd, "parsing args cmd 1");

    /*****************************************
     * arg parsing test 2
     */
    strcpy(cmd, "/bin/cmd blah blub   foo");
    parse_command_line(cmd,args);
    like(args[0], "/bin/cmd", "parsing args cmd 2");
    like(args[1], "blah", "parsing args cmd 2");
    like(args[2], "blub", "parsing args cmd 2");
    like(args[3], "foo", "parsing args cmd 2");

    /*****************************************
     * send_gearman
     */
    strcpy(cmd, "./send_gearman --server=blah --key=testtest --host=test --service=test --message=test --returncode=0");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    //diag(result);
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    if(atof(gearman_version()) >= 0.31) {
        like(result, "send_gearman UNKNOWN:", "result");
    } else {
        like(result, "sending job to gearmand failed:", "result");
    }
    free(result);
    free(error);

    /*****************************************
     * send_gearman
     */
    //mod_gm_opt->debug_level = 4;
    strcpy(cmd, "./send_multi --server=blah --host=blah < t/data/send_multi.txt");
    rrc = real_exit_code(run_check(cmd, &result, &error));
    //diag(result);
    cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc);
    if(atof(gearman_version()) >= 0.31) {
        like(result, "send_multi UNKNOWN:", "result");
    } else {
        like(result, "sending job to gearmand failed:", "result");
    }
    free(result);
    free(error);

    /*****************************************
     * simple test command 1
     */
    strcpy(cmd, "/bin/hostname");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 2
     */
    strcpy(cmd, "/bin/hostname 2>&1");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 3
     */
    strcpy(cmd, "/usr/lib/nagios/plugins/check_icmp -H 127.0.0.1");
    rc = run_check(cmd, &result, &error);
    cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc);
    free(result);
    free(error);

    /*****************************************
     * simple test command 4
     */
    strcpy(cmd, "echo -n 'test'; exit 2");
    rc  = run_check(cmd, &result, &error);
    rrc = real_exit_code(rc);
    cmp_ok(rrc, "==", 2, "cmd '%s' returned rc %d", cmd, rrc);
    like(result, "test", "returned result string");
    free(result);
    free(error);

    gm_job_t * exec_job;
    exec_job = ( gm_job_t * )malloc( sizeof *exec_job );
    set_default_job(exec_job, mod_gm_opt);



    /*****************************************
     * non existing command 1
     */
    exec_job->command_line = strdup("/bin/doesntexist");
    exec_job->type         = strdup("service");
    exec_job->timeout      = 10;
    int fork_on_exec       = 0;

    execute_safe_command(exec_job, fork_on_exec, hostname);
    cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line);
    like(exec_job->output, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. \\(worker:", "returned result string");
    free(exec_job->output);
    free(exec_job->error);

    fork_on_exec = 1;
    lives_ok({execute_safe_command(exec_job, fork_on_exec, hostname);}, "executing command using fork on exec");