#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "distcc.h"
#include "trace.h"
#include "exec.h"
#include "rpc.h"
#include "exitcode.h"
#include "util.h"
#include "clinet.h"
#include "bulk.h"
#include "hosts.h"
#include "state.h"
#include "include_server_if.h"
#include "emaillog.h"
#ifdef XCODE_INTEGRATION
# include "xci.h"
#endif
int dcc_x_req_header(int fd,
enum dcc_protover protover)
{
return dcc_x_token_int(fd, "DIST", protover);
}
int dcc_x_argv(int fd, char **argv)
{
int i;
int ret;
int argc;
argc = dcc_argv_len(argv);
if (dcc_x_token_int(fd, "ARGC", (unsigned) argc))
return EXIT_PROTOCOL_ERROR;
for (i = 0; i < argc; i++) {
if ((ret = dcc_x_token_string(fd, "ARGV", argv[i])))
return ret;
}
return 0;
}
int dcc_x_cwd(int fd)
{
int ret;
char cwd[MAXPATHLEN + 1];
char * cwd_ret;
cwd_ret = getcwd(cwd, MAXPATHLEN);
if (cwd_ret == NULL) {
return 0;
}
ret = dcc_x_token_string(fd, "CDIR", cwd);
return ret;
}
int dcc_r_result_header(int ifd,
enum dcc_protover expect_ver)
{
unsigned vers;
int ret;
if ((ret = dcc_r_token_int(ifd, "DONE", &vers)))
rs_log_error("server provided no answer. "
"Is the server configured to allow access from your IP"
" address? Does the server have the compiler installed?"
" Is the server configured to access the compiler?");
return ret;
if (vers != expect_ver) {
rs_log_error("got version %d not %d in response from server",
vers, expect_ver);
return EXIT_PROTOCOL_ERROR;
}
rs_trace("got response header");
return 0;
}
int dcc_r_cc_status(int ifd, int *status)
{
unsigned u_status;
int ret;
ret = dcc_r_token_int(ifd, "STAT", &u_status);
*status = u_status;
return ret;
}
int dcc_retrieve_results(int net_fd,
int *status,
const char *output_fname,
const char *deps_fname,
const char *server_stderr_fname,
struct dcc_hostdef *host)
{
unsigned len;
int ret;
unsigned o_len;
if ((ret = dcc_r_result_header(net_fd, host->protover)))
return ret;
dcc_note_state(DCC_PHASE_RECEIVE, NULL, NULL);
if ((ret = dcc_r_cc_status(net_fd, status)))
return ret;
if ((ret = dcc_r_token_int(net_fd, "SERR", &len)))
return ret;
if ((ret = dcc_r_file(net_fd, server_stderr_fname, len, host->compr)))
return ret;
if (dcc_add_file_to_log_email("server-side stderr", server_stderr_fname))
return ret;
if ((ret = dcc_r_token_int(net_fd, "SOUT", &len))
|| (ret = dcc_r_bulk(STDOUT_FILENO, net_fd, len, host->compr))
|| (ret = dcc_r_token_int(net_fd, "DOTO", &o_len)))
return ret;
if (*status == 0) {
if ((ret = dcc_r_file_timed(net_fd, output_fname, o_len, host->compr)))
return ret;
if (host->cpp_where == DCC_CPP_ON_SERVER) {
if ((ret = dcc_r_token_int(net_fd, "DOTD", &len) == 0)
&& deps_fname != NULL) {
ret = dcc_r_file_timed(net_fd, deps_fname, len, host->compr);
return ret;
}
}
} else if (o_len != 0) {
rs_log_error("remote compiler failed but also returned output: "
"I don't know what to do");
}
return 0;
}
int dcc_read_link(const char* fname, char *points_to)
{
int len;
if ((len = readlink(fname, points_to, MAXPATHLEN)) == -1) {
rs_log_error("readlink '%s' failed: %s", fname, strerror(errno));
return EXIT_IO_ERROR;
}
points_to[len] = '\0';
return 0;
}
int dcc_is_link(const char *fname, int *is_link)
{
struct stat buf;
if (lstat(fname, &buf) == -1) {
rs_log_error("stat '%s' failed: %s", fname, strerror(errno));
return EXIT_IO_ERROR;
}
*is_link = S_ISLNK(buf.st_mode);
return 0;
}
int dcc_x_many_files(int ofd,
unsigned int n_files,
char **fnames)
{
int ret = 0;
char link_points_to[MAXPATHLEN + 1];
int is_link;
const char *fname;
char *original_fname = NULL;
#ifdef XCODE_INTEGRATION
char *xci_original_fname, *xci_link_points_to;
#endif
dcc_x_token_int(ofd, "NFIL", n_files);
for (; *fnames != NULL; ++fnames) {
fname = *fnames;
ret = dcc_get_original_fname(fname, &original_fname);
if (ret) goto out_error;
if ((ret = dcc_is_link(fname, &is_link))) {
goto out_error;
}
#ifdef XCODE_INTEGRATION
xci_original_fname = dcc_xci_mask_developer_dir(original_fname);
if (xci_original_fname) {
free(original_fname);
original_fname = xci_original_fname;
xci_original_fname = NULL;
} else {
ret = EXIT_OUT_OF_MEMORY;
goto out_error;
}
#endif
if (is_link) {
if ((ret = dcc_read_link(fname, link_points_to))) {
goto out_error;
}
#ifdef XCODE_INTEGRATION
xci_link_points_to = dcc_xci_mask_developer_dir(link_points_to);
if (xci_link_points_to) {
strlcpy(link_points_to, xci_link_points_to,
sizeof(link_points_to));
free(xci_link_points_to);
xci_link_points_to = NULL;
} else {
ret = EXIT_OUT_OF_MEMORY;
goto out_error;
}
#endif
if ((ret = dcc_x_token_string(ofd, "NAME", original_fname)) ||
(ret = dcc_x_token_string(ofd, "LINK", link_points_to))) {
goto out_error;
}
} else {
ret = dcc_x_token_string(ofd, "NAME", original_fname);
if (ret) goto out_error;
ret = dcc_x_file(ofd, fname, "FILE", DCC_COMPRESS_NONE,
NULL);
if (ret) goto out_error;
}
free(original_fname);
original_fname = NULL;
}
return 0;
out_error:
if (original_fname)
free(original_fname);
return ret;
}