1
/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
3
* distcc -- A simple distributed compiler system
5
* Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
6
* Copyright 2007 Google Inc.
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License
10
* as published by the Free Software Foundation; either version 2
11
* of the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
34
#include <sys/types.h>
47
#include "include_server_if.h"
53
* @brief Client-side RPC functions.
57
* Transmit header for whole request.
59
int dcc_x_req_header(int fd,
60
enum dcc_protover protover)
62
return dcc_x_token_int(fd, "DIST", protover);
68
* Transmit an argv array.
70
int dcc_x_argv(int fd, char **argv)
76
argc = dcc_argv_len(argv);
78
if (dcc_x_token_int(fd, "ARGC", (unsigned) argc))
79
return EXIT_PROTOCOL_ERROR;
81
for (i = 0; i < argc; i++) {
82
if ((ret = dcc_x_token_string(fd, "ARGV", argv[i])))
90
* Transmit the current working directory
95
char cwd[MAXPATHLEN + 1];
97
cwd_ret = getcwd(cwd, MAXPATHLEN);
98
if (cwd_ret == NULL) {
101
ret = dcc_x_token_string(fd, "CDIR", cwd);
106
* Read the "DONE" token from the network that introduces a response.
108
int dcc_r_result_header(int ifd,
109
enum dcc_protover expect_ver)
114
if ((ret = dcc_r_token_int(ifd, "DONE", &vers)))
115
rs_log_error("server provided no answer. "
116
"Is the server configured to allow access from your IP"
117
" address? Does the server have the compiler installed?"
118
" Is the server configured to access the compiler?");
121
if (vers != expect_ver) {
122
rs_log_error("got version %d not %d in response from server",
124
return EXIT_PROTOCOL_ERROR;
127
rs_trace("got response header");
133
int dcc_r_cc_status(int ifd, int *status)
138
ret = dcc_r_token_int(ifd, "STAT", &u_status);
145
* The second half of the client protocol: retrieve all results from the server.
147
int dcc_retrieve_results(int net_fd,
149
const char *output_fname,
150
const char *deps_fname,
151
const char *server_stderr_fname,
152
struct dcc_hostdef *host)
158
if ((ret = dcc_r_result_header(net_fd, host->protover)))
161
/* We've started to see the response, so the server is done
163
dcc_note_state(DCC_PHASE_RECEIVE, NULL, NULL);
165
if ((ret = dcc_r_cc_status(net_fd, status)))
168
if ((ret = dcc_r_token_int(net_fd, "SERR", &len)))
171
/* Save the server-side errors into a file. This way, we can
172
decide later whether we want to report them to the user
173
or not. We don't want to report them to the user if
174
we are going to redo the compilation locally, because then
175
the local errors are going to appear.
176
Always put the server-side errors in the email we will
177
send to the maintainers, though.
180
if ((ret = dcc_r_file(net_fd, server_stderr_fname, len, host->compr)))
183
if (dcc_add_file_to_log_email("server-side stderr", server_stderr_fname))
186
if ((ret = dcc_r_token_int(net_fd, "SOUT", &len))
187
|| (ret = dcc_r_bulk(STDOUT_FILENO, net_fd, len, host->compr))
188
|| (ret = dcc_r_token_int(net_fd, "DOTO", &o_len)))
192
/* If the compiler succeeded, then we always retrieve the result,
193
* even if it's 0 bytes. */
195
if ((ret = dcc_r_file_timed(net_fd, output_fname, o_len, host->compr)))
197
if (host->cpp_where == DCC_CPP_ON_SERVER) {
198
if ((ret = dcc_r_token_int(net_fd, "DOTD", &len) == 0)
199
&& deps_fname != NULL) {
200
ret = dcc_r_file_timed(net_fd, deps_fname, len, host->compr);
204
} else if (o_len != 0) {
205
rs_log_error("remote compiler failed but also returned output: "
206
"I don't know what to do");
212
/* points_to must be at least MAXPATHLEN + 1 long */
213
int dcc_read_link(const char* fname, char *points_to)
216
if ((len = readlink(fname, points_to, MAXPATHLEN)) == -1) {
217
rs_log_error("readlink '%s' failed: %s", fname, strerror(errno));
218
return EXIT_IO_ERROR;
220
points_to[len] = '\0';
224
int dcc_is_link(const char *fname, int *is_link)
228
if (lstat(fname, &buf) == -1) {
229
rs_log_error("stat '%s' failed: %s", fname, strerror(errno));
230
return EXIT_IO_ERROR;
233
*is_link = S_ISLNK(buf.st_mode);
237
/* Send to @p ofd @p n_files whose names are in @p fnames.
238
* @fnames must be null-terminated.
239
* The names can be coming from the include server, so
240
* we consult dcc_get_original_fname to get the real names.
241
* Always uses lzo compression.
243
/* TODO: This code is highly specific to DCC_VER_3; it assumes
244
lzo compression is on, and that the include server has
245
actually compressed the files. */
246
int dcc_x_many_files(int ofd,
247
unsigned int n_files,
251
char link_points_to[MAXPATHLEN + 1];
254
char *original_fname;
256
dcc_x_token_int(ofd, "NFIL", n_files);
258
for (; *fnames != NULL; ++fnames) {
260
ret = dcc_get_original_fname(fname, &original_fname);
263
if ((ret = dcc_is_link(fname, &is_link))) {
268
if ((ret = dcc_read_link(fname, link_points_to)) ||
269
(ret = dcc_x_token_string(ofd, "NAME", original_fname)) ||
270
(ret = dcc_x_token_string(ofd, "LINK", link_points_to))) {
274
ret = dcc_x_token_string(ofd, "NAME", original_fname);
276
/* File should be compressed already.
277
If we ever support non-compressed server-side-cpp,
278
we should have some checks here and then uncompress
279
the file if it is compressed. */
280
ret = dcc_x_file(ofd, fname, "FILE", DCC_COMPRESS_NONE,