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 35RCSID("$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 */ 99static 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 104static struct rusage zru; 105# endif /* convex */ 106#else /* !BSDTIMES */ 107# ifdef _SEQUENT_ 108static 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 112static struct tms zru = {0, 0, 0, 0}, lru = {0, 0, 0, 0}; 113# else /* !_SX */ 114static 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 120static int timesdone; /* shtimes buffer full ? */ 121#endif /* BSDTIMES */ 122 123#ifndef RUSAGE_CHILDREN 124# define RUSAGE_CHILDREN -1 125#endif /* RUSAGE_CHILDREN */ 126 127static void pflushall (void); 128static void pflush (struct process *); 129static void pfree (struct process *); 130static void pclrcurr (struct process *); 131static void morecommand (size_t); 132static void padd (struct command *); 133static int pprint (struct process *, int); 134static void ptprint (struct process *); 135static void pads (Char *); 136static void pkill (Char **, int); 137static struct process *pgetcurr (struct process *); 138static void okpcntl (void); 139static 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 */ 148void 149pchild(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 179loop: 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 */ 285found: 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 424void 425pnote(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 445static void 446pfree(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 */ 460void 461pwait(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 */ 482void 483pjwait(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*/ 592void 593dowait(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); 606loop: 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 */ 626static void 627pflushall(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 */ 641static void 642pflush(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 */ 674static void 675pclrcurr(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 << >& >> */ 692static Char *cmdstr; 693static size_t cmdmax; 694static size_t cmdlen; 695static Char *cmdp; 696#define CMD_INIT 1024 697#define CMD_INCR 64 698 699static void 700morecommand(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 */ 715Char * 716unparse(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 */ 732void 733palloc(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 818static void 819padd(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 881static void 882pads(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 */ 908void 909psavejob(void) 910{ 911 pholdjob = pcurrjob; 912 pcurrjob = NULL; 913} 914 915void 916psavejob_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 */ 927void 928pendjob(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 959static int 960pprint(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 } 1106prcomd: 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 1203static void 1204ptprint(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*/ 1283void 1284dojobs(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*/ 1312void 1313dofg(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*/ 1335void 1336dofg1(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*/ 1355void 1356dobg(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*/ 1376void 1377dobg1(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*/ 1393void 1394dostop(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*/ 1406void 1407dokill(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 } 1453gotsig: 1454 v++; 1455 } 1456 else 1457 signum = SIGTERM; 1458 pkill(v, signum); 1459} 1460 1461static void 1462pkill(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 } 1553cont: 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 */ 1564int 1565pstart(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 1627void 1628panystop(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 1638struct process * 1639pfind(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 */ 1692static struct process * 1693pgetcurr(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*/ 1713void 1714donotify(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 1724static void 1725synch_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 1743pid_t 1744pfork(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 1908static void 1909okpcntl(void) 1910{ 1911 if (tpgrp == -1) 1912 stderror(ERR_JOBCONTROL); 1913 if (tpgrp == 0) 1914 stderror(ERR_JOBCTRLSUB); 1915} 1916 1917 1918static void 1919setttypgrp(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 */ 1962void 1963pgetty(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