VirtualBox

source: kBuild/trunk/src/gmake/remote-cstms.c@ 930

Last change on this file since 930 was 503, checked in by bird, 18 years ago

Untested merge with GNU Make v3.81 (vendor/gnumake/2005-05-16 -> vendor/gnumake/current).

  • Property svn:eol-style set to native
File size: 8.3 KB
Line 
1/* GNU Make remote job exportation interface to the Customs daemon.
2 THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT.
3 Please do not send bug reports or questions about it to
4 the Make maintainers.
5
6Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
71998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
8Foundation, Inc.
9This file is part of GNU Make.
10
11GNU Make is free software; you can redistribute it and/or modify it under the
12terms of the GNU General Public License as published by the Free Software
13Foundation; either version 2, or (at your option) any later version.
14
15GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License along with
20GNU Make; see the file COPYING. If not, write to the Free Software
21Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
22
23#include "make.h"
24#include "job.h"
25#include "filedef.h"
26#include "commands.h"
27#include "job.h"
28#include "debug.h"
29
30#include <sys/time.h>
31#include <netdb.h>
32
33#include "customs.h"
34
35char *remote_description = "Customs";
36
37/* File name of the Customs `export' client command.
38 A full path name can be used to avoid some path-searching overhead. */
39#define EXPORT_COMMAND "/usr/local/bin/export"
40
41/* ExportPermit gotten by start_remote_job_p, and used by start_remote_job. */
42static ExportPermit permit;
43
44/* Normalized path name of the current directory. */
45static char *normalized_cwd;
46
47/* Call once at startup even if no commands are run. */
48
49void
50remote_setup (void)
51{
52}
53
54/* Called before exit. */
55
56void
57remote_cleanup (void)
58{
59}
60
61
62/* Return nonzero if the next job should be done remotely. */
63
64int
65start_remote_job_p (int first_p)
66{
67 static int inited = 0;
68 int status;
69 int njobs;
70
71 if (!inited)
72 {
73 /* Allow the user to turn off job exportation (useful while he is
74 debugging Customs, for example). */
75 if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0)
76 {
77 inited = -1;
78 return 0;
79 }
80
81 /* For secure Customs, make is installed setuid root and
82 Customs requires a privileged source port be used. */
83 make_access ();
84
85 if (ISDB (DB_JOBS))
86 Rpc_Debug(1);
87
88 /* Ping the daemon once to see if it is there. */
89 inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1;
90
91 /* Return to normal user access. */
92 user_access ();
93
94 if (starting_directory == 0)
95 /* main couldn't figure it out. */
96 inited = -1;
97 else
98 {
99 /* Normalize the current directory path name to something
100 that should work on all machines exported to. */
101
102 normalized_cwd = (char *) xmalloc (GET_PATH_MAX);
103 strcpy (normalized_cwd, starting_directory);
104 if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0)
105 /* Path normalization failure means using Customs
106 won't work, but it's not really an error. */
107 inited = -1;
108 }
109 }
110
111 if (inited < 0)
112 return 0;
113
114 njobs = job_slots_used;
115 if (!first_p)
116 njobs -= 1; /* correction for being called from reap_children() */
117
118 /* the first job should run locally, or, if the -l flag is given, we use
119 that as clue as to how many local jobs should be scheduled locally */
120 if (max_load_average < 0 && njobs == 0 || njobs < max_load_average)
121 return 0;
122
123 status = Customs_Host (EXPORT_SAME, &permit);
124 if (status != RPC_SUCCESS)
125 {
126 DB (DB_JOBS, (_("Customs won't export: %s\n"),
127 Rpc_ErrorMessage (status)));
128 return 0;
129 }
130
131 return !CUSTOMS_FAIL (&permit.addr);
132}
133
134
135/* Start a remote job running the command in ARGV, with environment from
136 ENVP. It gets standard input from STDIN_FD. On failure, return
137 nonzero. On success, return zero, and set *USED_STDIN to nonzero if it
138 will actually use STDIN_FD, zero if not, set *ID_PTR to a unique
139 identification, and set *IS_REMOTE to nonzero if the job is remote, zero
140 if it is local (meaning *ID_PTR is a process ID). */
141
142int
143start_remote_job (char **argv, char **envp, int stdin_fd,
144 int *is_remote, int *id_ptr, int *used_stdin)
145{
146 char waybill[MAX_DATA_SIZE], msg[128];
147 struct hostent *host;
148 struct timeval timeout;
149 struct sockaddr_in sin;
150 int len;
151 int retsock, retport, sock;
152 Rpc_Stat status;
153 int pid;
154
155 /* Create the return socket. */
156 retsock = Rpc_UdpCreate (True, 0);
157 if (retsock < 0)
158 {
159 error (NILF, "exporting: Couldn't create return socket.");
160 return 1;
161 }
162
163 /* Get the return socket's port number. */
164 len = sizeof (sin);
165 if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0)
166 {
167 (void) close (retsock);
168 perror_with_name ("exporting: ", "getsockname");
169 return 1;
170 }
171 retport = sin.sin_port;
172
173 /* Create the TCP socket for talking to the remote child. */
174 sock = Rpc_TcpCreate (False, 0);
175
176 /* Create a WayBill to give to the server. */
177 len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv,
178 envp, retport, waybill);
179
180 /* Modify the waybill as if the remote child had done `child_access ()'. */
181 {
182 WayBill *wb = (WayBill *) waybill;
183 wb->ruid = wb->euid;
184 wb->rgid = wb->egid;
185 }
186
187 /* Send the request to the server, timing out in 20 seconds. */
188 timeout.tv_usec = 0;
189 timeout.tv_sec = 20;
190 sin.sin_family = AF_INET;
191 sin.sin_port = htons (Customs_Port ());
192 sin.sin_addr = permit.addr;
193 status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT,
194 len, (Rpc_Opaque) waybill,
195 sizeof(msg), (Rpc_Opaque) msg,
196 1, &timeout);
197
198 host = gethostbyaddr((char *)&permit.addr, sizeof(permit.addr), AF_INET);
199
200 if (status != RPC_SUCCESS)
201 {
202 (void) close (retsock);
203 (void) close (sock);
204 error (NILF, "exporting to %s: %s",
205 host ? host->h_name : inet_ntoa (permit.addr),
206 Rpc_ErrorMessage (status));
207 return 1;
208 }
209 else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0')
210 {
211 (void) close (retsock);
212 (void) close (sock);
213 error (NILF, "exporting to %s: %s",
214 host ? host->h_name : inet_ntoa (permit.addr),
215 msg);
216 return 1;
217 }
218 else
219 {
220 error (NILF, "*** exported to %s (id %u)",
221 host ? host->h_name : inet_ntoa (permit.addr),
222 permit.id);
223 }
224
225 fflush (stdout);
226 fflush (stderr);
227
228 pid = vfork ();
229 if (pid < 0)
230 {
231 /* The fork failed! */
232 perror_with_name ("vfork", "");
233 return 1;
234 }
235 else if (pid == 0)
236 {
237 /* Child side. Run `export' to handle the connection. */
238 static char sock_buf[20], retsock_buf[20], id_buf[20];
239 static char *new_argv[6] =
240 { EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 };
241
242 /* Set up the arguments. */
243 (void) sprintf (sock_buf, "%d", sock);
244 (void) sprintf (retsock_buf, "%d", retsock);
245 (void) sprintf (id_buf, "%x", permit.id);
246
247 /* Get the right stdin. */
248 if (stdin_fd != 0)
249 (void) dup2 (stdin_fd, 0);
250
251 /* Unblock signals in the child. */
252 unblock_sigs ();
253
254 /* Run the command. */
255 exec_command (new_argv, envp);
256 }
257
258 /* Parent side. Return the `export' process's ID. */
259 (void) close (retsock);
260 (void) close (sock);
261 *is_remote = 0;
262 *id_ptr = pid;
263 *used_stdin = 1;
264 return 0;
265}
266
267
268/* Get the status of a dead remote child. Block waiting for one to die
269 if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR
270 to the termination signal or zero if it exited normally, and *COREDUMP_PTR
271 nonzero if it dumped core. Return the ID of the child that died,
272 0 if we would have to block and !BLOCK, or < 0 if there were none. */
273
274int
275remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr,
276 int block)
277{
278 return -1;
279}
280
281/* Block asynchronous notification of remote child death.
282 If this notification is done by raising the child termination
283 signal, do not block that signal. */
284void
285block_remote_children (void)
286{
287 return;
288}
289
290/* Restore asynchronous notification of remote child death.
291 If this is done by raising the child termination signal,
292 do not unblock that signal. */
293void
294unblock_remote_children (void)
295{
296 return;
297}
298
299/* Send signal SIG to child ID. Return 0 if successful, -1 if not. */
300int
301remote_kill (int id, int sig)
302{
303 return -1;
304}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette