Annotation of src/usr.bin/make/job.c, Revision 1.383
1.383 ! rillig 1: /* $NetBSD: job.c,v 1.382 2020/12/12 12:54:58 rillig Exp $ */
1.10 christos 2:
1.1 cgd 3: /*
4: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
1.82 agc 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Adam de Boor.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: /*
1.1 cgd 36: * Copyright (c) 1988, 1989 by Adam de Boor
37: * Copyright (c) 1989 by Berkeley Softworks
38: * All rights reserved.
39: *
40: * This code is derived from software contributed to Berkeley by
41: * Adam de Boor.
42: *
43: * Redistribution and use in source and binary forms, with or without
44: * modification, are permitted provided that the following conditions
45: * are met:
46: * 1. Redistributions of source code must retain the above copyright
47: * notice, this list of conditions and the following disclaimer.
48: * 2. Redistributions in binary form must reproduce the above copyright
49: * notice, this list of conditions and the following disclaimer in the
50: * documentation and/or other materials provided with the distribution.
51: * 3. All advertising materials mentioning features or use of this software
52: * must display the following acknowledgement:
53: * This product includes software developed by the University of
54: * California, Berkeley and its contributors.
55: * 4. Neither the name of the University nor the names of its contributors
56: * may be used to endorse or promote products derived from this software
57: * without specific prior written permission.
58: *
59: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69: * SUCH DAMAGE.
70: */
71:
72: /*-
73: * job.c --
74: * handle the creation etc. of our child processes.
75: *
76: * Interface:
1.278 rillig 77: * Job_Init Called to initialize this module. In addition,
78: * any commands attached to the .BEGIN target
79: * are executed before this function returns.
80: * Hence, the makefiles must have been parsed
81: * before this function is called.
82: *
83: * Job_End Clean up any memory used.
84: *
1.246 rillig 85: * Job_Make Start the creation of the given target.
1.1 cgd 86: *
1.246 rillig 87: * Job_CatchChildren
88: * Check for and handle the termination of any
89: * children. This must be called reasonably
90: * frequently to keep the whole make going at
91: * a decent clip, since job table entries aren't
92: * removed until their process is caught this way.
93: *
94: * Job_CatchOutput
95: * Print any output our children have produced.
96: * Should also be called fairly frequently to
97: * keep the user informed of what's going on.
98: * If no output is waiting, it will block for
99: * a time given by the SEL_* constants, below,
100: * or until output is ready.
101: *
102: * Job_ParseShell Given the line following a .SHELL target, parse
103: * the line as a shell specification. Returns
104: * FALSE if the spec was incorrect.
105: *
106: * Job_Finish Perform any final processing which needs doing.
107: * This includes the execution of any commands
108: * which have been/were attached to the .END
109: * target. It should only be called when the
110: * job table is empty.
111: *
112: * Job_AbortAll Abort all currently running jobs. It doesn't
113: * handle output or do anything for the jobs,
114: * just kills them. It should only be called in
1.278 rillig 115: * an emergency.
1.246 rillig 116: *
117: * Job_CheckCommands
118: * Verify that the commands for a target are
119: * ok. Provide them if necessary and possible.
1.1 cgd 120: *
1.246 rillig 121: * Job_Touch Update a target without really updating it.
1.1 cgd 122: *
1.246 rillig 123: * Job_Wait Wait for all currently-running jobs to finish.
1.1 cgd 124: */
125:
1.5 cgd 126: #include <sys/types.h>
1.1 cgd 127: #include <sys/stat.h>
128: #include <sys/file.h>
129: #include <sys/time.h>
130: #include <sys/wait.h>
1.72 wiz 131:
132: #include <errno.h>
1.35 christos 133: #ifndef USE_SELECT
134: #include <poll.h>
135: #endif
1.72 wiz 136: #include <signal.h>
137: #include <utime.h>
138:
1.5 cgd 139: #include "make.h"
140: #include "dir.h"
1.1 cgd 141: #include "job.h"
142: #include "pathnames.h"
1.40 sommerfe 143: #include "trace.h"
1.232 rillig 144:
145: /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
1.383 ! rillig 146: MAKE_RCSID("$NetBSD: job.c,v 1.382 2020/12/12 12:54:58 rillig Exp $");
1.1 cgd 147:
1.341 rillig 148: /*
149: * A shell defines how the commands are run. All commands for a target are
1.275 rillig 150: * written into a single file, which is then given to the shell to execute
151: * the commands from it. The commands are written to the file using a few
152: * templates for echo control and error control.
153: *
154: * The name of the shell is the basename for the predefined shells, such as
155: * "sh", "csh", "bash". For custom shells, it is the full pathname, and its
156: * basename is used to select the type of shell; the longest match wins.
157: * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh.
158: *
159: * The echoing of command lines is controlled using hasEchoCtl, echoOff,
160: * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it
161: * still outputs something, but this something is not interesting, therefore
162: * it is filtered out using noPrint and noPrintLen.
163: *
164: * The error checking for individual commands is controlled using hasErrCtl,
1.364 rillig 165: * errOn, errOff and runChkTmpl.
1.275 rillig 166: *
1.364 rillig 167: * If a shell doesn't have error control, echoTmpl becomes a printf template
168: * for echoing the command, should echoing be on; runIgnTmpl becomes
1.276 rillig 169: * another printf template for executing the command while ignoring the return
1.364 rillig 170: * status. Finally runChkTmpl is a printf template for running the command and
1.275 rillig 171: * causing the shell to exit on error. If any of these strings are empty when
1.276 rillig 172: * hasErrCtl is FALSE, the command will be executed anyway as is, and if it
1.319 rillig 173: * causes an error, so be it. Any templates set up to echo the command will
1.275 rillig 174: * escape any '$ ` \ "' characters in the command string to avoid common
175: * problems with echo "%s\n" as a template.
176: *
177: * The command-line flags "echo" and "exit" also control the behavior. The
178: * "echo" flag causes the shell to start echoing commands right away. The
179: * "exit" flag causes the shell to exit when an error is detected in one of
180: * the commands.
1.266 rillig 181: */
182: typedef struct Shell {
1.272 rillig 183:
1.341 rillig 184: /*
185: * The name of the shell. For Bourne and C shells, this is used only
186: * to find the shell description when used as the single source of a
187: * .SHELL target. For user-defined shells, this is the full path of
188: * the shell.
189: */
190: const char *name;
191:
1.375 rillig 192: Boolean hasEchoCtl; /* whether both echoOff and echoOn are there */
1.365 rillig 193: const char *echoOff; /* command to turn echoing off */
194: const char *echoOn; /* command to turn echoing back on */
1.375 rillig 195: const char *noPrint; /* text to skip when printing output from the
1.272 rillig 196: * shell. This is usually the same as echoOff */
1.341 rillig 197: size_t noPrintLen; /* length of noPrint command */
1.272 rillig 198:
1.375 rillig 199: Boolean hasErrCtl; /* whether error checking can be controlled
200: * for individual commands */
1.359 rillig 201: const char *errOn; /* command to turn on error checking */
202: const char *errOff; /* command to turn off error checking */
1.364 rillig 203:
204: const char *echoTmpl; /* template to echo a command */
205: const char *runIgnTmpl; /* template to run a command
206: * without error checking */
207: const char *runChkTmpl; /* template to run a command
208: * with error checking */
1.266 rillig 209:
1.341 rillig 210: /* string literal that results in a newline character when it appears
211: * outside of any 'quote' or "quote" characters */
212: const char *newline;
213: char commentChar; /* character used by shell for comment lines */
214:
1.366 rillig 215: const char *echoFlag; /* shell flag to echo commands */
1.375 rillig 216: const char *errFlag; /* shell flag to exit on error */
1.266 rillig 217: } Shell;
218:
1.360 rillig 219: typedef struct CommandFlags {
1.350 rillig 220: /* Whether to echo the command before running it. */
221: Boolean echo;
1.348 rillig 222:
1.360 rillig 223: /* Run the command even in -n or -N mode. */
1.348 rillig 224: Boolean always;
1.349 rillig 225:
226: /*
227: * true if we turned error checking off before printing the command
228: * and need to turn it back on
229: */
230: Boolean ignerr;
1.360 rillig 231: } CommandFlags;
1.347 rillig 232:
1.1 cgd 233: /*
1.371 rillig 234: * Write shell commands to a file.
235: *
236: * TODO: keep track of whether commands are echoed.
237: * TODO: keep track of whether error checking is active.
238: */
239: typedef struct ShellWriter {
240: FILE *f;
1.374 rillig 241:
242: /* we've sent 'set -x' */
243: Boolean xtraced;
244:
1.371 rillig 245: } ShellWriter;
246:
247: /*
1.16 christos 248: * error handling variables
1.1 cgd 249: */
1.331 rillig 250: static int job_errors = 0; /* number of errors reported */
1.283 rillig 251: typedef enum AbortReason { /* why is the make aborting? */
1.341 rillig 252: ABORT_NONE,
253: ABORT_ERROR, /* Because of an error */
254: ABORT_INTERRUPT, /* Because it was interrupted */
255: ABORT_WAIT /* Waiting for jobs to finish */
1.283 rillig 256: } AbortReason;
257: static AbortReason aborting = ABORT_NONE;
1.341 rillig 258: #define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
1.1 cgd 259:
1.16 christos 260: /*
1.103 dsl 261: * this tracks the number of tokens currently "out" to build jobs.
262: */
263: int jobTokensRunning = 0;
264:
1.284 rillig 265: typedef enum JobStartResult {
1.341 rillig 266: JOB_RUNNING, /* Job is running */
267: JOB_ERROR, /* Error in starting the job */
268: JOB_FINISHED /* The job is already finished */
1.284 rillig 269: } JobStartResult;
1.1 cgd 270:
271: /*
272: * Descriptions for various shells.
1.121 apb 273: *
1.133 apb 274: * The build environment may set DEFSHELL_INDEX to one of
275: * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
1.243 rillig 276: * select one of the predefined shells as the default shell.
1.133 apb 277: *
278: * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
279: * name or the full path of a sh-compatible shell, which will be used as
280: * the default shell.
281: *
282: * ".SHELL" lines in Makefiles can choose the default shell from the
1.289 rillig 283: * set defined here, or add additional shells.
1.133 apb 284: */
285:
286: #ifdef DEFSHELL_CUSTOM
287: #define DEFSHELL_INDEX_CUSTOM 0
288: #define DEFSHELL_INDEX_SH 1
289: #define DEFSHELL_INDEX_KSH 2
290: #define DEFSHELL_INDEX_CSH 3
291: #else /* !DEFSHELL_CUSTOM */
292: #define DEFSHELL_INDEX_SH 0
293: #define DEFSHELL_INDEX_KSH 1
294: #define DEFSHELL_INDEX_CSH 2
295: #endif /* !DEFSHELL_CUSTOM */
296:
297: #ifndef DEFSHELL_INDEX
298: #define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
299: #endif /* !DEFSHELL_INDEX */
300:
1.341 rillig 301: static Shell shells[] = {
1.133 apb 302: #ifdef DEFSHELL_CUSTOM
1.1 cgd 303: /*
1.121 apb 304: * An sh-compatible shell with a non-standard name.
305: *
306: * Keep this in sync with the "sh" description below, but avoid
307: * non-portable features that might not be supplied by all
308: * sh-compatible shells.
1.1 cgd 309: */
1.341 rillig 310: {
311: DEFSHELL_CUSTOM, /* .name */
312: FALSE, /* .hasEchoCtl */
313: "", /* .echoOff */
314: "", /* .echoOn */
315: "", /* .noPrint */
316: 0, /* .noPrintLen */
317: FALSE, /* .hasErrCtl */
1.358 rillig 318: "", /* .errOn */
1.359 rillig 319: "", /* .errOff */
1.364 rillig 320: "echo \"%s\"\n", /* .echoTmpl */
321: "%s\n", /* .runIgnTmpl */
322: "{ %s \n} || exit $?\n", /* .runChkTmpl */
1.341 rillig 323: "'\n'", /* .newline */
324: '#', /* .commentChar */
1.375 rillig 325: "", /* .echoFlag */
326: "", /* .errFlag */
1.341 rillig 327: },
1.133 apb 328: #endif /* DEFSHELL_CUSTOM */
1.1 cgd 329: /*
330: * SH description. Echo control is also possible and, under
331: * sun UNIX anyway, one can even control error checking.
332: */
1.341 rillig 333: {
334: "sh", /* .name */
335: FALSE, /* .hasEchoCtl */
336: "", /* .echoOff */
337: "", /* .echoOn */
338: "", /* .noPrint */
339: 0, /* .noPrintLen */
340: FALSE, /* .hasErrCtl */
1.358 rillig 341: "", /* .errOn */
1.359 rillig 342: "", /* .errOff */
1.364 rillig 343: "echo \"%s\"\n", /* .echoTmpl */
344: "%s\n", /* .runIgnTmpl */
345: "{ %s \n} || exit $?\n", /* .runChkTmpl */
1.341 rillig 346: "'\n'", /* .newline */
347: '#', /* .commentChar*/
1.121 apb 348: #if defined(MAKE_NATIVE) && defined(__NetBSD__)
1.375 rillig 349: /* XXX: -q is not really echoFlag, it's more like noEchoInSysFlag. */
350: "q", /* .echoFlag */
1.27 christos 351: #else
1.375 rillig 352: "", /* .echoFlag */
1.27 christos 353: #endif
1.375 rillig 354: "", /* .errFlag */
1.341 rillig 355: },
1.1 cgd 356: /*
1.201 rillig 357: * KSH description.
1.81 sjg 358: */
1.341 rillig 359: {
360: "ksh", /* .name */
361: TRUE, /* .hasEchoCtl */
362: "set +v", /* .echoOff */
363: "set -v", /* .echoOn */
364: "set +v", /* .noPrint */
365: 6, /* .noPrintLen */
366: FALSE, /* .hasErrCtl */
1.358 rillig 367: "", /* .errOn */
1.359 rillig 368: "", /* .errOff */
1.364 rillig 369: "echo \"%s\"\n", /* .echoTmpl */
370: "%s\n", /* .runIgnTmpl */
371: "{ %s \n} || exit $?\n", /* .runChkTmpl */
1.341 rillig 372: "'\n'", /* .newline */
373: '#', /* .commentChar */
1.375 rillig 374: "v", /* .echoFlag */
375: "", /* .errFlag */
1.341 rillig 376: },
1.81 sjg 377: /*
1.121 apb 378: * CSH description. The csh can do echo control by playing
379: * with the setting of the 'echo' shell variable. Sadly,
380: * however, it is unable to do error control nicely.
381: */
1.341 rillig 382: {
383: "csh", /* .name */
384: TRUE, /* .hasEchoCtl */
385: "unset verbose", /* .echoOff */
386: "set verbose", /* .echoOn */
387: "unset verbose", /* .noPrint */
388: 13, /* .noPrintLen */
389: FALSE, /* .hasErrCtl */
1.358 rillig 390: "", /* .errOn */
1.359 rillig 391: "", /* .errOff */
1.364 rillig 392: "echo \"%s\"\n", /* .echoTmpl */
393: "csh -c \"%s || exit 0\"\n", /* .runIgnTmpl */
394: "", /* .runChkTmpl */
1.341 rillig 395: "'\\\n'", /* .newline */
396: '#', /* .commentChar */
1.375 rillig 397: "v", /* .echoFlag */
398: "e", /* .errFlag */
1.341 rillig 399: }
1.1 cgd 400: };
1.243 rillig 401:
402: /* This is the shell to which we pass all commands in the Makefile.
403: * It is set by the Job_ParseShell function. */
1.355 rillig 404: static Shell *shell = &shells[DEFSHELL_INDEX];
1.243 rillig 405: const char *shellPath = NULL; /* full pathname of executable image */
406: const char *shellName = NULL; /* last component of shellPath */
1.174 sjg 407: char *shellErrFlag = NULL;
1.209 rillig 408: static char *shellArgv = NULL; /* Custom shell args */
1.1 cgd 409:
410:
1.285 rillig 411: static Job *job_table; /* The structures that describe them */
412: static Job *job_table_end; /* job_table + maxJobs */
1.261 rillig 413: static unsigned int wantToken; /* we want a token */
1.316 rillig 414: static Boolean lurking_children = FALSE;
1.341 rillig 415: static Boolean make_suspended = FALSE; /* Whether we've seen a SIGTSTP (etc) */
1.40 sommerfe 416:
1.35 christos 417: /*
418: * Set of descriptors of pipes connected to
419: * the output channels of children
420: */
421: static struct pollfd *fds = NULL;
1.330 rillig 422: static Job **allJobs = NULL;
423: static nfds_t nJobs = 0;
1.72 wiz 424: static void watchfd(Job *);
425: static void clearfd(Job *);
426: static int readyfd(Job *);
1.1 cgd 427:
1.339 rillig 428: static char *targPrefix = NULL; /* To identify a job change in the output. */
1.40 sommerfe 429: static Job tokenWaitJob; /* token wait pseudo-job */
1.12 christos 430:
1.73 gson 431: static Job childExitJob; /* child exit pseudo-job */
1.341 rillig 432: #define CHILD_EXIT "."
433: #define DO_JOB_RESUME "R"
1.73 gson 434:
1.341 rillig 435: enum {
436: npseudojobs = 2 /* number of pseudo-jobs */
437: };
1.196 riastrad 438:
1.104 dsl 439: static sigset_t caught_signals; /* Set of signals we handle */
1.1 cgd 440:
1.72 wiz 441: static void JobDoOutput(Job *, Boolean);
1.162 joerg 442: static void JobInterrupt(int, int) MAKE_ATTR_DEAD;
1.72 wiz 443: static void JobRestartJobs(void);
1.69 pk 444: static void JobSigReset(void);
445:
1.339 rillig 446: static void
1.340 rillig 447: SwitchOutputTo(GNode *gn)
1.339 rillig 448: {
1.340 rillig 449: /* The node for which output was most recently produced. */
450: static GNode *lastNode = NULL;
451:
452: if (gn == lastNode)
453: return;
454: lastNode = gn;
455:
1.339 rillig 456: if (opts.maxJobs != 1 && targPrefix != NULL && targPrefix[0] != '\0')
457: (void)fprintf(stdout, "%s %s ---\n", targPrefix, gn->name);
458: }
459:
1.196 riastrad 460: static unsigned
461: nfds_per_job(void)
462: {
1.197 sjg 463: #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
1.341 rillig 464: if (useMeta)
465: return 2;
1.196 riastrad 466: #endif
1.341 rillig 467: return 1;
1.196 riastrad 468: }
469:
1.354 rillig 470: void
1.356 rillig 471: Job_FlagsToString(const Job *job, char *buf, size_t bufsize)
1.354 rillig 472: {
1.374 rillig 473: snprintf(buf, bufsize, "%c%c%c",
1.356 rillig 474: job->ignerr ? 'i' : '-',
1.357 rillig 475: !job->echo ? 's' : '-',
1.374 rillig 476: job->special ? 'S' : '-');
1.354 rillig 477: }
478:
1.114 dsl 479: static void
480: job_table_dump(const char *where)
481: {
1.341 rillig 482: Job *job;
1.374 rillig 483: char flags[4];
1.114 dsl 484:
1.341 rillig 485: debug_printf("job table @ %s\n", where);
486: for (job = job_table; job < job_table_end; job++) {
1.356 rillig 487: Job_FlagsToString(job, flags, sizeof flags);
1.354 rillig 488: debug_printf("job %d, status %d, flags %s, pid %d\n",
489: (int)(job - job_table), job->status, flags, job->pid);
1.341 rillig 490: }
1.114 dsl 491: }
1.69 pk 492:
493: /*
1.188 dholland 494: * Delete the target of a failed, interrupted, or otherwise
495: * unsuccessful job unless inhibited by .PRECIOUS.
496: */
497: static void
498: JobDeleteTarget(GNode *gn)
499: {
1.341 rillig 500: const char *file;
501:
502: if (gn->type & OP_JOIN)
503: return;
504: if (gn->type & OP_PHONY)
505: return;
506: if (Targ_Precious(gn))
507: return;
508: if (opts.noExecute)
509: return;
1.287 rillig 510:
1.341 rillig 511: file = GNode_Path(gn);
512: if (eunlink(file) != -1)
513: Error("*** %s removed", file);
1.188 dholland 514: }
515:
516: /*
1.69 pk 517: * JobSigLock/JobSigUnlock
518: *
519: * Signal lock routines to get exclusive access. Currently used to
520: * protect `jobs' and `stoppedJobs' list manipulations.
521: */
1.72 wiz 522: static void JobSigLock(sigset_t *omaskp)
1.69 pk 523: {
524: if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) {
525: Punt("JobSigLock: sigprocmask: %s", strerror(errno));
1.104 dsl 526: sigemptyset(omaskp);
1.69 pk 527: }
528: }
529:
1.72 wiz 530: static void JobSigUnlock(sigset_t *omaskp)
1.69 pk 531: {
1.96 christos 532: (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
1.69 pk 533: }
1.1 cgd 534:
1.122 dsl 535: static void
536: JobCreatePipe(Job *job, int minfd)
537: {
1.341 rillig 538: int i, fd, flags;
539: int pipe_fds[2];
1.122 dsl 540:
1.341 rillig 541: if (pipe(pipe_fds) == -1)
542: Punt("Cannot create pipe: %s", strerror(errno));
1.122 dsl 543:
1.341 rillig 544: for (i = 0; i < 2; i++) {
545: /* Avoid using low numbered fds */
546: fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
547: if (fd != -1) {
548: close(pipe_fds[i]);
549: pipe_fds[i] = fd;
550: }
1.247 rillig 551: }
1.201 rillig 552:
1.341 rillig 553: job->inPipe = pipe_fds[0];
554: job->outPipe = pipe_fds[1];
1.249 rillig 555:
1.341 rillig 556: /* Set close-on-exec flag for both */
557: if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
558: Punt("Cannot set close-on-exec: %s", strerror(errno));
559: if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
560: Punt("Cannot set close-on-exec: %s", strerror(errno));
561:
562: /*
563: * We mark the input side of the pipe non-blocking; we poll(2) the
564: * pipe when we're waiting for a job token, but we might lose the
565: * race for the token when a new one becomes available, so the read
566: * from the pipe should not block.
567: */
568: flags = fcntl(job->inPipe, F_GETFL, 0);
569: if (flags == -1)
570: Punt("Cannot get flags: %s", strerror(errno));
571: flags |= O_NONBLOCK;
572: if (fcntl(job->inPipe, F_SETFL, flags) == -1)
573: Punt("Cannot set flags: %s", strerror(errno));
1.122 dsl 574: }
575:
1.243 rillig 576: /* Pass the signal to each running job. */
1.114 dsl 577: static void
578: JobCondPassSig(int signo)
1.1 cgd 579: {
1.341 rillig 580: Job *job;
1.106 dsl 581:
1.341 rillig 582: DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo);
1.116 dsl 583:
1.341 rillig 584: for (job = job_table; job < job_table_end; job++) {
585: if (job->status != JOB_ST_RUNNING)
586: continue;
587: DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n",
588: signo, job->pid);
589: KILLPG(job->pid, signo);
590: }
1.1 cgd 591: }
592:
1.341 rillig 593: /*
594: * SIGCHLD handler.
1.37 sommerfe 595: *
1.341 rillig 596: * Sends a token on the child exit pipe to wake us up from select()/poll().
597: */
1.37 sommerfe 598: static void
1.162 joerg 599: JobChildSig(int signo MAKE_ATTR_UNUSED)
1.37 sommerfe 600: {
1.341 rillig 601: while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 &&
602: errno == EAGAIN)
603: continue;
1.37 sommerfe 604: }
605:
606:
1.243 rillig 607: /* Resume all stopped jobs. */
1.47 sommerfe 608: static void
1.162 joerg 609: JobContinueSig(int signo MAKE_ATTR_UNUSED)
1.47 sommerfe 610: {
1.341 rillig 611: /*
612: * Defer sending SIGCONT to our stopped children until we return
613: * from the signal handler.
614: */
615: while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
616: errno == EAGAIN)
617: continue;
1.47 sommerfe 618: }
1.37 sommerfe 619:
1.341 rillig 620: /*
621: * Pass a signal on to all jobs, then resend to ourselves.
622: * We die by the same signal.
623: */
1.162 joerg 624: MAKE_ATTR_DEAD static void
1.116 dsl 625: JobPassSig_int(int signo)
626: {
1.341 rillig 627: /* Run .INTERRUPT target then exit */
628: JobInterrupt(TRUE, signo);
1.116 dsl 629: }
630:
1.341 rillig 631: /*
632: * Pass a signal on to all jobs, then resend to ourselves.
633: * We die by the same signal.
634: */
1.162 joerg 635: MAKE_ATTR_DEAD static void
1.116 dsl 636: JobPassSig_term(int signo)
637: {
1.341 rillig 638: /* Dont run .INTERRUPT target then exit */
639: JobInterrupt(FALSE, signo);
1.116 dsl 640: }
641:
642: static void
643: JobPassSig_suspend(int signo)
1.1 cgd 644: {
1.341 rillig 645: sigset_t nmask, omask;
646: struct sigaction act;
1.118 dsl 647:
1.341 rillig 648: /* Suppress job started/continued messages */
649: make_suspended = TRUE;
1.16 christos 650:
1.341 rillig 651: /* Pass the signal onto every job */
652: JobCondPassSig(signo);
1.1 cgd 653:
1.341 rillig 654: /*
655: * Send ourselves the signal now we've given the message to everyone
656: * else. Note we block everything else possible while we're getting
657: * the signal. This ensures that all our jobs get continued when we
658: * wake up before we take any other signal.
659: */
660: sigfillset(&nmask);
661: sigdelset(&nmask, signo);
662: (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
663:
664: act.sa_handler = SIG_DFL;
665: sigemptyset(&act.sa_mask);
666: act.sa_flags = 0;
667: (void)sigaction(signo, &act, NULL);
1.13 christos 668:
1.343 rillig 669: DEBUG1(JOB, "JobPassSig passing signal %d to self.\n", signo);
1.1 cgd 670:
1.341 rillig 671: (void)kill(getpid(), signo);
1.115 dsl 672:
1.341 rillig 673: /*
674: * We've been continued.
675: *
676: * A whole host of signals continue to happen!
677: * SIGCHLD for any processes that actually suspended themselves.
678: * SIGCHLD for any processes that exited while we were alseep.
679: * The SIGCONT that actually caused us to wakeup.
680: *
681: * Since we defer passing the SIGCONT on to our children until
682: * the main processing loop, we can be sure that all the SIGCHLD
683: * events will have happened by then - and that the waitpid() will
684: * collect the child 'suspended' events.
685: * For correct sequencing we just need to ensure we process the
686: * waitpid() before passing on the SIGCONT.
687: *
688: * In any case nothing else is needed here.
689: */
1.1 cgd 690:
1.341 rillig 691: /* Restore handler and signal mask */
692: act.sa_handler = JobPassSig_suspend;
693: (void)sigaction(signo, &act, NULL);
694: (void)sigprocmask(SIG_SETMASK, &omask, NULL);
1.1 cgd 695: }
696:
1.114 dsl 697: static Job *
1.317 rillig 698: JobFindPid(int pid, JobStatus status, Boolean isJobs)
1.1 cgd 699: {
1.341 rillig 700: Job *job;
1.114 dsl 701:
1.341 rillig 702: for (job = job_table; job < job_table_end; job++) {
703: if (job->status == status && job->pid == pid)
704: return job;
705: }
706: if (DEBUG(JOB) && isJobs)
707: job_table_dump("no pid");
708: return NULL;
1.12 christos 709: }
710:
1.298 rillig 711: /* Parse leading '@', '-' and '+', which control the exact execution mode. */
712: static void
1.383 ! rillig 713: ParseCommandFlags(char **pp, CommandFlags *out_cmdFlags)
1.341 rillig 714: {
715: char *p = *pp;
1.360 rillig 716: out_cmdFlags->echo = TRUE;
717: out_cmdFlags->ignerr = FALSE;
718: out_cmdFlags->always = FALSE;
1.341 rillig 719:
720: for (;;) {
721: if (*p == '@')
1.360 rillig 722: out_cmdFlags->echo = DEBUG(LOUD);
1.341 rillig 723: else if (*p == '-')
1.360 rillig 724: out_cmdFlags->ignerr = TRUE;
1.341 rillig 725: else if (*p == '+')
1.360 rillig 726: out_cmdFlags->always = TRUE;
1.341 rillig 727: else
728: break;
729: p++;
730: }
1.298 rillig 731:
1.341 rillig 732: pp_skip_whitespace(&p);
1.298 rillig 733:
1.341 rillig 734: *pp = p;
1.298 rillig 735: }
736:
1.299 rillig 737: /* Escape a string for a double-quoted string literal in sh, csh and ksh. */
738: static char *
739: EscapeShellDblQuot(const char *cmd)
740: {
1.341 rillig 741: size_t i, j;
1.299 rillig 742:
1.341 rillig 743: /* Worst that could happen is every char needs escaping. */
744: char *esc = bmake_malloc(strlen(cmd) * 2 + 1);
745: for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) {
746: if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' ||
747: cmd[i] == '"')
748: esc[j++] = '\\';
749: esc[j] = cmd[i];
750: }
751: esc[j] = '\0';
1.299 rillig 752:
1.341 rillig 753: return esc;
1.299 rillig 754: }
755:
1.318 rillig 756: static void
1.371 rillig 757: ShellWriter_PrintFmt(ShellWriter *wr, const char *fmt, const char *arg)
1.318 rillig 758: {
1.343 rillig 759: DEBUG1(JOB, fmt, arg);
1.318 rillig 760:
1.371 rillig 761: (void)fprintf(wr->f, fmt, arg);
762: /* XXX: Is flushing needed in any case, or only if f == stdout? */
763: (void)fflush(wr->f);
764: }
765:
766: static void
767: ShellWriter_Println(ShellWriter *wr, const char *line)
1.318 rillig 768: {
1.371 rillig 769: ShellWriter_PrintFmt(wr, "%s\n", line);
1.318 rillig 770: }
771:
1.373 rillig 772: static void
773: ShellWriter_EchoOff(ShellWriter *wr)
774: {
775: if (shell->hasEchoCtl)
776: ShellWriter_Println(wr, shell->echoOff);
777: }
778:
779: static void
780: ShellWriter_EchoCmd(ShellWriter *wr, const char *escCmd)
781: {
1.376 rillig 782: ShellWriter_PrintFmt(wr, shell->echoTmpl, escCmd);
1.373 rillig 783: }
784:
785: static void
786: ShellWriter_EchoOn(ShellWriter *wr)
787: {
788: if (shell->hasEchoCtl)
789: ShellWriter_Println(wr, shell->echoOn);
790: }
791:
1.374 rillig 792: static void
793: ShellWriter_TraceOn(ShellWriter *wr)
794: {
795: if (!wr->xtraced) {
796: ShellWriter_Println(wr, "set -x");
797: wr->xtraced = TRUE;
798: }
799: }
800:
1.346 rillig 801: static void
1.373 rillig 802: ShellWriter_ErrOff(ShellWriter *wr, Boolean echo)
1.346 rillig 803: {
1.382 rillig 804: if (echo)
1.373 rillig 805: ShellWriter_EchoOff(wr);
1.382 rillig 806: ShellWriter_Println(wr, shell->errOff);
807: if (echo)
808: ShellWriter_EchoOn(wr);
809: }
810:
811: static void
812: ShellWriter_ErrOn(ShellWriter *wr, Boolean echo)
813: {
814: if (echo)
815: ShellWriter_EchoOff(wr);
816: ShellWriter_Println(wr, shell->errOn);
817: if (echo)
1.373 rillig 818: ShellWriter_EchoOn(wr);
1.346 rillig 819: }
820:
821: /*
822: * The shell has no error control, so we need to be weird to get it to
823: * ignore any errors from the command. If echoing is turned on, we turn it
1.364 rillig 824: * off and use the echoTmpl template to echo the command. Leave echoing
1.346 rillig 825: * off so the user doesn't see the weirdness we go through to ignore errors.
826: * Set cmdTemplate to use the weirdness instead of the simple "%s\n" template.
827: */
828: static void
1.371 rillig 829: JobPrintSpecialsEchoCtl(Job *job, ShellWriter *wr, CommandFlags *inout_cmdFlags,
1.360 rillig 830: const char *escCmd, const char **inout_cmdTemplate)
1.346 rillig 831: {
1.372 rillig 832: /* XXX: Why is the job modified at this point? */
1.356 rillig 833: job->ignerr = TRUE;
1.346 rillig 834:
1.360 rillig 835: if (job->echo && inout_cmdFlags->echo) {
1.373 rillig 836: ShellWriter_EchoOff(wr);
837: ShellWriter_EchoCmd(wr, escCmd);
1.360 rillig 838: inout_cmdFlags->echo = FALSE;
1.346 rillig 839: } else {
1.360 rillig 840: if (inout_cmdFlags->echo)
1.373 rillig 841: ShellWriter_EchoCmd(wr, escCmd);
1.346 rillig 842: }
1.364 rillig 843: *inout_cmdTemplate = shell->runIgnTmpl;
1.346 rillig 844:
845: /*
1.364 rillig 846: * The template runIgnTmpl already takes care of ignoring errors,
847: * so pretend error checking is still on.
848: * XXX: What effects does this have, and why is it necessary?
1.346 rillig 849: */
1.360 rillig 850: inout_cmdFlags->ignerr = FALSE;
1.346 rillig 851: }
852:
1.345 rillig 853: static void
1.371 rillig 854: JobPrintSpecials(Job *job, ShellWriter *wr, const char *escCmd, Boolean run,
1.370 rillig 855: CommandFlags *inout_cmdFlags, const char **inout_cmdTemplate)
1.345 rillig 856: {
1.351 rillig 857: if (!run)
1.360 rillig 858: inout_cmdFlags->ignerr = FALSE;
1.355 rillig 859: else if (shell->hasErrCtl)
1.373 rillig 860: ShellWriter_ErrOff(wr, job->echo && inout_cmdFlags->echo);
1.364 rillig 861: else if (shell->runIgnTmpl != NULL && shell->runIgnTmpl[0] != '\0') {
1.371 rillig 862: JobPrintSpecialsEchoCtl(job, wr, inout_cmdFlags, escCmd,
1.349 rillig 863: inout_cmdTemplate);
1.346 rillig 864: } else
1.360 rillig 865: inout_cmdFlags->ignerr = FALSE;
1.345 rillig 866: }
867:
1.338 rillig 868: /*
1.358 rillig 869: * Put out another command for the given job.
1.72 wiz 870: *
1.358 rillig 871: * If the command starts with '@' and neither the -s nor the -n flag was
872: * given to make, we stick a shell-specific echoOff command in the script.
873: *
874: * If the command starts with '-' and the shell has no error control (none
875: * of the predefined shells has that), we ignore errors for the entire job.
876: * XXX: Why ignore errors for the entire job?
877: * XXX: Even ignore errors for the commands before this command?
878: *
1.363 rillig 879: * If the command is just "...", all further commands of this job are skipped
880: * for now. They are attached to the .END node and will be run by Job_Finish
881: * after all other targets have been made.
1.1 cgd 882: */
1.270 rillig 883: static void
1.371 rillig 884: JobPrintCommand(Job *job, ShellWriter *wr, const char *ucmd)
1.1 cgd 885: {
1.351 rillig 886: Boolean run;
1.347 rillig 887:
1.360 rillig 888: CommandFlags cmdFlags;
1.363 rillig 889: /* Template for printing a command to the shell file */
1.341 rillig 890: const char *cmdTemplate;
1.363 rillig 891: char *xcmd; /* The expanded command */
892: char *xcmdStart;
893: char *escCmd; /* xcmd escaped to be used in double quotes */
1.1 cgd 894:
1.351 rillig 895: run = GNode_ShouldExecute(job->node);
1.298 rillig 896:
1.363 rillig 897: Var_Subst(ucmd, job->node, VARE_WANTRES, &xcmd);
1.341 rillig 898: /* TODO: handle errors */
1.363 rillig 899: xcmdStart = xcmd;
1.1 cgd 900:
1.341 rillig 901: cmdTemplate = "%s\n";
1.83 jmc 902:
1.383 ! rillig 903: ParseCommandFlags(&xcmd, &cmdFlags);
1.83 jmc 904:
1.351 rillig 905: /* The '+' command flag overrides the -n or -N options. */
1.360 rillig 906: if (cmdFlags.always && !run) {
1.341 rillig 907: /*
908: * We're not actually executing anything...
909: * but this one needs to be - use compat mode just for it.
910: */
1.363 rillig 911: Compat_RunCommand(ucmd, job->node);
912: free(xcmdStart);
1.341 rillig 913: return;
1.1 cgd 914: }
915:
1.341 rillig 916: /*
1.363 rillig 917: * If the shell doesn't have error control, the alternate echoing
918: * will be done (to avoid showing additional error checking code)
919: * and this needs some characters escaped.
1.341 rillig 920: */
1.363 rillig 921: escCmd = shell->hasErrCtl ? NULL : EscapeShellDblQuot(xcmd);
1.341 rillig 922:
1.360 rillig 923: if (!cmdFlags.echo) {
1.357 rillig 924: if (job->echo && run && shell->hasEchoCtl) {
1.373 rillig 925: ShellWriter_EchoOff(wr);
1.1 cgd 926: } else {
1.355 rillig 927: if (shell->hasErrCtl)
1.360 rillig 928: cmdFlags.echo = TRUE;
1.1 cgd 929: }
1.341 rillig 930: }
931:
1.360 rillig 932: if (cmdFlags.ignerr) {
1.371 rillig 933: JobPrintSpecials(job, wr, escCmd, run, &cmdFlags, &cmdTemplate);
1.341 rillig 934: } else {
935:
1.1 cgd 936: /*
1.341 rillig 937: * If errors are being checked and the shell doesn't have
1.364 rillig 938: * error control but does supply an runChkTmpl template, then
1.341 rillig 939: * set up commands to run through it.
940: */
941:
1.364 rillig 942: if (!shell->hasErrCtl && shell->runChkTmpl &&
943: shell->runChkTmpl[0] != '\0') {
1.360 rillig 944: if (job->echo && cmdFlags.echo) {
1.373 rillig 945: ShellWriter_EchoOff(wr);
946: ShellWriter_EchoCmd(wr, escCmd);
1.360 rillig 947: cmdFlags.echo = FALSE;
1.341 rillig 948: }
949: /*
1.367 rillig 950: * If it's a comment line or blank, avoid the possible
1.381 rillig 951: * syntax error generated by "{\n} || exit $?".
1.341 rillig 952: */
1.367 rillig 953: cmdTemplate = escCmd[0] == shell->commentChar ||
954: escCmd[0] == '\0'
955: ? shell->runIgnTmpl
956: : shell->runChkTmpl;
1.360 rillig 957: cmdFlags.ignerr = FALSE;
1.341 rillig 958: }
1.1 cgd 959: }
1.83 jmc 960:
1.374 rillig 961: if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0)
962: ShellWriter_TraceOn(wr);
1.16 christos 963:
1.376 rillig 964: ShellWriter_PrintFmt(wr, cmdTemplate, xcmd);
1.363 rillig 965: free(xcmdStart);
1.341 rillig 966: free(escCmd);
1.382 rillig 967:
968: if (cmdFlags.ignerr)
969: ShellWriter_ErrOn(wr, cmdFlags.echo && job->echo);
970:
1.373 rillig 971: if (!cmdFlags.echo)
972: ShellWriter_EchoOn(wr);
1.269 rillig 973: }
974:
1.341 rillig 975: /*
976: * Print all commands to the shell file that is later executed.
1.270 rillig 977: *
978: * The special command "..." stops printing and saves the remaining commands
1.341 rillig 979: * to be executed later.
1.362 rillig 980: *
981: * Return whether at least one command was written to the shell file.
1.341 rillig 982: */
1.362 rillig 983: static Boolean
1.269 rillig 984: JobPrintCommands(Job *job)
985: {
1.341 rillig 986: StringListNode *ln;
1.362 rillig 987: Boolean seen = FALSE;
1.374 rillig 988: ShellWriter wr = { job->cmdFILE, FALSE };
1.341 rillig 989:
990: for (ln = job->node->commands.first; ln != NULL; ln = ln->next) {
991: const char *cmd = ln->datum;
1.269 rillig 992:
1.341 rillig 993: if (strcmp(cmd, "...") == 0) {
994: job->node->type |= OP_SAVE_CMDS;
995: job->tailCmds = ln->next;
996: break;
997: }
1.270 rillig 998:
1.371 rillig 999: JobPrintCommand(job, &wr, ln->datum);
1.362 rillig 1000: seen = TRUE;
1.314 rillig 1001: }
1.362 rillig 1002:
1003: return seen;
1.1 cgd 1004: }
1005:
1.236 rillig 1006: /* Save the delayed commands, to be executed when everything else is done. */
1007: static void
1008: JobSaveCommands(Job *job)
1.1 cgd 1009: {
1.341 rillig 1010: StringListNode *ln;
1.236 rillig 1011:
1.341 rillig 1012: for (ln = job->tailCmds; ln != NULL; ln = ln->next) {
1013: const char *cmd = ln->datum;
1014: char *expanded_cmd;
1015: /* XXX: This Var_Subst is only intended to expand the dynamic
1016: * variables such as .TARGET, .IMPSRC. It is not intended to
1017: * expand the other variables as well; see deptgt-end.mk. */
1018: (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
1019: /* TODO: handle errors */
1020: Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
1021: }
1.12 christos 1022: }
1023:
1024:
1.243 rillig 1025: /* Called to close both input and output pipes when a job is finished. */
1.12 christos 1026: static void
1.320 rillig 1027: JobClosePipes(Job *job)
1.12 christos 1028: {
1.341 rillig 1029: clearfd(job);
1030: (void)close(job->outPipe);
1031: job->outPipe = -1;
1032:
1033: JobDoOutput(job, TRUE);
1034: (void)close(job->inPipe);
1035: job->inPipe = -1;
1.1 cgd 1036: }
1037:
1.378 rillig 1038: static void
1.379 rillig 1039: JobFinishDoneExitedError(Job *job, int *inout_status)
1.378 rillig 1040: {
1.379 rillig 1041: SwitchOutputTo(job->node);
1.378 rillig 1042: #ifdef USE_META
1.379 rillig 1043: if (useMeta) {
1044: meta_job_error(job, job->node,
1045: job->ignerr, WEXITSTATUS(*inout_status));
1046: }
1.378 rillig 1047: #endif
1.379 rillig 1048: if (!shouldDieQuietly(job->node, -1)) {
1049: (void)printf("*** [%s] Error code %d%s\n",
1050: job->node->name, WEXITSTATUS(*inout_status),
1051: job->ignerr ? " (ignored)" : "");
1052: }
1053:
1054: if (job->ignerr)
1055: *inout_status = 0;
1056: else {
1057: if (deleteOnError)
1058: JobDeleteTarget(job->node);
1059: PrintOnError(job->node, NULL);
1060: }
1061: }
1062:
1063: static void
1064: JobFinishDoneExited(Job *job, int *inout_status)
1065: {
1066: DEBUG2(JOB, "Process %d [%s] exited.\n", job->pid, job->node->name);
1067:
1068: if (WEXITSTATUS(*inout_status) != 0)
1069: JobFinishDoneExitedError(job, inout_status);
1070: else if (DEBUG(JOB)) {
1.378 rillig 1071: SwitchOutputTo(job->node);
1.379 rillig 1072: (void)printf("*** [%s] Completed successfully\n",
1073: job->node->name);
1.378 rillig 1074: }
1.379 rillig 1075: }
1076:
1077: static void
1078: JobFinishDoneSignaled(Job *job, int status)
1079: {
1080: SwitchOutputTo(job->node);
1081: (void)printf("*** [%s] Signal %d\n", job->node->name, WTERMSIG(status));
1082: if (deleteOnError)
1083: JobDeleteTarget(job->node);
1084: }
1085:
1086: static void
1087: JobFinishDone(Job *job, int *inout_status)
1088: {
1089: if (WIFEXITED(*inout_status))
1090: JobFinishDoneExited(job, inout_status);
1091: else
1092: JobFinishDoneSignaled(job, *inout_status);
1.378 rillig 1093:
1094: (void)fflush(stdout);
1095: }
1096:
1.341 rillig 1097: /*
1098: * Do final processing for the given job including updating parent nodes and
1.320 rillig 1099: * starting new jobs as available/necessary.
1100: *
1101: * Deferred commands for the job are placed on the .END node.
1102: *
1.331 rillig 1103: * If there was a serious error (job_errors != 0; not an ignored one), no more
1.320 rillig 1104: * jobs will be started.
1.1 cgd 1105: *
1.72 wiz 1106: * Input:
1107: * job job to finish
1108: * status sub-why job went away
1.1 cgd 1109: */
1.5 cgd 1110: static void
1.116 dsl 1111: JobFinish(Job *job, int status)
1.1 cgd 1112: {
1.341 rillig 1113: Boolean done, return_job_token;
1.1 cgd 1114:
1.341 rillig 1115: DEBUG3(JOB, "JobFinish: %d [%s], status %d\n",
1116: job->pid, job->node->name, status);
1.116 dsl 1117:
1.341 rillig 1118: if ((WIFEXITED(status) &&
1.356 rillig 1119: ((WEXITSTATUS(status) != 0 && !job->ignerr))) ||
1.341 rillig 1120: WIFSIGNALED(status)) {
1.377 rillig 1121: /* Finished because of an error. */
1122:
1.341 rillig 1123: JobClosePipes(job);
1124: if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1125: (void)fclose(job->cmdFILE);
1126: job->cmdFILE = NULL;
1127: }
1128: done = TRUE;
1.377 rillig 1129:
1.341 rillig 1130: } else if (WIFEXITED(status)) {
1131: /*
1132: * Deal with ignored errors in -B mode. We need to print a
1133: * message telling of the ignored error as well as to run
1134: * the next command.
1135: */
1136: done = WEXITSTATUS(status) != 0;
1.377 rillig 1137:
1.341 rillig 1138: JobClosePipes(job);
1.377 rillig 1139:
1.341 rillig 1140: } else {
1.377 rillig 1141: /* No need to close things down or anything. */
1.341 rillig 1142: done = FALSE;
1.1 cgd 1143: }
1.16 christos 1144:
1.378 rillig 1145: if (done)
1146: JobFinishDone(job, &status);
1.16 christos 1147:
1.156 sjg 1148: #ifdef USE_META
1.341 rillig 1149: if (useMeta) {
1150: int meta_status = meta_job_finish(job);
1151: if (meta_status != 0 && status == 0)
1152: status = meta_status;
1153: }
1.156 sjg 1154: #endif
1.201 rillig 1155:
1.341 rillig 1156: return_job_token = FALSE;
1.102 dsl 1157:
1.341 rillig 1158: Trace_Log(JOBEND, job);
1.356 rillig 1159: if (!job->special) {
1.341 rillig 1160: if (status != 0 ||
1161: (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT)
1162: return_job_token = TRUE;
1163: }
1.1 cgd 1164:
1.341 rillig 1165: if (aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT &&
1166: (status == 0)) {
1167: /*
1168: * As long as we aren't aborting and the job didn't return a
1169: * non-zero status that we shouldn't ignore, we call
1170: * Make_Update to update the parents.
1171: */
1172: JobSaveCommands(job);
1173: job->node->made = MADE;
1.356 rillig 1174: if (!job->special)
1.341 rillig 1175: return_job_token = TRUE;
1176: Make_Update(job->node);
1177: job->status = JOB_ST_FREE;
1178: } else if (status != 0) {
1179: job_errors++;
1180: job->status = JOB_ST_FREE;
1181: }
1182:
1183: if (job_errors > 0 && !opts.keepgoing && aborting != ABORT_INTERRUPT) {
1184: /* Prevent more jobs from getting started. */
1185: aborting = ABORT_ERROR;
1186: }
1.1 cgd 1187:
1.341 rillig 1188: if (return_job_token)
1189: Job_TokenReturn();
1.16 christos 1190:
1.341 rillig 1191: if (aborting == ABORT_ERROR && jobTokensRunning == 0)
1192: Finish(job_errors);
1.321 rillig 1193: }
1194:
1195: static void
1196: TouchRegular(GNode *gn)
1197: {
1.341 rillig 1198: const char *file = GNode_Path(gn);
1199: struct utimbuf times = { now, now };
1200: int fd;
1201: char c;
1202:
1203: if (utime(file, ×) >= 0)
1204: return;
1.321 rillig 1205:
1.341 rillig 1206: fd = open(file, O_RDWR | O_CREAT, 0666);
1207: if (fd < 0) {
1208: (void)fprintf(stderr, "*** couldn't touch %s: %s\n",
1209: file, strerror(errno));
1210: (void)fflush(stderr);
1211: return; /* XXX: What about propagating the error? */
1212: }
1213:
1214: /* Last resort: update the file's time stamps in the traditional way.
1215: * XXX: This doesn't work for empty files, which are sometimes used
1216: * as marker files. */
1217: if (read(fd, &c, 1) == 1) {
1218: (void)lseek(fd, 0, SEEK_SET);
1219: while (write(fd, &c, 1) == -1 && errno == EAGAIN)
1220: continue;
1221: }
1222: (void)close(fd); /* XXX: What about propagating the error? */
1.1 cgd 1223: }
1224:
1.243 rillig 1225: /* Touch the given target. Called by JobStart when the -t flag was given.
1.1 cgd 1226: *
1.243 rillig 1227: * The modification date of the file is changed.
1228: * If the file did not exist, it is created. */
1.1 cgd 1229: void
1.357 rillig 1230: Job_Touch(GNode *gn, Boolean echo)
1.1 cgd 1231: {
1.341 rillig 1232: if (gn->type &
1233: (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC | OP_OPTIONAL |
1234: OP_SPECIAL | OP_PHONY)) {
1235: /*
1236: * These are "virtual" targets and should not really be
1237: * created.
1238: */
1239: return;
1240: }
1.16 christos 1241:
1.357 rillig 1242: if (echo || !GNode_ShouldExecute(gn)) {
1.341 rillig 1243: (void)fprintf(stdout, "touch %s\n", gn->name);
1244: (void)fflush(stdout);
1245: }
1.1 cgd 1246:
1.341 rillig 1247: if (!GNode_ShouldExecute(gn))
1248: return;
1.1 cgd 1249:
1.380 rillig 1250: if (gn->type & OP_ARCHV)
1.341 rillig 1251: Arch_Touch(gn);
1.380 rillig 1252: else if (gn->type & OP_LIB)
1.341 rillig 1253: Arch_TouchLib(gn);
1.380 rillig 1254: else
1255: TouchRegular(gn);
1.1 cgd 1256: }
1257:
1.243 rillig 1258: /* Make sure the given node has all the commands it needs.
1259: *
1260: * The node will have commands from the .DEFAULT rule added to it if it
1261: * needs them.
1.1 cgd 1262: *
1.72 wiz 1263: * Input:
1264: * gn The target whose commands need verifying
1265: * abortProc Function to abort with message
1266: *
1.1 cgd 1267: * Results:
1268: * TRUE if the commands list is/was ok.
1269: */
1270: Boolean
1.77 christos 1271: Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
1.1 cgd 1272: {
1.341 rillig 1273: if (GNode_IsTarget(gn))
1274: return TRUE;
1275: if (!Lst_IsEmpty(&gn->commands))
1276: return TRUE;
1277: if ((gn->type & OP_LIB) && !Lst_IsEmpty(&gn->children))
1278: return TRUE;
1.280 rillig 1279:
1.281 rillig 1280: /*
1.341 rillig 1281: * No commands. Look for .DEFAULT rule from which we might infer
1282: * commands.
1.281 rillig 1283: */
1.341 rillig 1284: if (defaultNode != NULL && !Lst_IsEmpty(&defaultNode->commands) &&
1285: !(gn->type & OP_SPECIAL)) {
1286: /*
1287: * The traditional Make only looks for a .DEFAULT if the node
1288: * was never the target of an operator, so that's what we do
1289: * too.
1290: *
1291: * The .DEFAULT node acts like a transformation rule, in that
1292: * gn also inherits any attributes or sources attached to
1293: * .DEFAULT itself.
1294: */
1295: Make_HandleUse(defaultNode, gn);
1296: Var_Set(IMPSRC, GNode_VarTarget(gn), gn);
1297: return TRUE;
1298: }
1299:
1300: Dir_UpdateMTime(gn, FALSE);
1301: if (gn->mtime != 0 || (gn->type & OP_SPECIAL))
1302: return TRUE;
1.281 rillig 1303:
1.341 rillig 1304: /*
1305: * The node wasn't the target of an operator. We have no .DEFAULT
1306: * rule to go on and the target doesn't already exist. There's
1307: * nothing more we can do for this branch. If the -k flag wasn't
1308: * given, we stop in our tracks, otherwise we just don't update
1309: * this node's parents so they never get examined.
1310: */
1.282 rillig 1311:
1.341 rillig 1312: if (gn->flags & FROM_DEPEND) {
1313: if (!Job_RunTarget(".STALE", gn->fname))
1314: fprintf(stdout,
1315: "%s: %s, %d: ignoring stale %s for %s\n",
1316: progname, gn->fname, gn->lineno, makeDependfile,
1317: gn->name);
1318: return TRUE;
1319: }
1.282 rillig 1320:
1.341 rillig 1321: if (gn->type & OP_OPTIONAL) {
1322: (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1323: progname, gn->name, "ignored");
1324: (void)fflush(stdout);
1325: return TRUE;
1326: }
1.282 rillig 1327:
1.341 rillig 1328: if (opts.keepgoing) {
1329: (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1330: progname, gn->name, "continuing");
1331: (void)fflush(stdout);
1332: return FALSE;
1333: }
1.282 rillig 1334:
1.341 rillig 1335: abortProc("%s: don't know how to make %s. Stop", progname, gn->name);
1.282 rillig 1336: return FALSE;
1.1 cgd 1337: }
1338:
1.284 rillig 1339: /* Execute the shell for the given job.
1.1 cgd 1340: *
1.325 rillig 1341: * See Job_CatchOutput for handling the output of the shell. */
1.1 cgd 1342: static void
1.72 wiz 1343: JobExec(Job *job, char **argv)
1.1 cgd 1344: {
1.341 rillig 1345: int cpid; /* ID of new child */
1346: sigset_t mask;
1.16 christos 1347:
1.341 rillig 1348: if (DEBUG(JOB)) {
1349: int i;
1.16 christos 1350:
1.341 rillig 1351: debug_printf("Running %s\n", job->node->name);
1352: debug_printf("\tCommand: ");
1353: for (i = 0; argv[i] != NULL; i++) {
1354: debug_printf("%s ", argv[i]);
1355: }
1356: debug_printf("\n");
1.1 cgd 1357: }
1.16 christos 1358:
1.341 rillig 1359: /*
1360: * Some jobs produce no output and it's disconcerting to have
1361: * no feedback of their running (since they produce no output, the
1362: * banner with their name in it never appears). This is an attempt to
1363: * provide that feedback, even if nothing follows it.
1364: */
1.357 rillig 1365: if (job->echo)
1.341 rillig 1366: SwitchOutputTo(job->node);
1.16 christos 1367:
1.341 rillig 1368: /* No interruptions until this job is on the `jobs' list */
1369: JobSigLock(&mask);
1.69 pk 1370:
1.341 rillig 1371: /* Pre-emptively mark job running, pid still zero though */
1372: job->status = JOB_ST_RUNNING;
1.116 dsl 1373:
1.341 rillig 1374: cpid = vFork();
1375: if (cpid == -1)
1376: Punt("Cannot vfork: %s", strerror(errno));
1377:
1378: if (cpid == 0) {
1379: /* Child */
1380: sigset_t tmask;
1.1 cgd 1381:
1.155 sjg 1382: #ifdef USE_META
1.341 rillig 1383: if (useMeta) {
1384: meta_job_child(job);
1385: }
1.155 sjg 1386: #endif
1.341 rillig 1387: /*
1388: * Reset all signal handlers; this is necessary because we
1389: * also need to unblock signals before we exec(2).
1390: */
1391: JobSigReset();
1.69 pk 1392:
1.341 rillig 1393: /* Now unblock signals */
1394: sigemptyset(&tmask);
1395: JobSigUnlock(&tmask);
1.69 pk 1396:
1.341 rillig 1397: /*
1398: * Must duplicate the input stream down to the child's input
1399: * and reset it to the beginning (again). Since the stream
1400: * was marked close-on-exec, we must clear that bit in the
1401: * new input.
1402: */
1403: if (dup2(fileno(job->cmdFILE), 0) == -1)
1404: execDie("dup2", "job->cmdFILE");
1405: if (fcntl(0, F_SETFD, 0) == -1)
1406: execDie("fcntl clear close-on-exec", "stdin");
1407: if (lseek(0, 0, SEEK_SET) == -1)
1408: execDie("lseek to 0", "stdin");
1409:
1410: if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
1411: /*
1412: * Pass job token pipe to submakes.
1413: */
1414: if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1)
1415: execDie("clear close-on-exec",
1416: "tokenWaitJob.inPipe");
1417: if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1)
1418: execDie("clear close-on-exec",
1419: "tokenWaitJob.outPipe");
1420: }
1.16 christos 1421:
1.341 rillig 1422: /*
1423: * Set up the child's output to be routed through the pipe
1424: * we've created for it.
1425: */
1426: if (dup2(job->outPipe, 1) == -1)
1427: execDie("dup2", "job->outPipe");
1.201 rillig 1428:
1.341 rillig 1429: /*
1430: * The output channels are marked close on exec. This bit
1431: * was duplicated by the dup2(on some systems), so we have
1432: * to clear it before routing the shell's error output to
1433: * the same place as its standard output.
1434: */
1435: if (fcntl(1, F_SETFD, 0) == -1)
1436: execDie("clear close-on-exec", "stdout");
1437: if (dup2(1, 2) == -1)
1438: execDie("dup2", "1, 2");
1.264 rillig 1439:
1.341 rillig 1440: /*
1441: * We want to switch the child into a different process
1442: * family so we can kill it and all its descendants in
1443: * one fell swoop, by killing its process family, but not
1444: * commit suicide.
1445: */
1.170 christos 1446: #if defined(MAKE_NATIVE) || defined(HAVE_SETPGID)
1.341 rillig 1447: # if defined(SYSV)
1448: /* XXX: dsl - I'm sure this should be setpgrp()... */
1449: (void)setsid();
1450: # else
1451: (void)setpgid(0, getpid());
1452: # endif
1.170 christos 1453: #endif
1.1 cgd 1454:
1.341 rillig 1455: Var_ExportVars();
1.126 sjg 1456:
1.341 rillig 1457: (void)execv(shellPath, argv);
1458: execDie("exec", shellPath);
1459: }
1.116 dsl 1460:
1.341 rillig 1461: /* Parent, continuing after the child exec */
1462: job->pid = cpid;
1.1 cgd 1463:
1.341 rillig 1464: Trace_Log(JOBSTART, job);
1.40 sommerfe 1465:
1.196 riastrad 1466: #ifdef USE_META
1.341 rillig 1467: if (useMeta) {
1468: meta_job_parent(job, cpid);
1469: }
1.196 riastrad 1470: #endif
1471:
1.341 rillig 1472: /*
1473: * Set the current position in the buffer to the beginning
1474: * and mark another stream to watch in the outputs mask
1475: */
1476: job->curPos = 0;
1.16 christos 1477:
1.341 rillig 1478: watchfd(job);
1.1 cgd 1479:
1.341 rillig 1480: if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1481: (void)fclose(job->cmdFILE);
1482: job->cmdFILE = NULL;
1483: }
1.1 cgd 1484:
1.341 rillig 1485: /*
1486: * Now the job is actually running, add it to the table.
1487: */
1488: if (DEBUG(JOB)) {
1489: debug_printf("JobExec(%s): pid %d added to jobs table\n",
1490: job->node->name, job->pid);
1491: job_table_dump("job started");
1492: }
1493: JobSigUnlock(&mask);
1.1 cgd 1494: }
1495:
1.228 rillig 1496: /* Create the argv needed to execute the shell for a given job. */
1.1 cgd 1497: static void
1.72 wiz 1498: JobMakeArgv(Job *job, char **argv)
1.1 cgd 1499: {
1.341 rillig 1500: int argc;
1501: static char args[10]; /* For merged arguments */
1.16 christos 1502:
1.341 rillig 1503: argv[0] = UNCONST(shellName);
1504: argc = 1;
1.1 cgd 1505:
1.375 rillig 1506: if ((shell->errFlag != NULL && shell->errFlag[0] != '-') ||
1.366 rillig 1507: (shell->echoFlag != NULL && shell->echoFlag[0] != '-')) {
1.341 rillig 1508: /*
1509: * At least one of the flags doesn't have a minus before it,
1510: * so merge them together. Have to do this because the Bourne
1511: * shell thinks its second argument is a file to source.
1512: * Grrrr. Note the ten-character limitation on the combined
1513: * arguments.
1514: *
1515: * TODO: Research until when the above comments were
1516: * practically relevant.
1517: */
1518: (void)snprintf(args, sizeof args, "-%s%s",
1.356 rillig 1519: (job->ignerr ? "" :
1.375 rillig 1520: (shell->errFlag != NULL ? shell->errFlag : "")),
1.357 rillig 1521: (!job->echo ? "" :
1.366 rillig 1522: (shell->echoFlag != NULL ? shell->echoFlag : "")));
1.341 rillig 1523:
1524: if (args[1]) {
1525: argv[argc] = args;
1526: argc++;
1527: }
1528: } else {
1.375 rillig 1529: if (!job->ignerr && shell->errFlag) {
1530: argv[argc] = UNCONST(shell->errFlag);
1.341 rillig 1531: argc++;
1532: }
1.366 rillig 1533: if (job->echo && shell->echoFlag) {
1534: argv[argc] = UNCONST(shell->echoFlag);
1.341 rillig 1535: argc++;
1536: }
1.1 cgd 1537: }
1.341 rillig 1538: argv[argc] = NULL;
1.1 cgd 1539: }
1540:
1.361 rillig 1541: static void
1542: JobOpenTmpFile(Job *job, GNode *gn, Boolean cmdsOK, Boolean *out_run)
1543: {
1544: /*
1545: * tfile is the name of a file into which all shell commands
1546: * are put. It is removed before the child shell is executed,
1547: * unless DEBUG(SCRIPT) is set.
1548: */
1549: char *tfile;
1550: sigset_t mask;
1551: int tfd; /* File descriptor to the temp file */
1552:
1553: /*
1554: * We're serious here, but if the commands were bogus, we're
1555: * also dead...
1556: */
1557: if (!cmdsOK) {
1558: PrintOnError(gn, NULL); /* provide some clue */
1559: DieHorribly();
1560: }
1561:
1562: JobSigLock(&mask);
1563: tfd = mkTempFile(TMPPAT, &tfile);
1564: if (!DEBUG(SCRIPT))
1565: (void)eunlink(tfile);
1566: JobSigUnlock(&mask);
1567:
1568: job->cmdFILE = fdopen(tfd, "w+");
1569: if (job->cmdFILE == NULL)
1570: Punt("Could not fdopen %s", tfile);
1571:
1572: (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC);
1573: /*
1574: * Send the commands to the command file, flush all its
1575: * buffers then rewind and remove the thing.
1576: */
1577: *out_run = TRUE;
1578:
1579: #ifdef USE_META
1580: if (useMeta) {
1581: meta_job_start(job, gn);
1.369 rillig 1582: if (gn->type & OP_SILENT) /* might have changed */
1.361 rillig 1583: job->echo = FALSE;
1584: }
1585: #endif
1.362 rillig 1586:
1.361 rillig 1587: /* We can do all the commands at once. hooray for sanity */
1.362 rillig 1588: if (!JobPrintCommands(job))
1.361 rillig 1589: *out_run = FALSE;
1590:
1591: free(tfile);
1592: }
1593:
1.338 rillig 1594: /*
1595: * Start a target-creation process going for the target described by the
1596: * graph node gn.
1.1 cgd 1597: *
1.72 wiz 1598: * Input:
1599: * gn target to create
1600: * flags flags for the job to override normal ones.
1601: * previous The previous Job structure for this node, if any.
1602: *
1.1 cgd 1603: * Results:
1604: * JOB_ERROR if there was an error in the commands, JOB_FINISHED
1605: * if there isn't actually anything left to do for the job and
1606: * JOB_RUNNING if the job has been started.
1607: *
1608: * Side Effects:
1609: * A new Job node is created and added to the list of running
1610: * jobs. PMake is forked and a child shell created.
1.110 dsl 1611: *
1.314 rillig 1612: * NB: The return value is ignored by everyone.
1.1 cgd 1613: */
1.284 rillig 1614: static JobStartResult
1.354 rillig 1615: JobStart(GNode *gn, Boolean special)
1.1 cgd 1616: {
1.341 rillig 1617: Job *job; /* new job descriptor */
1618: char *argv[10]; /* Argument vector to shell */
1619: Boolean cmdsOK; /* true if the nodes commands were all right */
1.353 rillig 1620: Boolean run;
1.341 rillig 1621:
1622: for (job = job_table; job < job_table_end; job++) {
1623: if (job->status == JOB_ST_FREE)
1624: break;
1625: }
1626: if (job >= job_table_end)
1627: Punt("JobStart no job slots vacant");
1.122 dsl 1628:
1.341 rillig 1629: memset(job, 0, sizeof *job);
1630: job->node = gn;
1631: job->tailCmds = NULL;
1632: job->status = JOB_ST_SET_UP;
1.1 cgd 1633:
1.369 rillig 1634: job->special = special || gn->type & OP_SPECIAL;
1635: job->ignerr = opts.ignoreErrors || gn->type & OP_IGNORE;
1636: job->echo = !(opts.beSilent || gn->type & OP_SILENT);
1.16 christos 1637:
1.1 cgd 1638: /*
1.341 rillig 1639: * Check the commands now so any attributes from .DEFAULT have a
1640: * chance to migrate to the node.
1.34 christos 1641: */
1.341 rillig 1642: cmdsOK = Job_CheckCommands(gn, Error);
1643:
1644: job->inPollfd = NULL;
1.34 christos 1645: /*
1.341 rillig 1646: * If the -n flag wasn't given, we open up OUR (not the child's)
1647: * temporary file to stuff commands in it. The thing is rd/wr so
1648: * we don't need to reopen it to feed it to the shell. If the -n
1649: * flag *was* given, we just set the file to be stdout. Cute, huh?
1.1 cgd 1650: */
1.341 rillig 1651: if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) ||
1652: (!opts.noExecute && !opts.touchFlag)) {
1.361 rillig 1653: JobOpenTmpFile(job, gn, cmdsOK, &run);
1.341 rillig 1654: } else if (!GNode_ShouldExecute(gn)) {
1655: /*
1656: * Not executing anything -- just print all the commands to
1657: * stdout in one fell swoop. This will still set up
1658: * job->tailCmds correctly.
1659: */
1660: SwitchOutputTo(gn);
1661: job->cmdFILE = stdout;
1662: /*
1663: * Only print the commands if they're ok, but don't die if
1664: * they're not -- just let the user know they're bad and
1665: * keep going. It doesn't do any harm in this case and may
1666: * do some good.
1667: */
1668: if (cmdsOK)
1669: JobPrintCommands(job);
1670: /* Don't execute the shell, thank you. */
1.353 rillig 1671: run = FALSE;
1.341 rillig 1672: } else {
1673: /*
1674: * Just touch the target and note that no shell should be
1675: * executed. Set cmdFILE to stdout to make life easier.
1676: * Check the commands, too, but don't die if they're no
1677: * good -- it does no harm to keep working up the graph.
1678: */
1679: job->cmdFILE = stdout;
1.357 rillig 1680: Job_Touch(gn, job->echo);
1.353 rillig 1681: run = FALSE;
1.341 rillig 1682: }
1683: /* Just in case it isn't already... */
1684: (void)fflush(job->cmdFILE);
1685:
1686: /* If we're not supposed to execute a shell, don't. */
1.353 rillig 1687: if (!run) {
1.356 rillig 1688: if (!job->special)
1.341 rillig 1689: Job_TokenReturn();
1690: /* Unlink and close the command file if we opened one */
1691: if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1692: (void)fclose(job->cmdFILE);
1693: job->cmdFILE = NULL;
1694: }
1.1 cgd 1695:
1.341 rillig 1696: /*
1697: * We only want to work our way up the graph if we aren't
1698: * here because the commands for the job were no good.
1699: */
1700: if (cmdsOK && aborting == ABORT_NONE) {
1701: JobSaveCommands(job);
1702: job->node->made = MADE;
1703: Make_Update(job->node);
1704: }
1705: job->status = JOB_ST_FREE;
1706: return cmdsOK ? JOB_FINISHED : JOB_ERROR;
1.1 cgd 1707: }
1708:
1709: /*
1.341 rillig 1710: * Set up the control arguments to the shell. This is based on the
1711: * flags set earlier for this job.
1.1 cgd 1712: */
1.341 rillig 1713: JobMakeArgv(job, argv);
1.1 cgd 1714:
1.341 rillig 1715: /* Create the pipe by which we'll get the shell's output. */
1716: JobCreatePipe(job, 3);
1.1 cgd 1717:
1.341 rillig 1718: JobExec(job, argv);
1719: return JOB_RUNNING;
1.1 cgd 1720: }
1721:
1.341 rillig 1722: /*
1723: * Print the output of the shell command, skipping the noPrint command of
1724: * the shell, if any.
1725: */
1.16 christos 1726: static char *
1.336 rillig 1727: JobOutput(char *cp, char *endp)
1.12 christos 1728: {
1.341 rillig 1729: char *ecp;
1.12 christos 1730:
1.355 rillig 1731: if (shell->noPrint == NULL || shell->noPrint[0] == '\0')
1.341 rillig 1732: return cp;
1.324 rillig 1733:
1.355 rillig 1734: while ((ecp = strstr(cp, shell->noPrint)) != NULL) {
1.341 rillig 1735: if (ecp != cp) {
1736: *ecp = '\0';
1737: /*
1738: * The only way there wouldn't be a newline after
1739: * this line is if it were the last in the buffer.
1740: * however, since the non-printable comes after it,
1741: * there must be a newline, so we don't print one.
1742: */
1743: (void)fprintf(stdout, "%s", cp);
1744: (void)fflush(stdout);
1745: }
1.355 rillig 1746: cp = ecp + shell->noPrintLen;
1.341 rillig 1747: if (cp != endp) {
1748: /*
1749: * Still more to print, look again after skipping
1750: * the whitespace following the non-printable
1751: * command.
1752: */
1753: cp++;
1754: pp_skip_whitespace(&cp);
1755: } else {
1756: return cp;
1757: }
1.12 christos 1758: }
1.341 rillig 1759: return cp;
1.12 christos 1760: }
1761:
1.325 rillig 1762: /*
1763: * This function is called whenever there is something to read on the pipe.
1764: * We collect more output from the given job and store it in the job's
1765: * outBuf. If this makes up a line, we print it tagged by the job's
1766: * identifier, as necessary.
1767: *
1768: * In the output of the shell, the 'noPrint' lines are removed. If the
1769: * command is not alone on the line (the character after it is not \0 or
1770: * \n), we do print whatever follows it.
1.1 cgd 1771: *
1.72 wiz 1772: * Input:
1773: * job the job whose output needs printing
1774: * finish TRUE if this is the last time we'll be called
1775: * for this job
1.1 cgd 1776: */
1.285 rillig 1777: static void
1.72 wiz 1778: JobDoOutput(Job *job, Boolean finish)
1.1 cgd 1779: {
1.341 rillig 1780: Boolean gotNL; /* true if got a newline */
1781: Boolean fbuf; /* true if our buffer filled up */
1782: size_t nr; /* number of bytes read */
1783: size_t i; /* auxiliary index into outBuf */
1784: size_t max; /* limit for i (end of current data) */
1785: ssize_t nRead; /* (Temporary) number of bytes read */
1.1 cgd 1786:
1.341 rillig 1787: /* Read as many bytes as will fit in the buffer. */
1.325 rillig 1788: again:
1.341 rillig 1789: gotNL = FALSE;
1790: fbuf = FALSE;
1.16 christos 1791:
1.341 rillig 1792: nRead = read(job->inPipe, &job->outBuf[job->curPos],
1793: JOB_BUFSIZE - job->curPos);
1794: if (nRead < 0) {
1795: if (errno == EAGAIN)
1796: return;
1797: if (DEBUG(JOB)) {
1798: perror("JobDoOutput(piperead)");
1799: }
1800: nr = 0;
1801: } else {
1802: nr = (size_t)nRead;
1.1 cgd 1803: }
1804:
1.341 rillig 1805: /*
1806: * If we hit the end-of-file (the job is dead), we must flush its
1807: * remaining output, so pretend we read a newline if there's any
1808: * output remaining in the buffer.
1809: * Also clear the 'finish' flag so we stop looping.
1810: */
1811: if (nr == 0 && job->curPos != 0) {
1812: job->outBuf[job->curPos] = '\n';
1813: nr = 1;
1814: finish = FALSE;
1815: } else if (nr == 0) {
1816: finish = FALSE;
1817: }
1.16 christos 1818:
1.341 rillig 1819: /*
1820: * Look for the last newline in the bytes we just got. If there is
1821: * one, break out of the loop with 'i' as its index and gotNL set
1822: * TRUE.
1823: */
1824: max = job->curPos + nr;
1825: for (i = job->curPos + nr - 1;
1826: i >= job->curPos && i != (size_t)-1; i--) {
1827: if (job->outBuf[i] == '\n') {
1828: gotNL = TRUE;
1829: break;
1830: } else if (job->outBuf[i] == '\0') {
1831: /*
1832: * Why?
1833: */
1834: job->outBuf[i] = ' ';
1835: }
1.1 cgd 1836: }
1.16 christos 1837:
1.341 rillig 1838: if (!gotNL) {
1839: job->curPos += nr;
1840: if (job->curPos == JOB_BUFSIZE) {
1841: /*
1842: * If we've run out of buffer space, we have no choice
1843: * but to print the stuff. sigh.
1844: */
1845: fbuf = TRUE;
1846: i = job->curPos;
1847: }
1.120 dsl 1848: }
1.341 rillig 1849: if (gotNL || fbuf) {
1850: /*
1851: * Need to send the output to the screen. Null terminate it
1852: * first, overwriting the newline character if there was one.
1853: * So long as the line isn't one we should filter (according
1854: * to the shell description), we print the line, preceded
1855: * by a target banner if this target isn't the same as the
1856: * one for which we last printed something.
1857: * The rest of the data in the buffer are then shifted down
1858: * to the start of the buffer and curPos is set accordingly.
1859: */
1860: job->outBuf[i] = '\0';
1861: if (i >= job->curPos) {
1862: char *cp;
1863:
1864: cp = JobOutput(job->outBuf, &job->outBuf[i]);
1865:
1866: /*
1867: * There's still more in that thar buffer. This time,
1868: * though, we know there's no newline at the end, so
1869: * we add one of our own free will.
1870: */
1871: if (*cp != '\0') {
1872: if (!opts.beSilent)
1873: SwitchOutputTo(job->node);
1.155 sjg 1874: #ifdef USE_META
1.341 rillig 1875: if (useMeta) {
1876: meta_job_output(job, cp,
1877: gotNL ? "\n" : "");
1878: }
1879: #endif
1880: (void)fprintf(stdout, "%s%s", cp,
1881: gotNL ? "\n" : "");
1882: (void)fflush(stdout);
1883: }
1884: }
1885: /*
1886: * max is the last offset still in the buffer. Move any
1887: * remaining characters to the start of the buffer and
1888: * update the end marker curPos.
1889: */
1890: if (i < max) {
1891: (void)memmove(job->outBuf, &job->outBuf[i + 1],
1892: max - (i + 1));
1893: job->curPos = max - (i + 1);
1894: } else {
1895: assert(i == max);
1896: job->curPos = 0;
1.155 sjg 1897: }
1.120 dsl 1898: }
1.341 rillig 1899: if (finish) {
1900: /*
1901: * If the finish flag is true, we must loop until we hit
1902: * end-of-file on the pipe. This is guaranteed to happen
1903: * eventually since the other end of the pipe is now closed
1904: * (we closed it explicitly and the child has exited). When
1905: * we do get an EOF, finish will be set FALSE and we'll fall
1906: * through and out.
1907: */
1908: goto again;
1.180 joerg 1909: }
1.1 cgd 1910: }
1911:
1.91 christos 1912: static void
1913: JobRun(GNode *targ)
1914: {
1.238 rillig 1915: #if 0
1.341 rillig 1916: /*
1917: * Unfortunately it is too complicated to run .BEGIN, .END, and
1918: * .INTERRUPT job in the parallel job module. As of 2020-09-25,
1919: * unit-tests/deptgt-end-jobs.mk hangs in an endless loop.
1920: *
1921: * Running these jobs in compat mode also guarantees that these
1922: * jobs do not overlap with other unrelated jobs.
1923: */
1924: List *lst = Lst_New();
1925: Lst_Append(lst, targ);
1926: (void)Make_Run(lst);
1927: Lst_Destroy(lst, NULL);
1928: JobStart(targ, JOB_SPECIAL);
1929: while (jobTokensRunning != 0) {
1930: Job_CatchOutput();
1931: }
1.91 christos 1932: #else
1.341 rillig 1933: Compat_Make(targ, targ);
1934: /* XXX: Replace with GNode_IsError(gn) */
1935: if (targ->made == ERROR) {
1936: PrintOnError(targ, "\n\nStop.");
1937: exit(1);
1938: }
1.91 christos 1939: #endif
1940: }
1941:
1.243 rillig 1942: /* Handle the exit of a child. Called from Make_Make.
1.1 cgd 1943: *
1.243 rillig 1944: * The job descriptor is removed from the list of children.
1.1 cgd 1945: *
1946: * Notes:
1947: * We do waits, blocking or not, according to the wisdom of our
1948: * caller, until there are no more children to report. For each
1.118 dsl 1949: * job, call JobFinish to finish things off.
1.1 cgd 1950: */
1951: void
1.120 dsl 1952: Job_CatchChildren(void)
1.1 cgd 1953: {
1.341 rillig 1954: int pid; /* pid of dead child */
1955: int status; /* Exit/termination status */
1.1 cgd 1956:
1.341 rillig 1957: /* Don't even bother if we know there's no one around. */
1958: if (jobTokensRunning == 0)
1959: return;
1.16 christos 1960:
1.341 rillig 1961: while ((pid = waitpid((pid_t)-1, &status, WNOHANG | WUNTRACED)) > 0) {
1962: DEBUG2(JOB, "Process %d exited/stopped status %x.\n",
1963: pid, status);
1964: JobReapChild(pid, status, TRUE);
1965: }
1.153 sjg 1966: }
1967:
1968: /*
1969: * It is possible that wait[pid]() was called from elsewhere,
1970: * this lets us reap jobs regardless.
1971: */
1972: void
1973: JobReapChild(pid_t pid, int status, Boolean isJobs)
1974: {
1.341 rillig 1975: Job *job; /* job descriptor for dead child */
1.153 sjg 1976:
1.341 rillig 1977: /* Don't even bother if we know there's no one around. */
1978: if (jobTokensRunning == 0)
1979: return;
1.16 christos 1980:
1.341 rillig 1981: job = JobFindPid(pid, JOB_ST_RUNNING, isJobs);
1982: if (job == NULL) {
1983: if (isJobs) {
1984: if (!lurking_children)
1985: Error("Child (%d) status %x not in table?",
1986: pid, status);
1987: }
1988: return; /* not ours */
1.116 dsl 1989: }
1.341 rillig 1990: if (WIFSTOPPED(status)) {
1991: DEBUG2(JOB, "Process %d (%s) stopped.\n",
1992: job->pid, job->node->name);
1993: if (!make_suspended) {
1994: switch (WSTOPSIG(status)) {
1995: case SIGTSTP:
1996: (void)printf("*** [%s] Suspended\n",
1997: job->node->name);
1998: break;
1999: case SIGSTOP:
2000: (void)printf("*** [%s] Stopped\n",
2001: job->node->name);
2002: break;
2003: default:
2004: (void)printf("*** [%s] Stopped -- signal %d\n",
2005: job->node->name, WSTOPSIG(status));
2006: }
2007: job->suspended = TRUE;
2008: }
2009: (void)fflush(stdout);
2010: return;
1.1 cgd 2011: }
2012:
1.341 rillig 2013: job->status = JOB_ST_FINISHED;
2014: job->exit_status = status;
1.116 dsl 2015:
1.341 rillig 2016: JobFinish(job, status);
1.1 cgd 2017: }
2018:
1.243 rillig 2019: /* Catch the output from our children, if we're using pipes do so. Otherwise
2020: * just block time until we get a signal(most likely a SIGCHLD) since there's
2021: * no point in just spinning when there's nothing to do and the reaping of a
2022: * child can wait for a while. */
1.1 cgd 2023: void
1.72 wiz 2024: Job_CatchOutput(void)
1.1 cgd 2025: {
1.341 rillig 2026: int nready;
2027: Job *job;
2028: unsigned int i;
1.169 christos 2029:
1.341 rillig 2030: (void)fflush(stdout);
1.120 dsl 2031:
1.341 rillig 2032: /* The first fd in the list is the job token pipe */
2033: do {
2034: nready = poll(fds + 1 - wantToken, nJobs - 1 + wantToken,
2035: POLL_MSEC);
2036: } while (nready < 0 && errno == EINTR);
2037:
2038: if (nready < 0)
2039: Punt("poll: %s", strerror(errno));
2040:
2041: if (nready > 0 && readyfd(&childExitJob)) {
2042: char token = 0;
2043: ssize_t count;
2044: count = read(childExitJob.inPipe, &token, 1);
2045: switch (count) {
2046: case 0:
2047: Punt("unexpected eof on token pipe");
2048: case -1:
2049: Punt("token pipe read: %s", strerror(errno));
2050: case 1:
2051: if (token == DO_JOB_RESUME[0])
2052: /*
2053: * Complete relay requested from our SIGCONT
2054: * handler
2055: */
2056: JobRestartJobs();
2057: break;
2058: default:
2059: abort();
2060: }
2061: nready--;
1.169 christos 2062: }
1.120 dsl 2063:
1.341 rillig 2064: Job_CatchChildren();
2065: if (nready == 0)
2066: return;
2067:
2068: for (i = npseudojobs * nfds_per_job(); i < nJobs; i++) {
2069: if (!fds[i].revents)
2070: continue;
2071: job = allJobs[i];
2072: if (job->status == JOB_ST_RUNNING)
2073: JobDoOutput(job, FALSE);
1.197 sjg 2074: #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
1.341 rillig 2075: /*
2076: * With meta mode, we may have activity on the job's filemon
2077: * descriptor too, which at the moment is any pollfd other
2078: * than job->inPollfd.
2079: */
2080: if (useMeta && job->inPollfd != &fds[i]) {
2081: if (meta_job_event(job) <= 0) {
2082: fds[i].events = 0; /* never mind */
2083: }
2084: }
2085: #endif
2086: if (--nready == 0)
2087: return;
1.196 riastrad 2088: }
1.1 cgd 2089: }
2090:
1.243 rillig 2091: /* Start the creation of a target. Basically a front-end for JobStart used by
2092: * the Make module. */
1.1 cgd 2093: void
1.72 wiz 2094: Job_Make(GNode *gn)
1.1 cgd 2095: {
1.354 rillig 2096: (void)JobStart(gn, FALSE);
1.1 cgd 2097: }
2098:
1.344 rillig 2099: static void
2100: InitShellNameAndPath(void)
2101: {
1.355 rillig 2102: shellName = shell->name;
1.344 rillig 2103:
2104: #ifdef DEFSHELL_CUSTOM
2105: if (shellName[0] == '/') {
2106: shellPath = shellName;
2107: shellName = strrchr(shellPath, '/') + 1;
2108: return;
2109: }
2110: #endif
2111:
2112: shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
2113: }
2114:
1.81 sjg 2115: void
1.120 dsl 2116: Shell_Init(void)
1.81 sjg 2117: {
1.344 rillig 2118: if (shellPath == NULL)
2119: InitShellNameAndPath();
2120:
1.341 rillig 2121: Var_SetWithFlags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY);
1.375 rillig 2122: if (shell->errFlag == NULL)
2123: shell->errFlag = "";
1.366 rillig 2124: if (shell->echoFlag == NULL)
2125: shell->echoFlag = "";
1.375 rillig 2126: if (shell->hasErrCtl && shell->errFlag[0] != '\0') {
1.341 rillig 2127: if (shellErrFlag &&
1.375 rillig 2128: strcmp(shell->errFlag, &shellErrFlag[1]) != 0) {
1.341 rillig 2129: free(shellErrFlag);
2130: shellErrFlag = NULL;
2131: }
2132: if (shellErrFlag == NULL) {
1.375 rillig 2133: size_t n = strlen(shell->errFlag) + 2;
1.341 rillig 2134:
2135: shellErrFlag = bmake_malloc(n);
1.355 rillig 2136: if (shellErrFlag != NULL)
1.366 rillig 2137: snprintf(shellErrFlag, n, "-%s",
1.375 rillig 2138: shell->errFlag);
1.341 rillig 2139: }
2140: } else if (shellErrFlag != NULL) {
2141: free(shellErrFlag);
2142: shellErrFlag = NULL;
2143: }
1.81 sjg 2144: }
2145:
1.341 rillig 2146: /*
2147: * Return the string literal that is used in the current command shell
2148: * to produce a newline character.
2149: */
1.112 rillig 2150: const char *
2151: Shell_GetNewline(void)
2152: {
1.355 rillig 2153: return shell->newline;
1.112 rillig 2154: }
2155:
1.125 sjg 2156: void
2157: Job_SetPrefix(void)
2158: {
1.341 rillig 2159: if (targPrefix != NULL) {
2160: free(targPrefix);
2161: } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) {
2162: Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL);
2163: }
1.128 dsl 2164:
1.341 rillig 2165: (void)Var_Subst("${" MAKE_JOB_PREFIX "}",
2166: VAR_GLOBAL, VARE_WANTRES, &targPrefix);
2167: /* TODO: handle errors */
1.125 sjg 2168: }
2169:
1.342 rillig 2170: static void
2171: AddSig(int sig, SignalProc handler)
2172: {
2173: if (bmake_signal(sig, SIG_IGN) != SIG_IGN) {
2174: sigaddset(&caught_signals, sig);
2175: (void)bmake_signal(sig, handler);
2176: }
2177: }
2178:
1.222 rillig 2179: /* Initialize the process module. */
1.1 cgd 2180: void
1.111 dsl 2181: Job_Init(void)
1.1 cgd 2182: {
1.341 rillig 2183: Job_SetPrefix();
2184: /* Allocate space for all the job info */
2185: job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table);
2186: memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table);
2187: job_table_end = job_table + opts.maxJobs;
2188: wantToken = 0;
2189:
2190: aborting = ABORT_NONE;
2191: job_errors = 0;
2192:
2193: /*
2194: * There is a non-zero chance that we already have children.
2195: * eg after 'make -f- <<EOF'
2196: * Since their termination causes a 'Child (pid) not in table'
2197: * message, Collect the status of any that are already dead, and
2198: * suppress the error message if there are any undead ones.
2199: */
2200: for (;;) {
2201: int rval, status;
2202: rval = waitpid((pid_t)-1, &status, WNOHANG);
2203: if (rval > 0)
2204: continue;
2205: if (rval == 0)
2206: lurking_children = TRUE;
2207: break;
2208: }
1.1 cgd 2209:
1.341 rillig 2210: Shell_Init();
1.1 cgd 2211:
1.341 rillig 2212: JobCreatePipe(&childExitJob, 3);
1.117 dsl 2213:
1.341 rillig 2214: /* Preallocate enough for the maximum number of jobs. */
2215: fds = bmake_malloc(sizeof *fds *
2216: (npseudojobs + (size_t)opts.maxJobs) *
2217: nfds_per_job());
2218: allJobs = bmake_malloc(sizeof *allJobs *
2219: (npseudojobs + (size_t)opts.maxJobs) *
2220: nfds_per_job());
1.1 cgd 2221:
1.341 rillig 2222: /* These are permanent entries and take slots 0 and 1 */
2223: watchfd(&tokenWaitJob);
2224: watchfd(&childExitJob);
1.73 gson 2225:
1.341 rillig 2226: sigemptyset(&caught_signals);
2227: /*
2228: * Install a SIGCHLD handler.
2229: */
2230: (void)bmake_signal(SIGCHLD, JobChildSig);
2231: sigaddset(&caught_signals, SIGCHLD);
1.122 dsl 2232:
1.341 rillig 2233: /*
2234: * Catch the four signals that POSIX specifies if they aren't ignored.
2235: * JobPassSig will take care of calling JobInterrupt if appropriate.
2236: */
1.342 rillig 2237: AddSig(SIGINT, JobPassSig_int);
2238: AddSig(SIGHUP, JobPassSig_term);
2239: AddSig(SIGTERM, JobPassSig_term);
2240: AddSig(SIGQUIT, JobPassSig_term);
1.69 pk 2241:
1.341 rillig 2242: /*
2243: * There are additional signals that need to be caught and passed if
2244: * either the export system wants to be told directly of signals or if
2245: * we're giving each job its own process group (since then it won't get
2246: * signals from the terminal driver as we own the terminal)
2247: */
1.342 rillig 2248: AddSig(SIGTSTP, JobPassSig_suspend);
2249: AddSig(SIGTTOU, JobPassSig_suspend);
2250: AddSig(SIGTTIN, JobPassSig_suspend);
2251: AddSig(SIGWINCH, JobCondPassSig);
2252: AddSig(SIGCONT, JobContinueSig);
1.16 christos 2253:
1.341 rillig 2254: (void)Job_RunTarget(".BEGIN", NULL);
2255: /* Create the .END node now, even though no code in the unit tests
2256: * depends on it. See also Targ_GetEndNode in Compat_Run. */
2257: (void)Targ_GetEndNode();
1.1 cgd 2258: }
2259:
1.342 rillig 2260: static void
2261: DelSig(int sig)
2262: {
2263: if (sigismember(&caught_signals, sig))
2264: (void)bmake_signal(sig, SIG_DFL);
2265: }
2266:
1.72 wiz 2267: static void JobSigReset(void)
1.69 pk 2268: {
1.342 rillig 2269: DelSig(SIGINT);
2270: DelSig(SIGHUP);
2271: DelSig(SIGQUIT);
2272: DelSig(SIGTERM);
2273: DelSig(SIGTSTP);
2274: DelSig(SIGTTOU);
2275: DelSig(SIGTTIN);
2276: DelSig(SIGWINCH);
2277: DelSig(SIGCONT);
1.341 rillig 2278: (void)bmake_signal(SIGCHLD, SIG_DFL);
1.69 pk 2279: }
2280:
1.222 rillig 2281: /* Find a shell in 'shells' given its name, or return NULL. */
1.1 cgd 2282: static Shell *
1.301 rillig 2283: FindShellByName(const char *name)
1.1 cgd 2284: {
1.341 rillig 2285: Shell *sh = shells;
2286: const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0];
1.1 cgd 2287:
1.341 rillig 2288: for (sh = shells; sh < shellsEnd; sh++) {
2289: if (strcmp(name, sh->name) == 0)
2290: return sh;
2291: }
2292: return NULL;
1.1 cgd 2293: }
2294:
1.338 rillig 2295: /*
1.355 rillig 2296: * Parse a shell specification and set up 'shell', shellPath and
1.338 rillig 2297: * shellName appropriately.
1.1 cgd 2298: *
1.72 wiz 2299: * Input:
2300: * line The shell spec
2301: *
1.1 cgd 2302: * Results:
1.224 rillig 2303: * FALSE if the specification was incorrect.
1.1 cgd 2304: *
2305: * Side Effects:
1.355 rillig 2306: * 'shell' points to a Shell structure (either predefined or
1.1 cgd 2307: * created from the shell spec), shellPath is the full path of the
1.355 rillig 2308: * shell described by 'shell', while shellName is just the
1.1 cgd 2309: * final component of shellPath.
2310: *
2311: * Notes:
2312: * A shell specification consists of a .SHELL target, with dependency
2313: * operator, followed by a series of blank-separated words. Double
2314: * quotes can be used to use blanks in words. A backslash escapes
2315: * anything (most notably a double-quote and a space) and
2316: * provides the functionality it does in C. Each word consists of
2317: * keyword and value separated by an equal sign. There should be no
2318: * unnecessary spaces in the word. The keywords are as follows:
1.246 rillig 2319: * name Name of shell.
2320: * path Location of shell.
2321: * quiet Command to turn off echoing.
2322: * echo Command to turn echoing on
2323: * filter Result of turning off echoing that shouldn't be
2324: * printed.
2325: * echoFlag Flag to turn echoing on at the start
2326: * errFlag Flag to turn error checking on at the start
2327: * hasErrCtl True if shell has error checking control
2328: * newline String literal to represent a newline char
2329: * check Command to turn on error checking if hasErrCtl
2330: * is TRUE or template of command to echo a command
2331: * for which error checking is off if hasErrCtl is
2332: * FALSE.
2333: * ignore Command to turn off error checking if hasErrCtl
2334: * is TRUE or template of command to execute a
2335: * command so as to ignore any errors it returns if
2336: * hasErrCtl is FALSE.
1.1 cgd 2337: */
1.224 rillig 2338: Boolean
1.72 wiz 2339: Job_ParseShell(char *line)
1.1 cgd 2340: {
1.341 rillig 2341: Words wordsList;
2342: char **words;
2343: char **argv;
2344: size_t argc;
2345: char *path;
2346: Shell newShell;
2347: Boolean fullSpec = FALSE;
2348: Shell *sh;
2349:
2350: pp_skip_whitespace(&line);
2351:
2352: free(shellArgv);
2353:
2354: memset(&newShell, 0, sizeof newShell);
2355:
2356: /*
2357: * Parse the specification by keyword
2358: */
2359: wordsList = Str_Words(line, TRUE);
2360: words = wordsList.words;
2361: argc = wordsList.len;
2362: path = wordsList.freeIt;
2363: if (words == NULL) {
2364: Error("Unterminated quoted string [%s]", line);
1.244 rillig 2365: return FALSE;
2366: }
1.341 rillig 2367: shellArgv = path;
1.1 cgd 2368:
1.341 rillig 2369: for (path = NULL, argv = words; argc != 0; argc--, argv++) {
2370: char *arg = *argv;
2371: if (strncmp(arg, "path=", 5) == 0) {
2372: path = arg + 5;
2373: } else if (strncmp(arg, "name=", 5) == 0) {
2374: newShell.name = arg + 5;
2375: } else {
2376: if (strncmp(arg, "quiet=", 6) == 0) {
2377: newShell.echoOff = arg + 6;
2378: } else if (strncmp(arg, "echo=", 5) == 0) {
2379: newShell.echoOn = arg + 5;
2380: } else if (strncmp(arg, "filter=", 7) == 0) {
2381: newShell.noPrint = arg + 7;
2382: newShell.noPrintLen = strlen(newShell.noPrint);
2383: } else if (strncmp(arg, "echoFlag=", 9) == 0) {
1.366 rillig 2384: newShell.echoFlag = arg + 9;
1.341 rillig 2385: } else if (strncmp(arg, "errFlag=", 8) == 0) {
1.375 rillig 2386: newShell.errFlag = arg + 8;
1.341 rillig 2387: } else if (strncmp(arg, "hasErrCtl=", 10) == 0) {
2388: char c = arg[10];
2389: newShell.hasErrCtl = c == 'Y' || c == 'y' ||
2390: c == 'T' || c == 't';
2391: } else if (strncmp(arg, "newline=", 8) == 0) {
2392: newShell.newline = arg + 8;
2393: } else if (strncmp(arg, "check=", 6) == 0) {
1.359 rillig 2394: /* Before 2020-12-10, these two variables
2395: * had been a single variable. */
1.358 rillig 2396: newShell.errOn = arg + 6;
1.364 rillig 2397: newShell.echoTmpl = arg + 6;
1.341 rillig 2398: } else if (strncmp(arg, "ignore=", 7) == 0) {
1.359 rillig 2399: /* Before 2020-12-10, these two variables
2400: * had been a single variable. */
2401: newShell.errOff = arg + 7;
1.364 rillig 2402: newShell.runIgnTmpl = arg + 7;
1.341 rillig 2403: } else if (strncmp(arg, "errout=", 7) == 0) {
1.364 rillig 2404: newShell.runChkTmpl = arg + 7;
1.341 rillig 2405: } else if (strncmp(arg, "comment=", 8) == 0) {
2406: newShell.commentChar = arg[8];
2407: } else {
2408: Parse_Error(PARSE_FATAL,
2409: "Unknown keyword \"%s\"", arg);
2410: free(words);
2411: return FALSE;
2412: }
2413: fullSpec = TRUE;
2414: }
1.1 cgd 2415: }
1.341 rillig 2416:
1.12 christos 2417: if (path == NULL) {
1.341 rillig 2418: /*
2419: * If no path was given, the user wants one of the
2420: * pre-defined shells, yes? So we find the one s/he wants
2421: * with the help of FindShellByName and set things up the
2422: * right way. shellPath will be set up by Shell_Init.
2423: */
2424: if (newShell.name == NULL) {
2425: Parse_Error(PARSE_FATAL,
2426: "Neither path nor name specified");
2427: free(words);
2428: return FALSE;
2429: } else {
2430: if ((sh = FindShellByName(newShell.name)) == NULL) {
2431: Parse_Error(PARSE_WARNING,
2432: "%s: No matching shell", newShell.name);
2433: free(words);
2434: return FALSE;
2435: }
1.355 rillig 2436: shell = sh;
1.341 rillig 2437: shellName = newShell.name;
2438: if (shellPath != NULL) {
2439: /*
2440: * Shell_Init has already been called!
2441: * Do it again.
2442: */
2443: free(UNCONST(shellPath));
2444: shellPath = NULL;
2445: Shell_Init();
2446: }
2447: }
1.1 cgd 2448: } else {
1.341 rillig 2449: /*
2450: * The user provided a path. If s/he gave nothing else
2451: * (fullSpec is FALSE), try and find a matching shell in the
2452: * ones we know of. Else we just take the specification at
2453: * its word and copy it to a new location. In either case,
2454: * we need to record the path the user gave for the shell.
2455: */
2456: shellPath = path;
2457: path = strrchr(path, '/');
2458: if (path == NULL) {
2459: path = UNCONST(shellPath);
2460: } else {
2461: path++;
2462: }
2463: if (newShell.name != NULL) {
2464: shellName = newShell.name;
2465: } else {
2466: shellName = path;
2467: }
2468: if (!fullSpec) {
2469: if ((sh = FindShellByName(shellName)) == NULL) {
2470: Parse_Error(PARSE_WARNING,
2471: "%s: No matching shell", shellName);
2472: free(words);
2473: return FALSE;
2474: }
1.355 rillig 2475: shell = sh;
1.341 rillig 2476: } else {
1.355 rillig 2477: shell = bmake_malloc(sizeof *shell);
2478: *shell = newShell;
1.341 rillig 2479: }
2480: /* this will take care of shellErrFlag */
2481: Shell_Init();
1.1 cgd 2482: }
1.341 rillig 2483:
1.355 rillig 2484: if (shell->echoOn && shell->echoOff)
2485: shell->hasEchoCtl = TRUE;
1.1 cgd 2486:
1.355 rillig 2487: if (!shell->hasErrCtl) {
1.364 rillig 2488: if (shell->echoTmpl == NULL)
2489: shell->echoTmpl = "";
2490: if (shell->runIgnTmpl == NULL)
2491: shell->runIgnTmpl = "%s\n";
1.1 cgd 2492: }
1.16 christos 2493:
1.341 rillig 2494: /*
2495: * Do not free up the words themselves, since they might be in use
2496: * by the shell specification.
2497: */
2498: free(words);
2499: return TRUE;
1.1 cgd 2500: }
2501:
1.341 rillig 2502: /*
2503: * Handle the receipt of an interrupt.
1.243 rillig 2504: *
2505: * All children are killed. Another job will be started if the .INTERRUPT
2506: * target is defined.
1.1 cgd 2507: *
1.72 wiz 2508: * Input:
2509: * runINTERRUPT Non-zero if commands for the .INTERRUPT target
2510: * should be executed
2511: * signo signal received
1.1 cgd 2512: */
2513: static void
1.72 wiz 2514: JobInterrupt(int runINTERRUPT, int signo)
1.69 pk 2515: {
1.341 rillig 2516: Job *job; /* job descriptor in that element */
2517: GNode *interrupt; /* the node describing the .INTERRUPT target */
2518: sigset_t mask;
2519: GNode *gn;
2520:
2521: aborting = ABORT_INTERRUPT;
2522:
2523: JobSigLock(&mask);
2524:
2525: for (job = job_table; job < job_table_end; job++) {
2526: if (job->status != JOB_ST_RUNNING)
2527: continue;
2528:
2529: gn = job->node;
2530:
2531: JobDeleteTarget(gn);
2532: if (job->pid) {
2533: DEBUG2(JOB,
2534: "JobInterrupt passing signal %d to child %d.\n",
2535: signo, job->pid);
2536: KILLPG(job->pid, signo);
2537: }
1.12 christos 2538: }
2539:
1.341 rillig 2540: JobSigUnlock(&mask);
1.69 pk 2541:
1.341 rillig 2542: if (runINTERRUPT && !opts.touchFlag) {
2543: interrupt = Targ_FindNode(".INTERRUPT");
2544: if (interrupt != NULL) {
2545: opts.ignoreErrors = FALSE;
2546: JobRun(interrupt);
2547: }
1.1 cgd 2548: }
1.341 rillig 2549: Trace_Log(MAKEINTR, NULL);
1.368 rillig 2550: exit(signo); /* XXX: why signo? */
1.1 cgd 2551: }
2552:
1.341 rillig 2553: /*
2554: * Do the final processing, i.e. run the commands attached to the .END target.
1.1 cgd 2555: *
1.341 rillig 2556: * Return the number of errors reported.
2557: */
1.1 cgd 2558: int
1.72 wiz 2559: Job_Finish(void)
1.1 cgd 2560: {
1.341 rillig 2561: GNode *endNode = Targ_GetEndNode();
2562: if (!Lst_IsEmpty(&endNode->commands) ||
2563: !Lst_IsEmpty(&endNode->children)) {
2564: if (job_errors != 0) {
2565: Error("Errors reported so .END ignored");
2566: } else {
2567: JobRun(endNode);
2568: }
1.1 cgd 2569: }
1.341 rillig 2570: return job_errors;
1.22 christos 2571: }
2572:
1.243 rillig 2573: /* Clean up any memory used by the jobs module. */
1.22 christos 2574: void
1.72 wiz 2575: Job_End(void)
1.22 christos 2576: {
1.30 mycroft 2577: #ifdef CLEANUP
1.341 rillig 2578: free(shellArgv);
1.30 mycroft 2579: #endif
1.1 cgd 2580: }
2581:
1.341 rillig 2582: /*
2583: * Waits for all running jobs to finish and returns.
2584: * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting.
2585: */
1.1 cgd 2586: void
1.72 wiz 2587: Job_Wait(void)
1.1 cgd 2588: {
1.341 rillig 2589: aborting = ABORT_WAIT;
2590: while (jobTokensRunning != 0) {
2591: Job_CatchOutput();
2592: }
2593: aborting = ABORT_NONE;
1.1 cgd 2594: }
2595:
1.341 rillig 2596: /*
2597: * Abort all currently running jobs without handling output or anything.
1.243 rillig 2598: * This function is to be called only in the event of a major error.
2599: * Most definitely NOT to be called from JobInterrupt.
1.1 cgd 2600: *
1.341 rillig 2601: * All children are killed, not just the firstborn.
2602: */
1.1 cgd 2603: void
1.72 wiz 2604: Job_AbortAll(void)
1.1 cgd 2605: {
1.341 rillig 2606: Job *job; /* the job descriptor in that element */
2607: int foo;
1.16 christos 2608:
1.341 rillig 2609: aborting = ABORT_ERROR;
1.16 christos 2610:
1.341 rillig 2611: if (jobTokensRunning != 0) {
2612: for (job = job_table; job < job_table_end; job++) {
2613: if (job->status != JOB_ST_RUNNING)
2614: continue;
2615: /*
2616: * kill the child process with increasingly drastic
2617: * signals to make darn sure it's dead.
2618: */
2619: KILLPG(job->pid, SIGINT);
2620: KILLPG(job->pid, SIGKILL);
2621: }
1.1 cgd 2622: }
1.16 christos 2623:
1.341 rillig 2624: /*
2625: * Catch as many children as want to report in at first, then give up
2626: */
2627: while (waitpid((pid_t)-1, &foo, WNOHANG) > 0)
2628: continue;
1.12 christos 2629: }
2630:
1.341 rillig 2631: /*
2632: * Tries to restart stopped jobs if there are slots available.
2633: * Called in process context in response to a SIGCONT.
2634: */
1.12 christos 2635: static void
1.72 wiz 2636: JobRestartJobs(void)
1.12 christos 2637: {
1.341 rillig 2638: Job *job;
1.69 pk 2639:
1.341 rillig 2640: for (job = job_table; job < job_table_end; job++) {
2641: if (job->status == JOB_ST_RUNNING &&
2642: (make_suspended || job->suspended)) {
2643: DEBUG1(JOB, "Restarting stopped job pid %d.\n",
2644: job->pid);
2645: if (job->suspended) {
2646: (void)printf("*** [%s] Continued\n",
2647: job->node->name);
2648: (void)fflush(stdout);
2649: }
2650: job->suspended = FALSE;
2651: if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) {
2652: debug_printf("Failed to send SIGCONT to %d\n",
2653: job->pid);
2654: }
2655: }
2656: if (job->status == JOB_ST_FINISHED) {
2657: /*
2658: * Job exit deferred after calling waitpid() in a
2659: * signal handler
2660: */
2661: JobFinish(job, job->exit_status);
2662: }
2663: }
2664: make_suspended = FALSE;
1.1 cgd 2665: }
1.35 christos 2666:
2667: static void
1.72 wiz 2668: watchfd(Job *job)
1.35 christos 2669: {
1.341 rillig 2670: if (job->inPollfd != NULL)
2671: Punt("Watching watched job");
1.35 christos 2672:
1.341 rillig 2673: fds[nJobs].fd = job->inPipe;
2674: fds[nJobs].events = POLLIN;
1.330 rillig 2675: allJobs[nJobs] = job;
1.341 rillig 2676: job->inPollfd = &fds[nJobs];
1.330 rillig 2677: nJobs++;
1.341 rillig 2678: #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2679: if (useMeta) {
2680: fds[nJobs].fd = meta_job_fd(job);
2681: fds[nJobs].events = fds[nJobs].fd == -1 ? 0 : POLLIN;
2682: allJobs[nJobs] = job;
2683: nJobs++;
2684: }
1.196 riastrad 2685: #endif
1.35 christos 2686: }
2687:
2688: static void
1.72 wiz 2689: clearfd(Job *job)
1.35 christos 2690: {
1.341 rillig 2691: size_t i;
2692: if (job->inPollfd == NULL)
2693: Punt("Unwatching unwatched job");
2694: i = (size_t)(job->inPollfd - fds);
2695: nJobs--;
1.197 sjg 2696: #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
1.341 rillig 2697: if (useMeta) {
2698: /*
2699: * Sanity check: there should be two fds per job, so the job's
2700: * pollfd number should be even.
2701: */
2702: assert(nfds_per_job() == 2);
2703: if (i % 2)
2704: Punt("odd-numbered fd with meta");
2705: nJobs--;
2706: }
2707: #endif
1.196 riastrad 2708: /*
1.341 rillig 2709: * Move last job in table into hole made by dead job.
1.196 riastrad 2710: */
1.341 rillig 2711: if (nJobs != i) {
2712: fds[i] = fds[nJobs];
2713: allJobs[i] = allJobs[nJobs];
2714: allJobs[i]->inPollfd = &fds[i];
2715: #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2716: if (useMeta) {
2717: fds[i + 1] = fds[nJobs + 1];
2718: allJobs[i + 1] = allJobs[nJobs + 1];
2719: }
1.196 riastrad 2720: #endif
2721: }
1.341 rillig 2722: job->inPollfd = NULL;
1.35 christos 2723: }
2724:
2725: static int
1.72 wiz 2726: readyfd(Job *job)
1.35 christos 2727: {
1.341 rillig 2728: if (job->inPollfd == NULL)
2729: Punt("Polling unwatched job");
2730: return (job->inPollfd->revents & POLLIN) != 0;
1.35 christos 2731: }
1.40 sommerfe 2732:
1.243 rillig 2733: /* Put a token (back) into the job pipe.
2734: * This allows a make process to start a build job. */
1.40 sommerfe 2735: static void
1.72 wiz 2736: JobTokenAdd(void)
1.40 sommerfe 2737: {
1.341 rillig 2738: char tok = JOB_TOKENS[aborting], tok1;
1.101 dsl 2739:
1.341 rillig 2740: /* If we are depositing an error token flush everything else */
2741: while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1)
2742: continue;
2743:
2744: DEBUG3(JOB, "(%d) aborting %d, deposit token %c\n",
2745: getpid(), aborting, JOB_TOKENS[aborting]);
2746: while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
2747: continue;
1.40 sommerfe 2748: }
2749:
1.243 rillig 2750: /* Prep the job token pipe in the root make process. */
1.72 wiz 2751: void
1.122 dsl 2752: Job_ServerStart(int max_tokens, int jp_0, int jp_1)
1.40 sommerfe 2753: {
1.341 rillig 2754: int i;
2755: char jobarg[64];
1.201 rillig 2756:
1.341 rillig 2757: if (jp_0 >= 0 && jp_1 >= 0) {
2758: /* Pipe passed in from parent */
2759: tokenWaitJob.inPipe = jp_0;
2760: tokenWaitJob.outPipe = jp_1;
2761: (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC);
2762: (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC);
2763: return;
2764: }
1.100 dsl 2765:
1.341 rillig 2766: JobCreatePipe(&tokenWaitJob, 15);
1.40 sommerfe 2767:
1.341 rillig 2768: snprintf(jobarg, sizeof jobarg, "%d,%d",
1.122 dsl 2769: tokenWaitJob.inPipe, tokenWaitJob.outPipe);
1.40 sommerfe 2770:
1.341 rillig 2771: Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
2772: Var_Append(MAKEFLAGS, jobarg, VAR_GLOBAL);
1.101 dsl 2773:
1.341 rillig 2774: /*
2775: * Preload the job pipe with one token per job, save the one
2776: * "extra" token for the primary job.
2777: *
2778: * XXX should clip maxJobs against PIPE_BUF -- if max_tokens is
2779: * larger than the write buffer size of the pipe, we will
2780: * deadlock here.
2781: */
2782: for (i = 1; i < max_tokens; i++)
2783: JobTokenAdd();
1.40 sommerfe 2784: }
2785:
1.243 rillig 2786: /* Return a withdrawn token to the pool. */
1.40 sommerfe 2787: void
1.72 wiz 2788: Job_TokenReturn(void)
1.40 sommerfe 2789: {
1.341 rillig 2790: jobTokensRunning--;
2791: if (jobTokensRunning < 0)
2792: Punt("token botch");
2793: if (jobTokensRunning || JOB_TOKENS[aborting] != '+')
2794: JobTokenAdd();
1.40 sommerfe 2795: }
2796:
1.341 rillig 2797: /*
2798: * Attempt to withdraw a token from the pool.
1.40 sommerfe 2799: *
1.243 rillig 2800: * If pool is empty, set wantToken so that we wake up when a token is
2801: * released.
1.40 sommerfe 2802: *
1.243 rillig 2803: * Returns TRUE if a token was withdrawn, and FALSE if the pool is currently
1.341 rillig 2804: * empty.
2805: */
1.40 sommerfe 2806: Boolean
1.72 wiz 2807: Job_TokenWithdraw(void)
1.40 sommerfe 2808: {
1.341 rillig 2809: char tok, tok1;
2810: ssize_t count;
1.40 sommerfe 2811:
1.341 rillig 2812: wantToken = 0;
2813: DEBUG3(JOB, "Job_TokenWithdraw(%d): aborting %d, running %d\n",
2814: getpid(), aborting, jobTokensRunning);
1.60 enami 2815:
1.341 rillig 2816: if (aborting != ABORT_NONE || (jobTokensRunning >= opts.maxJobs))
2817: return FALSE;
1.40 sommerfe 2818:
1.341 rillig 2819: count = read(tokenWaitJob.inPipe, &tok, 1);
2820: if (count == 0)
2821: Fatal("eof on job pipe!");
2822: if (count < 0 && jobTokensRunning != 0) {
2823: if (errno != EAGAIN) {
2824: Fatal("job pipe read: %s", strerror(errno));
2825: }
2826: DEBUG1(JOB, "(%d) blocked for token\n", getpid());
2827: return FALSE;
1.40 sommerfe 2828: }
1.102 dsl 2829:
1.341 rillig 2830: if (count == 1 && tok != '+') {
2831: /* make being aborted - remove any other job tokens */
2832: DEBUG2(JOB, "(%d) aborted by token %c\n", getpid(), tok);
2833: while (read(tokenWaitJob.inPipe, &tok1, 1) == 1)
2834: continue;
2835: /* And put the stopper back */
2836: while (write(tokenWaitJob.outPipe, &tok, 1) == -1 &&
2837: errno == EAGAIN)
2838: continue;
2839: if (shouldDieQuietly(NULL, 1))
2840: exit(2);
2841: Fatal("A failure has been detected "
2842: "in another branch of the parallel make");
2843: }
2844:
2845: if (count == 1 && jobTokensRunning == 0)
2846: /* We didn't want the token really */
2847: while (write(tokenWaitJob.outPipe, &tok, 1) == -1 &&
2848: errno == EAGAIN)
2849: continue;
1.102 dsl 2850:
1.341 rillig 2851: jobTokensRunning++;
2852: DEBUG1(JOB, "(%d) withdrew token\n", getpid());
2853: return TRUE;
1.41 sommerfe 2854: }
2855:
1.341 rillig 2856: /*
2857: * Run the named target if found. If a filename is specified, then set that
1.243 rillig 2858: * to the sources.
1.172 christos 2859: *
1.341 rillig 2860: * Exits if the target fails.
2861: */
1.172 christos 2862: Boolean
1.341 rillig 2863: Job_RunTarget(const char *target, const char *fname)
2864: {
2865: GNode *gn = Targ_FindNode(target);
2866: if (gn == NULL)
2867: return FALSE;
1.172 christos 2868:
1.341 rillig 2869: if (fname != NULL)
2870: Var_Set(ALLSRC, fname, gn);
1.172 christos 2871:
1.341 rillig 2872: JobRun(gn);
2873: /* XXX: Replace with GNode_IsError(gn) */
2874: if (gn->made == ERROR) {
2875: PrintOnError(gn, "\n\nStop.");
2876: exit(1);
2877: }
2878: return TRUE;
1.172 christos 2879: }
2880:
1.73 gson 2881: #ifdef USE_SELECT
2882: int
2883: emul_poll(struct pollfd *fd, int nfd, int timeout)
2884: {
1.341 rillig 2885: fd_set rfds, wfds;
2886: int i, maxfd, nselect, npoll;
2887: struct timeval tv, *tvp;
2888: long usecs;
1.73 gson 2889:
1.341 rillig 2890: FD_ZERO(&rfds);
2891: FD_ZERO(&wfds);
1.73 gson 2892:
1.341 rillig 2893: maxfd = -1;
2894: for (i = 0; i < nfd; i++) {
2895: fd[i].revents = 0;
1.73 gson 2896:
1.341 rillig 2897: if (fd[i].events & POLLIN)
2898: FD_SET(fd[i].fd, &rfds);
2899:
2900: if (fd[i].events & POLLOUT)
2901: FD_SET(fd[i].fd, &wfds);
2902:
2903: if (fd[i].fd > maxfd)
2904: maxfd = fd[i].fd;
2905: }
1.201 rillig 2906:
1.341 rillig 2907: if (maxfd >= FD_SETSIZE) {
2908: Punt("Ran out of fd_set slots; "
2909: "recompile with a larger FD_SETSIZE.");
2910: }
1.73 gson 2911:
1.341 rillig 2912: if (timeout < 0) {
2913: tvp = NULL;
2914: } else {
2915: usecs = timeout * 1000;
2916: tv.tv_sec = usecs / 1000000;
2917: tv.tv_usec = usecs % 1000000;
2918: tvp = &tv;
2919: }
1.73 gson 2920:
1.341 rillig 2921: nselect = select(maxfd + 1, &rfds, &wfds, NULL, tvp);
1.73 gson 2922:
1.341 rillig 2923: if (nselect <= 0)
2924: return nselect;
1.73 gson 2925:
1.341 rillig 2926: npoll = 0;
2927: for (i = 0; i < nfd; i++) {
2928: if (FD_ISSET(fd[i].fd, &rfds))
2929: fd[i].revents |= POLLIN;
1.73 gson 2930:
1.341 rillig 2931: if (FD_ISSET(fd[i].fd, &wfds))
2932: fd[i].revents |= POLLOUT;
1.73 gson 2933:
1.341 rillig 2934: if (fd[i].revents)
2935: npoll++;
2936: }
1.73 gson 2937:
1.341 rillig 2938: return npoll;
1.73 gson 2939: }
2940: #endif /* USE_SELECT */
CVSweb <webmaster@jp.NetBSD.org>