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