1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
*
* distcc -- A simple distributed compiler system
*
* Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* And the magicians did so with their enchantments,
* and brought up frogs upon the land of Egypt.
* -- Exodus 8:7
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "distcc.h"
#include "util.h"
#include "trace.h"
#include "exitcode.h"
/**
* For masquerade mode, change the path to remove the directory containing the
* distcc mask, so that invoking the same name will find the underlying
* compiler instead.
*
* @param progname basename under which distcc was introduced. If we reached
* this point, then it's the same as the name of the real compiler, e.g. "cc".
*
* @param did_masquerade specifies an integer that will be set to 1 if the
* path was changed.
*
* @return 0 or standard error.
**/
int dcc_support_masquerade(char *argv[], char *progname, int *did_masquerade)
{
const char *envpath, *findpath, *p, *n;
char *buf;
size_t len;
size_t findlen;
if (!(envpath = getenv("PATH")))
/* strange but true*/
return 0;
if (!(buf = malloc(strlen(envpath)+1+strlen(progname)+1))) {
rs_log_error("failed to allocate buffer for new PATH");
return EXIT_OUT_OF_MEMORY;
}
/* Filter PATH to contain only the part that is past our dir.
* If we were called explicitly, find the named dir on the PATH. */
if (progname != argv[0]) {
findpath = dcc_abspath(argv[0], progname - argv[0] - 1);
findlen = strlen(findpath);
} else {
findpath = NULL;
findlen = 0;
}
for (n = p = envpath; *n; p = n) {
/* Find the length of this component of the path */
n = strchr(p, ':');
if (n)
len = n++ - p;
else {
len = strlen(p);
n = p + len;
}
if (findpath) {
/* Looking for a component in the path equal to findpath */
/* FIXME: This won't catch paths that are in fact the same, but
* that are not the same string. This might happen if you have
* multiple slashes, or dots, or symlinks... */
if (len != findlen || strncmp(p, findpath, findlen) != 0)
continue;
} else {
/* Looking for a component in the path containing a file
* progname. */
/* FIXME: This gets a false match if you have a subdirectory that
* happens to be of the right name, e.g. /usr/bin/distcc... */
strncpy(buf, p, (size_t) len);
sprintf(buf + len, "/%s", progname);
if (access(buf, X_OK) != 0)
continue;
}
/* Set p to the part of the path past our match. */
p = n;
break;
}
if (*p != '\0') {
int ret = dcc_set_path(p);
if (ret)
return ret;
*did_masquerade = 1;
}
else {
rs_trace("not modifying PATH");
*did_masquerade = 0;
}
free(buf);
return 0;
}
|