1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.proc.c,v 3.121 2012/01/25 15:34:41 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.121 2012/01/25 15:34:41 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 for (;;) { 511 (void)handle_pending_signals(); 512 jobflags = 0; 513 do 514 jobflags |= fp->p_flags; 515 while ((fp = (fp->p_friends)) != pp); 516 if ((jobflags & PRUNNING) == 0) 517 break; 518 jobdebug_xprintf(("%d starting to sigsuspend for SIGCHLD on %d\n", 519 getpid(), fp->p_procid)); 520 sigsuspend(&pause_mask); 521 } 522 cleanup_until(&oset); 523 jobdebug_xprintf(("%d returned from sigsuspend loop\n", getpid())); 524 #ifdef BSDJOBS 525 if (tpgrp > 0) /* get tty back */ 526 (void) tcsetpgrp(FSHTTY, tpgrp); 527 #endif /* BSDJOBS */ 528 if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) || 529 fp->p_cwd == NULL || !eq(dcwd->di_name, fp->p_cwd->di_name)) { 530 if (jobflags & PSTOPPED) { 531 xputchar('\n'); 532 if (adrof(STRlistjobs)) { 533 Char *jobcommand[3]; 534 535 jobcommand[0] = STRjobs; 536 if (eq(varval(STRlistjobs), STRlong)) 537 jobcommand[1] = STRml; 538 else 539 jobcommand[1] = NULL; 540 jobcommand[2] = NULL; 541 542 dojobs(jobcommand, NULL); 543 (void) pprint(pp, SHELLDIR); 544 } 545 else 546 (void) pprint(pp, AREASON | SHELLDIR); 547 } 548 else 549 (void) pprint(pp, AREASON | SHELLDIR); 550 } 551 if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr && 552 (!gointr || !eq(gointr, STRminus))) { 553 if ((jobflags & PSTOPPED) == 0) 554 pflush(pp); 555 pintr1(0); 556 /* NOTREACHED */ 557 } 558 reason = 0; 559 fp = pp; 560 do { 561 /* In case of pipelines only the result of the last 562 * command should be taken in account */ 563 if (!anyerror && !(fp->p_flags & PBRACE) 564 && ((fp->p_flags & PPOU) || (fp->p_flags & PBACKQ))) 565 continue; 566 if (fp->p_reason) 567 reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ? 568 fp->p_reason | META : fp->p_reason; 569 } while ((fp = fp->p_friends) != pp); 570 /* 571 * Don't report on backquoted jobs, cause it will mess up 572 * their output. 573 */ 574 if ((reason != 0) && (adrof(STRprintexitvalue)) && 575 (pp->p_flags & PBACKQ) == 0) 576 xprintf(CGETS(17, 2, "Exit %d\n"), reason); 577 reason_str = putn((tcsh_number_t)reason); 578 cleanup_push(reason_str, xfree); 579 setv(STRstatus, reason_str, VAR_READWRITE); 580 cleanup_ignore(reason_str); 581 cleanup_until(reason_str); 582 if (reason && exiterr) 583 exitstat(); 584 pflush(pp); 585 } 586 587 /* 588 * dowait - wait for all processes to finish 589 */ 590 591 /*ARGSUSED*/ 592 void 593 dowait(Char **v, struct command *c) 594 { 595 struct process *pp; 596 sigset_t pause_mask; 597 int opintr_disabled, gotsig; 598 599 USE(c); 600 USE(v); 601 pjobs++; 602 sigprocmask(SIG_BLOCK, NULL, &pause_mask); 603 sigdelset(&pause_mask, SIGCHLD); 604 if (setintr) 605 sigdelset(&pause_mask, SIGINT); 606 loop: 607 for (pp = proclist.p_next; pp; pp = pp->p_next) 608 if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */ 609 pp->p_flags & PRUNNING) { 610 (void)handle_pending_signals(); 611 sigsuspend(&pause_mask); 612 opintr_disabled = pintr_disabled; 613 pintr_disabled = 0; 614 gotsig = handle_pending_signals(); 615 pintr_disabled = opintr_disabled; 616 if (gotsig) 617 break; 618 goto loop; 619 } 620 pjobs = 0; 621 } 622 623 /* 624 * pflushall - flush all jobs from list (e.g. at fork()) 625 */ 626 static void 627 pflushall(void) 628 { 629 struct process *pp; 630 631 for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) 632 if (pp->p_procid) 633 pflush(pp); 634 } 635 636 /* 637 * pflush - flag all process structures in the same job as the 638 * the argument process for deletion. The actual free of the 639 * space is not done here since pflush is called at interrupt level. 640 */ 641 static void 642 pflush(struct process *pp) 643 { 644 struct process *np; 645 int idx; 646 647 if (pp->p_procid == 0) { 648 xprintf("%s", CGETS(17, 3, "BUG: process flushed twice")); 649 return; 650 } 651 while (pp->p_procid != pp->p_jobid) 652 pp = pp->p_friends; 653 pclrcurr(pp); 654 if (pp == pcurrjob) 655 pcurrjob = 0; 656 idx = pp->p_index; 657 np = pp; 658 do { 659 np->p_index = np->p_procid = 0; 660 np->p_flags &= ~PNEEDNOTE; 661 } while ((np = np->p_friends) != pp); 662 if (idx == pmaxindex) { 663 for (np = proclist.p_next, idx = 0; np; np = np->p_next) 664 if (np->p_index > idx) 665 idx = np->p_index; 666 pmaxindex = idx; 667 } 668 } 669 670 /* 671 * pclrcurr - make sure the given job is not the current or previous job; 672 * pp MUST be the job leader 673 */ 674 static void 675 pclrcurr(struct process *pp) 676 { 677 if (pp == pcurrent) { 678 if (pprevious != NULL) { 679 pcurrent = pprevious; 680 pprevious = pgetcurr(pp); 681 } 682 else { 683 pcurrent = pgetcurr(pp); 684 pprevious = pgetcurr(pp); 685 } 686 } 687 else if (pp == pprevious) 688 pprevious = pgetcurr(pp); 689 } 690 691 /* +4 here is 1 for '\0', 1 ea for << >& >> */ 692 static Char *cmdstr; 693 static size_t cmdmax; 694 static size_t cmdlen; 695 static Char *cmdp; 696 #define CMD_INIT 1024 697 #define CMD_INCR 64 698 699 static void 700 morecommand(size_t s) 701 { 702 Char *ncmdstr; 703 ptrdiff_t d; 704 705 cmdmax += s; 706 ncmdstr = xrealloc(cmdstr, cmdmax * sizeof(*cmdstr)); 707 d = ncmdstr - cmdstr; 708 cmdstr = ncmdstr; 709 cmdp += d; 710 } 711 712 /* GrP 713 * unparse - Export padd() functionality 714 */ 715 Char * 716 unparse(struct command *t) 717 { 718 if (cmdmax == 0) 719 morecommand(CMD_INIT); 720 cmdp = cmdstr; 721 cmdlen = 0; 722 padd(t); 723 *cmdp++ = '\0'; 724 return Strsave(cmdstr); 725 } 726 727 728 /* 729 * palloc - allocate a process structure and fill it up. 730 * an important assumption is made that the process is running. 731 */ 732 void 733 palloc(pid_t pid, struct command *t) 734 { 735 struct process *pp; 736 int i; 737 738 pp = xcalloc(1, sizeof(struct process)); 739 pp->p_procid = pid; 740 pp->p_parentid = shpgrp; 741 pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING; 742 if (t->t_dflg & F_TIME) 743 pp->p_flags |= PPTIME; 744 if (t->t_dflg & F_BACKQ) 745 pp->p_flags |= PBACKQ; 746 if (t->t_dflg & F_HUP) 747 pp->p_flags |= PHUP; 748 if (t->t_dcom && t->t_dcom[0] && (*t->t_dcom[0] == '{')) 749 pp->p_flags |= PBRACE; 750 if (cmdmax == 0) 751 morecommand(CMD_INIT); 752 cmdp = cmdstr; 753 cmdlen = 0; 754 padd(t); 755 *cmdp++ = 0; 756 if (t->t_dflg & F_PIPEOUT) { 757 pp->p_flags |= PPOU; 758 if (t->t_dflg & F_STDERR) 759 pp->p_flags |= PDIAG; 760 } 761 pp->p_command = Strsave(cmdstr); 762 if (pcurrjob) { 763 struct process *fp; 764 765 /* careful here with interrupt level */ 766 pp->p_cwd = 0; 767 pp->p_index = pcurrjob->p_index; 768 pp->p_friends = pcurrjob; 769 pp->p_jobid = pcurrjob->p_procid; 770 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) 771 continue; 772 fp->p_friends = pp; 773 } 774 else { 775 pcurrjob = pp; 776 pp->p_jobid = pid; 777 pp->p_friends = pp; 778 pp->p_cwd = dcwd; 779 dcwd->di_count++; 780 if (pmaxindex < BIGINDEX) 781 pp->p_index = ++pmaxindex; 782 else { 783 struct process *np; 784 785 for (i = 1;; i++) { 786 for (np = proclist.p_next; np; np = np->p_next) 787 if (np->p_index == i) 788 goto tryagain; 789 pp->p_index = i; 790 if (i > pmaxindex) 791 pmaxindex = i; 792 break; 793 tryagain:; 794 } 795 } 796 if (pcurrent == NULL) 797 pcurrent = pp; 798 else if (pprevious == NULL) 799 pprevious = pp; 800 } 801 pp->p_next = proclist.p_next; 802 proclist.p_next = pp; 803 #ifdef BSDTIMES 804 (void) gettimeofday(&pp->p_btime, NULL); 805 #else /* !BSDTIMES */ 806 # ifdef _SEQUENT_ 807 (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL); 808 # else /* !_SEQUENT_ */ 809 { 810 struct tms tmptimes; 811 812 pp->p_btime = times(&tmptimes); 813 } 814 # endif /* !_SEQUENT_ */ 815 #endif /* !BSDTIMES */ 816 } 817 818 static void 819 padd(struct command *t) 820 { 821 Char **argp; 822 823 if (t == 0) 824 return; 825 switch (t->t_dtyp) { 826 827 case NODE_PAREN: 828 pads(STRLparensp); 829 padd(t->t_dspr); 830 pads(STRspRparen); 831 break; 832 833 case NODE_COMMAND: 834 for (argp = t->t_dcom; *argp; argp++) { 835 pads(*argp); 836 if (argp[1]) 837 pads(STRspace); 838 } 839 break; 840 841 case NODE_OR: 842 case NODE_AND: 843 case NODE_PIPE: 844 case NODE_LIST: 845 padd(t->t_dcar); 846 switch (t->t_dtyp) { 847 case NODE_OR: 848 pads(STRspor2sp); 849 break; 850 case NODE_AND: 851 pads(STRspand2sp); 852 break; 853 case NODE_PIPE: 854 pads(STRsporsp); 855 break; 856 case NODE_LIST: 857 pads(STRsemisp); 858 break; 859 default: 860 break; 861 } 862 padd(t->t_dcdr); 863 return; 864 865 default: 866 break; 867 } 868 if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) { 869 pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp); 870 pads(t->t_dlef); 871 } 872 if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) { 873 pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow); 874 if (t->t_dflg & F_STDERR) 875 pads(STRand); 876 pads(STRspace); 877 pads(t->t_drit); 878 } 879 } 880 881 static void 882 pads(Char *cp) 883 { 884 size_t i, len; 885 886 /* 887 * Avoid the Quoted Space alias hack! Reported by: 888 * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks) 889 */ 890 if (cp[0] == STRQNULL[0]) 891 cp++; 892 893 i = Strlen(cp); 894 895 len = cmdlen + i + CMD_INCR; 896 if (len >= cmdmax) 897 morecommand(len); 898 (void) Strcpy(cmdp, cp); 899 cmdp += i; 900 cmdlen += i; 901 } 902 903 /* 904 * psavejob - temporarily save the current job on a one level stack 905 * so another job can be created. Used for { } in exp6 906 * and `` in globbing. 907 */ 908 void 909 psavejob(void) 910 { 911 pholdjob = pcurrjob; 912 pcurrjob = NULL; 913 } 914 915 void 916 psavejob_cleanup(void *dummy) 917 { 918 USE(dummy); 919 pcurrjob = pholdjob; 920 pholdjob = NULL; 921 } 922 923 /* 924 * pendjob - indicate that a job (set of commands) has been completed 925 * or is about to begin. 926 */ 927 void 928 pendjob(void) 929 { 930 struct process *pp, *tp; 931 932 if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) { 933 pp = pcurrjob; 934 pcurrjob = NULL; 935 while (pp->p_procid != pp->p_jobid) 936 pp = pp->p_friends; 937 xprintf("[%d]", pp->p_index); 938 tp = pp; 939 do { 940 xprintf(" %d", pp->p_procid); 941 pp = pp->p_friends; 942 } while (pp != tp); 943 xputchar('\n'); 944 } 945 pholdjob = pcurrjob = 0; 946 } 947 948 /* 949 * pprint - print a job 950 */ 951 952 /* 953 * Hacks have been added for SVR4 to deal with pipe's being spawned in 954 * reverse order 955 * 956 * David Dawes (dawes@physics.su.oz.au) Oct 1991 957 */ 958 959 static int 960 pprint(struct process *pp, int flag) 961 { 962 int status, reason; 963 struct process *tp; 964 int jobflags, pstatus, pcond; 965 const char *format; 966 967 #ifdef BACKPIPE 968 struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL; 969 int inpipe = 0; 970 #endif /* BACKPIPE */ 971 972 while (pp->p_procid != pp->p_jobid) 973 pp = pp->p_friends; 974 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { 975 pp->p_flags &= ~PPTIME; 976 pp->p_flags |= PTIME; 977 } 978 tp = pp; 979 status = reason = -1; 980 jobflags = 0; 981 do { 982 #ifdef BACKPIPE 983 /* 984 * The pipeline is reversed, so locate the real head of the pipeline 985 * if pp is at the tail of a pipe (and not already in a pipeline) 986 */ 987 if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) { 988 inpipe = 1; 989 pipetail = pp; 990 do 991 pp = pp->p_friends; 992 while (pp->p_friends->p_flags & PPOU); 993 pipehead = pp; 994 pmarker = pp; 995 /* 996 * pmarker is used to hold the place of the proc being processed, so 997 * we can search for the next one downstream later. 998 */ 999 } 1000 pcond = (tp != pp || (inpipe && tp == pp)); 1001 #else /* !BACKPIPE */ 1002 pcond = (tp != pp); 1003 #endif /* BACKPIPE */ 1004 1005 jobflags |= pp->p_flags; 1006 pstatus = (int) (pp->p_flags & PALLSTATES); 1007 if (pcond && linp != linbuf && !(flag & FANCY) && 1008 ((pstatus == status && pp->p_reason == reason) || 1009 !(flag & REASON))) 1010 xputchar(' '); 1011 else { 1012 if (pcond && linp != linbuf) 1013 xputchar('\n'); 1014 if (flag & NUMBER) { 1015 #ifdef BACKPIPE 1016 pcond = ((pp == tp && !inpipe) || 1017 (inpipe && pipetail == tp && pp == pipehead)); 1018 #else /* BACKPIPE */ 1019 pcond = (pp == tp); 1020 #endif /* BACKPIPE */ 1021 if (pcond) 1022 xprintf("[%d]%s %c ", pp->p_index, 1023 pp->p_index < 10 ? " " : "", 1024 pp == pcurrent ? '+' : 1025 (pp == pprevious ? '-' : ' ')); 1026 else 1027 xprintf(" "); 1028 } 1029 if (flag & FANCY) { 1030 xprintf("%5d ", pp->p_procid); 1031 #ifdef TCF 1032 xprintf("%11s ", sitename(pp->p_procid)); 1033 #endif /* TCF */ 1034 } 1035 if (flag & (REASON | AREASON)) { 1036 if (flag & NAME) 1037 format = "%-30s"; 1038 else 1039 format = "%s"; 1040 if (pstatus == status) { 1041 if (pp->p_reason == reason) { 1042 xprintf(format, ""); 1043 goto prcomd; 1044 } 1045 else 1046 reason = (int) pp->p_reason; 1047 } 1048 else { 1049 status = pstatus; 1050 reason = (int) pp->p_reason; 1051 } 1052 switch (status) { 1053 1054 case PRUNNING: 1055 xprintf(format, CGETS(17, 4, "Running ")); 1056 break; 1057 1058 case PINTERRUPTED: 1059 case PSTOPPED: 1060 case PSIGNALED: 1061 /* 1062 * tell what happened to the background job 1063 * From: Michael Schroeder 1064 * <mlschroe@immd4.informatik.uni-erlangen.de> 1065 */ 1066 if ((flag & REASON) 1067 || ((flag & AREASON) 1068 && reason != SIGINT 1069 && (reason != SIGPIPE 1070 || (pp->p_flags & PPOU) == 0))) { 1071 char *ptr; 1072 int free_ptr; 1073 1074 free_ptr = 0; 1075 ptr = (char *)(intptr_t)mesg[pp->p_reason & 0177].pname; 1076 if (ptr == NULL) { 1077 ptr = xasprintf("%s %d", CGETS(17, 5, "Signal"), 1078 pp->p_reason & 0177); 1079 cleanup_push(ptr, xfree); 1080 free_ptr = 1; 1081 } 1082 xprintf(format, ptr); 1083 if (free_ptr != 0) 1084 cleanup_until(ptr); 1085 } 1086 else 1087 reason = -1; 1088 break; 1089 1090 case PNEXITED: 1091 case PAEXITED: 1092 if (flag & REASON) { 1093 if (pp->p_reason) 1094 xprintf(CGETS(17, 6, "Exit %-25d"), pp->p_reason); 1095 else 1096 xprintf(format, CGETS(17, 7, "Done")); 1097 } 1098 break; 1099 1100 default: 1101 xprintf(CGETS(17, 8, "BUG: status=%-9o"), 1102 status); 1103 } 1104 } 1105 } 1106 prcomd: 1107 if (flag & NAME) { 1108 xprintf("%S", pp->p_command); 1109 if (pp->p_flags & PPOU) 1110 xprintf(" |"); 1111 if (pp->p_flags & PDIAG) 1112 xprintf("&"); 1113 } 1114 if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) 1115 xprintf("%s", CGETS(17, 9, " (core dumped)")); 1116 if (tp == pp->p_friends) { 1117 if (flag & AMPERSAND) 1118 xprintf(" &"); 1119 if (flag & JOBDIR && 1120 !eq(tp->p_cwd->di_name, dcwd->di_name)) { 1121 xprintf("%s", CGETS(17, 10, " (wd: ")); 1122 dtildepr(tp->p_cwd->di_name); 1123 xprintf(")"); 1124 } 1125 } 1126 if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) { 1127 if (linp != linbuf) 1128 xprintf("\n\t"); 1129 #if defined(BSDTIMES) || defined(_SEQUENT_) 1130 prusage(&zru, &pp->p_rusage, &pp->p_etime, 1131 &pp->p_btime); 1132 #else /* !BSDTIMES && !SEQUENT */ 1133 lru.tms_utime = pp->p_utime; 1134 lru.tms_stime = pp->p_stime; 1135 lru.tms_cutime = 0; 1136 lru.tms_cstime = 0; 1137 prusage(&zru, &lru, pp->p_etime, 1138 pp->p_btime); 1139 #endif /* !BSDTIMES && !SEQUENT */ 1140 1141 } 1142 #ifdef BACKPIPE 1143 pcond = ((tp == pp->p_friends && !inpipe) || 1144 (inpipe && pipehead->p_friends == tp && pp == pipetail)); 1145 #else /* !BACKPIPE */ 1146 pcond = (tp == pp->p_friends); 1147 #endif /* BACKPIPE */ 1148 if (pcond) { 1149 if (linp != linbuf) 1150 xputchar('\n'); 1151 if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { 1152 xprintf("%s", CGETS(17, 11, "(wd now: ")); 1153 dtildepr(dcwd->di_name); 1154 xprintf(")\n"); 1155 } 1156 } 1157 #ifdef BACKPIPE 1158 if (inpipe) { 1159 /* 1160 * if pmaker == pipetail, we are finished that pipeline, and 1161 * can now skip to past the head 1162 */ 1163 if (pmarker == pipetail) { 1164 inpipe = 0; 1165 pp = pipehead; 1166 } 1167 else { 1168 /* 1169 * set pp to one before the one we want next, so the while below 1170 * increments to the correct spot. 1171 */ 1172 do 1173 pp = pp->p_friends; 1174 while (pp->p_friends->p_friends != pmarker); 1175 pmarker = pp->p_friends; 1176 } 1177 } 1178 pcond = ((pp = pp->p_friends) != tp || inpipe); 1179 #else /* !BACKPIPE */ 1180 pcond = ((pp = pp->p_friends) != tp); 1181 #endif /* BACKPIPE */ 1182 } while (pcond); 1183 1184 if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) { 1185 if (jobflags & NUMBER) 1186 xprintf(" "); 1187 ptprint(tp); 1188 } 1189 return (jobflags); 1190 } 1191 1192 /* 1193 * All 4.3 BSD derived implementations are buggy and I've had enough. 1194 * The following implementation produces similar code and works in all 1195 * cases. The 4.3BSD one works only for <, >, != 1196 */ 1197 # undef timercmp 1198 # define timercmp(tvp, uvp, cmp) \ 1199 (((tvp)->tv_sec == (uvp)->tv_sec) ? \ 1200 ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ 1201 ((tvp)->tv_sec cmp (uvp)->tv_sec)) 1202 1203 static void 1204 ptprint(struct process *tp) 1205 { 1206 #ifdef BSDTIMES 1207 struct timeval tetime, diff; 1208 static struct timeval ztime; 1209 struct sysrusage ru; 1210 struct process *pp = tp; 1211 1212 ru = zru; 1213 tetime = ztime; 1214 do { 1215 ruadd(&ru, &pp->p_rusage); 1216 tvsub(&diff, &pp->p_etime, &pp->p_btime); 1217 if (timercmp(&diff, &tetime, >)) 1218 tetime = diff; 1219 } while ((pp = pp->p_friends) != tp); 1220 prusage(&zru, &ru, &tetime, &ztime); 1221 #else /* !BSDTIMES */ 1222 # ifdef _SEQUENT_ 1223 timeval_t tetime, diff; 1224 static timeval_t ztime; 1225 struct process_stats ru; 1226 struct process *pp = tp; 1227 1228 ru = zru; 1229 tetime = ztime; 1230 do { 1231 ruadd(&ru, &pp->p_rusage); 1232 tvsub(&diff, &pp->p_etime, &pp->p_btime); 1233 if (timercmp(&diff, &tetime, >)) 1234 tetime = diff; 1235 } while ((pp = pp->p_friends) != tp); 1236 prusage(&zru, &ru, &tetime, &ztime); 1237 # else /* !_SEQUENT_ */ 1238 # ifndef POSIX 1239 static time_t ztime = 0; 1240 static time_t zu_time = 0; 1241 static time_t zs_time = 0; 1242 time_t tetime, diff; 1243 time_t u_time, s_time; 1244 1245 # else /* POSIX */ 1246 static clock_t ztime = 0; 1247 static clock_t zu_time = 0; 1248 static clock_t zs_time = 0; 1249 clock_t tetime, diff; 1250 clock_t u_time, s_time; 1251 1252 # endif /* POSIX */ 1253 struct tms zts, rts; 1254 struct process *pp = tp; 1255 1256 u_time = zu_time; 1257 s_time = zs_time; 1258 tetime = ztime; 1259 do { 1260 u_time += pp->p_utime; 1261 s_time += pp->p_stime; 1262 diff = pp->p_etime - pp->p_btime; 1263 if (diff > tetime) 1264 tetime = diff; 1265 } while ((pp = pp->p_friends) != tp); 1266 zts.tms_utime = zu_time; 1267 zts.tms_stime = zs_time; 1268 zts.tms_cutime = 0; 1269 zts.tms_cstime = 0; 1270 rts.tms_utime = u_time; 1271 rts.tms_stime = s_time; 1272 rts.tms_cutime = 0; 1273 rts.tms_cstime = 0; 1274 prusage(&zts, &rts, tetime, ztime); 1275 # endif /* !_SEQUENT_ */ 1276 #endif /* !BSDTIMES */ 1277 } 1278 1279 /* 1280 * dojobs - print all jobs 1281 */ 1282 /*ARGSUSED*/ 1283 void 1284 dojobs(Char **v, struct command *c) 1285 { 1286 struct process *pp; 1287 int flag = NUMBER | NAME | REASON; 1288 int i; 1289 1290 USE(c); 1291 if (chkstop) 1292 chkstop = 2; 1293 if (*++v) { 1294 if (v[1] || !eq(*v, STRml)) 1295 stderror(ERR_JOBS); 1296 flag |= FANCY | JOBDIR; 1297 } 1298 for (i = 1; i <= pmaxindex; i++) 1299 for (pp = proclist.p_next; pp; pp = pp->p_next) 1300 if (pp->p_index == i && pp->p_procid == pp->p_jobid) { 1301 pp->p_flags &= ~PNEEDNOTE; 1302 if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED))) 1303 pflush(pp); 1304 break; 1305 } 1306 } 1307 1308 /* 1309 * dofg - builtin - put the job into the foreground 1310 */ 1311 /*ARGSUSED*/ 1312 void 1313 dofg(Char **v, struct command *c) 1314 { 1315 struct process *pp; 1316 1317 USE(c); 1318 okpcntl(); 1319 ++v; 1320 do { 1321 pp = pfind(*v); 1322 if (!pstart(pp, 1)) { 1323 pp->p_procid = 0; 1324 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1325 continue; 1326 } 1327 pjwait(pp); 1328 } while (*v && *++v); 1329 } 1330 1331 /* 1332 * %... - builtin - put the job into the foreground 1333 */ 1334 /*ARGSUSED*/ 1335 void 1336 dofg1(Char **v, struct command *c) 1337 { 1338 struct process *pp; 1339 1340 USE(c); 1341 okpcntl(); 1342 pp = pfind(v[0]); 1343 if (!pstart(pp, 1)) { 1344 pp->p_procid = 0; 1345 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1346 return; 1347 } 1348 pjwait(pp); 1349 } 1350 1351 /* 1352 * dobg - builtin - put the job into the background 1353 */ 1354 /*ARGSUSED*/ 1355 void 1356 dobg(Char **v, struct command *c) 1357 { 1358 struct process *pp; 1359 1360 USE(c); 1361 okpcntl(); 1362 ++v; 1363 do { 1364 pp = pfind(*v); 1365 if (!pstart(pp, 0)) { 1366 pp->p_procid = 0; 1367 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1368 } 1369 } while (*v && *++v); 1370 } 1371 1372 /* 1373 * %... & - builtin - put the job into the background 1374 */ 1375 /*ARGSUSED*/ 1376 void 1377 dobg1(Char **v, struct command *c) 1378 { 1379 struct process *pp; 1380 1381 USE(c); 1382 pp = pfind(v[0]); 1383 if (!pstart(pp, 0)) { 1384 pp->p_procid = 0; 1385 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, strerror(errno)); 1386 } 1387 } 1388 1389 /* 1390 * dostop - builtin - stop the job 1391 */ 1392 /*ARGSUSED*/ 1393 void 1394 dostop(Char **v, struct command *c) 1395 { 1396 USE(c); 1397 #ifdef BSDJOBS 1398 pkill(++v, SIGSTOP); 1399 #endif /* BSDJOBS */ 1400 } 1401 1402 /* 1403 * dokill - builtin - superset of kill (1) 1404 */ 1405 /*ARGSUSED*/ 1406 void 1407 dokill(Char **v, struct command *c) 1408 { 1409 int signum, len = 0; 1410 const char *name; 1411 Char *sigptr; 1412 1413 USE(c); 1414 v++; 1415 if (v[0] && v[0][0] == '-') { 1416 if (v[0][1] == 'l') { 1417 for (signum = 0; signum <= nsig; signum++) { 1418 if ((name = mesg[signum].iname) != NULL) { 1419 len += strlen(name) + 1; 1420 if (len >= TermH - 1) { 1421 xputchar('\n'); 1422 len = strlen(name) + 1; 1423 } 1424 xprintf("%s ", name); 1425 } 1426 } 1427 xputchar('\n'); 1428 return; 1429 } 1430 sigptr = &v[0][1]; 1431 if (v[0][1] == 's') { 1432 if (v[1]) { 1433 v++; 1434 sigptr = &v[0][0]; 1435 } else { 1436 stderror(ERR_NAME | ERR_TOOFEW); 1437 } 1438 } 1439 if (Isdigit(*sigptr)) { 1440 char *ep; 1441 signum = strtoul(short2str(sigptr), &ep, 0); 1442 if (*ep || signum < 0 || signum > (MAXSIG-1)) 1443 stderror(ERR_NAME | ERR_BADSIG); 1444 } 1445 else { 1446 for (signum = 0; signum <= nsig; signum++) 1447 if (mesg[signum].iname && 1448 eq(sigptr, str2short(mesg[signum].iname))) 1449 goto gotsig; 1450 setname(short2str(sigptr)); 1451 stderror(ERR_NAME | ERR_UNKSIG); 1452 } 1453 gotsig: 1454 v++; 1455 } 1456 else 1457 signum = SIGTERM; 1458 pkill(v, signum); 1459 } 1460 1461 static void 1462 pkill(Char **v, int signum) 1463 { 1464 struct process *pp, *np; 1465 int jobflags = 0, err1 = 0; 1466 pid_t pid; 1467 Char *cp, **vp, **globbed; 1468 1469 /* Avoid globbing %?x patterns */ 1470 for (vp = v; vp && *vp; vp++) 1471 if (**vp == '%') 1472 (void) quote(*vp); 1473 1474 v = glob_all_or_error(v); 1475 globbed = v; 1476 cleanup_push(globbed, blk_cleanup); 1477 1478 pchild_disabled++; 1479 cleanup_push(&pchild_disabled, disabled_cleanup); 1480 if (setintr) { 1481 pintr_disabled++; 1482 cleanup_push(&pintr_disabled, disabled_cleanup); 1483 } 1484 1485 while (v && (cp = *v)) { 1486 if (*cp == '%') { 1487 np = pp = pfind(cp); 1488 do 1489 jobflags |= np->p_flags; 1490 while ((np = np->p_friends) != pp); 1491 #ifdef BSDJOBS 1492 switch (signum) { 1493 1494 case SIGSTOP: 1495 case SIGTSTP: 1496 case SIGTTIN: 1497 case SIGTTOU: 1498 if ((jobflags & PRUNNING) == 0) { 1499 # ifdef SUSPENDED 1500 xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp); 1501 # else /* !SUSPENDED */ 1502 xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp); 1503 # endif /* !SUSPENDED */ 1504 err1++; 1505 goto cont; 1506 } 1507 break; 1508 /* 1509 * suspend a process, kill -CONT %, then type jobs; the shell 1510 * says it is suspended, but it is running; thanks jaap.. 1511 */ 1512 case SIGCONT: 1513 if (!pstart(pp, 0)) { 1514 pp->p_procid = 0; 1515 stderror(ERR_NAME|ERR_BADJOB, pp->p_command, 1516 strerror(errno)); 1517 } 1518 goto cont; 1519 default: 1520 break; 1521 } 1522 #endif /* BSDJOBS */ 1523 if (killpg(pp->p_jobid, signum) < 0) { 1524 xprintf("%S: %s\n", cp, strerror(errno)); 1525 err1++; 1526 } 1527 #ifdef BSDJOBS 1528 if (signum == SIGTERM || signum == SIGHUP) 1529 (void) killpg(pp->p_jobid, SIGCONT); 1530 #endif /* BSDJOBS */ 1531 } 1532 else if (!(Isdigit(*cp) || *cp == '-')) 1533 stderror(ERR_NAME | ERR_JOBARGS); 1534 else { 1535 char *ep; 1536 #ifndef WINNT_NATIVE 1537 pid = strtol(short2str(cp), &ep, 10); 1538 #else 1539 pid = strtoul(short2str(cp), &ep, 0); 1540 #endif /* WINNT_NATIVE */ 1541 if (*ep) 1542 stderror(ERR_NAME | ERR_JOBARGS); 1543 else if (kill(pid, signum) < 0) { 1544 xprintf("%d: %s\n", pid, strerror(errno)); 1545 err1++; 1546 goto cont; 1547 } 1548 #ifdef BSDJOBS 1549 if (signum == SIGTERM || signum == SIGHUP) 1550 (void) kill(pid, SIGCONT); 1551 #endif /* BSDJOBS */ 1552 } 1553 cont: 1554 v++; 1555 } 1556 cleanup_until(&pchild_disabled); 1557 if (err1) 1558 stderror(ERR_SILENT); 1559 } 1560 1561 /* 1562 * pstart - start the job in foreground/background 1563 */ 1564 int 1565 pstart(struct process *pp, int foregnd) 1566 { 1567 int rv = 0; 1568 struct process *np; 1569 /* We don't use jobflags in this function right now (see below) */ 1570 /* long jobflags = 0; */ 1571 1572 pchild_disabled++; 1573 cleanup_push(&pchild_disabled, disabled_cleanup); 1574 np = pp; 1575 do { 1576 /* We don't use jobflags in this function right now (see below) */ 1577 /* jobflags |= np->p_flags; */ 1578 if (np->p_flags & (PRUNNING | PSTOPPED)) { 1579 np->p_flags |= PRUNNING; 1580 np->p_flags &= ~PSTOPPED; 1581 if (foregnd) 1582 np->p_flags |= PFOREGND; 1583 else 1584 np->p_flags &= ~PFOREGND; 1585 } 1586 } while ((np = np->p_friends) != pp); 1587 if (!foregnd) 1588 pclrcurr(pp); 1589 (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND); 1590 1591 /* GrP run jobcmd hook if foregrounding */ 1592 if (foregnd) { 1593 job_cmd(pp->p_command); 1594 } 1595 1596 #ifdef BSDJOBS 1597 if (foregnd) { 1598 rv = tcsetpgrp(FSHTTY, pp->p_jobid); 1599 } 1600 /* 1601 * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU 1602 * 2. parent process (csh) receives SIGCHLD 1603 * 3. The "csh" signal handling function pchild() is invoked 1604 * with a SIGCHLD signal. 1605 * 4. pchild() calls wait3(WNOHANG) which returns 0. 1606 * The child process is NOT ready to be waited for at this time. 1607 * pchild() returns without picking-up the correct status 1608 * for the child process which generated the SIGCHLD. 1609 * 5. CONSEQUENCE : csh is UNaware that the process is stopped 1610 * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED) 1611 * (beto@aixwiz.austin.ibm.com - aug/03/91) 1612 * 7. I removed the line completely and added extra checks for 1613 * pstart, so that if a job gets attached to and dies inside 1614 * a debugger it does not confuse the shell. [christos] 1615 * 8. on the nec sx-4 there seems to be a problem, which requires 1616 * a syscall(151, getpid(), getpid()) in osinit. Don't ask me 1617 * what this is doing. [schott@rzg.mpg.de] 1618 */ 1619 1620 if (rv != -1) 1621 rv = killpg(pp->p_jobid, SIGCONT); 1622 #endif /* BSDJOBS */ 1623 cleanup_until(&pchild_disabled); 1624 return rv != -1; 1625 } 1626 1627 void 1628 panystop(int neednl) 1629 { 1630 struct process *pp; 1631 1632 chkstop = 2; 1633 for (pp = proclist.p_next; pp; pp = pp->p_next) 1634 if (pp->p_flags & PSTOPPED) 1635 stderror(ERR_STOPPED, neednl ? "\n" : ""); 1636 } 1637 1638 struct process * 1639 pfind(Char *cp) 1640 { 1641 struct process *pp, *np; 1642 1643 if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) { 1644 if (pcurrent == NULL) 1645 stderror(ERR_NAME | ERR_JOBCUR); 1646 return (pcurrent); 1647 } 1648 if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) { 1649 if (pprevious == NULL) 1650 stderror(ERR_NAME | ERR_JOBPREV); 1651 return (pprevious); 1652 } 1653 if (Isdigit(cp[1])) { 1654 int idx = atoi(short2str(cp + 1)); 1655 1656 for (pp = proclist.p_next; pp; pp = pp->p_next) 1657 if (pp->p_index == idx && pp->p_procid == pp->p_jobid) 1658 return (pp); 1659 stderror(ERR_NAME | ERR_NOSUCHJOB); 1660 } 1661 np = NULL; 1662 for (pp = proclist.p_next; pp; pp = pp->p_next) 1663 if (pp->p_procid == pp->p_jobid) { 1664 if (cp[1] == '?') { 1665 Char *dp; 1666 1667 for (dp = pp->p_command; *dp; dp++) { 1668 if (*dp != cp[2]) 1669 continue; 1670 if (prefix(cp + 2, dp)) 1671 goto match; 1672 } 1673 } 1674 else if (prefix(cp + 1, pp->p_command)) { 1675 match: 1676 if (np) 1677 stderror(ERR_NAME | ERR_AMBIG); 1678 np = pp; 1679 } 1680 } 1681 if (np) 1682 return (np); 1683 stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB)); 1684 /* NOTREACHED */ 1685 return (0); 1686 } 1687 1688 1689 /* 1690 * pgetcurr - find most recent job that is not pp, preferably stopped 1691 */ 1692 static struct process * 1693 pgetcurr(struct process *pp) 1694 { 1695 struct process *np; 1696 struct process *xp = NULL; 1697 1698 for (np = proclist.p_next; np; np = np->p_next) 1699 if (np != pcurrent && np != pp && np->p_procid && 1700 np->p_procid == np->p_jobid) { 1701 if (np->p_flags & PSTOPPED) 1702 return (np); 1703 if (xp == NULL) 1704 xp = np; 1705 } 1706 return (xp); 1707 } 1708 1709 /* 1710 * donotify - flag the job so as to report termination asynchronously 1711 */ 1712 /*ARGSUSED*/ 1713 void 1714 donotify(Char **v, struct command *c) 1715 { 1716 struct process *pp; 1717 1718 USE(c); 1719 pp = pfind(*++v); 1720 pp->p_flags |= PNOTIFY; 1721 } 1722 1723 #ifdef SIGSYNCH 1724 static void 1725 synch_handler(int sno) 1726 { 1727 USE(sno); 1728 } 1729 #endif /* SIGSYNCH */ 1730 1731 /* 1732 * Do the fork and whatever should be done in the child side that 1733 * should not be done if we are not forking at all (like for simple builtin's) 1734 * Also do everything that needs any signals fiddled with in the parent side 1735 * 1736 * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1737 * -1: leave tty alone; inherit pgrp from parent 1738 * 0: already have tty; manipulate process pgrps only 1739 * 1: want to claim tty; manipulate process and tty pgrps 1740 * It is usually just the value of tpgrp. 1741 */ 1742 1743 pid_t 1744 pfork(struct command *t, int wanttty) 1745 { 1746 pid_t pid; 1747 int ignint = 0; 1748 pid_t pgrp; 1749 #ifdef SIGSYNCH 1750 struct sigaction osa, nsa; 1751 #endif /* SIGSYNCH */ 1752 1753 /* 1754 * A child will be uninterruptible only under very special conditions. 1755 * Remember that the semantics of '&' is implemented by disconnecting the 1756 * process from the tty so signals do not need to ignored just for '&'. 1757 * Thus signals are set to default action for children unless: we have had 1758 * an "onintr -" (then specifically ignored) we are not playing with 1759 * signals (inherit action) 1760 */ 1761 if (setintr) 1762 ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) 1763 || (gointr && eq(gointr, STRminus)); 1764 1765 /* 1766 * Check for maximum nesting of 16 processes to avoid Forking loops 1767 */ 1768 if (child == 16) 1769 stderror(ERR_NESTING, 16); 1770 #ifdef SIGSYNCH 1771 nsa.sa_handler = synch_handler; 1772 sigfillset(&nsa.sa_mask); 1773 nsa.sa_flags = SA_RESTART; 1774 if (sigaction(SIGSYNCH, &nsa, &osa)) 1775 stderror(ERR_SYSTEM, "pfork: sigaction set", strerror(errno)); 1776 #endif /* SIGSYNCH */ 1777 /* 1778 * Hold pchild() until we have the process installed in our table. 1779 */ 1780 if (wanttty < 0) { 1781 pchild_disabled++; 1782 cleanup_push(&pchild_disabled, disabled_cleanup); 1783 } 1784 while ((pid = fork()) == -1) 1785 if (setintr == 0) 1786 (void) sleep(FORKSLEEP); 1787 else 1788 stderror(ERR_NOPROC); 1789 if (pid == 0) { 1790 (void)cleanup_push_mark(); /* Never to be popped */ 1791 pchild_disabled = 0; 1792 settimes(); 1793 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); 1794 pflushall(); 1795 pcurrjob = NULL; 1796 #if !defined(BSDTIMES) && !defined(_SEQUENT_) 1797 timesdone = 0; 1798 #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */ 1799 child++; 1800 if (setintr) { 1801 setintr = 0; /* until I think otherwise */ 1802 /* 1803 * Children just get blown away on SIGINT, SIGQUIT unless "onintr 1804 * -" seen. 1805 */ 1806 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1807 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1808 #ifdef BSDJOBS 1809 if (wanttty >= 0) { 1810 /* make stoppable */ 1811 (void) signal(SIGTSTP, SIG_DFL); 1812 (void) signal(SIGTTIN, SIG_DFL); 1813 (void) signal(SIGTTOU, SIG_DFL); 1814 } 1815 #endif /* BSDJOBS */ 1816 sigaction(SIGTERM, &parterm, NULL); 1817 } 1818 else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { 1819 (void) signal(SIGINT, SIG_IGN); 1820 (void) signal(SIGQUIT, SIG_IGN); 1821 } 1822 #ifdef OREO 1823 signal(SIGIO, SIG_IGN); /* ignore SIGIO in child too */ 1824 #endif /* OREO */ 1825 1826 pgetty(wanttty, pgrp); 1827 /* 1828 * Nohup and nice apply only to NODE_COMMAND's but it would be nice 1829 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have 1830 * to know about nice/nohup/time 1831 */ 1832 if (t->t_dflg & F_NOHUP) 1833 (void) signal(SIGHUP, SIG_IGN); 1834 if (t->t_dflg & F_NICE) { 1835 int nval = SIGN_EXTEND_CHAR(t->t_nice); 1836 #ifdef HAVE_SETPRIORITY 1837 if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno) 1838 stderror(ERR_SYSTEM, "setpriority", strerror(errno)); 1839 #else /* !HAVE_SETPRIORITY */ 1840 (void) nice(nval); 1841 #endif /* !HAVE_SETPRIORITY */ 1842 } 1843 #ifdef F_VER 1844 if (t->t_dflg & F_VER) { 1845 tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53); 1846 dohash(NULL, NULL); 1847 } 1848 #endif /* F_VER */ 1849 #ifdef SIGSYNCH 1850 /* rfw 8/89 now parent can continue */ 1851 if (kill(getppid(), SIGSYNCH)) 1852 stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno)); 1853 #endif /* SIGSYNCH */ 1854 1855 } 1856 else { 1857 #ifdef POSIXJOBS 1858 if (wanttty >= 0) { 1859 /* 1860 * `Walking' process group fix from Beto Appleton. 1861 * (beto@aixwiz.austin.ibm.com) 1862 * If setpgid fails at this point that means that 1863 * our process leader has died. We flush the current 1864 * job and become the process leader ourselves. 1865 * The parent will figure that out later. 1866 */ 1867 pgrp = pcurrjob ? pcurrjob->p_jobid : pid; 1868 if (setpgid(pid, pgrp) == -1 && errno == EPERM) { 1869 pcurrjob = NULL; 1870 /* 1871 * We don't care if this causes an error here; 1872 * then we are already in the right process group 1873 */ 1874 (void) setpgid(pid, pgrp = pid); 1875 } 1876 } 1877 #endif /* POSIXJOBS */ 1878 palloc(pid, t); 1879 #ifdef SIGSYNCH 1880 { 1881 sigset_t pause_mask; 1882 1883 /* 1884 * rfw 8/89 Wait for child to own terminal. Solves half of ugly 1885 * synchronization problem. With this change, we know that the only 1886 * reason setpgrp to a previous process in a pipeline can fail is that 1887 * the previous process has already exited. Without this hack, he may 1888 * either have exited or not yet started to run. Two uglies become 1889 * one. 1890 */ 1891 sigprocmask(SIG_BLOCK, NULL, &pause); 1892 sigdelset(&pause_mask, SIGCHLD); 1893 sigdelset(&pause_mask, SIGSYNCH); 1894 sigsuspend(&pause_mask); 1895 (void)handle_pending_signals(); 1896 if (sigaction(SIGSYNCH, &osa, NULL)) 1897 stderror(ERR_SYSTEM, "pfork parent: sigaction restore", 1898 strerror(errno)); 1899 } 1900 #endif /* SIGSYNCH */ 1901 1902 if (wanttty < 0) 1903 cleanup_until(&pchild_disabled); 1904 } 1905 return (pid); 1906 } 1907 1908 static void 1909 okpcntl(void) 1910 { 1911 if (tpgrp == -1) 1912 stderror(ERR_JOBCONTROL); 1913 if (tpgrp == 0) 1914 stderror(ERR_JOBCTRLSUB); 1915 } 1916 1917 1918 static void 1919 setttypgrp(int pgrp) 1920 { 1921 /* 1922 * If we are piping out a builtin, eg. 'echo | more' things can go 1923 * out of sequence, i.e. the more can run before the echo. This 1924 * can happen even if we have vfork, since the echo will be forked 1925 * with the regular fork. In this case, we need to set the tty 1926 * pgrp ourselves. If that happens, then the process will be still 1927 * alive. And the tty process group will already be set. 1928 * This should fix the famous sequent problem as a side effect: 1929 * The controlling terminal is lost if all processes in the 1930 * terminal process group are zombies. In this case tcgetpgrp() 1931 * returns 0. If this happens we must set the terminal process 1932 * group again. 1933 */ 1934 if (tcgetpgrp(FSHTTY) != pgrp) { 1935 #ifdef POSIXJOBS 1936 struct sigaction old; 1937 1938 /* 1939 * tcsetpgrp will set SIGTTOU to all the the processes in 1940 * the background according to POSIX... We ignore this here. 1941 */ 1942 sigaction(SIGTTOU, NULL, &old); 1943 signal(SIGTTOU, SIG_IGN); 1944 #endif 1945 (void) tcsetpgrp(FSHTTY, pgrp); 1946 # ifdef POSIXJOBS 1947 sigaction(SIGTTOU, &old, NULL); 1948 # endif 1949 1950 } 1951 } 1952 1953 1954 /* 1955 * if we don't have vfork(), things can still go in the wrong order 1956 * resulting in the famous 'Stopped (tty output)'. But some systems 1957 * don't permit the setpgid() call, (these are more recent secure 1958 * systems such as ibm's aix), when they do. Then we'd rather print 1959 * an error message than hang the shell! 1960 * I am open to suggestions how to fix that. 1961 */ 1962 void 1963 pgetty(int wanttty, pid_t pgrp) 1964 { 1965 #ifdef BSDJOBS 1966 # ifdef POSIXJOBS 1967 sigset_t oset, set; 1968 # endif /* POSIXJOBS */ 1969 1970 jobdebug_xprintf(("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n", 1971 wanttty, (int)getpid(), (int)pgrp, (int)mygetpgrp(), 1972 (int)tcgetpgrp(FSHTTY))); 1973 # ifdef POSIXJOBS 1974 /* 1975 * christos: I am blocking the tty signals till I've set things 1976 * correctly.... 1977 */ 1978 if (wanttty > 0) { 1979 sigemptyset(&set); 1980 sigaddset(&set, SIGTSTP); 1981 sigaddset(&set, SIGTTIN); 1982 (void)sigprocmask(SIG_BLOCK, &set, &oset); 1983 cleanup_push(&oset, sigprocmask_cleanup); 1984 } 1985 # endif /* POSIXJOBS */ 1986 1987 # ifndef POSIXJOBS 1988 if (wanttty > 0) 1989 setttypgrp(pgrp); 1990 # endif /* !POSIXJOBS */ 1991 1992 /* 1993 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 1994 * Don't check for tpgrp >= 0 so even non-interactive shells give 1995 * background jobs process groups Same for the comparison in the other part 1996 * of the #ifdef 1997 */ 1998 if (wanttty >= 0) { 1999 if (setpgid(0, pgrp) == -1) { 2000 # ifdef POSIXJOBS 2001 /* Walking process group fix; see above */ 2002 if (setpgid(0, pgrp = getpid()) == -1) { 2003 # endif /* POSIXJOBS */ 2004 stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno)); 2005 xexit(0); 2006 # ifdef POSIXJOBS 2007 } 2008 wanttty = pgrp; /* Now we really want the tty, since we became the 2009 * the process group leader 2010 */ 2011 # endif /* POSIXJOBS */ 2012 } 2013 } 2014 2015 # ifdef POSIXJOBS 2016 if (wanttty > 0) { 2017 setttypgrp(pgrp); 2018 cleanup_until(&oset); 2019 } 2020 # endif /* POSIXJOBS */ 2021 2022 jobdebug_xprintf(("wanttty %d pid %d pgrp %d tpgrp %d\n", 2023 wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY))); 2024 2025 if (tpgrp > 0) 2026 tpgrp = 0; /* gave tty away */ 2027 #endif /* BSDJOBS */ 2028 } 2029