Print this page
make: ship the Joyent patch to enable parallel make (originally from rm)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/lib/mksh/dosys.cc
+++ new/usr/src/cmd/make/lib/mksh/dosys.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * dosys.cc
29 29 *
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
30 30 * Execute one commandline
31 31 */
32 32
33 33 /*
34 34 * Included files
35 35 */
36 36 #include <sys/wait.h> /* WIFEXITED(status) */
37 37 #include <alloca.h> /* alloca() */
38 38
39 39 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) /* tolik */
40 -# include <avo/strings.h> /* AVO_STRDUP() */
41 40 #if defined(DISTRIBUTED)
42 41 # include <dm/Avo_CmdOutput.h>
43 42 # include <rw/xdrstrea.h>
44 43 #endif
45 44 #endif
46 45
47 46 #include <stdio.h> /* errno */
48 47 #include <errno.h> /* errno */
49 48 #include <fcntl.h> /* open() */
50 49 #include <mksh/dosys.h>
51 50 #include <mksh/macro.h> /* getvar() */
52 51 #include <mksh/misc.h> /* getmem(), fatal_mksh(), errmsg() */
53 52 #include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */
54 53 #include <sys/signal.h> /* SIG_DFL */
55 54 #include <sys/stat.h> /* open() */
56 55 #include <sys/wait.h> /* wait() */
57 56 #include <ulimit.h> /* ulimit() */
58 57 #include <unistd.h> /* close(), dup2() */
59 58
60 59
61 60
62 61 /*
63 62 * Defined macros
64 63 */
65 64 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
66 65 #define SEND_MTOOL_MSG(cmds) \
67 66 if (send_mtool_msgs) { \
68 67 cmds \
69 68 }
70 69 #else
71 70 #define SEND_MTOOL_MSG(cmds)
72 71 #endif
73 72
74 73 /*
75 74 * typedefs & structs
76 75 */
77 76
78 77 /*
79 78 * Static variables
80 79 */
81 80
82 81 /*
83 82 * File table of contents
84 83 */
85 84 static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path);
86 85
87 86 /*
88 87 * Workaround for NFS bug. Sometimes, when running 'open' on a remote
89 88 * dmake server, it fails with "Stale NFS file handle" error.
90 89 * The second attempt seems to work.
91 90 */
92 91 int
93 92 my_open(const char *path, int oflag, mode_t mode) {
94 93 int res = open(path, oflag, mode);
95 94 if (res < 0 && (errno == ESTALE || errno == EAGAIN)) {
96 95 /* Stale NFS file handle. Try again */
97 96 res = open(path, oflag, mode);
98 97 }
99 98 return res;
100 99 }
101 100
102 101 /*
103 102 * void
104 103 * redirect_io(char *stdout_file, char *stderr_file)
105 104 *
106 105 * Redirects stdout and stderr for a child mksh process.
107 106 */
108 107 void
109 108 redirect_io(char *stdout_file, char *stderr_file)
110 109 {
111 110 long descriptor_limit;
112 111 int i;
113 112
114 113 if ((descriptor_limit = ulimit(UL_GDESLIM)) < 0) {
115 114 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 89, "ulimit() failed: %s"), errmsg(errno));
116 115 }
117 116 for (i = 3; i < descriptor_limit; i++) {
118 117 (void) close(i);
119 118 }
120 119 if ((i = my_open(stdout_file,
121 120 O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
122 121 S_IREAD | S_IWRITE)) < 0) {
123 122 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 90, "Couldn't open standard out temp file `%s': %s"),
124 123 stdout_file,
125 124 errmsg(errno));
126 125 } else {
127 126 if (dup2(i, 1) == -1) {
128 127 fatal_mksh(NOCATGETS("*** Error: dup2(3, 1) failed: %s"),
129 128 errmsg(errno));
130 129 }
131 130 close(i);
132 131 }
133 132 if (stderr_file == NULL) {
134 133 if (dup2(1, 2) == -1) {
135 134 fatal_mksh(NOCATGETS("*** Error: dup2(1, 2) failed: %s"),
136 135 errmsg(errno));
137 136 }
138 137 } else if ((i = my_open(stderr_file,
139 138 O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC,
140 139 S_IREAD | S_IWRITE)) < 0) {
141 140 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 91, "Couldn't open standard error temp file `%s': %s"),
142 141 stderr_file,
143 142 errmsg(errno));
144 143 } else {
145 144 if (dup2(i, 2) == -1) {
146 145 fatal_mksh(NOCATGETS("*** Error: dup2(3, 2) failed: %s"),
147 146 errmsg(errno));
148 147 }
149 148 close(i);
150 149 }
151 150 }
152 151
153 152 /*
154 153 * dosys_mksh(command, ignore_error, call_make, silent_error, target)
155 154 *
156 155 * Check if command string contains meta chars and dispatch to
157 156 * the proper routine for executing one command line.
158 157 *
159 158 * Return value:
160 159 * Indicates if the command execution failed
161 160 *
162 161 * Parameters:
163 162 * command The command to run
164 163 * ignore_error Should we abort when an error is seen?
165 164 * call_make Did command reference $(MAKE) ?
166 165 * silent_error Should error messages be suppressed for dmake?
167 166 * target Target we are building
168 167 *
169 168 * Global variables used:
170 169 * do_not_exec_rule Is -n on?
171 170 * working_on_targets We started processing real targets
172 171 */
173 172 Doname
174 173 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)
175 174 {
176 175 register int length = command->hash.length;
177 176 register wchar_t *p;
178 177 register wchar_t *q;
179 178 register wchar_t *cmd_string;
180 179 struct stat before;
181 180 Doname result;
182 181 Boolean working_on_targets_mksh = true;
183 182 Wstring wcb(command);
184 183 p = wcb.get_string();
185 184 cmd_string = p;
186 185
187 186 /* Strip spaces from head of command string */
188 187 while (iswspace(*p)) {
189 188 p++, length--;
190 189 }
191 190 if (*p == (int) nul_char) {
192 191 return build_failed;
193 192 }
194 193 /* If we are faking it we just return */
195 194 if (do_not_exec_rule &&
196 195 working_on_targets_mksh &&
197 196 !call_make &&
198 197 !always_exec) {
199 198 return build_ok;
200 199 }
201 200
202 201 /* Copy string to make it OK to write it. */
203 202 q = ALLOC_WC(length + 1);
204 203 (void) wscpy(q, p);
205 204 /* Write the state file iff this command uses make. */
206 205 /* XXX - currently does not support recursive make's, $(MAKE)'s
207 206 if (call_make && command_changed) {
208 207 write_state_file(0, false);
209 208 }
210 209 (void) stat(make_state->string_mb, &before);
211 210 */
212 211 /*
213 212 * Run command directly if it contains no shell meta chars,
214 213 * else run it using the shell.
215 214 */
216 215 /* XXX - command->meta *may* not be set correctly */
217 216 if (await(ignore_error,
218 217 silent_error,
219 218 target,
220 219 cmd_string,
221 220 command->meta ?
222 221 doshell(q, ignore_error, redirect_out_err, stdout_file, stderr_file, nice_prio) :
223 222 doexec(q, ignore_error, redirect_out_err, stdout_file, stderr_file, vroot_path, nice_prio),
224 223 false,
225 224 NULL,
226 225 -1)) {
227 226
228 227 #ifdef PRINT_EXIT_STATUS
229 228 warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_ok."));
230 229 #endif
231 230
232 231 result = build_ok;
233 232 } else {
234 233
235 234 #ifdef PRINT_EXIT_STATUS
236 235 warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_failed."));
237 236 #endif
238 237
239 238 result = build_failed;
240 239 }
241 240 retmem(q);
242 241
243 242 /* XXX - currently does not support recursive make's, $(MAKE)'s
244 243 if ((report_dependencies_level == 0) &&
245 244 call_make) {
246 245 make_state->stat.time = (time_t)file_no_time;
247 246 (void)exists(make_state);
248 247 if (before.st_mtime == make_state->stat.time) {
249 248 return result;
250 249 }
251 250 makefile_type = reading_statefile;
252 251 if (read_trace_level > 1) {
253 252 trace_reader = true;
254 253 }
255 254 (void) read_simple_file(make_state,
256 255 false,
257 256 false,
258 257 false,
259 258 false,
260 259 false,
261 260 true);
262 261 trace_reader = false;
263 262 }
264 263 */
265 264 return result;
266 265 }
267 266
268 267 /*
269 268 * doshell(command, ignore_error)
270 269 *
271 270 * Used to run command lines that include shell meta-characters.
272 271 * The make macro SHELL is supposed to contain a path to the shell.
273 272 *
274 273 * Return value:
275 274 * The pid of the process we started
276 275 *
277 276 * Parameters:
278 277 * command The command to run
279 278 * ignore_error Should we abort on error?
280 279 *
281 280 * Global variables used:
282 281 * filter_stderr If -X is on we redirect stderr
283 282 * shell_name The Name "SHELL", used to get the path to shell
284 283 */
285 284 int
286 285 doshell(wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, int nice_prio)
287 286 {
288 287 char *argv[6];
289 288 int argv_index = 0;
290 289 int cmd_argv_index;
291 290 int length;
292 291 char nice_prio_buf[MAXPATHLEN];
293 292 register Name shell = getvar(shell_name);
294 293 register char *shellname;
295 294 char *tmp_mbs_buffer;
296 295
297 296
298 297 if (IS_EQUAL(shell->string_mb, "")) {
299 298 shell = shell_name;
300 299 }
301 300 if ((shellname = strrchr(shell->string_mb, (int) slash_char)) == NULL) {
302 301 shellname = shell->string_mb;
303 302 } else {
304 303 shellname++;
305 304 }
306 305
307 306 /*
308 307 * Only prepend the /usr/bin/nice command to the original command
309 308 * if the nice priority, nice_prio, is NOT zero (0).
310 309 * Nice priorities can be a positive or a negative number.
311 310 */
312 311 if (nice_prio != 0) {
313 312 argv[argv_index++] = (char *)NOCATGETS("nice");
314 313 (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio);
315 314 argv[argv_index++] = strdup(nice_prio_buf);
316 315 }
317 316 argv[argv_index++] = shellname;
318 317 argv[argv_index++] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce"));
319 318 if ((length = wslen(command)) >= MAXPATHLEN) {
320 319 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
321 320 (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
322 321 cmd_argv_index = argv_index;
323 322 argv[argv_index++] = strdup(tmp_mbs_buffer);
324 323 retmem_mb(tmp_mbs_buffer);
325 324 } else {
326 325 WCSTOMBS(mbs_buffer, command);
327 326 cmd_argv_index = argv_index;
328 327 argv[argv_index++] = strdup(mbs_buffer);
329 328 }
330 329 argv[argv_index] = NULL;
331 330 (void) fflush(stdout);
332 331 if ((childPid = fork()) == 0) {
333 332 enable_interrupt((void (*) (int)) SIG_DFL);
334 333 if (redirect_out_err) {
335 334 redirect_io(stdout_file, stderr_file);
336 335 }
337 336 #if 0
338 337 if (filter_stderr) {
339 338 redirect_stderr();
340 339 }
341 340 #endif
342 341 if (nice_prio != 0) {
343 342 (void) execve(NOCATGETS("/usr/bin/nice"), argv, environ);
344 343 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 92, "Could not load `/usr/bin/nice': %s"),
345 344 errmsg(errno));
346 345 } else {
347 346 (void) execve(shell->string_mb, argv, environ);
348 347 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 93, "Could not load Shell from `%s': %s"),
349 348 shell->string_mb,
350 349 errmsg(errno));
351 350 }
352 351 }
353 352 if (childPid == -1) {
354 353 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 94, "fork failed: %s"),
355 354 errmsg(errno));
356 355 }
357 356 retmem_mb(argv[cmd_argv_index]);
358 357 return childPid;
359 358 }
360 359
361 360 /*
362 361 * exec_vp(name, argv, envp, ignore_error)
363 362 *
364 363 * Like execve, but does path search.
365 364 * This starts command when make invokes it directly (without a shell).
366 365 *
367 366 * Return value:
368 367 * Returns false if the exec failed
369 368 *
370 369 * Parameters:
371 370 * name The name of the command to run
372 371 * argv Arguments for the command
373 372 * envp The environment for it
374 373 * ignore_error Should we abort on error?
375 374 *
376 375 * Global variables used:
377 376 * shell_name The Name "SHELL", used to get the path to shell
378 377 * vroot_path The path used by the vroot package
379 378 */
380 379 static Boolean
381 380 exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path)
382 381 {
383 382 register Name shell = getvar(shell_name);
384 383 register char *shellname;
385 384 char *shargv[4];
386 385 Name tmp_shell;
387 386
388 387 if (IS_EQUAL(shell->string_mb, "")) {
389 388 shell = shell_name;
390 389 }
391 390
392 391 for (int i = 0; i < 5; i++) {
393 392 (void) execve_vroot(name,
394 393 argv + 1,
395 394 envp,
396 395 vroot_path,
397 396 VROOT_DEFAULT);
398 397 switch (errno) {
399 398 case ENOEXEC:
400 399 case ENOENT:
401 400 /* That failed. Let the shell handle it */
402 401 shellname = strrchr(shell->string_mb, (int) slash_char);
403 402 if (shellname == NULL) {
404 403 shellname = shell->string_mb;
405 404 } else {
406 405 shellname++;
407 406 }
408 407 shargv[0] = shellname;
409 408 shargv[1] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce"));
410 409 shargv[2] = argv[0];
411 410 shargv[3] = NULL;
412 411 tmp_shell = getvar(shell_name);
413 412 if (IS_EQUAL(tmp_shell->string_mb, "")) {
414 413 tmp_shell = shell_name;
415 414 }
416 415 (void) execve_vroot(tmp_shell->string_mb,
417 416 shargv,
418 417 envp,
419 418 vroot_path,
420 419 VROOT_DEFAULT);
421 420 return failed;
422 421 case ETXTBSY:
423 422 /*
424 423 * The program is busy (debugged?).
425 424 * Wait and then try again.
426 425 */
427 426 (void) sleep((unsigned) i);
428 427 case EAGAIN:
429 428 break;
430 429 default:
431 430 return failed;
432 431 }
433 432 }
434 433 return failed;
435 434 }
436 435
437 436 /*
438 437 * doexec(command, ignore_error)
439 438 *
440 439 * Will scan an argument string and split it into words
441 440 * thus building an argument list that can be passed to exec_ve()
442 441 *
443 442 * Return value:
444 443 * The pid of the process started here
445 444 *
446 445 * Parameters:
447 446 * command The command to run
448 447 * ignore_error Should we abort on error?
449 448 *
450 449 * Global variables used:
451 450 * filter_stderr If -X is on we redirect stderr
452 451 */
453 452 int
454 453 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)
455 454 {
456 455 int arg_count = 5;
457 456 char **argv;
458 457 int length;
459 458 char nice_prio_buf[MAXPATHLEN];
460 459 register char **p;
461 460 wchar_t *q;
462 461 register wchar_t *t;
463 462 char *tmp_mbs_buffer;
464 463
465 464 /*
466 465 * Only prepend the /usr/bin/nice command to the original command
467 466 * if the nice priority, nice_prio, is NOT zero (0).
468 467 * Nice priorities can be a positive or a negative number.
469 468 */
470 469 if (nice_prio != 0) {
471 470 arg_count += 2;
472 471 }
473 472 for (t = command; *t != (int) nul_char; t++) {
474 473 if (iswspace(*t)) {
475 474 arg_count++;
476 475 }
477 476 }
478 477 argv = (char **)alloca(arg_count * (sizeof(char *)));
479 478 /*
480 479 * Reserve argv[0] for sh in case of exec_vp failure.
481 480 * Don't worry about prepending /usr/bin/nice command to argv[0].
482 481 * In fact, doing it may cause the sh command to fail!
483 482 */
484 483 p = &argv[1];
485 484 if ((length = wslen(command)) >= MAXPATHLEN) {
486 485 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
487 486 (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1);
488 487 argv[0] = strdup(tmp_mbs_buffer);
489 488 retmem_mb(tmp_mbs_buffer);
490 489 } else {
491 490 WCSTOMBS(mbs_buffer, command);
492 491 argv[0] = strdup(mbs_buffer);
493 492 }
494 493
495 494 if (nice_prio != 0) {
496 495 *p++ = strdup(NOCATGETS("/usr/bin/nice"));
497 496 (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio);
498 497 *p++ = strdup(nice_prio_buf);
499 498 }
500 499 /* Build list of argument words. */
501 500 for (t = command; *t;) {
502 501 if (p >= &argv[arg_count]) {
503 502 /* This should never happen, right? */
504 503 WCSTOMBS(mbs_buffer, command);
505 504 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 95, "Command `%s' has more than %d arguments"),
506 505 mbs_buffer,
507 506 arg_count);
508 507 }
509 508 q = t;
510 509 while (!iswspace(*t) && (*t != (int) nul_char)) {
511 510 t++;
512 511 }
513 512 if (*t) {
514 513 for (*t++ = (int) nul_char; iswspace(*t); t++);
515 514 }
516 515 if ((length = wslen(q)) >= MAXPATHLEN) {
517 516 tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1);
518 517 (void) wcstombs(tmp_mbs_buffer, q, (length * MB_LEN_MAX) + 1);
519 518 *p++ = strdup(tmp_mbs_buffer);
520 519 retmem_mb(tmp_mbs_buffer);
521 520 } else {
522 521 WCSTOMBS(mbs_buffer, q);
523 522 *p++ = strdup(mbs_buffer);
524 523 }
525 524 }
526 525 *p = NULL;
527 526
528 527 /* Then exec the command with that argument list. */
529 528 (void) fflush(stdout);
530 529 if ((childPid = fork()) == 0) {
531 530 enable_interrupt((void (*) (int)) SIG_DFL);
532 531 if (redirect_out_err) {
533 532 redirect_io(stdout_file, stderr_file);
534 533 }
535 534 #if 0
536 535 if (filter_stderr) {
537 536 redirect_stderr();
538 537 }
539 538 #endif
540 539 (void) exec_vp(argv[1], argv, environ, ignore_error, vroot_path);
541 540 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 96, "Cannot load command `%s': %s"), argv[1], errmsg(errno));
542 541 }
543 542 if (childPid == -1) {
544 543 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 97, "fork failed: %s"),
545 544 errmsg(errno));
546 545 }
547 546 for (int i = 0; argv[i] != NULL; i++) {
548 547 retmem_mb(argv[i]);
549 548 }
550 549 return childPid;
551 550 }
552 551
553 552 /*
554 553 * await(ignore_error, silent_error, target, command, running_pid)
555 554 *
556 555 * Wait for one child process and analyzes
557 556 * the returned status when the child process terminates.
558 557 *
559 558 * Return value:
560 559 * Returns true if commands ran OK
561 560 *
562 561 * Parameters:
563 562 * ignore_error Should we abort on error?
564 563 * silent_error Should error messages be suppressed for dmake?
565 564 * target The target we are building, for error msgs
566 565 * command The command we ran, for error msgs
567 566 * running_pid The pid of the process we are waiting for
568 567 *
569 568 * Static variables used:
570 569 * filter_file The fd for the filter file
571 570 * filter_file_name The name of the filter file
572 571 *
573 572 * Global variables used:
574 573 * filter_stderr Set if -X is on
575 574 */
576 575 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
577 576 Boolean
578 577 await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, XDR *xdrs_p, int job_msg_id)
579 578 #else
580 579 Boolean
581 580 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)
582 581 #endif
583 582 {
584 583 int status;
585 584 char *buffer;
586 585 int core_dumped;
587 586 int exit_status;
588 587 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
589 588 Avo_CmdOutput *make_output_msg;
590 589 #endif
591 590 FILE *outfp;
592 591 register pid_t pid;
593 592 struct stat stat_buff;
594 593 int termination_signal;
595 594 char tmp_buf[MAXPATHLEN];
596 595 #if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */
597 596 RWCollectable *xdr_msg;
598 597 #endif
599 598
600 599 while ((pid = wait(&status)) != running_pid) {
601 600 if (pid == -1) {
602 601 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 98, "wait() failed: %s"), errmsg(errno));
603 602 }
604 603 }
605 604 (void) fflush(stdout);
606 605 (void) fflush(stderr);
607 606
608 607 if (status == 0) {
609 608
610 609 #ifdef PRINT_EXIT_STATUS
611 610 warning_mksh(NOCATGETS("I'm in await(), and status is 0."));
612 611 #endif
613 612
614 613 return succeeded;
615 614 }
616 615
617 616 #ifdef PRINT_EXIT_STATUS
618 617 warning_mksh(NOCATGETS("I'm in await(), and status is *NOT* 0."));
619 618 #endif
620 619
621 620
622 621 exit_status = WEXITSTATUS(status);
623 622
624 623 #ifdef PRINT_EXIT_STATUS
625 624 warning_mksh(NOCATGETS("I'm in await(), and exit_status is %d."), exit_status);
626 625 #endif
627 626
↓ open down ↓ |
577 lines elided |
↑ open up ↑ |
628 627 termination_signal = WTERMSIG(status);
629 628 core_dumped = WCOREDUMP(status);
630 629
631 630 /*
632 631 * If the child returned an error, we now try to print a
633 632 * nice message about it.
634 633 */
635 634 SEND_MTOOL_MSG(
636 635 make_output_msg = new Avo_CmdOutput();
637 636 (void) sprintf(tmp_buf, "%d", job_msg_id);
638 - make_output_msg->appendOutput(AVO_STRDUP(tmp_buf));
637 + make_output_msg->appendOutput(strdup(tmp_buf));
639 638 );
640 639
641 640 tmp_buf[0] = (int) nul_char;
642 641 if (!silent_error) {
643 642 if (exit_status != 0) {
644 643 (void) fprintf(stdout,
645 644 catgets(libmksdmsi18n_catd, 1, 103, "*** Error code %d"),
646 645 exit_status);
647 646 SEND_MTOOL_MSG(
648 647 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
649 648 catgets(libmksdmsi18n_catd, 1, 104, "*** Error code %d"),
650 649 exit_status);
651 650 );
652 651 } else {
653 652 (void) fprintf(stdout,
654 653 catgets(libmksdmsi18n_catd, 1, 105, "*** Signal %d"),
655 654 termination_signal);
656 655 SEND_MTOOL_MSG(
657 656 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
658 657 catgets(libmksdmsi18n_catd, 1, 106, "*** Signal %d"),
659 658 termination_signal);
660 659 );
661 660 if (core_dumped) {
662 661 (void) fprintf(stdout,
663 662 catgets(libmksdmsi18n_catd, 1, 107, " - core dumped"));
664 663 SEND_MTOOL_MSG(
665 664 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
666 665 catgets(libmksdmsi18n_catd, 1, 108, " - core dumped"));
667 666 );
668 667 }
669 668 }
670 669 if (ignore_error) {
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
671 670 (void) fprintf(stdout,
672 671 catgets(libmksdmsi18n_catd, 1, 109, " (ignored)"));
673 672 SEND_MTOOL_MSG(
674 673 (void) sprintf(&tmp_buf[strlen(tmp_buf)],
675 674 catgets(libmksdmsi18n_catd, 1, 110, " (ignored)"));
676 675 );
677 676 }
678 677 (void) fprintf(stdout, "\n");
679 678 (void) fflush(stdout);
680 679 SEND_MTOOL_MSG(
681 - make_output_msg->appendOutput(AVO_STRDUP(tmp_buf));
680 + make_output_msg->appendOutput(strdup(tmp_buf));
682 681 );
683 682 }
684 683 SEND_MTOOL_MSG(
685 684 xdr_msg = (RWCollectable*) make_output_msg;
686 685 xdr(xdrs_p, xdr_msg);
687 686 delete make_output_msg;
688 687 );
689 688
690 689 #ifdef PRINT_EXIT_STATUS
691 690 warning_mksh(NOCATGETS("I'm in await(), returning failed."));
692 691 #endif
693 692
694 693 return failed;
695 694 }
696 695
697 696 /*
698 697 * sh_command2string(command, destination)
699 698 *
700 699 * Run one sh command and capture the output from it.
701 700 *
702 701 * Return value:
703 702 *
704 703 * Parameters:
705 704 * command The command to run
706 705 * destination Where to deposit the output from the command
707 706 *
708 707 * Static variables used:
709 708 *
710 709 * Global variables used:
711 710 */
712 711 void
713 712 sh_command2string(register String command, register String destination)
714 713 {
715 714 register FILE *fd;
716 715 register int chr;
717 716 int status;
718 717 Boolean command_generated_output = false;
719 718
720 719 command->text.p = (int) nul_char;
721 720 WCSTOMBS(mbs_buffer, command->buffer.start);
722 721 if ((fd = popen(mbs_buffer, "r")) == NULL) {
723 722 WCSTOMBS(mbs_buffer, command->buffer.start);
724 723 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 111, "Could not run command `%s' for :sh transformation"),
725 724 mbs_buffer);
726 725 }
727 726 while ((chr = getc(fd)) != EOF) {
728 727 if (chr == (int) newline_char) {
729 728 chr = (int) space_char;
730 729 }
731 730 command_generated_output = true;
732 731 append_char(chr, destination);
733 732 }
734 733
735 734 /*
736 735 * We don't want to keep the last LINE_FEED since usually
737 736 * the output of the 'sh:' command is used to evaluate
738 737 * some MACRO. ( /bin/sh and other shell add a line feed
739 738 * to the output so that the prompt appear in the right place.
740 739 * We don't need that
741 740 */
742 741 if (command_generated_output){
743 742 if ( *(destination->text.p-1) == (int) space_char) {
744 743 * (-- destination->text.p) = '\0';
745 744 }
746 745 } else {
747 746 /*
748 747 * If the command didn't generate any output,
749 748 * set the buffer to a null string.
750 749 */
751 750 *(destination->text.p) = '\0';
752 751 }
753 752
754 753 status = pclose(fd);
755 754 if (status != 0) {
756 755 WCSTOMBS(mbs_buffer, command->buffer.start);
757 756 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 112, "The command `%s' returned status `%d'"),
758 757 mbs_buffer,
759 758 WEXITSTATUS(status));
760 759 }
761 760 }
762 761
763 762
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX