autodriver/autodriver.c
static void run_job(void) {
    // Unblock signals
    sigprocmask(SIG_UNBLOCK, &sigchld_sigint_set, NULL);

    // Set ulimits
    if (args.nproc != 0) {
        struct rlimit rlimit = {args.nproc, args.nproc};
        if (setrlimit(RLIMIT_NPROC, &rlimit) < 0) {
            perror("Setting process limit");
            exit(EXIT_OSERROR);
        }
    }

    if (args.fsize != 0) {
        struct rlimit rlimit = {args.fsize, args.fsize};
        if (setrlimit(RLIMIT_FSIZE, &rlimit) < 0) {
            ERROR_ERRNO("Setting filesize limit");
            exit(EXIT_OSERROR);
        }
    }

    // Drop permissions
    if (initgroups(args.user_info.pw_name, args.user_info.pw_gid) < 0) {
        ERROR_ERRNO("Setting supplementary group IDs");
        exit(EXIT_OSERROR);
    }

    if (setresgid(args.user_info.pw_gid, args.user_info.pw_gid,
            args.user_info.pw_gid) < 0) {
        ERROR_ERRNO("Setting group ID");
        exit(EXIT_OSERROR);
    }

    if (setresuid(args.user_info.pw_uid, args.user_info.pw_uid,
            args.user_info.pw_uid) < 0) {
        ERROR_ERRNO("Setting user ID");
        exit(EXIT_OSERROR);
    }

    if (clearenv() < 0) {
        ERROR_ERRNO("Clearing environment variables");
        exit(EXIT_OSERROR);
    }

    char *home = calloc(strlen("/home/") + strlen(GRADING_USER) + 1, 1);
    sprintf(home, "/home/%s", GRADING_USER);
    if (setenv("USER", GRADING_USER, 1) < 0
            || setenv("HOME", home, 1) < 0) {
        ERROR_ERRNO("Setting USER and HOME environment variables");
        exit(EXIT_OSERROR);
    }
    free(home);

    // Redirect output
    int fd = child_output_fd;

    // If streaming, tail output file.
    // However, monitor output file for exceeding output size.
    if (args.stream) {
        pid_t tail_pid = tail(OUTPUT_FILE);

        // We want SIG_DFL behavior for SIGINT in the forked monitor.
        sigprocmask(SIG_BLOCK, &sigint_set, NULL);

        // Monitor size of streaming feedback in another thread.
        pid_t monitor_pid;
        if ((monitor_pid = fork()) < 0) {
            ERROR_ERRNO("Forking monitor");
            exit(EXIT_OSERROR);
        } else if (monitor_pid == 0) {
            // set SIG_DFL to make this process exit on interrupt
            signal(SIGINT, SIG_DFL);
            sigprocmask(SIG_UNBLOCK, &sigint_set, NULL);

            monitor_streaming_feedback(OUTPUT_FILE, tail_pid);
            ERROR_ERRNO("monitor_streaming_feedback... returned?");
            exit(EXIT_OSERROR);
        }
    }

    if (dup2(fd, STDOUT_FILENO) < 0) {
        ERROR_ERRNO("Redirecting standard output");
        exit(EXIT_OSERROR);
    }

    if (close(fd) < 0) {
        ERROR_ERRNO("Closing output file by child process");
        exit(EXIT_OSERROR);
    }

    if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
        ERROR_ERRNO("Redirecting standard error");
        exit(EXIT_OSERROR);
    }


    // Switch into the folder
    if (chdir(args.directory) < 0) {
        ERROR_ERRNO("Changing directory");
        exit(EXIT_OSERROR);
    }

    // Finally exec job
    execl("/usr/bin/make", "make", NULL);
    ERROR_ERRNO("Eexecuting make");
    exit(EXIT_OSERROR);
}
/**
 * @brief Sets up the environment for the autograding job and then runs it.
 *
 * Permission dropping method adaped from http://tinyurl.com/6wgacq6
 *
 * @arg arguments Pointer to struct containing arguments
 *
 * @return Does not return
 */
@brief Sets up the environment for the autograding job and then runs it.

@arg arguments Pointer to struct containing arguments

@return Does not return
@brief Sets up the environment for the autograding job and then runs it . @arg arguments Pointer to struct containing arguments @return Does not return
static void run_job(void) {
    sigprocmask(SIG_UNBLOCK, &sigchld_sigint_set, NULL);
    if (args.nproc != 0) {
        struct rlimit rlimit = {args.nproc, args.nproc};
        if (setrlimit(RLIMIT_NPROC, &rlimit) < 0) {
            perror("Setting process limit");
            exit(EXIT_OSERROR);
        }
    }
    if (args.fsize != 0) {
        struct rlimit rlimit = {args.fsize, args.fsize};
        if (setrlimit(RLIMIT_FSIZE, &rlimit) < 0) {
            ERROR_ERRNO("Setting filesize limit");
            exit(EXIT_OSERROR);
        }
    }
    if (initgroups(args.user_info.pw_name, args.user_info.pw_gid) < 0) {
        ERROR_ERRNO("Setting supplementary group IDs");
        exit(EXIT_OSERROR);
    }
    if (setresgid(args.user_info.pw_gid, args.user_info.pw_gid,
            args.user_info.pw_gid) < 0) {
        ERROR_ERRNO("Setting group ID");
        exit(EXIT_OSERROR);
    }
    if (setresuid(args.user_info.pw_uid, args.user_info.pw_uid,
            args.user_info.pw_uid) < 0) {
        ERROR_ERRNO("Setting user ID");
        exit(EXIT_OSERROR);
    }
    if (clearenv() < 0) {
        ERROR_ERRNO("Clearing environment variables");
        exit(EXIT_OSERROR);
    }
    char *home = calloc(strlen("/home/") + strlen(GRADING_USER) + 1, 1);
    sprintf(home, "/home/%s", GRADING_USER);
    if (setenv("USER", GRADING_USER, 1) < 0
            || setenv("HOME", home, 1) < 0) {
        ERROR_ERRNO("Setting USER and HOME environment variables");
        exit(EXIT_OSERROR);
    }
    free(home);
    int fd = child_output_fd;
    if (args.stream) {
        pid_t tail_pid = tail(OUTPUT_FILE);
        sigprocmask(SIG_BLOCK, &sigint_set, NULL);
        pid_t monitor_pid;
        if ((monitor_pid = fork()) < 0) {
            ERROR_ERRNO("Forking monitor");
            exit(EXIT_OSERROR);
        } else if (monitor_pid == 0) {
            signal(SIGINT, SIG_DFL);
            sigprocmask(SIG_UNBLOCK, &sigint_set, NULL);
            monitor_streaming_feedback(OUTPUT_FILE, tail_pid);
            ERROR_ERRNO("monitor_streaming_feedback... returned?");
            exit(EXIT_OSERROR);
        }
    }
    if (dup2(fd, STDOUT_FILENO) < 0) {
        ERROR_ERRNO("Redirecting standard output");
        exit(EXIT_OSERROR);
    }
    if (close(fd) < 0) {
        ERROR_ERRNO("Closing output file by child process");
        exit(EXIT_OSERROR);
    }
    if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) {
        ERROR_ERRNO("Redirecting standard error");
        exit(EXIT_OSERROR);
    }
    if (chdir(args.directory) < 0) {
        ERROR_ERRNO("Changing directory");
        exit(EXIT_OSERROR);
    }
    execl("/usr/bin/make", "make", NULL);
    ERROR_ERRNO("Eexecuting make");
    exit(EXIT_OSERROR);
}
static void run_job ( void ) { sigprocmask ( SIG_UNBLOCK , & sigchld_sigint_set , NULL ) ; if ( args . nproc != 0 ) { struct rlimit rlimit = { args . nproc , args . nproc } ; if ( setrlimit ( RLIMIT_NPROC , & rlimit ) < 0 ) { perror ( " " ) ; exit ( EXIT_OSERROR ) ; } } if ( args . fsize != 0 ) { struct rlimit rlimit = { args . fsize , args . fsize } ; if ( setrlimit ( RLIMIT_FSIZE , & rlimit ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } } if ( initgroups ( args . user_info . pw_name , args . user_info . pw_gid ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( setresgid ( args . user_info . pw_gid , args . user_info . pw_gid , args . user_info . pw_gid ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( setresuid ( args . user_info . pw_uid , args . user_info . pw_uid , args . user_info . pw_uid ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( clearenv ( ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } char * home = calloc ( strlen ( " " ) + strlen ( GRADING_USER ) + 1 , 1 ) ; sprintf ( home , " " , GRADING_USER ) ; if ( setenv ( " " , GRADING_USER , 1 ) < 0 || setenv ( " " , home , 1 ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } free ( home ) ; int fd = child_output_fd ; if ( args . stream ) { pid_t tail_pid = tail ( OUTPUT_FILE ) ; sigprocmask ( SIG_BLOCK , & sigint_set , NULL ) ; pid_t monitor_pid ; if ( ( monitor_pid = fork ( ) ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } else if ( monitor_pid == 0 ) { signal ( SIGINT , SIG_DFL ) ; sigprocmask ( SIG_UNBLOCK , & sigint_set , NULL ) ; monitor_streaming_feedback ( OUTPUT_FILE , tail_pid ) ; ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } } if ( dup2 ( fd , STDOUT_FILENO ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( close ( fd ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( dup2 ( STDOUT_FILENO , STDERR_FILENO ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } if ( chdir ( args . directory ) < 0 ) { ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; } execl ( " " , " " , NULL ) ; ERROR_ERRNO ( " " ) ; exit ( EXIT_OSERROR ) ; }
@brief Sets up the environment for the autograding job and then runs it.
@brief Sets up the environment for the autograding job and then runs it .
// Unblock signals // Set ulimits // Drop permissions // Redirect output // If streaming, tail output file. // However, monitor output file for exceeding output size. // We want SIG_DFL behavior for SIGINT in the forked monitor. // Monitor size of streaming feedback in another thread. // set SIG_DFL to make this process exit on interrupt // Switch into the folder // Finally exec job