Пример #1
0
static int dcc_input_tmpnam(char * orig_input,
                            char **tmpnam_ret)
{
    const char *input_exten;
    
    rs_trace("input file %s", orig_input);
    input_exten = dcc_find_extension(orig_input);
    if (input_exten)
        input_exten = dcc_preproc_exten(input_exten);
    if (!input_exten)           /* previous line might return NULL */
        input_exten = ".tmp";
    return dcc_make_tmpnam("distccd", input_exten, tmpnam_ret);
}
Пример #2
0
/**
 * Read a request, run the compiler, and send a response.
 **/
static int dcc_run_job(int in_fd,
                       int out_fd)
{
    char **argv;
    int status;
    char *temp_i, *temp_o, *err_fname, *out_fname;
    int ret, compile_ret;
    char *orig_input, *orig_output;
    pid_t cc_pid;
    enum dcc_protover protover;
    enum dcc_compress compr;
    dcc_indirection indirect;
    
    if ((ret = dcc_make_tmpnam("distcc", ".stderr", &err_fname)))
        goto out_cleanup;
    if ((ret = dcc_make_tmpnam("distcc", ".stdout", &out_fname)))
        goto out_cleanup;
    
    dcc_remove_if_exists(err_fname);
    dcc_remove_if_exists(out_fname);

    /* Capture any messages relating to this compilation to the same file as
     * compiler errors so that they can all be sent back to the client. */
    dcc_add_log_to_file(err_fname);

    /* Ignore SIGPIPE; we consistently check error codes and will see the
     * EPIPE.  Note that it is set back to the default behaviour when spawning
     * a child, to handle cases like the assembler dying while its being fed
     * from the compiler */
    dcc_ignore_sigpipe(1);

    /* Allow output to accumulate into big packets. */
    tcp_cork_sock(out_fd, 1);

    if ((ret = dcc_r_request_header(in_fd, &protover))
        || (ret = dcc_r_argv(in_fd, &argv))
        || (ret = dcc_scan_args(argv, &orig_input, &orig_output, &argv)))
        goto out_cleanup;
    
    if (strcmp(argv[0],"--host-info") == 0) {
        if ((ret = dcc_x_result_header(out_fd, protover)) ||
            (ret = dcc_send_host_info(out_fd)))
            dcc_x_token_int(out_fd, "DOTO", 0);
    } else {
        
        rs_trace("output file %s", orig_output);
        
        if ((ret = dcc_input_tmpnam(orig_input, &temp_i)))
            goto out_cleanup;
        if ((ret = dcc_make_tmpnam("distccd", ".o", &temp_o)))
            goto out_cleanup;
        
        compr = (protover == 2) ? DCC_COMPRESS_LZO1X : DCC_COMPRESS_NONE;
        
        if ((ret = dcc_r_token_file(in_fd, "DOTI", temp_i, compr))
            || (ret = dcc_set_input(argv, temp_i))
            || (ret = dcc_set_output(argv, temp_o)))
            goto out_cleanup;
        
        if ((ret = dcc_check_compiler_masq(argv[0])))
            goto out_cleanup;
        
        indirect.in_fd = in_fd;
        indirect.out_fd = out_fd;
        if ((compile_ret = dcc_spawn_child(argv, &cc_pid,
                                           "/dev/null", out_fname, err_fname, &indirect))
            || (compile_ret = dcc_collect_child("cc", cc_pid, &status))) {
            /* We didn't get around to finding a wait status from the actual compiler */
            status = W_EXITCODE(compile_ret, 0);
        }
        
        if ((ret = dcc_x_result_header(out_fd, protover))
            || (ret = dcc_send_system_info(out_fd))
            || (ret = dcc_send_compiler_version(out_fd, argv[0]))
            || (ret = dcc_x_cc_status(out_fd, status))
            || (ret = dcc_x_file(out_fd, err_fname, "SERR", compr, NULL))
            || (ret = dcc_x_file(out_fd, out_fname, "SOUT", compr, NULL))
            || WIFSIGNALED(status)
            || WEXITSTATUS(status)) {
            /* Something went wrong, so send DOTO 0 */
            dcc_x_token_int(out_fd, "DOTO", 0);
        } else {
            ret = dcc_x_file(out_fd, temp_o, "DOTO", compr, NULL);
        }
        
        dcc_critique_status(status, argv[0], orig_input, dcc_hostdef_local, 0);
    }
    tcp_cork_sock(out_fd, 0);

    rs_log(RS_LOG_INFO|RS_LOG_NONAME, "job complete");

    out_cleanup:
    dcc_remove_log_to_file();
    dcc_cleanup_tempfiles();

    return ret;
}
Пример #3
0
/* Given the name of a dotd file, and the name of the directory
 * masquerading as root, write a @p new_dotd file that
 * contains everything in dotd, but with the "root" directory removed.
 * It will also substitute client_out_name for server_out_name,
 * rewriting the dependency target.
 */
int dcc_cleanup_dotd(const char *dotd_fname,
                     char **new_dotd_fname,
                     const char *root_dir,
                     const char *client_out_name,
                     const char *server_out_name)
{
    /* When we do the substitution of server-side output name to
     * client-side output name, we may end up with a line that
     * longer than the longest line we expect from the compiler.
     */
    char buf[2 * MAX_DOTD_LINE_LEN];

    FILE *dotd, *tmp_dotd;
    char *found;
    int ret;

    dotd = fopen(dotd_fname, "r");
    if (dotd == NULL) {
        return 1;
    }
    ret = dcc_make_tmpnam(dcc_find_basename(dotd_fname),
                          ".d", new_dotd_fname);

    if (ret) {
        fclose(dotd);
        return ret;
    }

    tmp_dotd = fopen(*new_dotd_fname, "w");
    if (tmp_dotd == NULL) {
        fclose(dotd);
        return 1;
    }

    while (fgets(buf, MAX_DOTD_LINE_LEN, dotd)) {
        if ((strchr(buf, '\n') == NULL) && !feof(dotd)) {
            /* Line length must have exceeded MAX_DOTD_LINE_LEN: bail out. */
            fclose(dotd);
            fclose(tmp_dotd);
            return 1;
        }

        /* First, the dependency target substitution */
        if (dcc_strgraft(buf, sizeof(buf),
                         server_out_name, client_out_name)) {
            fclose(dotd);
            fclose(tmp_dotd);
            return 1;
        }

        /* Second, the trimming of the "root" directory" */
        found = strstr(buf, root_dir);
        while (found) {
            char *rest_of_buf = found + strlen(root_dir);
            memmove(found, rest_of_buf, strlen(rest_of_buf) + 1);
            found = strstr(found, root_dir);
        }
        if (fprintf(tmp_dotd, "%s", buf) < 0) {
            fclose(dotd);
            fclose(tmp_dotd);
            return 1;
        }
    }
    if (ferror(dotd) || ferror(tmp_dotd)) {
       return 1;
    }
    fclose(dotd);
    if (fclose(tmp_dotd) < 0) {
        return 1;
    }
    return 0;
}