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