1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.proc.c,v 3.127 2015/02/22 21:40:14 christos Exp $ */ 2 /* 3 * sh.proc.c: Job manipulations 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 #include "sh.h" 34 35 RCSID("$tcsh: sh.proc.c,v 3.127 2015/02/22 21:40:14 christos Exp $") 36 37 #include "ed.h" 38 #include "tc.h" 39 #include "tc.wait.h" 40 41 #ifdef WINNT_NATIVE 42 #undef POSIX 43 #define POSIX 44 #endif /* WINNT_NATIVE */ 45 #ifdef aiws 46 # undef HZ 47 # define HZ 16 48 #endif /* aiws */ 49 50 #if defined(_BSD) || (defined(IRIS4D) && __STDC__) || defined(__lucid) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) 51 # if !defined(__ANDROID__) 52 # define BSDWAIT 53 # endif 54 #endif /* _BSD || (IRIS4D && __STDC__) || __lucid || glibc */ 55 #ifndef WTERMSIG 56 # define WTERMSIG(w) (((union wait *) &(w))->w_termsig) 57 # ifndef BSDWAIT 58 # define BSDWAIT 59 # endif /* !BSDWAIT */ 60 #endif /* !WTERMSIG */ 61 #ifndef WEXITSTATUS 62 # define WEXITSTATUS(w) (((union wait *) &(w))->w_retcode) 63 #endif /* !WEXITSTATUS */ 64 #ifndef WSTOPSIG 65 # define WSTOPSIG(w) (((union wait *) &(w))->w_stopsig) 66 #endif /* !WSTOPSIG */ 67 68 #ifdef __osf__ 69 # ifndef WCOREDUMP 70 # define WCOREDUMP(x) (_W_INT(x) & WCOREFLAG) 71 # endif 72 #endif 73 74 #ifndef WCOREDUMP 75 # ifdef BSDWAIT 76 # define WCOREDUMP(w) (((union wait *) &(w))->w_coredump) 77 # else /* !BSDWAIT */ 78 # define WCOREDUMP(w) ((w) & 0200) 79 # endif /* !BSDWAIT */ 80 #endif /* !WCOREDUMP */ 81 82 #ifndef JOBDEBUG 83 # define jobdebug_xprintf(x) (void)0 84 # define jobdebug_flush() (void)0 85 #else 86 # define jobdebug_xprintf(s) xprintf s 87 # define jobdebug_flush() flush() 88 #endif 89 90 /* 91 * C Shell - functions that manage processes, handling hanging, termination 92 */ 93 94 #define BIGINDEX 9 /* largest desirable job index */ 95 96 #ifdef BSDTIMES 97 # ifdef convex 98 /* use 'cvxrusage' to get parallel statistics */ 99 static struct cvxrusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L, 100 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 101 {0L, 0L}, 0LL, 0LL, 0LL, 0LL, 0L, 0L, 0L, 102 0LL, 0LL, {0L, 0L, 0L, 0L, 0L}}; 103 # else 104 static struct rusage zru; 105 # endif /* convex */ 106 #else /* !BSDTIMES */ 107 # ifdef _SEQUENT_ 108 static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0, 109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 110 # else /* !_SEQUENT_ */ 111 # ifdef _SX 112 static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0}; 113 # else /* !_SX */ 114 static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L}; 115 # endif /* !_SX */ 116 # endif /* !_SEQUENT_ */ 117 #endif /* !BSDTIMES */ 118 119 #ifndef BSDTIMES 120 static int timesdone; /* shtimes buffer full ? */ 121 #endif /* BSDTIMES */ 122 123 #ifndef RUSAGE_CHILDREN 124 # define RUSAGE_CHILDREN -1 125 #endif /* RUSAGE_CHILDREN */ 126 127 static void pflushall (void); 128 static void pflush (struct process *); 129 static void pfree (struct process *); 130 static void pclrcurr (struct process *); 131 static void morecommand (size_t); 132 static void padd (struct command *); 133 static int pprint (struct process *, int); 134 static void ptprint (struct process *); 135 static void pads (Char *); 136 static void pkill (Char **, int); 137 static struct process *pgetcurr (struct process *); 138 static void okpcntl (void); 139 static void setttypgrp (int); 140 141 /* 142 * pchild - call queued by the SIGCHLD signal 143 * indicating that at least one child has terminated or stopped 144 * thus at least one wait system call will definitely return a 145 * childs status. Top level routines (like pwait) must be sure 146 * to mask interrupts when playing with the proclist data structures! 147 */ 148 void 149 pchild(void) 150 { 151 struct process *pp; 152 struct process *fp; 153 pid_t pid; 154 #ifdef BSDWAIT 155 union wait w; 156 #else /* !BSDWAIT */ 157 int w; 158 #endif /* !BSDWAIT */ 159 int jobflags; 160 #ifdef BSDTIMES 161 struct sysrusage ru; 162 #else /* !BSDTIMES */ 163 # ifdef _SEQUENT_ 164 struct process_stats ru; 165 struct process_stats cpst1, cpst2; 166 timeval_t tv; 167 # else /* !_SEQUENT_ */ 168 struct tms proctimes; 169 170 if (!timesdone) { 171 timesdone++; 172 (void) times(&shtimes); 173 } 174 # endif /* !_SEQUENT_ */ 175 #endif /* !BSDTIMES */ 176 177 jobdebug_xprintf(("pchild()\n")); 178 179 loop: 180 jobdebug_xprintf(("Waiting...\n")); 181 jobdebug_flush(); 182 errno = 0; /* reset, just in case */ 183 184 #ifndef WINNT_NATIVE 185 # ifdef BSDJOBS 186 # ifdef BSDTIMES 187 # ifdef convex 188 /* use 'cvxwait' to get parallel statistics */ 189 pid = cvxwait(&w, 190 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); 191 # else 192 /* both a wait3 and rusage */ 193 # if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || (defined(IRIS4D) && SYSVREL <= 3) || defined(__lucid) || defined(__osf__) 194 pid = wait3(&w, 195 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); 196 # else /* BSDWAIT */ 197 pid = wait3(&w.w_status, 198 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); 199 # endif /* BSDWAIT */ 200 # endif /* convex */ 201 # else /* !BSDTIMES */ 202 # ifdef _SEQUENT_ 203 (void) get_process_stats(&tv, PS_SELF, 0, &cpst1); 204 pid = waitpid(-1, &w, 205 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG)); 206 (void) get_process_stats(&tv, PS_SELF, 0, &cpst2); 207 pr_stat_sub(&cpst2, &cpst1, &ru); 208 # else /* !_SEQUENT_ */ 209 # ifndef POSIX 210 /* we have a wait3, but no rusage stuff */ 211 pid = wait3(&w.w_status, 212 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0); 213 # else /* POSIX */ 214 pid = waitpid(-1, &w, 215 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG)); 216 # endif /* POSIX */ 217 # endif /* !_SEQUENT_ */ 218 # endif /* !BSDTIMES */ 219 # else /* !BSDJOBS */ 220 # ifdef BSDTIMES 221 # define HAVEwait3 222 /* both a wait3 and rusage */ 223 # ifdef hpux 224 pid = wait3(&w.w_status, WNOHANG, 0); 225 # else /* !hpux */ 226 # ifndef BSDWAIT 227 pid = wait3(&w, WNOHANG, &ru); 228 # else 229 pid = wait3(&w.w_status, WNOHANG, &ru); 230 # endif /* BSDWAIT */ 231 # endif /* !hpux */ 232 # else /* !BSDTIMES */ 233 # ifdef ODT /* For Sco Unix 3.2.0 or ODT 1.0 */ 234 # define HAVEwait3 235 pid = waitpid(-1, &w, 236 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG)); 237 # endif /* ODT */ 238 # if defined(aiws) || defined(uts) 239 # define HAVEwait3 240 pid = wait3(&w.w_status, 241 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0); 242 # endif /* aiws || uts */ 243 # ifndef HAVEwait3 244 # ifndef BSDWAIT 245 /* no wait3, therefore no rusage */ 246 /* on Sys V, this may hang. I hope it's not going to be a problem */ 247 pid = wait(&w); 248 # else /* BSDWAIT */ 249 /* 250 * XXX: for greater than 3 we should use waitpid(). 251 * but then again, SVR4 falls into the POSIX/BSDJOBS category. 252 */ 253 pid = wait(&w.w_status); 254 # endif /* BSDWAIT */ 255 # endif /* !HAVEwait3 */ 256 # endif /* !BSDTIMES */ 257 # endif /* !BSDJOBS */ 258 #else /* WINNT_NATIVE */ 259 pid = waitpid(-1, &w, 260 (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG)); 261 #endif /* WINNT_NATIVE */ 262 263 jobdebug_xprintf(("parent %d pid %d, retval %x termsig %x retcode %x\n", 264 (int)getpid(), (int)pid, w, WTERMSIG(w), 265 WEXITSTATUS(w))); 266 jobdebug_flush(); 267 268 if ((pid == 0) || (pid == -1)) { 269 (void)handle_pending_signals(); 270 jobdebug_xprintf(("errno == %d\n", errno)); 271 if (errno == EINTR) 272 goto loop; 273 goto end; 274 } 275 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) 276 if (pid == pp->p_procid) 277 goto found; 278 #if !defined(BSDJOBS) && !defined(WINNT_NATIVE) 279 /* this should never have happened */ 280 stderror(ERR_SYNC, pid); 281 xexit(0); 282 #else /* BSDJOBS || WINNT_NATIVE */ 283 goto loop; 284 #endif /* !BSDJOBS && !WINNT_NATIVE */ 285 found: 286 pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED); 287 if (WIFSTOPPED(w)) { 288 pp->p_flags |= PSTOPPED; 289 pp->p_reason = WSTOPSIG(w); 290 } 291 else { 292 if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime)) 293 #ifndef BSDTIMES 294 # ifdef _SEQUENT_ 295 (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL); 296 # else /* !_SEQUENT_ */ 297 pp->p_etime = times(&proctimes); 298 # endif /* !_SEQUENT_ */ 299 #else /* BSDTIMES */ 300 (void) gettimeofday(&pp->p_etime, NULL); 301 #endif /* BSDTIMES */ 302 303 304 #if defined(BSDTIMES) || defined(_SEQUENT_) 305 pp->p_rusage = ru; 306 #else /* !BSDTIMES && !_SEQUENT_ */ 307 (void) times(&proctimes); 308 pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime; 309 pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime; 310 shtimes = proctimes; 311 #endif /* !BSDTIMES && !_SEQUENT_ */ 312 if (WIFSIGNALED(w)) { 313 if (WTERMSIG(w) == SIGINT) 314 pp->p_flags |= PINTERRUPTED; 315 else 316 pp->p_flags |= PSIGNALED; 317 if (WCOREDUMP(w)) 318 pp->p_flags |= PDUMPED; 319 pp->p_reason = WTERMSIG(w); 320 } 321 else { 322 pp->p_reason = WEXITSTATUS(w); 323 if (pp->p_reason != 0) 324 pp->p_flags |= PAEXITED; 325 else 326 pp->p_flags |= PNEXITED; 327 } 328 } 329 jobflags = 0; 330 fp = pp; 331 do { 332 if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 && 333 !child && adrof(STRtime) && 334 #ifdef BSDTIMES 335 fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec 336 #else /* !BSDTIMES */ 337 # ifdef _SEQUENT_ 338 fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec 339 # else /* !_SEQUENT_ */ 340 # ifndef POSIX 341 (fp->p_utime + fp->p_stime) / HZ 342 # else /* POSIX */ 343 (fp->p_utime + fp->p_stime) / clk_tck 344 # endif /* POSIX */ 345 # endif /* !_SEQUENT_ */ 346 #endif /* !BSDTIMES */ 347 >= atoi(short2str(varval(STRtime)))) 348 fp->p_flags |= PTIME; 349 jobflags |= fp->p_flags; 350 } while ((fp = fp->p_friends) != pp); 351 pp->p_flags &= ~PFOREGND; 352 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { 353 pp->p_flags &= ~PPTIME; 354 pp->p_flags |= PTIME; 355 } 356 if ((jobflags & (PRUNNING | PREPORTED)) == 0) { 357 fp = pp; 358 do { 359 if (fp->p_flags & PSTOPPED) 360 fp->p_flags |= PREPORTED; 361 } while ((fp = fp->p_friends) != pp); 362 while (fp->p_procid != fp->p_jobid) 363 fp = fp->p_friends; 364 if (jobflags & PSTOPPED) { 365 if (pcurrent && pcurrent != fp) 366 pprevious = pcurrent; 367 pcurrent = fp; 368 } 369 else 370 pclrcurr(fp); 371 if (jobflags & PFOREGND) { 372 if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) || 373 #ifdef notdef 374 jobflags & PAEXITED || 375 #endif /* notdef */ 376 fp->p_cwd == NULL || 377 !eq(dcwd->di_name, fp->p_cwd->di_name))) { 378 /* PWP: print a newline after ^C */ 379 if (jobflags & PINTERRUPTED) { 380 xputchar('\r' | QUOTE); 381 xputchar('\n'); 382 } 383 #ifdef notdef 384 else if ((jobflags & (PTIME|PSTOPPED)) == PTIME) 385 ptprint(fp); 386 #endif /* notdef */ 387 } 388 } 389 else { 390 if (jobflags & PNOTIFY || adrof(STRnotify)) { 391 xputchar('\r' | QUOTE); 392 xputchar('\n'); 393 (void) pprint(pp, NUMBER | NAME | REASON); 394 if ((jobflags & PSTOPPED) == 0) 395 pflush(pp); 396 if (GettingInput) { 397 errno = 0; 398 (void) Rawmode(); 399 #ifdef notdef 400 /* 401 * don't really want to do that, because it 402 * will erase our message in case of multi-line 403 * input 404 */ 405 ClearLines(); 406 #endif /* notdef */ 407 ClearDisp(); 408 Refresh(); 409 } 410 } 411 else { 412 fp->p_flags |= PNEEDNOTE; 413 neednote = 1; 414 } 415 } 416 } 417 #if defined(BSDJOBS) || defined(HAVEwait3) ||defined(WINNT_NATIVE) 418 goto loop; 419 #endif /* BSDJOBS || HAVEwait3 */ 420 end: 421 ; 422 } 423 424 void 425 pnote(void) 426 { 427 struct process *pp; 428 int flags; 429 430 neednote = 0; 431 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) { 432 if (pp->p_flags & PNEEDNOTE) { 433 pchild_disabled++; 434 cleanup_push(&pchild_disabled, disabled_cleanup); 435 pp->p_flags &= ~PNEEDNOTE; 436 flags = pprint(pp, NUMBER | NAME | REASON); 437 if ((flags & (PRUNNING | PSTOPPED)) == 0) 438 pflush(pp); 439 cleanup_until(&pchild_disabled); 440 } 441 } 442 } 443 444 445 static void 446 pfree(struct process *pp) 447 { 448 xfree(pp->p_command); 449 if (pp->p_cwd && --pp->p_cwd->di_count == 0) 450 if (pp->p_cwd->di_next == 0) 451 dfree(pp->p_cwd); 452 xfree(pp); 453 } 454 455 456 /* 457 * pwait - wait for current job to terminate, maintaining integrity 458 * of current and previous job indicators. 459 */ 460 void 461 pwait(void) 462 { 463 struct process *fp, *pp; 464 465 /* 466 * Here's where dead procs get flushed. 467 */ 468 for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next) 469 if (pp->p_procid == 0) { 470 fp->p_next = pp->p_next; 471 pfree(pp); 472 pp = fp; 473 } 474 pjwait(pcurrjob); 475 } 476 477 478 /* 479 * pjwait - wait for a job to finish or become stopped 480 * It is assumed to be in the foreground state (PFOREGND) 481 */ 482 void 483 pjwait(struct process *pp) 484 { 485 struct process *fp; 486 int jobflags, reason; 487 sigset_t oset, set, pause_mask; 488 Char *reason_str; 489 490 while (pp->p_procid != pp->p_jobid) 491 pp = pp->p_friends; 492 fp = pp; 493 494 do { 495 if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING) 496 xprintf("%s", CGETS(17, 1, "BUG: waiting for background job!\n")); 497 } while ((fp = fp->p_friends) != pp); 498 /* 499 * Now keep pausing as long as we are not interrupted (SIGINT), and the 500 * target process, or any of its friends, are running 501 */ 502 fp = pp; 503 sigemptyset(&set); 504 sigaddset(&set, SIGINT); 505 sigaddset(&set, SIGCHLD); 506 (void)sigprocmask(SIG_BLOCK, &set, &oset); 507 cleanup_push(&oset, sigprocmask_cleanup); 508 pause_mask = oset; 509 sigdelset(&pause_mask, SIGCHLD); 510 sigaddset(&pause_mask, SIGINT); 511 for (;;) { 512 (void)handle_pending_signals(); 513 jobflags = 0; 514 do 515 jobflags |= fp->p_flags; 516 while ((fp = (fp->p_friends)) != pp); 517 if ((jobflags & PRUNNING) == 0) 518 break; 519 jobdebug_xprintf(("%d starting to sigsuspend for SIGCHLD on %d\n", 520 getpid(), fp->p_procid)); 521 sigsuspend(&pause_mask); 522 } 523 cleanup_until(&oset); 524 jobdebug_xprintf(("%d returned from sigsuspend loop\n", getpid())); 525 #ifdef BSDJOBS 526 if (tpgrp > 0) /* get tty back */ 527 (void) tcsetpgrp(FSHTTY, tpgrp); 528 #endif /* BSDJOBS */ 529 if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) || 530 fp->p_cwd == NULL || !eq(dcwd->di_name, fp->p_cwd->di_name)) { 531 if (jobflags & PSTOPPED) { 532 xputchar('\n'); 533 if (adrof(STRlistjobs)) { 534 Char *jobcommand[3]; 535 536 jobcommand[0] = STRjobs; 537 if (eq(varval(STRlistjobs), STRlong)) 538 jobcommand[1] = STRml; 539 else 540 jobcommand[1] = NULL; 541 jobcommand[2] = NULL; 542 543 dojobs(jobcommand, NULL); 544 (void) pprint(pp, SHELLDIR); 545 } 546 else 547 (void) pprint(pp, AREASON | SHELLDIR); 548 } 549 else 550 (void) pprint(pp, AREASON | SHELLDIR); 551 } 552 if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr && 553 (!gointr || !eq(gointr, STRminus))) { 554 if ((jobflags & PSTOPPED) == 0) 555 pflush(pp); 556 pintr1(0); 557 /* NOTREACHED */ 558 } 559 reason = 0; 560 fp = pp; 561 do { 562 /* In case of pipelines only the result of the last 563 * command should be taken in account */ 564 if (!anyerror && !(fp->p_flags & PBRACE) 565 && ((fp->p_flags & PPOU) || (fp->p_flags & PBACKQ))) 566 continue; 567 if (fp->p_reason) 568 reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ? 569 fp->p_reason | META : fp->p_reason; 570 } while ((fp = fp->p_friends) != pp); 571 /* 572 * Don't report on backquoted jobs, cause it will mess up 573 * their output. 574 */ 575 if ((reason != 0) && (adrof(STRprintexitvalue)) && 576 (pp->p_flags & PBACKQ) == 0) 577 xprintf(CGETS(17, 2, "Exit %d\n"), reason); 578 reason_str = putn((tcsh_number_t)reason); 579 cleanup_push(reason_str, xfree); 580 setv(STRstatus, reason_str, VAR_READWRITE); 581 cleanup_ignore(reason_str); 582 cleanup_until(reason_str); 583 if (reason && exiterr) 584 exitstat(); 585 pflush(pp); 586 } 587 588 /* 589 * dowait - wait for all processes to finish 590 */ 591 592 /*ARGSUSED*/ 593 void 594 dowait(Char **v, struct command *c) 595 { 596 struct process *pp; 597 598 /* the current block mask to be able to restore */ 599 sigset_t old_mask; 600 601 /* block mask for critical section: OLD_MASK U {SIGCHLD} */ 602 sigset_t block_mask; 603 604 /* ignore those during blocking sigsuspend: 605 OLD_MASK / {SIGCHLD, possibly(SIGINT)} */ 606 sigset_t pause_mask; 607 608 int opintr_disabled, gotsig; 609 610 USE(c); 611 USE(v); 612 pjobs++; 613 614 sigprocmask(SIG_BLOCK, NULL, &pause_mask); 615 sigdelset(&pause_mask, SIGCHLD); 616 if (setintr) 617 sigdelset(&pause_mask, SIGINT); 618 619 /* critical section, block also SIGCHLD */ 620 sigprocmask(SIG_BLOCK, NULL, &block_mask); 621 sigaddset(&block_mask, SIGCHLD); 622 sigprocmask(SIG_BLOCK, &block_mask, &old_mask); 623 624 /* detect older SIGCHLDs and remove PRUNNING flag from proclist */ 625 (void)handle_pending_signals(); 626 627 loop: 628 for (pp = proclist.p_next; pp; pp = pp->p_next) 629 if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */ 630 pp->p_flags & PRUNNING) { 631 /* wait for (or pick up alredy blocked) SIGCHLD */ 632 sigsuspend(&pause_mask); 633 634 /* make the 'wait' interuptable by CTRL-C */ 635 opintr_disabled = pintr_disabled; 636 pintr_disabled = 0; 637 gotsig = handle_pending_signals(); 638 pintr_disabled = opintr_disabled; 639 if (gotsig) 640 break; 641 goto loop; 642 } 643 pjobs = 0; 644 645 sigprocmask(SIG_SETMASK, &old_mask, NULL); 646 } 647 648 /* 649 * pflushall - flush all jobs from list (e.g. at fork()) 650 */ 651 static void 652 pflushall(void) 653 { 654 struct process *pp; 655 656 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) 657 if (pp->p_procid) 658 pflush(pp); 659 } 660 661 /* 662 * pflush - flag all process structures in the same job as the 663 * the argument process for deletion. The actual free of the 664 * space is not done here since pflush is called at interrupt level. 665 */ 666 static void 667 pflush(struct process *pp) 668 { 669 struct process *np; 670 int idx; 671 672 if (pp->p_procid == 0) { 673 xprintf("%s", CGETS(17, 3, "BUG: process flushed twice")); 674 return; 675 } 676 while (pp->p_procid != pp->p_jobid) 677 pp = pp->p_friends; 678 pclrcurr(pp); 679 if (pp == pcurrjob) 680 pcurrjob = 0; 681 idx = pp->p_index; 682 np = pp; 683 do { 684 np->p_index = np->p_procid = 0; 685 np->p_flags &= ~PNEEDNOTE; 686 } while ((np = np->p_friends) != pp); 687 if (idx == pmaxindex) { 688 for (np = proclist.p_next, idx = 0; np; np = np->p_next) 689 if (np->p_index > idx) 690 idx = np->p_index; 691 pmaxindex = idx; 692 } 693 } 694 695 /* 696 * pclrcurr - make sure the given job is not the current or previous job; 697 * pp MUST be the job leader 698 */ 699 static void 700 pclrcurr(struct process *pp) 701 { 702 if (pp == pcurrent) { 703 if (pprevious != NULL) { 704 pcurrent = pprevious; 705 pprevious = pgetcurr(pp); 706 } 707 else { 708 pcurrent = pgetcurr(pp); 709 pprevious = pgetcurr(pp); 710 } 711 } 712 else if (pp == pprevious) 713 pprevious = pgetcurr(pp); 714 } 715 716 /* +4 here is 1 for '\0', 1 ea for << >& >> */ 717 static Char *cmdstr; 718 static size_t cmdmax; 719 static size_t cmdlen; 720 static Char *cmdp; 721 #define CMD_INIT 1024 722 #define CMD_INCR 64 723 724 static void 725 morecommand(size_t s) 726 { 727 Char *ncmdstr; 728 ptrdiff_t d; 729 730 cmdmax += s; 731 ncmdstr = xrealloc(cmdstr, cmdmax * sizeof(*cmdstr)); 732 d = ncmdstr - cmdstr; 733 cmdstr = ncmdstr; 734 cmdp += d; 735 } 736 737 /* GrP 738 * unparse - Export padd() functionality 739 */ 740 Char * 741 unparse(struct command *t) 742 { 743 if (cmdmax == 0) 744 morecommand(CMD_INIT); 745 cmdp = cmdstr; 746 cmdlen = 0; 747 padd(t); 748 *cmdp++ = '\0'; 749 return Strsave(cmdstr); 750 } 751 752 753 /* 754 * palloc - allocate a process structure and fill it up. 755 * an important assumption is made that the process is running. 756 */ 757 void 758 palloc(pid_t pid, struct command *t) 759 { 760 struct process *pp; 761 int i; 762 763 pp = xcalloc(1, sizeof(struct process)); 764 pp->p_procid = pid; 765 pp->p_parentid = shpgrp; 766 pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING; 767 if (t->t_dflg & F_TIME) 768 pp->p_flags |= PPTIME; 769 if (t->t_dflg & F_BACKQ) 770 pp->p_flags |= PBACKQ; 771 if (t->t_dflg & F_HUP) 772 pp->p_flags |= PHUP; 773 if (t->t_dcom && t->t_dcom[0] && (*t->t_dcom[0] == '{')) 774 pp->p_flags |= PBRACE; 775 if (cmdmax == 0) 776 morecommand(CMD_INIT); 777 cmdp = cmdstr; 778 cmdlen = 0; 779 padd(t); 780 *cmdp++ = 0; 781 if (t->t_dflg & F_PIPEOUT) { 782 pp->p_flags |= PPOU; 783 if (t->t_dflg & F_STDERR) 784 pp->p_flags |= PDIAG; 785 } 786 pp->p_command = Strsave(cmdstr); 787 if (pcurrjob) { 788 struct process *fp; 789 790 /* careful here with interrupt level */ 791 pp->p_cwd = 0; 792 pp->p_index = pcurrjob->p_index; 793 pp->p_friends = pcurrjob; 794 pp->p_jobid = pcurrjob->p_procid; 795 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) 796 continue; 797 fp->p_friends = pp; 798 } 799 else { 800 pcurrjob = pp; 801 pp->p_jobid = pid; 802 pp->p_friends = pp; 803 pp->p_cwd = dcwd; 804 dcwd->di_count++; 805 if (pmaxindex < BIGINDEX) 806 pp->p_index = ++pmaxindex; 807 else { 808 struct process *np; 809 810 for (i = 1;; i++) { 811 for (np = proclist.p_next; np; np = np->p_next) 812 if (np->p_index == i) 813 goto tryagain; 814 pp->p_index = i; 815 if (i > pmaxindex) 816 pmaxindex = i; 817 break; 818 tryagain:; 819 } 820 } 821 if (pcurrent == NULL) 822 pcurrent = pp; 823 else if (pprevious == NULL) 824 pprevious = pp; 825 } 826 pp->p_next = proclist.p_next; 827 proclist.p_next = pp; 828 #ifdef BSDTIMES 829 (void) gettimeofday(&pp->p_btime, NULL); 830 #else /* !BSDTIMES */ 831 # ifdef _SEQUENT_ 832 (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL); 833 # else /* !_SEQUENT_ */ 834 { 835 struct tms tmptimes; 836 837 pp->p_btime = times(&tmptimes); 838 } 839 # endif /* !_SEQUENT_ */ 840 #endif /* !BSDTIMES */ 841 } 842 843 static void 844 padd(struct command *t) 845 { 846 Char **argp; 847 848 if (t == 0) 849 return; 850 switch (t->t_dtyp) { 851 852 case NODE_PAREN: 853 pads(STRLparensp); 854 padd(t->t_dspr); 855 pads(STRspRparen); 856 break; 857 858 case NODE_COMMAND: 859 for (argp = t->t_dcom; *argp; argp++) { 860 pads(*argp); 861 if (argp[1]) 862 pads(STRspace); 863 } 864 break; 865 866 case NODE_OR: 867 case NODE_AND: 868 case NODE_PIPE: 869 case NODE_LIST: 870 padd(t->t_dcar); 871 switch (t->t_dtyp) { 872 case NODE_OR: 873 pads(STRspor2sp); 874 break; 875 case NODE_AND: 876 pads(STRspand2sp); 877 break; 878 case NODE_PIPE: 879 pads(STRsporsp); 880 break; 881 case NODE_LIST: 882 pads(STRsemisp); 883 break; 884 default: 885 break; 886 } 887 padd(t->t_dcdr); 888 return; 889 890 default: 891 break; 892 } 893 if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) { 894 pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp); 895 pads(t->t_dlef); 896 } 897 if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) { 898 pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow); 899 if (t->t_dflg & F_STDERR) 900 pads(STRand); 901 pads(STRspace); 902 pads(t->t_drit); 903 } 904 } 905 906 static void 907 pads(Char *cp) 908 { 909 size_t i, len; 910 911 /* 912 * Avoid the Quoted Space alias hack! Reported by: 913 * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks) 914 */ 915 if (cp[0] == STRQNULL[0]) 916 cp++; 917 918 i = Strlen(cp); 919 920 len = cmdlen + i + CMD_INCR; 921 if (len >= cmdmax) 922 morecommand(len); 923 (void) Strcpy(cmdp, cp); 924 cmdp += i; 925 cmdlen += i; 926 } 927 928 /* 929 * psavejob - temporarily save the current job on a one level stack 930 * so another job can be created. Used for { } in exp6 931 * and `` in globbing. 932 */ 933 void 934 psavejob(void) 935 { 936 pholdjob = pcurrjob; 937 pcurrjob = NULL; 938 } 939 940 void 941 psavejob_cleanup(void *dummy) 942 { 943 USE(dummy); 944 pcurrjob = pholdjob; 945 pholdjob = NULL; 946 } 947 948 /* 949 * pendjob - indicate that a job (set of commands) has been completed 950 * or is about to begin. 951 */ 952 void 953 pendjob(void) 954 { 955 struct process *pp, *tp; 956 957 if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) { 958 pp = pcurrjob; 959 pcurrjob = NULL; 960 while (pp->p_procid != pp->p_jobid) 961 pp = pp->p_friends; 962 xprintf("[%d]", pp->p_index); 963 tp = pp; 964 do { 965 xprintf(" %d", pp->p_procid); 966 pp = pp->p_friends; 967 } while (pp != tp); 968 xputchar('\n'); 969 } 970 pholdjob = pcurrjob = 0; 971 } 972 973 /* 974 * pprint - print a job 975 */ 976 977 /* 978 * Hacks have been added for SVR4 to deal with pipe's being spawned in 979 * reverse order 980 * 981 * David Dawes (dawes@physics.su.oz.au) Oct 1991 982 */ 983 984 static int 985 pprint(struct process *pp, int flag) 986 { 987 int status, reason; 988 struct process *tp; 989 int jobflags, pstatus, pcond; 990 const char *format; 991 992 #ifdef BACKPIPE 993 struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL; 994 int inpipe = 0; 995 #endif /* BACKPIPE */ 996 997 while (pp->p_procid != pp->p_jobid) 998 pp = pp->p_friends; 999 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { 1000 pp->p_flags &= ~PPTIME; 1001 pp->p_flags |= PTIME; 1002 } 1003 tp = pp; 1004 status = reason = -1; 1005 jobflags = 0; 1006 haderr = 1; /* Print statuc to stderr */ 1007 do { 1008 #ifdef BACKPIPE 1009 /* 1010 * The pipeline is reversed, so locate the real head of the pipeline 1011 * if pp is at the tail of a pipe (and not already in a pipeline) 1012 */ 1013 if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) { 1014 inpipe = 1; 1015 pipetail = pp; 1016 do 1017 pp = pp->p_friends; 1018 while (pp->p_friends->p_flags & PPOU); 1019 pipehead = pp; 1020 pmarker = pp; 1021 /* 1022 * pmarker is used to hold the place of the proc being processed, so 1023 * we can search for the next one downstream later. 1024 */ 1025 } 1026 pcond = (tp != pp || (inpipe && tp == pp)); 1027 #else /* !BACKPIPE */ 1028 pcond = (tp != pp); 1029 #endif /* BACKPIPE */ 1030 1031 jobflags |= pp->p_flags; 1032 pstatus = (int) (pp->p_flags & PALLSTATES); 1033 if (pcond && linp != linbuf && !(flag & FANCY) && 1034 ((pstatus == status && pp->p_reason == reason) || 1035 !(flag & REASON))) 1036 xputchar(' '); 1037 else { 1038 if (pcond && linp != linbuf) 1039 xputchar('\n'); 1040 if (flag & NUMBER) { 1041 #ifdef BACKPIPE 1042 pcond = ((pp == tp && !inpipe) || 1043 (inpipe && pipetail == tp && pp == pipehead)); 1044 #else /* BACKPIPE */ 1045 pcond = (pp == tp); 1046 #endif /* BACKPIPE */ 1047 if (pcond) 1048 xprintf("[%d]%s %c ", pp->p_index, 1049 pp->p_index < 10 ? " " : "", 1050 pp == pcurrent ? '+' : 1051 (pp == pprevious ? '-' : ' ')); 1052 else 1053 xprintf(" "); 1054 } 1055 if (flag & FANCY) { 1056 xprintf("%5d ", pp->p_procid); 1057 #ifdef TCF 1058 xprintf("%11s ", sitename(pp->p_procid)); 1059 #endif /* TCF */ 1060 } 1061 if (flag & (REASON | AREASON)) { 1062 if (flag & NAME) 1063 format = "%-30s"; 1064 else 1065 format = "%s"; 1066 if (pstatus == status) { 1067 if (pp->p_reason == reason) { 1068 xprintf(format, ""); 1069 goto prcomd; 1070 } 1071 else 1072 reason = (int) pp->p_reason; 1073 } 1074 else { 1075 status = pstatus; 1076 reason = (int) pp->p_reason; 1077 } 1078 switch (status) { 1079 1080 case PRUNNING: 1081 xprintf(format, CGETS(17, 4, "Running ")); 1082 break; 1083 1084 case PINTERRUPTED: 1085 case PSTOPPED: 1086 case PSIGNALED: 1087 /* 1088 * tell what happened to the background job 1089 * From: Michael Schroeder 1090 * <mlschroe@immd4.informatik.uni-erlangen.de> 1091 */ 1092 if ((flag & REASON) 1093 || ((flag & AREASON) 1094 && reason != SIGINT 1095 && (reason != SIGPIPE 1096 || (pp->p_flags & PPOU) == 0))) { 1097 char *ptr; 1098 int free_ptr; 1099 1100 free_ptr = 0; 1101 ptr = (char *)(intptr_t)mesg[pp->p_reason & 0177].pname; 1102 if (ptr == NULL) { 1103 ptr = xasprintf("%s %d", CGETS(17, 5, "Signal"), 1104 pp->p_reason & 0177); 1105 cleanup_push(ptr, xfree); 1106 free_ptr = 1; 1107 } 1108 xprintf(format, ptr); 1109 if (free_ptr != 0) 1110 cleanup_until(ptr); 1111 } 1112 else 1113 reason = -1; 1114 break; 1115 1116 case PNEXITED: 1117 case PAEXITED: 1118 if (flag & REASON) { 1119 if (pp->p_reason) 1120 xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason); 1121 else 1122 xprintf(format, CGETS(17, 7, "Done")); 1123 } 1124 break; 1125 1126 default: 1127 xprintf(CGETS(17, 8, "BUG: status=%-9o"), 1128 status); 1129 } 1130 } 1131 } 1132 prcomd: 1133 if (flag & NAME) { 1134 xprintf("%S", pp->p_command); 1135 if (pp->p_flags & PPOU) 1136 xprintf(" |"); 1137 if (pp->p_flags & PDIAG) 1138 xprintf("&"); 1139 } 1140 if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) 1141 xprintf("%s", CGETS(17, 9, " (core dumped)")); 1142 if (tp == pp->p_friends) { 1143 if (flag & AMPERSAND) 1144 xprintf(" &"); 1145 if (flag & JOBDIR && 1146 !eq(tp->p_cwd->di_name, dcwd->di_name)) { 1147 xprintf("%s", CGETS(17, 10, " (wd: ")); 1148 dtildepr(tp->p_cwd->di_name); 1149 xprintf(")"); 1150 } 1151 } 1152 if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) { 1153 if (linp != linbuf) 1154 xprintf("\n\t"); 1155 #if defined(BSDTIMES) || defined(_SEQUENT_) 1156 prusage(&zru, &pp->p_rusage, &pp->p_etime, 1157 &pp->p_btime); 1158 #else /* !BSDTIMES && !SEQUENT */ 1159 lru.tms_utime = pp->p_utime; 1160 lru.tms_stime = pp->p_stime; 1161 lru.tms_cutime = 0; 1162 lru.tms_cstime = 0; 1163 prusage(&zru, &lru, pp->p_etime, 1164 pp->p_btime); 1165 #endif /* !BSDTIMES && !SEQUENT */ 1166 1167 } 1168 #ifdef BACKPIPE 1169 pcond = ((tp == pp->p_friends && !inpipe) || 1170 (inpipe && pipehead->p_friends == tp && pp == pipetail)); 1171 #else /* !BACKPIPE */ 1172 pcond = (tp == pp->p_friends); 1173 #endif /* BACKPIPE */ 1174 if (pcond) { 1175 if (linp != linbuf) 1176 xputchar('\n'); 1177 if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { 1178 xprintf("%s", CGETS(17, 11, "(wd now: ")); 1179 dtildepr(dcwd->di_name); 1180 xprintf(")\n"); 1181 } 1182 } 1183 #ifdef BACKPIPE 1184 if (inpipe) { 1185 /* 1186 * if pmaker == pipetail, we are finished that pipeline, and 1187 * can now skip to past the head 1188 */ 1189 if (pmarker == pipetail) { 1190 inpipe = 0; 1191 pp = pipehead; 1192 } 1193 else { 1194 /* 1195 * set pp to one before the one we want next, so the while below 1196 * increments to the correct spot. 1197 */ 1198 do 1199 pp = pp->p_friends; 1200 while (pp->p_friends->p_friends != pmarker); 1201 pmarker = pp->p_friends; 1202 } 1203 } 1204 pcond = ((pp = pp->p_friends) != tp || inpipe); 1205 #else /* !BACKPIPE */ 1206 pcond = ((pp = pp->p_friends) != tp); 1207 #endif /* BACKPIPE */ 1208 } while (pcond); 1209 1210 if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) { 1211 if (jobflags & NUMBER) 1212 xprintf(" "); 1213 ptprint(tp); 1214 } 1215 haderr = 0; 1216 return (jobflags); 1217 } 1218 1219 /* 1220 * All 4.3 BSD derived implementations are buggy and I've had enough. 1221 * The following implementation produces similar code and works in all 1222 * cases. The 4.3BSD one works only for <, >, != 1223 */ 1224 # undef timercmp 1225 # define timercmp(tvp, uvp, cmp) \ 1226 (((tvp)->tv_sec == (uvp)->tv_sec) ? \ 1227 ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 1228 ((tvp)->tv_sec cmp (uvp)->tv_sec)) 1229 1230 static void 1231 ptprint(struct process *tp) 1232 { 1233 #ifdef BSDTIMES 1234 struct timeval tetime, diff; 1235 static struct timeval ztime; 1236 struct sysrusage ru; 1237 struct process *pp = tp; 1238 1239 ru = zru; 1240 tetime = ztime; 1241 do { 1242 ruadd(&ru, &pp->p_rusage); 1243 tvsub(&diff, &pp->p_etime, &pp->p_btime); 1244 if (timercmp(&diff, &tetime, >)) 1245 tetime = diff; 1246 } while ((pp = pp->p_friends) != tp); 1247 prusage(&zru, &ru, &tetime, &ztime); 1248 #else /* !BSDTIMES */ 1249 # ifdef _SEQUENT_ 1250 timeval_t tetime, diff; 1251 static timeval_t ztime; 1252 struct process_stats ru; 1253 struct process *pp = tp; 1254 1255 ru = zru; 1256 tetime = ztime; 1257 do { 1258 ruadd(&ru, &pp->p_rusage); 1259 tvsub(&diff, &pp->p_etime, &pp->p_btime); 1260 if (timercmp(&diff, &tetime, >)) 1261 tetime = diff; 1262 } while ((pp = pp->p_friends) != tp); 1263 prusage(&zru, &ru, &tetime, &ztime); 1264 # else /* !_SEQUENT_ */ 1265 # ifndef POSIX 1266 static time_t ztime = 0; 1267 static time_t zu_time = 0; 1268 static time_t zs_time = 0; 1269 time_t tetime, diff; 1270 time_t u_time, s_time; 1271 1272 # else /* POSIX */ 1273 static clock_t ztime = 0; 1274 static clock_t zu_time = 0; 1275 static clock_t zs_time = 0; 1276 clock_t tetime, diff; 1277 clock_t u_time, s_time; 1278 1279 # endif /* POSIX */ 1280 struct tms zts, rts; 1281 struct process *pp = tp; 1282 1283 u_time = zu_time; 1284 s_time = zs_time; 1285 tetime = ztime; 1286 do { 1287 u_time += pp->p_utime; 1288 s_time += pp->p_stime; 1289 diff = pp->p_etime - pp->p_btime; 1290 if (diff > tetime) 1291 tetime = diff; 1292 } while ((pp = pp->p_friends) != tp); 1293 zts.tms_utime = zu_time; 1294 zts.tms_stime = zs_time; 1295 zts.tms_cutime = 0; 1296 zts.tms_cstime = 0; 1297 rts.tms_utime = u_time; 1298 rts.tms_stime = s_time; 1299 rts.tms_cutime = 0; 1300 rts.tms_cstime = 0; 1301 prusage(&zts, &rts, tetime, ztime); 1302 # endif /* !_SEQUENT_ */ 1303 #endif /* !BSDTIMES */ 1304 } 1305 1306 /* 1307 * dojobs - print all jobs 1308 */ 1309 /*ARGSUSED*/ 1310 void 1311 dojobs(Char **v, struct command *c) 1312 { 1313 struct process *pp; 1314 int flag = NUMBER | NAME | REASON; 1315 int i; 1316 1317 USE(c); 1318 if (chkstop) 1319 chkstop = 2; 1320 if (*++v) { 1321 if (v[1] || !eq(*v, STRml)) 1322 stderror(ERR_JOBS); 1323 flag |= FANCY | JOBDIR; 1324 } 1325 for (i = 1; i <= pmaxindex; i++) 1326 for (pp = proclist.p_next; pp; pp = pp->p_next) 1327 if (pp->p_index == i && pp->p_procid == pp->p_jobid) { 1328 pp->p_flags &= ~PNEEDNOTE; 1329 if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED))) 1330 pflush(pp); 1331 break; 1332 } 1333 } 1334 1335 /* 1336 * dofg - builtin - put the job into the foreground 1337 */ 1338 /*ARGSUSED*/ 1339 void 1340 dofg(Char **v, struct command *c) 1341 { 1342 struct process *pp; 1343 1344 USE(c); 1345 okpcntl(); 1346 ++v; 1347 do { 1348 pp = pfind(*v); 1349 if (!pstart(pp, 1)) { 1350 pp->p_procid = 0; 1351 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1352 continue; 1353 } 1354 pjwait(pp); 1355 } while (*v && *++v); 1356 } 1357 1358 /* 1359 * %... - builtin - put the job into the foreground 1360 */ 1361 /*ARGSUSED*/ 1362 void 1363 dofg1(Char **v, struct command *c) 1364 { 1365 struct process *pp; 1366 1367 USE(c); 1368 okpcntl(); 1369 pp = pfind(v[0]); 1370 if (!pstart(pp, 1)) { 1371 pp->p_procid = 0; 1372 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1373 return; 1374 } 1375 pjwait(pp); 1376 } 1377 1378 /* 1379 * dobg - builtin - put the job into the background 1380 */ 1381 /*ARGSUSED*/ 1382 void 1383 dobg(Char **v, struct command *c) 1384 { 1385 struct process *pp; 1386 1387 USE(c); 1388 okpcntl(); 1389 ++v; 1390 do { 1391 pp = pfind(*v); 1392 if (!pstart(pp, 0)) { 1393 pp->p_procid = 0; 1394 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1395 } 1396 } while (*v && *++v); 1397 } 1398 1399 /* 1400 * %... & - builtin - put the job into the background 1401 */ 1402 /*ARGSUSED*/ 1403 void 1404 dobg1(Char **v, struct command *c) 1405 { 1406 struct process *pp; 1407 1408 USE(c); 1409 pp = pfind(v[0]); 1410 if (!pstart(pp, 0)) { 1411 pp->p_procid = 0; 1412 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1413 } 1414 } 1415 1416 /* 1417 * dostop - builtin - stop the job 1418 */ 1419 /*ARGSUSED*/ 1420 void 1421 dostop(Char **v, struct command *c) 1422 { 1423 USE(c); 1424 #ifdef BSDJOBS 1425 pkill(++v, SIGSTOP); 1426 #endif /* BSDJOBS */ 1427 } 1428 1429 /* 1430 * dokill - builtin - superset of kill (1) 1431 */ 1432 /*ARGSUSED*/ 1433 void 1434 dokill(Char **v, struct command *c) 1435 { 1436 int signum, len = 0; 1437 const char *name; 1438 Char *sigptr; 1439 1440 USE(c); 1441 v++; 1442 if (v[0] && v[0][0] == '-') { 1443 if (v[0][1] == 'l') { 1444 for (signum = 0; signum <= nsig; signum++) { 1445 if ((name = mesg[signum].iname) != NULL) { 1446 len += strlen(name) + 1; 1447 if (len >= TermH - 1) { 1448 xputchar('\n'); 1449 len = strlen(name) + 1; 1450 } 1451 xprintf("%s ", name); 1452 } 1453 } 1454 xputchar('\n'); 1455 return; 1456 } 1457 sigptr = &v[0][1]; 1458 if (v[0][1] == 's') { 1459 if (v[1]) { 1460 v++; 1461 sigptr = &v[0][0]; 1462 } else { 1463 stderror(ERR_NAME | ERR_TOOFEW); 1464 } 1465 } 1466 if (Isdigit(*sigptr)) { 1467 char *ep; 1468 signum = strtoul(short2str(sigptr), &ep, 0); 1469 if (*ep || signum < 0 || signum > (MAXSIG-1)) 1470 stderror(ERR_NAME | ERR_BADSIG); 1471 } 1472 else { 1473 for (signum = 0; signum <= nsig; signum++) 1474 if (mesg[signum].iname && 1475 eq(sigptr, str2short(mesg[signum].iname))) 1476 goto gotsig; 1477 setname(short2str(sigptr)); 1478 stderror(ERR_NAME | ERR_UNKSIG); 1479 } 1480 gotsig: 1481 v++; 1482 } 1483 else 1484 signum = SIGTERM; 1485 pkill(v, signum); 1486 } 1487 1488 static void 1489 pkill(Char **v, int signum) 1490 { 1491 struct process *pp, *np; 1492 int jobflags = 0, err1 = 0; 1493 pid_t pid; 1494 Char *cp, **vp, **globbed; 1495 1496 /* Avoid globbing %?x patterns */ 1497 for (vp = v; vp && *vp; vp++) 1498 if (**vp == '%') 1499 (void) quote(*vp); 1500 1501 v = glob_all_or_error(v); 1502 globbed = v; 1503 cleanup_push(globbed, blk_cleanup); 1504 1505 pchild_disabled++; 1506 cleanup_push(&pchild_disabled, disabled_cleanup); 1507 if (setintr) { 1508 pintr_disabled++; 1509 cleanup_push(&pintr_disabled, disabled_cleanup); 1510 } 1511 1512 while (v && (cp = *v)) { 1513 if (*cp == '%') { 1514 np = pp = pfind(cp); 1515 do 1516 jobflags |= np->p_flags; 1517 while ((np = np->p_friends) != pp); 1518 #ifdef BSDJOBS 1519 switch (signum) { 1520 1521 case SIGSTOP: 1522 case SIGTSTP: 1523 case SIGTTIN: 1524 case SIGTTOU: 1525 if ((jobflags & PRUNNING) == 0) { 1526 # ifdef SUSPENDED 1527 xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp); 1528 # else /* !SUSPENDED */ 1529 xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp); 1530 # endif /* !SUSPENDED */ 1531 err1++; 1532 goto cont; 1533 } 1534 break; 1535 /* 1536 * suspend a process, kill -CONT %, then type jobs; the shell 1537 * says it is suspended, but it is running; thanks jaap.. 1538 */ 1539 case SIGCONT: 1540 if (!pstart(pp, 0)) { 1541 pp->p_procid = 0; 1542 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, 1543 strerror(errno)); 1544 } 1545 goto cont; 1546 default: 1547 break; 1548 } 1549 #endif /* BSDJOBS */ 1550 if (killpg(pp->p_jobid, signum) < 0) { 1551 xprintf("%S: %s\n", cp, strerror(errno)); 1552 err1++; 1553 } 1554 #ifdef BSDJOBS 1555 if (signum == SIGTERM || signum == SIGHUP) 1556 (void) killpg(pp->p_jobid, SIGCONT); 1557 #endif /* BSDJOBS */ 1558 } 1559 else if (!(Isdigit(*cp) || *cp == '-')) 1560 stderror(ERR_NAME | ERR_JOBARGS); 1561 else { 1562 char *ep; 1563 #ifndef WINNT_NATIVE 1564 pid = strtol(short2str(cp), &ep, 10); 1565 #else 1566 pid = strtoul(short2str(cp), &ep, 0); 1567 #endif /* WINNT_NATIVE */ 1568 if (*ep) 1569 stderror(ERR_NAME | ERR_JOBARGS); 1570 else if (kill(pid, signum) < 0) { 1571 xprintf("%d: %s\n", pid, strerror(errno)); 1572 err1++; 1573 goto cont; 1574 } 1575 #ifdef BSDJOBS 1576 if (signum == SIGTERM || signum == SIGHUP) 1577 (void) kill(pid, SIGCONT); 1578 #endif /* BSDJOBS */ 1579 } 1580 cont: 1581 v++; 1582 } 1583 cleanup_until(&pchild_disabled); 1584 if (err1) 1585 stderror(ERR_SILENT); 1586 } 1587 1588 /* 1589 * pstart - start the job in foreground/background 1590 */ 1591 int 1592 pstart(struct process *pp, int foregnd) 1593 { 1594 int rv = 0; 1595 struct process *np; 1596 /* We don't use jobflags in this function right now (see below) */ 1597 /* long jobflags = 0; */ 1598 1599 pchild_disabled++; 1600 cleanup_push(&pchild_disabled, disabled_cleanup); 1601 np = pp; 1602 do { 1603 /* We don't use jobflags in this function right now (see below) */ 1604 /* jobflags |= np->p_flags; */ 1605 if (np->p_flags & (PRUNNING | PSTOPPED)) { 1606 np->p_flags |= PRUNNING; 1607 np->p_flags &= ~PSTOPPED; 1608 if (foregnd) 1609 np->p_flags |= PFOREGND; 1610 else 1611 np->p_flags &= ~PFOREGND; 1612 } 1613 } while ((np = np->p_friends) != pp); 1614 if (!foregnd) 1615 pclrcurr(pp); 1616 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND); 1617 1618 /* GrP run jobcmd hook if foregrounding */ 1619 if (foregnd) { 1620 job_cmd(pp->p_command); 1621 } 1622 1623 #ifdef BSDJOBS 1624 if (foregnd) { 1625 rv = tcsetpgrp(FSHTTY, pp->p_jobid); 1626 } 1627 /* 1628 * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU 1629 * 2. parent process (csh) receives SIGCHLD 1630 * 3. The "csh" signal handling function pchild() is invoked 1631 * with a SIGCHLD signal. 1632 * 4. pchild() calls wait3(WNOHANG) which returns 0. 1633 * The child process is NOT ready to be waited for at this time. 1634 * pchild() returns without picking-up the correct status 1635 * for the child process which generated the SIGCHLD. 1636 * 5. CONSEQUENCE : csh is UNaware that the process is stopped 1637 * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED) 1638 * (beto@aixwiz.austin.ibm.com - aug/03/91) 1639 * 7. I removed the line completely and added extra checks for 1640 * pstart, so that if a job gets attached to and dies inside 1641 * a debugger it does not confuse the shell. [christos] 1642 * 8. on the nec sx-4 there seems to be a problem, which requires 1643 * a syscall(151, getpid(), getpid()) in osinit. Don't ask me 1644 * what this is doing. [schott@rzg.mpg.de] 1645 */ 1646 1647 if (rv != -1) 1648 rv = killpg(pp->p_jobid, SIGCONT); 1649 #endif /* BSDJOBS */ 1650 cleanup_until(&pchild_disabled); 1651 return rv != -1; 1652 } 1653 1654 void 1655 panystop(int neednl) 1656 { 1657 struct process *pp; 1658 1659 chkstop = 2; 1660 for (pp = proclist.p_next; pp; pp = pp->p_next) 1661 if (pp->p_flags & PSTOPPED) 1662 stderror(ERR_STOPPED, neednl ? "\n" : ""); 1663 } 1664 1665 struct process * 1666 pfind(Char *cp) 1667 { 1668 struct process *pp, *np; 1669 1670 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) { 1671 if (pcurrent == NULL) 1672 stderror(ERR_NAME | ERR_JOBCUR); 1673 return (pcurrent); 1674 } 1675 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) { 1676 if (pprevious == NULL) 1677 stderror(ERR_NAME | ERR_JOBPREV); 1678 return (pprevious); 1679 } 1680 if (Isdigit(cp[1])) { 1681 int idx = atoi(short2str(cp + 1)); 1682 1683 for (pp = proclist.p_next; pp; pp = pp->p_next) 1684 if (pp->p_index == idx && pp->p_procid == pp->p_jobid) 1685 return (pp); 1686 stderror(ERR_NAME | ERR_NOSUCHJOB); 1687 } 1688 np = NULL; 1689 for (pp = proclist.p_next; pp; pp = pp->p_next) 1690 if (pp->p_procid == pp->p_jobid) { 1691 if (cp[1] == '?') { 1692 Char *dp; 1693 1694 for (dp = pp->p_command; *dp; dp++) { 1695 if (*dp != cp[2]) 1696 continue; 1697 if (prefix(cp + 2, dp)) 1698 goto match; 1699 } 1700 } 1701 else if (prefix(cp + 1, pp->p_command)) { 1702 match: 1703 if (np) 1704 stderror(ERR_NAME | ERR_AMBIG); 1705 np = pp; 1706 } 1707 } 1708 if (np) 1709 return (np); 1710 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB)); 1711 /* NOTREACHED */ 1712 return (0); 1713 } 1714 1715 1716 /* 1717 * pgetcurr - find most recent job that is not pp, preferably stopped 1718 */ 1719 static struct process * 1720 pgetcurr(struct process *pp) 1721 { 1722 struct process *np; 1723 struct process *xp = NULL; 1724 1725 for (np = proclist.p_next; np; np = np->p_next) 1726 if (np != pcurrent && np != pp && np->p_procid && 1727 np->p_procid == np->p_jobid) { 1728 if (np->p_flags & PSTOPPED) 1729 return (np); 1730 if (xp == NULL) 1731 xp = np; 1732 } 1733 return (xp); 1734 } 1735 1736 /* 1737 * donotify - flag the job so as to report termination asynchronously 1738 */ 1739 /*ARGSUSED*/ 1740 void 1741 donotify(Char **v, struct command *c) 1742 { 1743 struct process *pp; 1744 1745 USE(c); 1746 pp = pfind(*++v); 1747 pp->p_flags |= PNOTIFY; 1748 } 1749 1750 #ifdef SIGSYNCH 1751 static void 1752 synch_handler(int sno) 1753 { 1754 USE(sno); 1755 } 1756 #endif /* SIGSYNCH */ 1757 1758 /* 1759 * Do the fork and whatever should be done in the child side that 1760 * should not be done if we are not forking at all (like for simple builtin's) 1761 * Also do everything that needs any signals fiddled with in the parent side 1762 * 1763 * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1764 * -1: leave tty alone; inherit pgrp from parent 1765 * 0: already have tty; manipulate process pgrps only 1766 * 1: want to claim tty; manipulate process and tty pgrps 1767 * It is usually just the value of tpgrp. 1768 */ 1769 1770 pid_t 1771 pfork(struct command *t, int wanttty) 1772 { 1773 pid_t pid; 1774 int ignint = 0; 1775 pid_t pgrp; 1776 #ifdef SIGSYNCH 1777 struct sigaction osa, nsa; 1778 #endif /* SIGSYNCH */ 1779 1780 /* 1781 * A child will be uninterruptible only under very special conditions. 1782 * Remember that the semantics of '&' is implemented by disconnecting the 1783 * process from the tty so signals do not need to ignored just for '&'. 1784 * Thus signals are set to default action for children unless: we have had 1785 * an "onintr -" (then specifically ignored) we are not playing with 1786 * signals (inherit action) 1787 */ 1788 if (setintr) 1789 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 1790 || (gointr && eq(gointr, STRminus)); 1791 1792 /* 1793 * Check for maximum nesting of 16 processes to avoid Forking loops 1794 */ 1795 if (child == 16) 1796 stderror(ERR_NESTING, 16); 1797 #ifdef SIGSYNCH 1798 nsa.sa_handler = synch_handler; 1799 sigfillset(&nsa.sa_mask); 1800 nsa.sa_flags = SA_RESTART; 1801 if (sigaction(SIGSYNCH, &nsa, &osa)) 1802 stderror(ERR_SYSTEM, "pfork: sigaction set", strerror(errno)); 1803 #endif /* SIGSYNCH */ 1804 /* 1805 * Hold pchild() until we have the process installed in our table. 1806 */ 1807 if (wanttty < 0) { 1808 pchild_disabled++; 1809 cleanup_push(&pchild_disabled, disabled_cleanup); 1810 } 1811 while ((pid = fork()) == -1) 1812 if (setintr == 0) 1813 (void) sleep(FORKSLEEP); 1814 else 1815 stderror(ERR_NOPROC); 1816 if (pid == 0) { 1817 (void)cleanup_push_mark(); /* Never to be popped */ 1818 pchild_disabled = 0; 1819 settimes(); 1820 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 1821 pflushall(); 1822 pcurrjob = NULL; 1823 #if !defined(BSDTIMES) && !defined(_SEQUENT_) 1824 timesdone = 0; 1825 #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */ 1826 child++; 1827 if (setintr) { 1828 setintr = 0; /* until I think otherwise */ 1829 /* 1830 * Children just get blown away on SIGINT, SIGQUIT unless "onintr 1831 * -" seen. 1832 */ 1833 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1834 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1835 #ifdef BSDJOBS 1836 if (wanttty >= 0) { 1837 /* make stoppable */ 1838 (void) signal(SIGTSTP, SIG_DFL); 1839 (void) signal(SIGTTIN, SIG_DFL); 1840 (void) signal(SIGTTOU, SIG_DFL); 1841 } 1842 #endif /* BSDJOBS */ 1843 sigaction(SIGTERM, &parterm, NULL); 1844 } 1845 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { 1846 (void) signal(SIGINT, SIG_IGN); 1847 (void) signal(SIGQUIT, SIG_IGN); 1848 } 1849 #ifdef OREO 1850 signal(SIGIO, SIG_IGN); /* ignore SIGIO in child too */ 1851 #endif /* OREO */ 1852 1853 pgetty(wanttty, pgrp); 1854 /* 1855 * Nohup and nice apply only to NODE_COMMAND's but it would be nice 1856 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have 1857 * to know about nice/nohup/time 1858 */ 1859 if (t->t_dflg & F_NOHUP) 1860 (void) signal(SIGHUP, SIG_IGN); 1861 if (t->t_dflg & F_NICE) { 1862 int nval = SIGN_EXTEND_CHAR(t->t_nice); 1863 #if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) 1864 if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) 1865 stderror(ERR_SYSTEM, "setpriority", strerror(errno)); 1866 #else /* !HAVE_SETPRIORITY || !PRIO_PROCESS */ 1867 (void) nice(nval); 1868 #endif /* HAVE_SETPRIORITY && PRIO_PROCESS */ 1869 } 1870 #ifdef F_VER 1871 if (t->t_dflg & F_VER) { 1872 tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 1873 dohash(NULL, NULL); 1874 } 1875 #endif /* F_VER */ 1876 #ifdef SIGSYNCH 1877 /* rfw 8/89 now parent can continue */ 1878 if (kill(getppid(), SIGSYNCH)) 1879 stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno)); 1880 #endif /* SIGSYNCH */ 1881 1882 } 1883 else { 1884 #ifdef POSIXJOBS 1885 if (wanttty >= 0) { 1886 /* 1887 * `Walking' process group fix from Beto Appleton. 1888 * (beto@aixwiz.austin.ibm.com) 1889 * If setpgid fails at this point that means that 1890 * our process leader has died. We flush the current 1891 * job and become the process leader ourselves. 1892 * The parent will figure that out later. 1893 */ 1894 pgrp = pcurrjob ? pcurrjob->p_jobid : pid; 1895 if (setpgid(pid, pgrp) == -1 && errno == EPERM) { 1896 pcurrjob = NULL; 1897 /* 1898 * We don't care if this causes an error here; 1899 * then we are already in the right process group 1900 */ 1901 (void) setpgid(pid, pgrp = pid); 1902 } 1903 } 1904 #endif /* POSIXJOBS */ 1905 palloc(pid, t); 1906 #ifdef SIGSYNCH 1907 { 1908 sigset_t pause_mask; 1909 1910 /* 1911 * rfw 8/89 Wait for child to own terminal. Solves half of ugly 1912 * synchronization problem. With this change, we know that the only 1913 * reason setpgrp to a previous process in a pipeline can fail is that 1914 * the previous process has already exited. Without this hack, he may 1915 * either have exited or not yet started to run. Two uglies become 1916 * one. 1917 */ 1918 sigprocmask(SIG_BLOCK, NULL, &pause); 1919 sigdelset(&pause_mask, SIGCHLD); 1920 sigdelset(&pause_mask, SIGSYNCH); 1921 sigsuspend(&pause_mask); 1922 (void)handle_pending_signals(); 1923 if (sigaction(SIGSYNCH, &osa, NULL)) 1924 stderror(ERR_SYSTEM, "pfork parent: sigaction restore", 1925 strerror(errno)); 1926 } 1927 #endif /* SIGSYNCH */ 1928 1929 if (wanttty < 0) 1930 cleanup_until(&pchild_disabled); 1931 } 1932 return (pid); 1933 } 1934 1935 static void 1936 okpcntl(void) 1937 { 1938 if (tpgrp == -1) 1939 stderror(ERR_JOBCONTROL); 1940 if (tpgrp == 0) 1941 stderror(ERR_JOBCTRLSUB); 1942 } 1943 1944 1945 static void 1946 setttypgrp(int pgrp) 1947 { 1948 /* 1949 * If we are piping out a builtin, eg. 'echo | more' things can go 1950 * out of sequence, i.e. the more can run before the echo. This 1951 * can happen even if we have vfork, since the echo will be forked 1952 * with the regular fork. In this case, we need to set the tty 1953 * pgrp ourselves. If that happens, then the process will be still 1954 * alive. And the tty process group will already be set. 1955 * This should fix the famous sequent problem as a side effect: 1956 * The controlling terminal is lost if all processes in the 1957 * terminal process group are zombies. In this case tcgetpgrp() 1958 * returns 0. If this happens we must set the terminal process 1959 * group again. 1960 */ 1961 if (tcgetpgrp(FSHTTY) != pgrp) { 1962 #ifdef POSIXJOBS 1963 struct sigaction old; 1964 1965 /* 1966 * tcsetpgrp will set SIGTTOU to all the the processes in 1967 * the background according to POSIX... We ignore this here. 1968 */ 1969 sigaction(SIGTTOU, NULL, &old); 1970 signal(SIGTTOU, SIG_IGN); 1971 #endif 1972 (void) tcsetpgrp(FSHTTY, pgrp); 1973 # ifdef POSIXJOBS 1974 sigaction(SIGTTOU, &old, NULL); 1975 # endif 1976 1977 } 1978 } 1979 1980 1981 /* 1982 * if we don't have vfork(), things can still go in the wrong order 1983 * resulting in the famous 'Stopped (tty output)'. But some systems 1984 * don't permit the setpgid() call, (these are more recent secure 1985 * systems such as ibm's aix), when they do. Then we'd rather print 1986 * an error message than hang the shell! 1987 * I am open to suggestions how to fix that. 1988 */ 1989 void 1990 pgetty(int wanttty, pid_t pgrp) 1991 { 1992 #ifdef BSDJOBS 1993 # ifdef POSIXJOBS 1994 sigset_t oset, set; 1995 # endif /* POSIXJOBS */ 1996 1997 jobdebug_xprintf(("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n", 1998 wanttty, (int)getpid(), (int)pgrp, (int)mygetpgrp(), 1999 (int)tcgetpgrp(FSHTTY))); 2000 # ifdef POSIXJOBS 2001 /* 2002 * christos: I am blocking the tty signals till I've set things 2003 * correctly.... 2004 */ 2005 if (wanttty > 0) { 2006 sigemptyset(&set); 2007 sigaddset(&set, SIGTSTP); 2008 sigaddset(&set, SIGTTIN); 2009 (void)sigprocmask(SIG_BLOCK, &set, &oset); 2010 cleanup_push(&oset, sigprocmask_cleanup); 2011 } 2012 # endif /* POSIXJOBS */ 2013 2014 # ifndef POSIXJOBS 2015 if (wanttty > 0) 2016 setttypgrp(pgrp); 2017 # endif /* !POSIXJOBS */ 2018 2019 /* 2020 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 2021 * Don't check for tpgrp >= 0 so even non-interactive shells give 2022 * background jobs process groups Same for the comparison in the other part 2023 * of the #ifdef 2024 */ 2025 if (wanttty >= 0) { 2026 if (setpgid(0, pgrp) == -1) { 2027 # ifdef POSIXJOBS 2028 /* Walking process group fix; see above */ 2029 if (setpgid(0, pgrp = getpid()) == -1) { 2030 # endif /* POSIXJOBS */ 2031 stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno)); 2032 xexit(0); 2033 # ifdef POSIXJOBS 2034 } 2035 wanttty = pgrp; /* Now we really want the tty, since we became the 2036 * the process group leader 2037 */ 2038 # endif /* POSIXJOBS */ 2039 } 2040 } 2041 2042 # ifdef POSIXJOBS 2043 if (wanttty > 0) { 2044 setttypgrp(pgrp); 2045 cleanup_until(&oset); 2046 } 2047 # endif /* POSIXJOBS */ 2048 2049 jobdebug_xprintf(("wanttty %d pid %d pgrp %d tpgrp %d\n", 2050 wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY))); 2051 2052 if (tpgrp > 0) 2053 tpgrp = 0; /* gave tty away */ 2054 #endif /* BSDJOBS */ 2055 } 2056