#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "distcc.h"
#include "exitcode.h"
#include "dotd.h"
#include "snprintf.h"
#define MAX_DOTD_LINE_LEN (MAXPATHLEN * 2)
static int dcc_strgraft(char *haystack, size_t hay_size,
const char *needle, const char *new_needle)
{
char *found;
size_t needle_len = 0;
size_t new_needle_len = 0;
found = strstr(haystack, needle);
if (found == NULL)
return 0;
needle_len = strlen(needle);
new_needle_len = strlen(new_needle);
if (strlen(haystack) - needle_len + new_needle_len + 1 > hay_size)
return 1;
memmove(found + new_needle_len,
found + needle_len,
strlen(found + needle_len) + 1);
memcpy(found, new_needle, new_needle_len);
return 0;
}
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)
{
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)) {
fclose(dotd);
fclose(tmp_dotd);
return 1;
}
if (dcc_strgraft(buf, sizeof(buf),
server_out_name, client_out_name)) {
fclose(dotd);
fclose(tmp_dotd);
return 1;
}
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;
}
int dcc_get_dotd_info(char **argv, char **dotd_fname,
int *needs_dotd, int *sets_dotd_target,
char **dotd_target)
{
char *deps_output = 0;
char *input_file;
char *output_file;
char **new_args;
int has_dash_o = 0;
char *env_var = 0;
int ret;
int i;
char *a;
*needs_dotd = 0;
*sets_dotd_target = 0;
*dotd_target = NULL;
env_var = getenv("DEPENDENCIES_OUTPUT");
if (env_var != NULL) {
*needs_dotd = 1;
}
for (i = 0; (a = argv[i]); i++) {
if (strcmp(a, "-MT") == 0) {
*sets_dotd_target = 1;
++i;
continue;
}
if (strcmp(a, "-MQ") == 0) {
*sets_dotd_target = 1;
++i;
continue;
}
if (strncmp(a, "-M", 2) == 0) {
*needs_dotd = 1;
}
if (strcmp(a, "-MF") == 0) {
++i;
deps_output = argv[i];
} else if (strncmp(a, "-MF", 3) == 0) {
deps_output = argv[i] + 3;
} else if (strcmp(a, "-o") == 0) {
has_dash_o = 1;
}
}
if (deps_output) {
*dotd_fname = strdup(deps_output);
if (*dotd_fname == NULL) {
return EXIT_OUT_OF_MEMORY;
} else {
return 0;
}
}
deps_output = env_var;
if (deps_output) {
char *space;
*dotd_fname = strdup(deps_output);
if (*dotd_fname == NULL) {
return EXIT_OUT_OF_MEMORY;
}
space = strchr(*dotd_fname, ' ');
if (space != NULL) {
*space = '\0';
*dotd_target = space + 1;
}
return 0;
}
{
char *extension;
char *tmp_dotd_fname;
ret = dcc_scan_args(argv, &input_file, &output_file, &new_args, NULL);
if (ret)
return ret;
if (has_dash_o)
tmp_dotd_fname = strdup(output_file);
else
tmp_dotd_fname = strdup(input_file);
if (tmp_dotd_fname == NULL) return EXIT_OUT_OF_MEMORY;
extension = dcc_find_extension(tmp_dotd_fname);
if (extension) {
extension[1] = 'd';
extension[2] = '\0';
*dotd_fname = tmp_dotd_fname;
}
else {
if (tmp_dotd_fname[strlen(tmp_dotd_fname) - 1] == '.')
asprintf(dotd_fname, "%s%s", tmp_dotd_fname, "d");
else
asprintf(dotd_fname, "%s%s", tmp_dotd_fname, ".d");
if (*dotd_fname == NULL) {
return EXIT_OUT_OF_MEMORY;
}
free(tmp_dotd_fname);
}
if (new_args)
dcc_free_argv(new_args);
return 0;
}
}