source: trunk/third/gmake/remote-cstms.c @ 15972

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