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