32
33 /*
34 * Included files
35 */
36 #include <sys/wait.h> /* WIFEXITED(status) */
37 #include <alloca.h> /* alloca() */
38
39 #include <stdio.h> /* errno */
40 #include <errno.h> /* errno */
41 #include <fcntl.h> /* open() */
42 #include <mksh/dosys.h>
43 #include <mksh/macro.h> /* getvar() */
44 #include <mksh/misc.h> /* getmem(), fatal_mksh(), errmsg() */
45 #include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */
46 #include <sys/signal.h> /* SIG_DFL */
47 #include <sys/stat.h> /* open() */
48 #include <sys/wait.h> /* wait() */
49 #include <ulimit.h> /* ulimit() */
50 #include <unistd.h> /* close(), dup2() */
51
52
53
54 /*
55 * Defined macros
56 */
57 #define SEND_MTOOL_MSG(cmds)
58
59 /*
60 * typedefs & structs
61 */
62
63 /*
64 * Static variables
65 */
66
67 /*
68 * File table of contents
69 */
70 static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path);
71
72 /*
73 * Workaround for NFS bug. Sometimes, when running 'open' on a remote
74 * dmake server, it fails with "Stale NFS file handle" error.
75 * The second attempt seems to work.
76 */
77 int
78 my_open(const char *path, int oflag, mode_t mode) {
119 if (dup2(1, 2) == -1) {
120 fatal_mksh(NOCATGETS("*** Error: dup2(1, 2) failed: %s"),
121 errmsg(errno));
122 }
123 } else if ((i = my_open(stderr_file,
124 O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
125 S_IREAD | S_IWRITE)) < 0) {
126 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 91, "Couldn't open standard error temp file `%s': %s"),
127 stderr_file,
128 errmsg(errno));
129 } else {
130 if (dup2(i, 2) == -1) {
131 fatal_mksh(NOCATGETS("*** Error: dup2(3, 2) failed: %s"),
132 errmsg(errno));
133 }
134 close(i);
135 }
136 }
137
138 /*
139 * dosys_mksh(command, ignore_error, call_make, silent_error, target)
140 *
141 * Check if command string contains meta chars and dispatch to
142 * the proper routine for executing one command line.
143 *
144 * Return value:
145 * Indicates if the command execution failed
146 *
147 * Parameters:
148 * command The command to run
149 * ignore_error Should we abort when an error is seen?
150 * call_make Did command reference $(MAKE) ?
151 * silent_error Should error messages be suppressed for dmake?
152 * target Target we are building
153 *
154 * Global variables used:
155 * do_not_exec_rule Is -n on?
156 * working_on_targets We started processing real targets
157 */
158 Doname
159 dosys_mksh(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio)
160 {
161 register int length = command->hash.length;
162 register wchar_t *p;
163 register wchar_t *q;
164 register wchar_t *cmd_string;
165 struct stat before;
166 Doname result;
167 Boolean working_on_targets_mksh = true;
168 Wstring wcb(command);
169 p = wcb.get_string();
170 cmd_string = p;
171
172 /* Strip spaces from head of command string */
173 while (iswspace(*p)) {
174 p++, length--;
175 }
176 if (*p == (int) nul_char) {
177 return build_failed;
178 }
179 /* If we are faking it we just return */
180 if (do_not_exec_rule &&
181 working_on_targets_mksh &&
182 !call_make &&
183 !always_exec) {
184 return build_ok;
185 }
186
187 /* Copy string to make it OK to write it. */
188 q = ALLOC_WC(length + 1);
189 (void) wscpy(q, p);
190 /* Write the state file iff this command uses make. */
191 /* XXX - currently does not support recursive make's, $(MAKE)'s
192 if (call_make && command_changed) {
193 write_state_file(0, false);
194 }
195 (void) stat(make_state->string_mb, &before);
196 */
197 /*
198 * Run command directly if it contains no shell meta chars,
199 * else run it using the shell.
200 */
201 /* XXX - command->meta *may* not be set correctly */
202 if (await(ignore_error,
203 silent_error,
204 target,
205 cmd_string,
206 command->meta ?
207 doshell(q, ignore_error, redirect_out_err, stdout_file, stderr_file, nice_prio) :
208 doexec(q, ignore_error, redirect_out_err, stdout_file, stderr_file, vroot_path, nice_prio),
209 false,
210 NULL,
211 -1)) {
212
213 #ifdef PRINT_EXIT_STATUS
214 warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_ok."));
215 #endif
216
217 result = build_ok;
218 } else {
219
220 #ifdef PRINT_EXIT_STATUS
221 warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_failed."));
222 #endif
223
224 result = build_failed;
225 }
226 retmem(q);
227
228 /* XXX - currently does not support recursive make's, $(MAKE)'s
229 if ((report_dependencies_level == 0) &&
230 call_make) {
231 make_state->stat.time = (time_t)file_no_time;
232 (void)exists(make_state);
233 if (before.st_mtime == make_state->stat.time) {
234 return result;
235 }
236 makefile_type = reading_statefile;
237 if (read_trace_level > 1) {
238 trace_reader = true;
239 }
240 (void) read_simple_file(make_state,
241 false,
242 false,
243 false,
244 false,
245 false,
246 true);
247 trace_reader = false;
248 }
249 */
250 return result;
251 }
252
253 /*
254 * doshell(command, ignore_error)
255 *
256 * Used to run command lines that include shell meta-characters.
257 * The make macro SHELL is supposed to contain a path to the shell.
258 *
259 * Return value:
260 * The pid of the process we started
261 *
262 * Parameters:
263 * command The command to run
264 * ignore_error Should we abort on error?
265 *
266 * Global variables used:
267 * filter_stderr If -X is on we redirect stderr
268 * shell_name The Name "SHELL", used to get the path to shell
269 */
270 int
271 doshell(wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, int nice_prio)
272 {
273 char *argv[6];
274 int argv_index = 0;
275 int cmd_argv_index;
276 int length;
277 char nice_prio_buf[MAXPATHLEN];
278 register Name shell = getvar(shell_name);
279 register char *shellname;
280 char *tmp_mbs_buffer;
281
282
283 if (IS_EQUAL(shell->string_mb, "")) {
284 shell = shell_name;
285 }
286 if ((shellname = strrchr(shell->string_mb, (int) slash_char)) == NULL) {
287 shellname = shell->string_mb;
288 } else {
289 shellname++;
290 }
291
299 (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio);
300 argv[argv_index++] = strdup(nice_prio_buf);
301 }
302 argv[argv_index++] = shellname;
303 argv[argv_index++] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce"));
304 if ((length = wslen(command)) >= MAXPATHLEN) {
305 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
306 (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
307 cmd_argv_index = argv_index;
308 argv[argv_index++] = strdup(tmp_mbs_buffer);
309 retmem_mb(tmp_mbs_buffer);
310 } else {
311 WCSTOMBS(mbs_buffer, command);
312 cmd_argv_index = argv_index;
313 argv[argv_index++] = strdup(mbs_buffer);
314 }
315 argv[argv_index] = NULL;
316 (void) fflush(stdout);
317 if ((childPid = fork()) == 0) {
318 enable_interrupt((void (*) (int)) SIG_DFL);
319 if (redirect_out_err) {
320 redirect_io(stdout_file, stderr_file);
321 }
322 #if 0
323 if (filter_stderr) {
324 redirect_stderr();
325 }
326 #endif
327 if (nice_prio != 0) {
328 (void) execve(NOCATGETS("/usr/bin/nice"), argv, environ);
329 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 92, "Could not load `/usr/bin/nice': %s"),
330 errmsg(errno));
331 } else {
332 (void) execve(shell->string_mb, argv, environ);
333 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 93, "Could not load Shell from `%s': %s"),
334 shell->string_mb,
335 errmsg(errno));
336 }
337 }
338 if (childPid == -1) {
339 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 94, "fork failed: %s"),
340 errmsg(errno));
341 }
419 return failed;
420 }
421
422 /*
423 * doexec(command, ignore_error)
424 *
425 * Will scan an argument string and split it into words
426 * thus building an argument list that can be passed to exec_ve()
427 *
428 * Return value:
429 * The pid of the process started here
430 *
431 * Parameters:
432 * command The command to run
433 * ignore_error Should we abort on error?
434 *
435 * Global variables used:
436 * filter_stderr If -X is on we redirect stderr
437 */
438 int
439 doexec(register wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio)
440 {
441 int arg_count = 5;
442 char **argv;
443 int length;
444 char nice_prio_buf[MAXPATHLEN];
445 register char **p;
446 wchar_t *q;
447 register wchar_t *t;
448 char *tmp_mbs_buffer;
449
450 /*
451 * Only prepend the /usr/bin/nice command to the original command
452 * if the nice priority, nice_prio, is NOT zero (0).
453 * Nice priorities can be a positive or a negative number.
454 */
455 if (nice_prio != 0) {
456 arg_count += 2;
457 }
458 for (t = command; *t != (int) nul_char; t++) {
459 if (iswspace(*t)) {
497 }
498 if (*t) {
499 for (*t++ = (int) nul_char; iswspace(*t); t++);
500 }
501 if ((length = wslen(q)) >= MAXPATHLEN) {
502 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
503 (void) wcstombs(tmp_mbs_buffer, q, (length * MB_LEN_MAX) + 1);
504 *p++ = strdup(tmp_mbs_buffer);
505 retmem_mb(tmp_mbs_buffer);
506 } else {
507 WCSTOMBS(mbs_buffer, q);
508 *p++ = strdup(mbs_buffer);
509 }
510 }
511 *p = NULL;
512
513 /* Then exec the command with that argument list. */
514 (void) fflush(stdout);
515 if ((childPid = fork()) == 0) {
516 enable_interrupt((void (*) (int)) SIG_DFL);
517 if (redirect_out_err) {
518 redirect_io(stdout_file, stderr_file);
519 }
520 #if 0
521 if (filter_stderr) {
522 redirect_stderr();
523 }
524 #endif
525 (void) exec_vp(argv[1], argv, environ, ignore_error, vroot_path);
526 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 96, "Cannot load command `%s': %s"), argv[1], errmsg(errno));
527 }
528 if (childPid == -1) {
529 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 97, "fork failed: %s"),
530 errmsg(errno));
531 }
532 for (int i = 0; argv[i] != NULL; i++) {
533 retmem_mb(argv[i]);
534 }
535 return childPid;
536 }
537
538 /*
539 * await(ignore_error, silent_error, target, command, running_pid)
542 * the returned status when the child process terminates.
543 *
544 * Return value:
545 * Returns true if commands ran OK
546 *
547 * Parameters:
548 * ignore_error Should we abort on error?
549 * silent_error Should error messages be suppressed for dmake?
550 * target The target we are building, for error msgs
551 * command The command we ran, for error msgs
552 * running_pid The pid of the process we are waiting for
553 *
554 * Static variables used:
555 * filter_file The fd for the filter file
556 * filter_file_name The name of the filter file
557 *
558 * Global variables used:
559 * filter_stderr Set if -X is on
560 */
561 Boolean
562 await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, void *xdrs_p, int job_msg_id)
563 {
564 int status;
565 char *buffer;
566 int core_dumped;
567 int exit_status;
568 FILE *outfp;
569 register pid_t pid;
570 struct stat stat_buff;
571 int termination_signal;
572 char tmp_buf[MAXPATHLEN];
573
574 while ((pid = wait(&status)) != running_pid) {
575 if (pid == -1) {
576 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 98, "wait() failed: %s"), errmsg(errno));
577 }
578 }
579 (void) fflush(stdout);
580 (void) fflush(stderr);
581
582 if (status == 0) {
589 }
590
591 #ifdef PRINT_EXIT_STATUS
592 warning_mksh(NOCATGETS("I'm in await(), and status is *NOT* 0."));
593 #endif
594
595
596 exit_status = WEXITSTATUS(status);
597
598 #ifdef PRINT_EXIT_STATUS
599 warning_mksh(NOCATGETS("I'm in await(), and exit_status is %d."), exit_status);
600 #endif
601
602 termination_signal = WTERMSIG(status);
603 core_dumped = WCOREDUMP(status);
604
605 /*
606 * If the child returned an error, we now try to print a
607 * nice message about it.
608 */
609 SEND_MTOOL_MSG(
610 make_output_msg = new Avo_CmdOutput();
611 (void) sprintf(tmp_buf, "%d", job_msg_id);
612 make_output_msg->appendOutput(strdup(tmp_buf));
613 );
614
615 tmp_buf[0] = (int) nul_char;
616 if (!silent_error) {
617 if (exit_status != 0) {
618 (void) fprintf(stdout,
619 catgets(libmksdmsi18n_catd, 1, 103, "*** Error code %d"),
620 exit_status);
621 SEND_MTOOL_MSG(
622 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
623 catgets(libmksdmsi18n_catd, 1, 104, "*** Error code %d"),
624 exit_status);
625 );
626 } else {
627 (void) fprintf(stdout,
628 catgets(libmksdmsi18n_catd, 1, 105, "*** Signal %d"),
629 termination_signal);
630 SEND_MTOOL_MSG(
631 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
632 catgets(libmksdmsi18n_catd, 1, 106, "*** Signal %d"),
633 termination_signal);
634 );
635 if (core_dumped) {
636 (void) fprintf(stdout,
637 catgets(libmksdmsi18n_catd, 1, 107, " - core dumped"));
638 SEND_MTOOL_MSG(
639 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
640 catgets(libmksdmsi18n_catd, 1, 108, " - core dumped"));
641 );
642 }
643 }
644 if (ignore_error) {
645 (void) fprintf(stdout,
646 catgets(libmksdmsi18n_catd, 1, 109, " (ignored)"));
647 SEND_MTOOL_MSG(
648 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
649 catgets(libmksdmsi18n_catd, 1, 110, " (ignored)"));
650 );
651 }
652 (void) fprintf(stdout, "\n");
653 (void) fflush(stdout);
654 SEND_MTOOL_MSG(
655 make_output_msg->appendOutput(strdup(tmp_buf));
656 );
657 }
658 SEND_MTOOL_MSG(
659 xdr_msg = (RWCollectable*) make_output_msg;
660 xdr(xdrs_p, xdr_msg);
661 delete make_output_msg;
662 );
663
664 #ifdef PRINT_EXIT_STATUS
665 warning_mksh(NOCATGETS("I'm in await(), returning failed."));
666 #endif
667
668 return failed;
669 }
670
671 /*
672 * sh_command2string(command, destination)
673 *
674 * Run one sh command and capture the output from it.
675 *
676 * Return value:
677 *
678 * Parameters:
679 * command The command to run
680 * destination Where to deposit the output from the command
681 *
682 * Static variables used:
|
32
33 /*
34 * Included files
35 */
36 #include <sys/wait.h> /* WIFEXITED(status) */
37 #include <alloca.h> /* alloca() */
38
39 #include <stdio.h> /* errno */
40 #include <errno.h> /* errno */
41 #include <fcntl.h> /* open() */
42 #include <mksh/dosys.h>
43 #include <mksh/macro.h> /* getvar() */
44 #include <mksh/misc.h> /* getmem(), fatal_mksh(), errmsg() */
45 #include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */
46 #include <sys/signal.h> /* SIG_DFL */
47 #include <sys/stat.h> /* open() */
48 #include <sys/wait.h> /* wait() */
49 #include <ulimit.h> /* ulimit() */
50 #include <unistd.h> /* close(), dup2() */
51
52 /*
53 * typedefs & structs
54 */
55
56 /*
57 * Static variables
58 */
59
60 /*
61 * File table of contents
62 */
63 static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path);
64
65 /*
66 * Workaround for NFS bug. Sometimes, when running 'open' on a remote
67 * dmake server, it fails with "Stale NFS file handle" error.
68 * The second attempt seems to work.
69 */
70 int
71 my_open(const char *path, int oflag, mode_t mode) {
112 if (dup2(1, 2) == -1) {
113 fatal_mksh(NOCATGETS("*** Error: dup2(1, 2) failed: %s"),
114 errmsg(errno));
115 }
116 } else if ((i = my_open(stderr_file,
117 O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
118 S_IREAD | S_IWRITE)) < 0) {
119 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 91, "Couldn't open standard error temp file `%s': %s"),
120 stderr_file,
121 errmsg(errno));
122 } else {
123 if (dup2(i, 2) == -1) {
124 fatal_mksh(NOCATGETS("*** Error: dup2(3, 2) failed: %s"),
125 errmsg(errno));
126 }
127 close(i);
128 }
129 }
130
131 /*
132 * doshell(command, ignore_error)
133 *
134 * Used to run command lines that include shell meta-characters.
135 * The make macro SHELL is supposed to contain a path to the shell.
136 *
137 * Return value:
138 * The pid of the process we started
139 *
140 * Parameters:
141 * command The command to run
142 * ignore_error Should we abort on error?
143 *
144 * Global variables used:
145 * filter_stderr If -X is on we redirect stderr
146 * shell_name The Name "SHELL", used to get the path to shell
147 */
148 int
149 doshell(wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, int nice_prio)
150 {
151 char *argv[6];
152 int argv_index = 0;
153 int cmd_argv_index;
154 int length;
155 char nice_prio_buf[MAXPATHLEN];
156 register Name shell = getvar(shell_name);
157 register char *shellname;
158 char *tmp_mbs_buffer;
159
160
161 if (IS_EQUAL(shell->string_mb, "")) {
162 shell = shell_name;
163 }
164 if ((shellname = strrchr(shell->string_mb, (int) slash_char)) == NULL) {
165 shellname = shell->string_mb;
166 } else {
167 shellname++;
168 }
169
177 (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio);
178 argv[argv_index++] = strdup(nice_prio_buf);
179 }
180 argv[argv_index++] = shellname;
181 argv[argv_index++] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce"));
182 if ((length = wslen(command)) >= MAXPATHLEN) {
183 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
184 (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
185 cmd_argv_index = argv_index;
186 argv[argv_index++] = strdup(tmp_mbs_buffer);
187 retmem_mb(tmp_mbs_buffer);
188 } else {
189 WCSTOMBS(mbs_buffer, command);
190 cmd_argv_index = argv_index;
191 argv[argv_index++] = strdup(mbs_buffer);
192 }
193 argv[argv_index] = NULL;
194 (void) fflush(stdout);
195 if ((childPid = fork()) == 0) {
196 enable_interrupt((void (*) (int)) SIG_DFL);
197 #if 0
198 if (filter_stderr) {
199 redirect_stderr();
200 }
201 #endif
202 if (nice_prio != 0) {
203 (void) execve(NOCATGETS("/usr/bin/nice"), argv, environ);
204 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 92, "Could not load `/usr/bin/nice': %s"),
205 errmsg(errno));
206 } else {
207 (void) execve(shell->string_mb, argv, environ);
208 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 93, "Could not load Shell from `%s': %s"),
209 shell->string_mb,
210 errmsg(errno));
211 }
212 }
213 if (childPid == -1) {
214 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 94, "fork failed: %s"),
215 errmsg(errno));
216 }
294 return failed;
295 }
296
297 /*
298 * doexec(command, ignore_error)
299 *
300 * Will scan an argument string and split it into words
301 * thus building an argument list that can be passed to exec_ve()
302 *
303 * Return value:
304 * The pid of the process started here
305 *
306 * Parameters:
307 * command The command to run
308 * ignore_error Should we abort on error?
309 *
310 * Global variables used:
311 * filter_stderr If -X is on we redirect stderr
312 */
313 int
314 doexec(register wchar_t *command, register Boolean ignore_error, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio)
315 {
316 int arg_count = 5;
317 char **argv;
318 int length;
319 char nice_prio_buf[MAXPATHLEN];
320 register char **p;
321 wchar_t *q;
322 register wchar_t *t;
323 char *tmp_mbs_buffer;
324
325 /*
326 * Only prepend the /usr/bin/nice command to the original command
327 * if the nice priority, nice_prio, is NOT zero (0).
328 * Nice priorities can be a positive or a negative number.
329 */
330 if (nice_prio != 0) {
331 arg_count += 2;
332 }
333 for (t = command; *t != (int) nul_char; t++) {
334 if (iswspace(*t)) {
372 }
373 if (*t) {
374 for (*t++ = (int) nul_char; iswspace(*t); t++);
375 }
376 if ((length = wslen(q)) >= MAXPATHLEN) {
377 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
378 (void) wcstombs(tmp_mbs_buffer, q, (length * MB_LEN_MAX) + 1);
379 *p++ = strdup(tmp_mbs_buffer);
380 retmem_mb(tmp_mbs_buffer);
381 } else {
382 WCSTOMBS(mbs_buffer, q);
383 *p++ = strdup(mbs_buffer);
384 }
385 }
386 *p = NULL;
387
388 /* Then exec the command with that argument list. */
389 (void) fflush(stdout);
390 if ((childPid = fork()) == 0) {
391 enable_interrupt((void (*) (int)) SIG_DFL);
392 #if 0
393 if (filter_stderr) {
394 redirect_stderr();
395 }
396 #endif
397 (void) exec_vp(argv[1], argv, environ, ignore_error, vroot_path);
398 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 96, "Cannot load command `%s': %s"), argv[1], errmsg(errno));
399 }
400 if (childPid == -1) {
401 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 97, "fork failed: %s"),
402 errmsg(errno));
403 }
404 for (int i = 0; argv[i] != NULL; i++) {
405 retmem_mb(argv[i]);
406 }
407 return childPid;
408 }
409
410 /*
411 * await(ignore_error, silent_error, target, command, running_pid)
414 * the returned status when the child process terminates.
415 *
416 * Return value:
417 * Returns true if commands ran OK
418 *
419 * Parameters:
420 * ignore_error Should we abort on error?
421 * silent_error Should error messages be suppressed for dmake?
422 * target The target we are building, for error msgs
423 * command The command we ran, for error msgs
424 * running_pid The pid of the process we are waiting for
425 *
426 * Static variables used:
427 * filter_file The fd for the filter file
428 * filter_file_name The name of the filter file
429 *
430 * Global variables used:
431 * filter_stderr Set if -X is on
432 */
433 Boolean
434 await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, void *xdrs_p, int job_msg_id)
435 {
436 int status;
437 char *buffer;
438 int core_dumped;
439 int exit_status;
440 FILE *outfp;
441 register pid_t pid;
442 struct stat stat_buff;
443 int termination_signal;
444 char tmp_buf[MAXPATHLEN];
445
446 while ((pid = wait(&status)) != running_pid) {
447 if (pid == -1) {
448 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 98, "wait() failed: %s"), errmsg(errno));
449 }
450 }
451 (void) fflush(stdout);
452 (void) fflush(stderr);
453
454 if (status == 0) {
461 }
462
463 #ifdef PRINT_EXIT_STATUS
464 warning_mksh(NOCATGETS("I'm in await(), and status is *NOT* 0."));
465 #endif
466
467
468 exit_status = WEXITSTATUS(status);
469
470 #ifdef PRINT_EXIT_STATUS
471 warning_mksh(NOCATGETS("I'm in await(), and exit_status is %d."), exit_status);
472 #endif
473
474 termination_signal = WTERMSIG(status);
475 core_dumped = WCOREDUMP(status);
476
477 /*
478 * If the child returned an error, we now try to print a
479 * nice message about it.
480 */
481
482 tmp_buf[0] = (int) nul_char;
483 if (!silent_error) {
484 if (exit_status != 0) {
485 (void) fprintf(stdout,
486 catgets(libmksdmsi18n_catd, 1, 103, "*** Error code %d"),
487 exit_status);
488 } else {
489 (void) fprintf(stdout,
490 catgets(libmksdmsi18n_catd, 1, 105, "*** Signal %d"),
491 termination_signal);
492 if (core_dumped) {
493 (void) fprintf(stdout,
494 catgets(libmksdmsi18n_catd, 1, 107, " - core dumped"));
495 }
496 }
497 if (ignore_error) {
498 (void) fprintf(stdout,
499 catgets(libmksdmsi18n_catd, 1, 109, " (ignored)"));
500 }
501 (void) fprintf(stdout, "\n");
502 (void) fflush(stdout);
503 }
504
505 #ifdef PRINT_EXIT_STATUS
506 warning_mksh(NOCATGETS("I'm in await(), returning failed."));
507 #endif
508
509 return failed;
510 }
511
512 /*
513 * sh_command2string(command, destination)
514 *
515 * Run one sh command and capture the output from it.
516 *
517 * Return value:
518 *
519 * Parameters:
520 * command The command to run
521 * destination Where to deposit the output from the command
522 *
523 * Static variables used:
|