1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | #include <signal.h> |
110 | |
111 | #include "extern.h" |
112 | |
113 | #ifdef HAVE_WAIT_H1 |
114 | # include <wait.h> |
115 | #else |
116 | # ifdef HAVE_SYS_WAIT_H1 |
117 | # include <sys/wait.h> |
118 | # endif |
119 | #endif |
120 | |
121 | #if HAVE_SPAWN_H1 && ENABLE_SPAWN |
122 | # include <spawn.h> |
123 | #endif |
124 | |
125 | #if __CYGWIN__ && ENABLE_SPAWN |
126 | #if HAVE_CYGWIN_PROCESS_H |
127 | # include <cygwin/process.h> |
128 | #else |
129 | # include <process.h> |
130 | #endif |
131 | #endif |
132 | |
133 | #ifdef __EMX__ |
134 | # include <process.h> |
135 | #define _P_NOWAIT P_NOWAIT |
136 | #endif |
137 | |
138 | #include "sysintf.h" |
139 | #if HAVE_ERRNO_H1 |
140 | # include <errno(*__errno_location ()).h> |
141 | #else |
142 | extern int errno(*__errno_location ()); |
143 | #endif |
144 | |
145 | typedef struct prp { |
146 | char *prp_cmd; |
147 | int prp_group; |
148 | t_attr prp_attr; |
149 | int prp_last; |
150 | struct prp *prp_next; |
151 | } RCP, *RCPPTR; |
152 | |
153 | #if defined(USE_CREATEPROCESS) |
154 | |
155 | typedef HANDLE DMHANDLE; |
156 | #else |
157 | typedef int DMHANDLE; |
158 | #endif |
159 | |
160 | typedef struct pr { |
161 | int pr_valid; |
162 | DMHANDLE pr_pid; |
163 | DMHANDLE pr_tid; |
164 | CELLPTR pr_target; |
165 | int pr_ignore; |
166 | int pr_last; |
167 | int pr_wfc; |
168 | RCPPTR pr_recipe; |
169 | RCPPTR pr_recipe_end; |
170 | char *pr_dir; |
171 | } PR; |
172 | |
173 | typedef struct tpid { |
174 | DMHANDLE pid; |
175 | DMHANDLE tid; |
176 | } TPID; |
177 | |
178 | const TPID DMNOPID = { (DMHANDLE)-1, (DMHANDLE)0 }; |
179 | |
180 | static PR *_procs = NIL(PR)((PR*)((void*)0)); |
181 | static int _procs_size = 0; |
182 | static int _proc_cnt = 0; |
183 | static int _abort_flg= FALSE0; |
184 | static int _use_i = -1; |
185 | #if defined(USE_CREATEPROCESS) |
186 | static HANDLE *_wpList = NIL(HANDLE)((HANDLE*)((void*)0)); |
187 | #endif |
188 | |
189 | static int _add_child ANSI((TPID, CELLPTR, int, int, int))(TPID, CELLPTR, int, int, int); |
190 | static void _attach_cmd ANSI((char *, int, CELLPTR, t_attr, int))(char *, int, CELLPTR, t_attr, int); |
191 | static void _finished_child ANSI((DMHANDLE, int))(DMHANDLE, int); |
192 | static int _running ANSI((CELLPTR))(CELLPTR); |
193 | |
194 | |
195 | static int dmwaitnext ANSI((DMHANDLE *, int *))(DMHANDLE *, int *); |
196 | static int dmwaitpid ANSI((int, DMHANDLE *, int *))(int, DMHANDLE *, int *); |
197 | |
198 | #if defined( USE_SPAWN ) |
199 | |
200 | int terrno; |
201 | |
202 | static TPID dmspawn ANSI((char **))(char **); |
203 | |
204 | static TPID |
205 | dmspawn( argv ) |
206 | char **argv; |
207 | { |
208 | TPID pid; |
209 | |
210 | |
211 | #if defined( __CYGWIN__) || defined( __EMX__) |
212 | pid.pid = spawnvp(_P_NOWAIT, argv[0], (const char**) argv); |
213 | pid.tid = 0; |
214 | #elif defined(USE_CREATEPROCESS) |
215 | static STARTUPINFO si; |
216 | static int initSTARTUPINFO = FALSE0; |
217 | PROCESS_INFORMATION pi; |
218 | |
219 | |
220 | if( initSTARTUPINFO == FALSE0 ) { |
221 | initSTARTUPINFO = TRUE1; |
222 | ZeroMemory( &si, sizeof(si) ); |
223 | si.cb = sizeof(si); |
224 | } |
225 | ZeroMemory( &pi, sizeof(pi) ); |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
237 | |
238 | if( CreateProcess(NULL((void*)0), argv[0], NULL((void*)0), NULL((void*)0), TRUE1, 0, NULL((void*)0), NULL((void*)0), &si, &pi) ) { |
239 | pid.pid = pi.hProcess; |
240 | pid.tid = pi.hThread; |
241 | } else { |
242 | fprintf(stderrstderr, "CreateProcess failed (%d).\n", GetLastError() ); |
243 | pid.pid = (DMHANDLE)-1; |
244 | } |
245 | #else /* Non cygwin, OS/2, MinGW and MSC */ |
246 | int tpid; |
247 | if (posix_spawnp (&tpid, argv[0], NULL((void*)0), NULL((void*)0), argv, (char *)NULL((void*)0))) |
248 | tpid = -1; |
249 | |
250 | pid.pid = tpid; |
251 | pid.tid = 0; |
252 | #endif /* __CYGWIN__ */ |
253 | return pid; |
254 | } |
255 | |
256 | #endif /* USE_SPAWN */ |
257 | |
258 | static int |
259 | dmwaitnext( wid, status ) |
260 | DMHANDLE *wid; |
261 | int *status; |
262 | |
263 | |
264 | { |
265 | |
266 | #if !defined(USE_CREATEPROCESS) |
267 | |
268 | |
269 | |
270 | *wid = wait(status); |
271 | |
272 | |
273 | if( *wid == -1 ) { |
274 | int realErr = errno(*__errno_location ()); |
275 | fprintf(stderrstderr, "%s: Internal Error: wait() failed: %d - %s\n", |
276 | Pname, errno(*__errno_location ()), strerror(errno(*__errno_location ())) ); |
277 | if( realErr != ECHILD10 ) { |
278 | |
279 | return -2; |
280 | } else { |
281 | return -1; |
282 | } |
283 | } |
284 | #else |
285 | DWORD pEvent; |
286 | DWORD dwExitCode; |
287 | int i; |
288 | int numProc = 0; |
289 | |
290 | *status = 0; |
291 | |
292 | |
293 | for( i=0; i<Max_proc; i++ ) { |
294 | if(_procs[i].pr_valid) { |
295 | _wpList[numProc++] = _procs[i].pr_pid; |
296 | } |
297 | } |
298 | if( numProc == 0 ) { |
299 | fprintf(stderrstderr, "%s: Internal Error: dmwaitnext() failed: " |
300 | "Nothing to wait for.\n", Pname ); |
301 | return -1; |
302 | } |
303 | |
304 | |
305 | |
306 | |
307 | pEvent = WaitForMultipleObjects( numProc, _wpList, FALSE0, INFINITE); |
308 | |
309 | if( pEvent >= 0 && pEvent < WAIT_OBJECT_0 + numProc ) { |
310 | *wid = _wpList[pEvent - WAIT_OBJECT_0]; |
311 | for( i=0; i<Max_proc && _procs[i].pr_pid != *wid; i++ ) |
312 | ; |
313 | if( i == Max_proc ) |
314 | Fatal("Internal Error: Process not in pq !"); |
315 | |
316 | GetExitCodeProcess(*wid, &dwExitCode); |
317 | if(dwExitCode == STILL_ACTIVE) { |
318 | |
319 | TerminateProcess(*wid, 1); |
320 | dwExitCode = 1; |
321 | fprintf(stderrstderr, "%s: Internal Error: Process still running - " |
322 | "terminate it!\n", Pname ); |
323 | } |
324 | |
325 | |
326 | CloseHandle( *wid ); |
327 | CloseHandle( _procs[i].pr_tid ); |
328 | *status = dwExitCode; |
329 | } |
330 | else { |
331 | int err = GetLastError(); |
332 | LPVOID lpMsgBuf; |
333 | |
334 | FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
335 | FORMAT_MESSAGE_FROM_SYSTEM | |
336 | FORMAT_MESSAGE_IGNORE_INSERTS, |
337 | NULL((void*)0), |
338 | err, |
339 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
340 | (LPTSTR) &lpMsgBuf, |
341 | 0, NULL((void*)0) ); |
342 | |
343 | fprintf(stderrstderr, "%s: Internal Error: WaitForMultipleObjects() (%d) failed:" |
344 | " %d - %s\n", Pname, numProc, err, lpMsgBuf); |
345 | LocalFree(lpMsgBuf); |
346 | |
347 | |
348 | return -2; |
349 | } |
350 | |
351 | #endif |
352 | return 1; |
353 | } |
354 | |
355 | |
356 | static int |
357 | dmwaitpid( pqid, wid, status ) |
358 | int pqid; |
359 | DMHANDLE *wid; |
360 | int *status; |
361 | |
362 | |
363 | { |
364 | |
365 | #if !defined(USE_CREATEPROCESS) |
366 | *wid = waitpid(_procs[pqid].pr_pid, status, WNOHANG1); |
367 | |
368 | |
369 | if( *wid == 0 ) { |
370 | *status = 0; |
371 | return 0; |
372 | } |
373 | |
374 | if( *wid == -1 ) { |
375 | int realErr = errno(*__errno_location ()); |
376 | fprintf(stderrstderr, "%s: Internal Error: waitpid() failed: %d - %s\n", |
377 | Pname, errno(*__errno_location ()), strerror(errno(*__errno_location ())) ); |
378 | if(realErr != ECHILD10) { |
379 | |
380 | return -2; |
381 | } else { |
382 | return -1; |
383 | } |
384 | } |
385 | #else |
386 | DWORD pEvent; |
387 | DWORD dwExitCode; |
388 | |
389 | *wid = _procs[pqid].pr_pid; |
390 | *status = 0; |
391 | |
392 | |
393 | pEvent = WaitForSingleObject(*wid, 0); |
394 | |
395 | if( pEvent == WAIT_OBJECT_0 ) { |
396 | GetExitCodeProcess(*wid, &dwExitCode); |
397 | if(dwExitCode == STILL_ACTIVE) { |
398 | |
399 | TerminateProcess(*wid, 1); |
400 | dwExitCode = 1; |
401 | fprintf(stderrstderr, "%s: Internal Error: Process still running - " |
402 | "terminate it!\n", Pname ); |
403 | } |
404 | |
405 | |
406 | CloseHandle( *wid ); |
407 | CloseHandle( _procs[pqid].pr_tid ); |
408 | *status = dwExitCode; |
409 | } |
410 | else if( pEvent == WAIT_TIMEOUT ) { |
411 | return 0; |
412 | } |
413 | else { |
414 | int err = GetLastError(); |
415 | LPVOID lpMsgBuf; |
416 | |
417 | FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
418 | FORMAT_MESSAGE_FROM_SYSTEM | |
419 | FORMAT_MESSAGE_IGNORE_INSERTS, |
420 | NULL((void*)0), |
421 | err, |
422 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
423 | (LPTSTR) &lpMsgBuf, |
424 | 0, NULL((void*)0) ); |
425 | |
426 | fprintf(stderrstderr, "%s: Internal Error: WaitForSingleObject() failed:" |
427 | " %d - %s\n", Pname, err, lpMsgBuf); |
428 | LocalFree(lpMsgBuf); |
429 | |
430 | |
431 | return -2; |
432 | } |
433 | #endif |
434 | |
435 | return 1; |
436 | } |
437 | |
438 | |
439 | #if ! HAVE_STRERROR1 |
440 | static char * |
441 | private_strerror (errnum) |
442 | int errnum; |
443 | { |
444 | #ifndef __APPLE__ |
445 | # if defined(arm32) || defined(linux1) || defined(__FreeBSD__) || \ |
446 | defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) |
447 | extern const char * const sys_errlist[]; |
448 | # else |
449 | extern char *sys_errlist[]; |
450 | # endif |
451 | #endif |
452 | extern int sys_nerr; |
453 | |
454 | if (errnum > 0 && errnum <= sys_nerr) |
455 | return sys_errlist[errnum]; |
456 | return "Unknown system error"; |
457 | } |
458 | #define strerror private_strerror |
459 | #endif /* HAVE_STRERROR */ |
460 | |
461 | PUBLIC int |
462 | runargv(target, group, last, cmnd_attr, cmd) |
463 | |
464 | |
465 | |
466 | |
467 | |
468 | |
469 | CELLPTR target; |
470 | int group; |
471 | int last; |
472 | t_attr cmnd_attr; |
473 | char **cmd; |
474 | { |
475 | int ignore = (cmnd_attr & A_IGNORE0x00020)!= 0; |
476 | int shell = (cmnd_attr & A_SHELL0x00800) != 0; |
477 | int mute = (cmnd_attr & A_MUTE0x80000000) != 0; |
478 | int wfc = (cmnd_attr & A_WFC0x00200) != 0; |
479 | |
480 | TPID pid; |
481 | int st_pq = 0; |
482 | char *tcmd = *cmd; |
483 | char **argv; |
484 | |
485 | int old_stdout = -1; |
486 | int old_stderr = -1; |
487 | int internal = 0; |
488 | |
489 | DB_ENTER( "runargv" ); |
490 | |
491 | |
492 | |
493 | |
494 | if( Is_exec_shell ) { |
495 | if( (st_pq = _running(Shell_exec_target)) != -1 ) { |
496 | RCPPTR rp; |
497 | |
498 | _procs[st_pq].pr_wfc = TRUE1; |
499 | |
500 | for( rp = _procs[st_pq].pr_recipe ; rp != NIL(RCP)((RCP*)((void*)0)); rp = rp->prp_next ) |
501 | rp->prp_attr |= A_WFC0x00200; |
502 | |
503 | Wait_for_child(FALSE0, st_pq); |
504 | } |
505 | } else { |
506 | if( _running(target) != -1 ) { |
507 | |
508 | |
509 | _attach_cmd( *cmd, group, target, cmnd_attr, last ); |
510 | DB_RETURN( 1 )return (1); |
511 | } |
512 | } |
513 | |
514 | |
515 | |
516 | while( _proc_cnt == Max_proc ) { |
517 | Wait_for_child(FALSE0, -1); |
518 | } |
519 | |
520 | |
521 | if ( !*tcmd || |
522 | ( strncmp(tcmd, "noop", 4) == 0 && |
523 | (iswhite(tcmd[4])((tcmd[4] == ' ') || (tcmd[4] == '\t')) || tcmd[4] == '\0')) ) { |
524 | internal = 1; |
525 | } |
526 | else if( !shell && |
527 | strncmp(tcmd, "echo", 4) == 0 && |
528 | (iswhite(tcmd[4])((tcmd[4] == ' ') || (tcmd[4] == '\t')) || tcmd[4] == '\0') ) { |
529 | int nl = 1; |
530 | |
531 | tcmd = tcmd+4; |
532 | while( iswhite(*tcmd)((*tcmd == ' ') || (*tcmd == '\t')) ) ++tcmd; |
533 | if ( strncmp(tcmd,"-n",2 ) == 0) { |
534 | nl = 0; |
535 | tcmd = tcmd+2; |
536 | while( iswhite(*tcmd)((*tcmd == ' ') || (*tcmd == '\t')) ) ++tcmd; |
537 | } |
538 | |
539 | |
540 | if( Is_exec_shell ) { |
541 | |
542 | old_stdout = dup(1); |
543 | dup2( fileno(stdout_redir), 1 ); |
544 | } |
545 | if( mute ) { |
546 | old_stderr = dup(2); |
547 | dup2( zerofd, 2 ); |
548 | |
549 | if( !Is_exec_shell ) { |
550 | old_stdout = dup(1); |
551 | dup2( zerofd, 1 ); |
552 | } |
553 | } |
554 | |
555 | printf("%s%s", tcmd, nl ? "\n" : ""); |
556 | fflush(stdoutstdout); |
557 | |
558 | |
559 | if( old_stdout != -1 ) { |
560 | dup2(old_stdout, 1); |
561 | close(old_stdout); |
562 | if( old_stderr != -1 ) { |
563 | dup2(old_stderr, 2); |
564 | close(old_stderr); |
565 | } |
566 | } |
567 | |
568 | internal = 1; |
569 | } |
570 | if ( internal ) { |
571 | |
572 | int cur_proc = _add_child(DMNOPID, target, ignore, last, FALSE0); |
573 | _finished_child( (DMHANDLE)-cur_proc, 0 ); |
574 | DB_RETURN( 0 )return (0); |
575 | } |
576 | |
577 | |
578 | argv = Pack_argv( group, shell, cmd ); |
579 | |
580 | |
581 | #if defined( USE_SPAWN ) |
582 | |
583 | |
584 | if( Is_exec_shell ) { |
585 | |
586 | old_stdout = dup(1); |
587 | dup2( fileno(stdout_redir), 1 ); |
588 | } |
589 | if( mute ) { |
590 | old_stderr = dup(2); |
591 | dup2( zerofd, 2 ); |
592 | |
593 | if( !Is_exec_shell ) { |
594 | old_stdout = dup(1); |
595 | dup2( zerofd, 1 ); |
596 | } |
597 | } |
598 | |
599 | pid = dmspawn( argv ); |
600 | terrno = errno(*__errno_location ()); |
601 | |
602 | if( old_stdout != -1 ) { |
603 | dup2(old_stdout, 1); |
604 | close(old_stdout); |
605 | if( old_stderr != -1 ) { |
606 | dup2(old_stderr, 2); |
607 | close(old_stderr); |
608 | } |
609 | } |
610 | if(pid.pid == (DMHANDLE)-1) { |
611 | |
612 | int cur_proc; |
613 | |
614 | fprintf(stderrstderr, "%s: Error executing '%s': %s", |
615 | Pname, argv[0], strerror(terrno) ); |
616 | if( ignore||Continue ) { |
617 | fprintf(stderrstderr, " (Ignored)" ); |
618 | } |
619 | fprintf(stderrstderr, "\n"); |
620 | |
621 | |
622 | |
623 | cur_proc = _add_child(DMNOPID, target, ignore, last, FALSE0); |
624 | _finished_child((DMHANDLE)cur_proc, SIGTERM15); |
625 | |
626 | |
627 | |
628 | |
629 | |
630 | DB_RETURN( 0 )return (0); |
631 | } else { |
632 | _add_child(pid, target, ignore, last, wfc); |
633 | } |
634 | #else /* USE_SPAWN */ |
635 | |
636 | fflush(stdoutstdout); |
637 | switch( pid.pid = fork() ){ |
638 | |
639 | case -1: |
640 | Fatal("fork failed: %s: %s", argv[0], strerror( errno(*__errno_location ()) )); |
641 | |
642 | case 0: |
643 | |
644 | if( Is_exec_shell ) { |
645 | |
646 | old_stdout = dup(1); |
647 | dup2( fileno(stdout_redir), 1 ); |
648 | } |
649 | if( mute ) { |
650 | old_stderr = dup(2); |
651 | dup2( zerofd, 2 ); |
652 | |
653 | if( !Is_exec_shell ) { |
654 | old_stdout = dup(1); |
655 | dup2( zerofd, 1 ); |
656 | } |
657 | } |
658 | execvp(argv[0], argv); |
659 | |
660 | |
661 | if( old_stdout != -1 ) { |
662 | dup2(old_stdout, 1); |
663 | close(old_stdout); |
664 | if( old_stderr != -1 ) { |
665 | dup2(old_stderr, 2); |
666 | close(old_stderr); |
667 | } |
668 | } |
669 | fprintf(stderrstderr, "%s: Error executing '%s': %s", |
670 | Pname, argv[0], strerror(errno(*__errno_location ())) ); |
671 | if( ignore||Continue ) { |
672 | fprintf(stderrstderr, " (Ignored)" ); |
673 | } |
674 | fprintf(stderrstderr, "\n"); |
675 | |
676 | kill(getpid(), SIGTERM15); |
677 | |
678 | Fatal("\nInternal Error - kill could't kill child %d.\n", getpid()); |
679 | |
680 | default: |
681 | _add_child(pid, target, ignore, last, wfc); |
682 | } |
683 | |
684 | #endif /* USE_SPAWN */ |
685 | |
686 | |
687 | if( wfc ) { |
688 | DB_RETURN( 0 )return (0); |
689 | } else { |
690 | DB_RETURN( 1 )return (1); |
691 | } |
692 | } |
693 | |
694 | |
695 | PUBLIC int |
696 | Wait_for_child( abort_flg, pqid ) |
697 | |
698 | |
699 | |
700 | |
701 | |
702 | |
703 | |
704 | |
705 | |
706 | |
707 | int abort_flg; |
708 | int pqid; |
709 | { |
710 | DMHANDLE pid; |
711 | DMHANDLE wid; |
712 | int status; |
713 | int waitret; |
714 | |
715 | int waitchild; |
716 | int is_exec_shell_status = Is_exec_shell; |
717 | |
718 | if( !_procs ) { |
719 | |
720 | |
721 | return -1; |
722 | } |
723 | |
724 | if( pqid > Max_proc ) Fatal("Internal Error: pqid > Max_proc !"); |
725 | |
726 | if( pqid == -1 ) { |
727 | |
728 | int i; |
729 | for( i=0; i<Max_proc && !_procs[i].pr_valid; i++ ) |
730 | ; |
731 | if( i == Max_proc ) |
732 | return(-1); |
733 | |
734 | pid = (DMHANDLE)-1; |
735 | waitchild = FALSE0; |
736 | } |
737 | else { |
738 | |
739 | if( !_procs[pqid].pr_valid ) { |
740 | |
741 | Warning("Internal Warning: pqid is not active!?"); |
742 | return(-1); |
743 | } |
744 | |
745 | pid = _procs[pqid].pr_pid; |
746 | waitchild = _procs[pqid].pr_wfc; |
747 | } |
748 | |
749 | |
750 | |
751 | |
752 | |
753 | |
754 | |
755 | Is_exec_shell = FALSE0; |
756 | |
757 | do { |
758 | |
759 | if( (pid != (DMHANDLE)-1) && (waitret = dmwaitpid(pqid, &wid, &status)) != 0 ) { |
760 | |
761 | |
762 | |
763 | |
764 | |
765 | |
766 | ; |
767 | } |
768 | else { |
769 | waitret = dmwaitnext(&wid, &status); |
770 | |
771 | |
772 | if( waitret < 0 ) { |
773 | pid = (DMHANDLE)-1; |
774 | } |
775 | } |
776 | |
777 | |
778 | if( waitret < 0 ) { |
779 | if(waitret == -2) { |
780 | |
781 | if ( in_quit() ) { |
782 | |
783 | return 0; |
784 | } else { |
785 | Fatal( "dmake was interrupted or a child terminated. " |
786 | "Stopping all children ..." ); |
787 | } |
788 | } else { |
789 | |
790 | |
791 | if( pid != (DMHANDLE)-1 ) { |
792 | |
793 | if( _procs[pqid].pr_valid ) { |
794 | _procs[pqid].pr_valid = 0; |
795 | _procs[pqid].pr_recipe = NIL(RCP)((RCP*)((void*)0)); |
796 | _proc_cnt--; |
797 | } |
798 | } else { |
799 | |
800 | |
801 | int i; |
802 | for( i=0; i<Max_proc; i++ ) { |
803 | _procs[i].pr_valid = 0; |
804 | _procs[i].pr_recipe = NIL(RCP)((RCP*)((void*)0)); |
805 | } |
806 | _proc_cnt = 0; |
807 | } |
808 | |
809 | |
810 | |
811 | Fatal( "Internal Error: Child is missing but still listed in _procs[x] %d: %s\n" |
812 | "\nTemporary or .ERRREMOVE targets might not have been removed!\n", |
813 | errno(*__errno_location ()), strerror( errno(*__errno_location ()) ) ); |
814 | } |
815 | } |
816 | |
817 | _abort_flg = abort_flg; |
818 | _finished_child(wid, status); |
819 | _abort_flg = FALSE0; |
820 | if( waitchild ) { |
821 | |
822 | |
823 | |
824 | if( pid != wid ) { |
825 | if( !_procs[pqid].pr_valid || _procs[pqid].pr_pid != pid ) { |
826 | |
827 | waitchild = FALSE0; |
828 | } |
829 | } |
830 | else |
831 | |
832 | waitchild = FALSE0; |
833 | } |
834 | } |
835 | while( waitchild ); |
836 | |
837 | Is_exec_shell = is_exec_shell_status; |
838 | return(0); |
839 | } |
840 | |
841 | |
842 | PUBLIC void |
843 | Clean_up_processes() |
844 | { |
845 | if( _procs != NIL(PR)((PR*)((void*)0)) ) |
846 | { |
847 | register int i; |
848 | for( i=0; i<Max_proc; i++ ) |
849 | if( _procs[i].pr_valid ) |
850 | { |
851 | #if !defined(USE_CREATEPROCESS) |
852 | int ret; |
853 | if( (ret = kill(_procs[i].pr_pid, SIGTERM15)) ) |
854 | { |
855 | fprintf(stderrstderr, "Killing of pid %d from pq[%d] failed with: %s - %d ret: %d\n", |
856 | _procs[i].pr_pid, i, strerror(errno(*__errno_location ())), SIGTERM15, ret ); |
857 | } |
858 | #else |
859 | TerminateProcess(_procs[i].pr_pid, 1); |
860 | #endif |
861 | } |
862 | } |
863 | } |
864 | |
865 | |
866 | static int |
867 | _add_child( pid, target, ignore, last, wfc ) |
868 | |
869 | |
870 | |
871 | |
872 | |
873 | |
874 | |
875 | |
876 | TPID pid; |
877 | CELLPTR target; |
878 | int ignore; |
879 | int last; |
880 | int wfc; |
881 | { |
882 | register int i; |
883 | register PR *pp; |
884 | |
885 | |
886 | if( _procs_size != Max_proc ) { |
887 | |
888 | if( _procs == NIL(PR)((PR*)((void*)0)) ) { |
889 | _procs_size = Max_proc; |
890 | TALLOC( _procs, Max_proc, PR )if ((_procs = (PR*) calloc((unsigned int)(Max_proc), (size_t) sizeof(PR))) == (PR*)0) {No_ram();}; |
891 | #if defined(USE_CREATEPROCESS) |
892 | TALLOC( _wpList, Max_proc, HANDLE )if ((_wpList = (HANDLE*) calloc((unsigned int)(Max_proc), (size_t )sizeof(HANDLE))) == (HANDLE*)0) {No_ram();}; |
893 | |
894 | |
895 | |
896 | if( sizeof(int) > sizeof(DMHANDLE) ) |
897 | Fatal( "Internal Error: Check type of DMHANDLE!" ); |
898 | #endif |
899 | } |
900 | else { |
901 | Fatal( "MAXPROCESS changed from `%d' to `%d' after a command was executed!", _procs_size, Max_proc ); |
902 | } |
903 | } |
904 | |
905 | if( Measure & M_RECIPE0x02 ) |
906 | Do_profile_output( "s", M_RECIPE0x02, target ); |
907 | |
908 | |
909 | |
910 | if( (i = _use_i) == -1 ) { |
911 | for( i=0; i<Max_proc; i++ ) |
912 | if( !_procs[i].pr_valid ) |
913 | break; |
914 | } |
915 | |
916 | pp = &(_procs[i]); |
917 | |
918 | pp->pr_valid = 1; |
919 | pp->pr_pid = pid.pid; |
920 | pp->pr_tid = pid.tid; |
921 | pp->pr_target = target; |
922 | pp->pr_ignore = ignore; |
923 | pp->pr_last = last; |
924 | pp->pr_wfc = wfc; |
925 | |
926 | if( pp->pr_dir != NIL(char)((char*)((void*)0)) ) |
927 | FREE(pp->pr_dir)free((char*)(pp->pr_dir)); |
928 | pp->pr_dir = DmStrDup(Get_current_dir()); |
929 | |
930 | Current_target = NIL(CELL)((CELL*)((void*)0)); |
931 | |
932 | _proc_cnt++; |
933 | |
934 | if( pid.pid != (DMHANDLE)-1 ) { |
935 | |
936 | |
937 | if( wfc ) { |
938 | Wait_for_child( FALSE0, i ); |
939 | } |
940 | |
941 | return -1; |
942 | } else |
943 | return i; |
944 | } |
945 | |
946 | |
947 | static void |
948 | _finished_child(cid, status) |
949 | |
950 | |
951 | |
952 | |
953 | |
954 | |
955 | |
956 | DMHANDLE cid; |
957 | int status; |
958 | { |
959 | register int i; |
960 | char *dir; |
961 | |
962 | if((int)cid < 1) { |
963 | |
964 | i = -((int)cid); |
965 | } |
966 | else { |
967 | for( i=0; i<Max_proc; i++ ) |
968 | if( _procs[i].pr_valid && _procs[i].pr_pid == cid ) |
969 | break; |
970 | |
971 | |
972 | |
973 | if( i == Max_proc ) { |
974 | Warning("Internal Warning: finished pid %d is not in pq!?", cid); |
975 | return; |
976 | } |
977 | } |
978 | |
979 | |
980 | |
981 | _procs[i].pr_valid = 0; |
982 | |
983 | if( Measure & M_RECIPE0x02 ) |
984 | Do_profile_output( "e", M_RECIPE0x02, _procs[i].pr_target ); |
985 | |
986 | _proc_cnt--; |
987 | dir = DmStrDup(Get_current_dir()); |
988 | Set_dir( _procs[i].pr_dir ); |
989 | |
990 | if( _procs[i].pr_recipe != NIL(RCP)((RCP*)((void*)0)) && !_abort_flg ) { |
991 | RCPPTR rp = _procs[i].pr_recipe; |
992 | |
993 | |
994 | Current_target = _procs[i].pr_target; |
995 | Handle_result( status, _procs[i].pr_ignore, FALSE0, _procs[i].pr_target ); |
996 | Current_target = NIL(CELL)((CELL*)((void*)0)); |
997 | |
998 | if ( _procs[i].pr_target->ce_attr & A_ERROR0x10000000 ) { |
999 | _procs[i].pr_last = TRUE1; |
1000 | goto ABORT_REMAINDER_OF_RECIPE; |
1001 | } |
1002 | |
1003 | _procs[i].pr_recipe = rp->prp_next; |
1004 | |
1005 | _use_i = i; |
1006 | |
1007 | |
1008 | runargv( _procs[i].pr_target, rp->prp_group, |
1009 | rp->prp_last, rp->prp_attr, &rp->prp_cmd ); |
1010 | _use_i = -1; |
1011 | |
1012 | FREE( rp->prp_cmd )free((char*)(rp->prp_cmd)); |
1013 | FREE( rp )free((char*)(rp)); |
1014 | |
1015 | |
1016 | |
1017 | if( _proc_cnt == Max_proc ) { |
1018 | Wait_for_child( FALSE0, -1 ); |
1019 | } |
1020 | } |
1021 | else { |
1022 | |
1023 | if( _abort_flg ) |
1024 | _procs[i].pr_recipe = NIL(RCP)((RCP*)((void*)0)); |
1025 | |
1026 | Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target); |
1027 | |
1028 | ABORT_REMAINDER_OF_RECIPE: |
1029 | if( _procs[i].pr_last ) { |
1030 | FREE(_procs[i].pr_dir )free((char*)(_procs[i].pr_dir)); _procs[i].pr_dir = NIL(char)((char*)((void*)0)); |
1031 | |
1032 | if( !Doing_bang ) { |
1033 | |
1034 | |
1035 | |
1036 | int my_use_i = _use_i; |
1037 | |
1038 | _use_i = -1; |
1039 | Update_time_stamp( _procs[i].pr_target ); |
1040 | _use_i = my_use_i; |
1041 | } |
1042 | } |
1043 | } |
1044 | |
1045 | Set_dir(dir); |
1046 | FREE(dir)free((char*)(dir)); |
1047 | } |
1048 | |
1049 | |
1050 | static int |
1051 | _running( cp ) |
1052 | |
1053 | |
1054 | |
1055 | |
1056 | CELLPTR cp; |
1057 | { |
1058 | register int i; |
1059 | |
1060 | if( !_procs ) return( -1 ); |
1061 | |
1062 | for( i=0; i<Max_proc; i++ ) |
1063 | if( _procs[i].pr_valid && |
1064 | _procs[i].pr_target == cp ) |
1065 | break; |
1066 | |
1067 | return( i == Max_proc ? -1 : i ); |
1068 | } |
1069 | |
1070 | |
1071 | static void |
1072 | _attach_cmd( cmd, group, cp, cmnd_attr, last ) |
1073 | |
1074 | |
1075 | char *cmd; |
1076 | int group; |
1077 | CELLPTR cp; |
1078 | t_attr cmnd_attr; |
1079 | int last; |
1080 | { |
1081 | register int i; |
1082 | RCPPTR rp; |
1083 | |
1084 | for( i=0; i<Max_proc; i++ ) |
| 1 | Loop condition is false. Execution continues on line 1089 | |
|
1085 | if( _procs[i].pr_valid && |
1086 | _procs[i].pr_target == cp ) |
1087 | break; |
1088 | |
1089 | TALLOC( rp, 1, RCP )if ((rp = (RCP*) calloc((unsigned int)(1), (size_t)sizeof(RCP ))) == (RCP*)0) {No_ram();}; |
| 2 | | Within the expansion of the macro 'TALLOC':
| |
b | Assuming pointer value is null |
|
1090 | rp->prp_cmd = DmStrDup(cmd); |
| 3 | | Access to field 'prp_cmd' results in a dereference of a null pointer (loaded from variable 'rp') |
|
1091 | rp->prp_attr = cmnd_attr; |
1092 | |
1093 | if( _procs[i].pr_wfc ) |
1094 | rp->prp_attr |= A_WFC0x00200; |
1095 | rp->prp_group = group; |
1096 | rp->prp_last = last; |
1097 | |
1098 | if( _procs[i].pr_recipe == NIL(RCP)((RCP*)((void*)0)) ) |
1099 | _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp; |
1100 | else { |
1101 | _procs[i].pr_recipe_end->prp_next = rp; |
1102 | _procs[i].pr_recipe_end = rp; |
1103 | } |
1104 | } |