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