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