17c478bd9Sstevel@tonic-gate /*
270a587ddSchin * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7*30699046SRichard Lowe /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #include "sh.h"
167c478bd9Sstevel@tonic-gate #include "sh.dir.h"
177c478bd9Sstevel@tonic-gate #include "sh.proc.h"
187c478bd9Sstevel@tonic-gate #include "wait.h"
197c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate * C Shell - functions that manage processes, handling hanging, termination
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
25258f91c6SToomas Soome bool neednote;
26258f91c6SToomas Soome bool pjobs;
27258f91c6SToomas Soome static struct process *pprevious;
28258f91c6SToomas Soome static short pmaxindex;
29258f91c6SToomas Soome static struct process proclist;
30258f91c6SToomas Soome static struct process *pcurrent;
31258f91c6SToomas Soome struct process *pcurrjob;
32258f91c6SToomas Soome static struct process *pholdjob;
33258f91c6SToomas Soome
3465b0c20eSnakanon #define BIGINDEX 9 /* largest desirable job index */
357c478bd9Sstevel@tonic-gate
366c02b4a4Smuffin void pjwait(struct process *);
376c02b4a4Smuffin void pflush(struct process *);
386c02b4a4Smuffin void pclrcurr(struct process *);
396c02b4a4Smuffin void padd(struct command *);
406c02b4a4Smuffin void pads(tchar *);
416c02b4a4Smuffin void ptprint(struct process *);
426c02b4a4Smuffin void pkill(tchar **, int);
436c02b4a4Smuffin void pstart(struct process *, int);
446c02b4a4Smuffin void okpcntl(void);
456c02b4a4Smuffin struct process *pgetcurr(struct process *);
466c02b4a4Smuffin struct process *pfind(tchar *);
476c02b4a4Smuffin
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate * pchild - called at interrupt level by the SIGCHLD signal
507c478bd9Sstevel@tonic-gate * indicating that at least one child has terminated or stopped
517c478bd9Sstevel@tonic-gate * thus at least one wait system call will definitely return a
527c478bd9Sstevel@tonic-gate * childs status. Top level routines (like pwait) must be sure
537c478bd9Sstevel@tonic-gate * to mask interrupts when playing with the proclist data structures!
547c478bd9Sstevel@tonic-gate */
557c478bd9Sstevel@tonic-gate void
pchild(int signal __unused)56*30699046SRichard Lowe pchild(int signal __unused)
577c478bd9Sstevel@tonic-gate {
586c02b4a4Smuffin struct process *pp;
596c02b4a4Smuffin struct process *fp;
606c02b4a4Smuffin int pid;
617c478bd9Sstevel@tonic-gate union wait w;
627c478bd9Sstevel@tonic-gate int jobflags;
637c478bd9Sstevel@tonic-gate struct rusage ru;
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate #ifdef TRACE
667c478bd9Sstevel@tonic-gate tprintf("TRACE- pchile()\n");
677c478bd9Sstevel@tonic-gate #endif
687c478bd9Sstevel@tonic-gate loop:
697c478bd9Sstevel@tonic-gate pid = csh_wait3(&w, (setintr ? WNOHANG|WUNTRACED:WNOHANG), &ru);
7065b0c20eSnakanon /*
7165b0c20eSnakanon * SysV sends a SIGCHLD when the child process
7265b0c20eSnakanon * receives a SIGCONT, and result of that action is ignored here
7365b0c20eSnakanon */
7465b0c20eSnakanon if (w.w_status == WCONTFLG)
7565b0c20eSnakanon return;
767c478bd9Sstevel@tonic-gate if (pid <= 0) {
777c478bd9Sstevel@tonic-gate if (errno == EINTR) {
787c478bd9Sstevel@tonic-gate errno = 0;
797c478bd9Sstevel@tonic-gate goto loop;
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate return;
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
847c478bd9Sstevel@tonic-gate if (pid == pp->p_pid)
857c478bd9Sstevel@tonic-gate goto found;
867c478bd9Sstevel@tonic-gate goto loop;
877c478bd9Sstevel@tonic-gate found:
8865b0c20eSnakanon if (pid == atoi_(value(S_child /* "child" */)))
8965b0c20eSnakanon unsetv(S_child /* "child" */);
907c478bd9Sstevel@tonic-gate pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED);
917c478bd9Sstevel@tonic-gate if (WIFSTOPPED(w)) {
927c478bd9Sstevel@tonic-gate pp->p_flags |= PSTOPPED;
937c478bd9Sstevel@tonic-gate pp->p_reason = w.w_stopsig;
947c478bd9Sstevel@tonic-gate } else {
9565b0c20eSnakanon if (pp->p_flags & (PTIME|PPTIME) || adrof(S_time /* "time" */))
967c478bd9Sstevel@tonic-gate (void) gettimeofday(&pp->p_etime, (struct timezone *)0);
977c478bd9Sstevel@tonic-gate pp->p_rusage = ru;
987c478bd9Sstevel@tonic-gate if (WIFSIGNALED(w)) {
997c478bd9Sstevel@tonic-gate if (w.w_termsig == SIGINT)
1007c478bd9Sstevel@tonic-gate pp->p_flags |= PINTERRUPTED;
1017c478bd9Sstevel@tonic-gate else
1027c478bd9Sstevel@tonic-gate pp->p_flags |= PSIGNALED;
1037c478bd9Sstevel@tonic-gate if (w.w_coredump)
1047c478bd9Sstevel@tonic-gate pp->p_flags |= PDUMPED;
1057c478bd9Sstevel@tonic-gate pp->p_reason = w.w_termsig;
1067c478bd9Sstevel@tonic-gate } else {
1077c478bd9Sstevel@tonic-gate pp->p_reason = w.w_retcode;
1087c478bd9Sstevel@tonic-gate if (pp->p_reason != 0)
1097c478bd9Sstevel@tonic-gate pp->p_flags |= PAEXITED;
1107c478bd9Sstevel@tonic-gate else
1117c478bd9Sstevel@tonic-gate pp->p_flags |= PNEXITED;
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate jobflags = 0;
1157c478bd9Sstevel@tonic-gate fp = pp;
1167c478bd9Sstevel@tonic-gate do {
1177c478bd9Sstevel@tonic-gate if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 &&
11865b0c20eSnakanon !child && adrof(S_time /* "time" */) &&
1197c478bd9Sstevel@tonic-gate fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >=
12065b0c20eSnakanon atoi_(value(S_time /* "time" */)))
1217c478bd9Sstevel@tonic-gate fp->p_flags |= PTIME;
1227c478bd9Sstevel@tonic-gate jobflags |= fp->p_flags;
1237c478bd9Sstevel@tonic-gate } while ((fp = fp->p_friends) != pp);
1247c478bd9Sstevel@tonic-gate pp->p_flags &= ~PFOREGND;
1257c478bd9Sstevel@tonic-gate if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
1267c478bd9Sstevel@tonic-gate pp->p_flags &= ~PPTIME;
1277c478bd9Sstevel@tonic-gate pp->p_flags |= PTIME;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate if ((jobflags & (PRUNNING|PREPORTED)) == 0) {
1307c478bd9Sstevel@tonic-gate fp = pp;
1317c478bd9Sstevel@tonic-gate do {
1327c478bd9Sstevel@tonic-gate if (fp->p_flags&PSTOPPED)
1337c478bd9Sstevel@tonic-gate fp->p_flags |= PREPORTED;
13465b0c20eSnakanon } while ((fp = fp->p_friends) != pp);
13565b0c20eSnakanon while (fp->p_pid != fp->p_jobid)
1367c478bd9Sstevel@tonic-gate fp = fp->p_friends;
1377c478bd9Sstevel@tonic-gate if (jobflags&PSTOPPED) {
1387c478bd9Sstevel@tonic-gate if (pcurrent && pcurrent != fp)
1397c478bd9Sstevel@tonic-gate pprevious = pcurrent;
1407c478bd9Sstevel@tonic-gate pcurrent = fp;
1417c478bd9Sstevel@tonic-gate } else
1427c478bd9Sstevel@tonic-gate pclrcurr(fp);
1437c478bd9Sstevel@tonic-gate if (jobflags&PFOREGND) {
1447c478bd9Sstevel@tonic-gate if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) ||
1457c478bd9Sstevel@tonic-gate #ifdef IIASA
1467c478bd9Sstevel@tonic-gate jobflags & PAEXITED ||
1477c478bd9Sstevel@tonic-gate #endif
1487c478bd9Sstevel@tonic-gate !eq(dcwd->di_name, fp->p_cwd->di_name)) {
1497c478bd9Sstevel@tonic-gate ; /* print in pjwait */
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate } else {
15265b0c20eSnakanon if (jobflags&PNOTIFY || adrof(S_notify /* "notify" */)) {
1537c478bd9Sstevel@tonic-gate write_string("\015\n");
1547c478bd9Sstevel@tonic-gate flush();
1557c478bd9Sstevel@tonic-gate (void) pprint(pp, NUMBER|NAME|REASON);
1567c478bd9Sstevel@tonic-gate if ((jobflags&PSTOPPED) == 0)
1577c478bd9Sstevel@tonic-gate pflush(pp);
1587c478bd9Sstevel@tonic-gate } else {
1597c478bd9Sstevel@tonic-gate fp->p_flags |= PNEEDNOTE;
1607c478bd9Sstevel@tonic-gate neednote++;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate goto loop;
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1676c02b4a4Smuffin void
pnote(void)1686c02b4a4Smuffin pnote(void)
1697c478bd9Sstevel@tonic-gate {
1706c02b4a4Smuffin struct process *pp;
1717c478bd9Sstevel@tonic-gate int flags, omask;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate #ifdef TRACE
1747c478bd9Sstevel@tonic-gate tprintf("TRACE- pnote()\n");
1757c478bd9Sstevel@tonic-gate #endif
1767c478bd9Sstevel@tonic-gate neednote = 0;
1777c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) {
1787c478bd9Sstevel@tonic-gate if (pp->p_flags & PNEEDNOTE) {
1797c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
1807c478bd9Sstevel@tonic-gate pp->p_flags &= ~PNEEDNOTE;
1817c478bd9Sstevel@tonic-gate flags = pprint(pp, NUMBER|NAME|REASON);
1827c478bd9Sstevel@tonic-gate if ((flags&(PRUNNING|PSTOPPED)) == 0)
1837c478bd9Sstevel@tonic-gate pflush(pp);
1847c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * pwait - wait for current job to terminate, maintaining integrity
1917c478bd9Sstevel@tonic-gate * of current and previous job indicators.
1927c478bd9Sstevel@tonic-gate */
1936c02b4a4Smuffin void
pwait(void)1946c02b4a4Smuffin pwait(void)
1957c478bd9Sstevel@tonic-gate {
1966c02b4a4Smuffin struct process *fp, *pp;
1977c478bd9Sstevel@tonic-gate int omask;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate #ifdef TRACE
2007c478bd9Sstevel@tonic-gate tprintf("TRACE- pwait()\n");
2017c478bd9Sstevel@tonic-gate #endif
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate * Here's where dead procs get flushed.
2047c478bd9Sstevel@tonic-gate */
2057c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
2067c478bd9Sstevel@tonic-gate for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next)
2077c478bd9Sstevel@tonic-gate if (pp->p_pid == 0) {
2087c478bd9Sstevel@tonic-gate fp->p_next = pp->p_next;
2097c478bd9Sstevel@tonic-gate xfree(pp->p_command);
2107c478bd9Sstevel@tonic-gate if (pp->p_cwd && --pp->p_cwd->di_count == 0)
2117c478bd9Sstevel@tonic-gate if (pp->p_cwd->di_next == 0)
2127c478bd9Sstevel@tonic-gate dfree(pp->p_cwd);
21365b0c20eSnakanon xfree((tchar *)pp);
2147c478bd9Sstevel@tonic-gate pp = fp;
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
2177c478bd9Sstevel@tonic-gate pjwait(pcurrjob);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * pjwait - wait for a job to finish or become stopped
2227c478bd9Sstevel@tonic-gate * It is assumed to be in the foreground state (PFOREGND)
2237c478bd9Sstevel@tonic-gate */
2246c02b4a4Smuffin void
pjwait(struct process * pp)2256c02b4a4Smuffin pjwait(struct process *pp)
2267c478bd9Sstevel@tonic-gate {
2276c02b4a4Smuffin struct process *fp;
2287c478bd9Sstevel@tonic-gate int jobflags, reason, omask;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate #ifdef TRACE
2317c478bd9Sstevel@tonic-gate tprintf("TRACE- pjwait()\n");
2327c478bd9Sstevel@tonic-gate #endif
2337c478bd9Sstevel@tonic-gate while (pp->p_pid != pp->p_jobid)
2347c478bd9Sstevel@tonic-gate pp = pp->p_friends;
2357c478bd9Sstevel@tonic-gate fp = pp;
2367c478bd9Sstevel@tonic-gate do {
2377c478bd9Sstevel@tonic-gate if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING)
2387c478bd9Sstevel@tonic-gate printf("BUG: waiting for background job!\n");
2397c478bd9Sstevel@tonic-gate } while ((fp = fp->p_friends) != pp);
2407c478bd9Sstevel@tonic-gate /*
2417c478bd9Sstevel@tonic-gate * Now keep pausing as long as we are not interrupted (SIGINT),
2427c478bd9Sstevel@tonic-gate * and the target process, or any of its friends, are running
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate fp = pp;
2457c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
2467c478bd9Sstevel@tonic-gate for (;;) {
2477c478bd9Sstevel@tonic-gate jobflags = 0;
2487c478bd9Sstevel@tonic-gate do
2497c478bd9Sstevel@tonic-gate jobflags |= fp->p_flags;
2507c478bd9Sstevel@tonic-gate while ((fp = (fp->p_friends)) != pp);
2517c478bd9Sstevel@tonic-gate if ((jobflags & PRUNNING) == 0)
2527c478bd9Sstevel@tonic-gate break;
2538e3c57a3Sraf /*
2548e3c57a3Sraf * At this point, csh used to call:
2558e3c57a3Sraf * sigpause(sigblock(0) &~ sigmask(SIGCHLD));
2568e3c57a3Sraf * expecting to receive a SIGCHLD signal from the
2578e3c57a3Sraf * termination of the child and to invoke the
2588e3c57a3Sraf * signal handler, pchild(), as a result.
2598e3c57a3Sraf *
2608e3c57a3Sraf * However, vfork() now causes a vfork()'d child to
2618e3c57a3Sraf * have all of its active signal handlers reset to
2628e3c57a3Sraf * SIG_DFL, to forstall parent memory corruption due
2638e3c57a3Sraf * to race conditions with signal handling.
2648e3c57a3Sraf *
2658e3c57a3Sraf * If this instance of csh is itself a child of vfork(),
2668e3c57a3Sraf * which can happen when the top-level csh performs a
2678e3c57a3Sraf * command substitution inside an i/o redirection, like:
2688e3c57a3Sraf * /bin/echo foo >`/bin/echo trash`
2698e3c57a3Sraf * then we will never receive SIGCHLD. To accommodate
2708e3c57a3Sraf * this, we wait until one of our children terminates
2718e3c57a3Sraf * (without actually reaping the child) and call the
2728e3c57a3Sraf * SIGCHLD signal handler (pchild()) directly.
2738e3c57a3Sraf */
2748e3c57a3Sraf if (csh_wait_noreap() > 0)
275*30699046SRichard Lowe pchild(SIGCHLD); /* simulate receipt of SIGCHLD */
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
2787c478bd9Sstevel@tonic-gate if (tpgrp > 0) /* get tty back */
2797c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp);
2807c478bd9Sstevel@tonic-gate if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) ||
28165b0c20eSnakanon !eq(dcwd->di_name, fp->p_cwd->di_name)) {
2827c478bd9Sstevel@tonic-gate if (jobflags&PSTOPPED)
2837c478bd9Sstevel@tonic-gate printf("\n");
2847c478bd9Sstevel@tonic-gate (void) pprint(pp, AREASON|SHELLDIR);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr &&
28765b0c20eSnakanon (!gointr || !eq(gointr, S_MINUS /* "-" */))) {
2887c478bd9Sstevel@tonic-gate if ((jobflags & PSTOPPED) == 0)
2897c478bd9Sstevel@tonic-gate pflush(pp);
2907c478bd9Sstevel@tonic-gate pintr1(0);
2917c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate reason = 0;
2947c478bd9Sstevel@tonic-gate fp = pp;
2957c478bd9Sstevel@tonic-gate do {
2967c478bd9Sstevel@tonic-gate if (fp->p_reason)
2977c478bd9Sstevel@tonic-gate reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ?
2987c478bd9Sstevel@tonic-gate fp->p_reason | ABN_TERM : fp->p_reason;
2997c478bd9Sstevel@tonic-gate } while ((fp = fp->p_friends) != pp);
30065b0c20eSnakanon set(S_status /* "status" */, putn(reason));
3017c478bd9Sstevel@tonic-gate if (reason && exiterr)
3027c478bd9Sstevel@tonic-gate exitstat();
3037c478bd9Sstevel@tonic-gate pflush(pp);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate * dowait - wait for all processes to finish
3087c478bd9Sstevel@tonic-gate */
3096c02b4a4Smuffin void
dowait(void)3106c02b4a4Smuffin dowait(void)
3117c478bd9Sstevel@tonic-gate {
3126c02b4a4Smuffin struct process *pp;
3137c478bd9Sstevel@tonic-gate int omask;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate #ifdef TRACE
3167c478bd9Sstevel@tonic-gate tprintf("TRACE- dowait()\n");
3177c478bd9Sstevel@tonic-gate #endif
3187c478bd9Sstevel@tonic-gate pjobs++;
3197c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
3207c478bd9Sstevel@tonic-gate loop:
3217c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp; pp = pp->p_next)
3227c478bd9Sstevel@tonic-gate if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */
3237c478bd9Sstevel@tonic-gate pp->p_flags&PRUNNING) {
3247c478bd9Sstevel@tonic-gate sigpause(0);
3257c478bd9Sstevel@tonic-gate goto loop;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
3287c478bd9Sstevel@tonic-gate pjobs = 0;
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * pflushall - flush all jobs from list (e.g. at fork())
3337c478bd9Sstevel@tonic-gate */
3346c02b4a4Smuffin void
pflushall(void)3356c02b4a4Smuffin pflushall(void)
3367c478bd9Sstevel@tonic-gate {
3376c02b4a4Smuffin struct process *pp;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate #ifdef TRACE
3407c478bd9Sstevel@tonic-gate tprintf("TRACE- pflush()\n");
3417c478bd9Sstevel@tonic-gate #endif
3427c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next)
3437c478bd9Sstevel@tonic-gate if (pp->p_pid)
3447c478bd9Sstevel@tonic-gate pflush(pp);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate * pflush - flag all process structures in the same job as the
3497c478bd9Sstevel@tonic-gate * the argument process for deletion. The actual free of the
3507c478bd9Sstevel@tonic-gate * space is not done here since pflush is called at interrupt level.
3517c478bd9Sstevel@tonic-gate */
3526c02b4a4Smuffin void
pflush(struct process * pp)3536c02b4a4Smuffin pflush(struct process *pp)
3547c478bd9Sstevel@tonic-gate {
3556c02b4a4Smuffin struct process *np;
3566c02b4a4Smuffin int index;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate #ifdef TRACE
3597c478bd9Sstevel@tonic-gate tprintf("TRACE- pflush()\n");
3607c478bd9Sstevel@tonic-gate #endif
3617c478bd9Sstevel@tonic-gate if (pp->p_pid == 0) {
3627c478bd9Sstevel@tonic-gate printf("BUG: process flushed twice");
3637c478bd9Sstevel@tonic-gate return;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate while (pp->p_pid != pp->p_jobid)
3667c478bd9Sstevel@tonic-gate pp = pp->p_friends;
3677c478bd9Sstevel@tonic-gate pclrcurr(pp);
3687c478bd9Sstevel@tonic-gate if (pp == pcurrjob)
3697c478bd9Sstevel@tonic-gate pcurrjob = 0;
3707c478bd9Sstevel@tonic-gate index = pp->p_index;
3717c478bd9Sstevel@tonic-gate np = pp;
3727c478bd9Sstevel@tonic-gate do {
3737c478bd9Sstevel@tonic-gate np->p_index = np->p_pid = 0;
3747c478bd9Sstevel@tonic-gate np->p_flags &= ~PNEEDNOTE;
3757c478bd9Sstevel@tonic-gate } while ((np = np->p_friends) != pp);
3767c478bd9Sstevel@tonic-gate if (index == pmaxindex) {
3777c478bd9Sstevel@tonic-gate for (np = proclist.p_next, index = 0; np; np = np->p_next)
3787c478bd9Sstevel@tonic-gate if (np->p_index > (tchar)index)
3797c478bd9Sstevel@tonic-gate index = np->p_index;
3807c478bd9Sstevel@tonic-gate pmaxindex = index;
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate * pclrcurr - make sure the given job is not the current or previous job;
3867c478bd9Sstevel@tonic-gate * pp MUST be the job leader
3877c478bd9Sstevel@tonic-gate */
3886c02b4a4Smuffin void
pclrcurr(struct process * pp)3896c02b4a4Smuffin pclrcurr(struct process *pp)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate #ifdef TRACE
3937c478bd9Sstevel@tonic-gate tprintf("TRACE- pclrcurr()\n");
3947c478bd9Sstevel@tonic-gate #endif
3957c478bd9Sstevel@tonic-gate if (pp == pcurrent)
3967c478bd9Sstevel@tonic-gate if (pprevious != PNULL) {
3977c478bd9Sstevel@tonic-gate pcurrent = pprevious;
3987c478bd9Sstevel@tonic-gate pprevious = pgetcurr(pp);
3997c478bd9Sstevel@tonic-gate } else {
4007c478bd9Sstevel@tonic-gate pcurrent = pgetcurr(pp);
4017c478bd9Sstevel@tonic-gate pprevious = pgetcurr(pp);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate else if (pp == pprevious)
4047c478bd9Sstevel@tonic-gate pprevious = pgetcurr(pp);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate /* +4 here is 1 for '\0', 1 ea for << >& >> */
4087c478bd9Sstevel@tonic-gate tchar command[PMAXLEN+4];
4097c478bd9Sstevel@tonic-gate int cmdlen;
4107c478bd9Sstevel@tonic-gate tchar *cmdp;
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate * palloc - allocate a process structure and fill it up.
4137c478bd9Sstevel@tonic-gate * an important assumption is made that the process is running.
4147c478bd9Sstevel@tonic-gate */
4156c02b4a4Smuffin void
palloc(int pid,struct command * t)4166c02b4a4Smuffin palloc(int pid, struct command *t)
4177c478bd9Sstevel@tonic-gate {
4186c02b4a4Smuffin struct process *pp;
4197c478bd9Sstevel@tonic-gate int i;
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate #ifdef TRACE
4227c478bd9Sstevel@tonic-gate tprintf("TRACE- palloc()\n");
4237c478bd9Sstevel@tonic-gate #endif
42465b0c20eSnakanon pp = (struct process *)xcalloc(1, sizeof (struct process));
4257c478bd9Sstevel@tonic-gate pp->p_pid = pid;
4267c478bd9Sstevel@tonic-gate pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND;
4277c478bd9Sstevel@tonic-gate if (t->t_dflg & FTIME)
4287c478bd9Sstevel@tonic-gate pp->p_flags |= PPTIME;
4297c478bd9Sstevel@tonic-gate cmdp = command;
4307c478bd9Sstevel@tonic-gate cmdlen = 0;
4317c478bd9Sstevel@tonic-gate padd(t);
4327c478bd9Sstevel@tonic-gate *cmdp++ = 0;
4337c478bd9Sstevel@tonic-gate if (t->t_dflg & FPOU) {
4347c478bd9Sstevel@tonic-gate pp->p_flags |= PPOU;
4357c478bd9Sstevel@tonic-gate if (t->t_dflg & FDIAG)
4367c478bd9Sstevel@tonic-gate pp->p_flags |= PDIAG;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate pp->p_command = savestr(command);
4397c478bd9Sstevel@tonic-gate if (pcurrjob) {
4407c478bd9Sstevel@tonic-gate struct process *fp;
4417c478bd9Sstevel@tonic-gate /* careful here with interrupt level */
4427c478bd9Sstevel@tonic-gate pp->p_cwd = 0;
4437c478bd9Sstevel@tonic-gate pp->p_index = pcurrjob->p_index;
4447c478bd9Sstevel@tonic-gate pp->p_friends = pcurrjob;
4457c478bd9Sstevel@tonic-gate pp->p_jobid = pcurrjob->p_pid;
4467c478bd9Sstevel@tonic-gate for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
4477c478bd9Sstevel@tonic-gate ;
4487c478bd9Sstevel@tonic-gate fp->p_friends = pp;
4497c478bd9Sstevel@tonic-gate } else {
4507c478bd9Sstevel@tonic-gate pcurrjob = pp;
4517c478bd9Sstevel@tonic-gate pp->p_jobid = pid;
4527c478bd9Sstevel@tonic-gate pp->p_friends = pp;
4537c478bd9Sstevel@tonic-gate pp->p_cwd = dcwd;
4547c478bd9Sstevel@tonic-gate dcwd->di_count++;
4557c478bd9Sstevel@tonic-gate if (pmaxindex < BIGINDEX)
4567c478bd9Sstevel@tonic-gate pp->p_index = ++pmaxindex;
4577c478bd9Sstevel@tonic-gate else {
4587c478bd9Sstevel@tonic-gate struct process *np;
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate for (i = 1; ; i++) {
4617c478bd9Sstevel@tonic-gate for (np = proclist.p_next; np; np = np->p_next)
4627c478bd9Sstevel@tonic-gate if (np->p_index == i)
4637c478bd9Sstevel@tonic-gate goto tryagain;
4647c478bd9Sstevel@tonic-gate pp->p_index = i;
4657c478bd9Sstevel@tonic-gate if (i > pmaxindex)
4667c478bd9Sstevel@tonic-gate pmaxindex = i;
46765b0c20eSnakanon break;
4687c478bd9Sstevel@tonic-gate tryagain:;
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate pprevious = pcurrent;
4727c478bd9Sstevel@tonic-gate pcurrent = pp;
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate pp->p_next = proclist.p_next;
4757c478bd9Sstevel@tonic-gate proclist.p_next = pp;
4767c478bd9Sstevel@tonic-gate (void) gettimeofday(&pp->p_btime, (struct timezone *)0);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4796c02b4a4Smuffin void
padd(struct command * t)4806c02b4a4Smuffin padd(struct command *t)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate tchar **argp;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate #ifdef TRACE
4857c478bd9Sstevel@tonic-gate tprintf("TRACE- padd()\n");
4867c478bd9Sstevel@tonic-gate #endif
4877c478bd9Sstevel@tonic-gate if (t == 0)
4887c478bd9Sstevel@tonic-gate return;
4897c478bd9Sstevel@tonic-gate switch (t->t_dtyp) {
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate case TPAR:
49265b0c20eSnakanon pads(S_LBRASP /* "( " */);
4937c478bd9Sstevel@tonic-gate padd(t->t_dspr);
49465b0c20eSnakanon pads(S_SPRBRA /* " )" */);
4957c478bd9Sstevel@tonic-gate break;
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate case TCOM:
4987c478bd9Sstevel@tonic-gate for (argp = t->t_dcom; *argp; argp++) {
4997c478bd9Sstevel@tonic-gate pads(*argp);
5007c478bd9Sstevel@tonic-gate if (argp[1])
50165b0c20eSnakanon pads(S_SP /* " " */);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate break;
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate case TOR:
5067c478bd9Sstevel@tonic-gate case TAND:
5077c478bd9Sstevel@tonic-gate case TFIL:
5087c478bd9Sstevel@tonic-gate case TLST:
5097c478bd9Sstevel@tonic-gate padd(t->t_dcar);
5107c478bd9Sstevel@tonic-gate switch (t->t_dtyp) {
5117c478bd9Sstevel@tonic-gate case TOR:
51265b0c20eSnakanon pads(S_SPBARBARSP /* " || " */);
5137c478bd9Sstevel@tonic-gate break;
5147c478bd9Sstevel@tonic-gate case TAND:
51565b0c20eSnakanon pads(S_SPANDANDSP /* " && " */);
5167c478bd9Sstevel@tonic-gate break;
5177c478bd9Sstevel@tonic-gate case TFIL:
51865b0c20eSnakanon pads(S_SPBARSP /* " | " */);
5197c478bd9Sstevel@tonic-gate break;
5207c478bd9Sstevel@tonic-gate case TLST:
52165b0c20eSnakanon pads(S_SEMICOLONSP /* "; " */);
5227c478bd9Sstevel@tonic-gate break;
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate padd(t->t_dcdr);
5257c478bd9Sstevel@tonic-gate return;
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate if ((t->t_dflg & FPIN) == 0 && t->t_dlef) {
52865b0c20eSnakanon pads((t->t_dflg & FHERE) ? S_SPLESLESSP /* " << " */ : S_SPLESSP /* " < " */);
5297c478bd9Sstevel@tonic-gate pads(t->t_dlef);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate if ((t->t_dflg & FPOU) == 0 && t->t_drit) {
53265b0c20eSnakanon pads((t->t_dflg & FCAT) ? S_SPGTRGTRSP /* " >>" */ : S_SPGTR /* " >" */);
5337c478bd9Sstevel@tonic-gate if (t->t_dflg & FDIAG)
53465b0c20eSnakanon pads(S_AND /* "&" */);
53565b0c20eSnakanon pads(S_SP /* " " */);
5367c478bd9Sstevel@tonic-gate pads(t->t_drit);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5406c02b4a4Smuffin void
pads(tchar * cp)5416c02b4a4Smuffin pads(tchar *cp)
5427c478bd9Sstevel@tonic-gate {
5436c02b4a4Smuffin int i = strlen_(cp);
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate #ifdef TRACE
5467c478bd9Sstevel@tonic-gate tprintf("TRACE- pads()\n");
5477c478bd9Sstevel@tonic-gate #endif
5487c478bd9Sstevel@tonic-gate if (cmdlen >= PMAXLEN)
5497c478bd9Sstevel@tonic-gate return;
5507c478bd9Sstevel@tonic-gate if (cmdlen + i >= PMAXLEN) {
55165b0c20eSnakanon (void) strcpy_(cmdp, S_SPPPP /* " ..." */);
5527c478bd9Sstevel@tonic-gate cmdlen = PMAXLEN;
5537c478bd9Sstevel@tonic-gate cmdp += 4;
5547c478bd9Sstevel@tonic-gate return;
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate (void) strcpy_(cmdp, cp);
5577c478bd9Sstevel@tonic-gate cmdp += i;
5587c478bd9Sstevel@tonic-gate cmdlen += i;
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate /*
5627c478bd9Sstevel@tonic-gate * psavejob - temporarily save the current job on a one level stack
5637c478bd9Sstevel@tonic-gate * so another job can be created. Used for { } in exp6
5647c478bd9Sstevel@tonic-gate * and `` in globbing.
5657c478bd9Sstevel@tonic-gate */
5666c02b4a4Smuffin void
psavejob(void)5676c02b4a4Smuffin psavejob(void)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate #ifdef TRACE
5717c478bd9Sstevel@tonic-gate tprintf("TRACE- psavejob()\n");
5727c478bd9Sstevel@tonic-gate #endif
5737c478bd9Sstevel@tonic-gate pholdjob = pcurrjob;
5747c478bd9Sstevel@tonic-gate pcurrjob = PNULL;
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate * prestjob - opposite of psavejob. This may be missed if we are interrupted
5797c478bd9Sstevel@tonic-gate * somewhere, but pendjob cleans up anyway.
5807c478bd9Sstevel@tonic-gate */
5816c02b4a4Smuffin void
prestjob(void)5826c02b4a4Smuffin prestjob(void)
5837c478bd9Sstevel@tonic-gate {
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate #ifdef TRACE
5867c478bd9Sstevel@tonic-gate tprintf("TRACE- prestjob()\n");
5877c478bd9Sstevel@tonic-gate #endif
5887c478bd9Sstevel@tonic-gate pcurrjob = pholdjob;
5897c478bd9Sstevel@tonic-gate pholdjob = PNULL;
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate /*
5937c478bd9Sstevel@tonic-gate * pendjob - indicate that a job (set of commands) has been completed
5947c478bd9Sstevel@tonic-gate * or is about to begin.
5957c478bd9Sstevel@tonic-gate */
5966c02b4a4Smuffin void
pendjob(void)5976c02b4a4Smuffin pendjob(void)
5987c478bd9Sstevel@tonic-gate {
5996c02b4a4Smuffin struct process *pp, *tp;
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate #ifdef TRACE
6027c478bd9Sstevel@tonic-gate tprintf("TRACE- pendjob()\n");
6037c478bd9Sstevel@tonic-gate #endif
6047c478bd9Sstevel@tonic-gate if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) {
6057c478bd9Sstevel@tonic-gate pp = pcurrjob;
6067c478bd9Sstevel@tonic-gate while (pp->p_pid != pp->p_jobid)
6077c478bd9Sstevel@tonic-gate pp = pp->p_friends;
6087c478bd9Sstevel@tonic-gate printf("[%d]", pp->p_index);
6097c478bd9Sstevel@tonic-gate tp = pp;
6107c478bd9Sstevel@tonic-gate do {
6117c478bd9Sstevel@tonic-gate printf(" %d", pp->p_pid);
6127c478bd9Sstevel@tonic-gate pp = pp->p_friends;
6137c478bd9Sstevel@tonic-gate } while (pp != tp);
6147c478bd9Sstevel@tonic-gate printf("\n");
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate pholdjob = pcurrjob = 0;
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate * pprint - print a job
6217c478bd9Sstevel@tonic-gate */
6226c02b4a4Smuffin int
pprint(struct process * pp,int flag)6236c02b4a4Smuffin pprint(struct process *pp, int flag)
6247c478bd9Sstevel@tonic-gate {
6256c02b4a4Smuffin int status, reason;
6267c478bd9Sstevel@tonic-gate struct process *tp;
6277c478bd9Sstevel@tonic-gate extern char *linp, linbuf[];
6287c478bd9Sstevel@tonic-gate int jobflags, pstatus;
6297c478bd9Sstevel@tonic-gate char *format;
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate #ifdef TRACE
6327c478bd9Sstevel@tonic-gate tprintf("TRACE- pprint()\n");
6337c478bd9Sstevel@tonic-gate #endif
6347c478bd9Sstevel@tonic-gate while (pp->p_pid != pp->p_jobid)
6357c478bd9Sstevel@tonic-gate pp = pp->p_friends;
6367c478bd9Sstevel@tonic-gate if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
6377c478bd9Sstevel@tonic-gate pp->p_flags &= ~PPTIME;
6387c478bd9Sstevel@tonic-gate pp->p_flags |= PTIME;
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate tp = pp;
64165b0c20eSnakanon status = reason = -1;
6427c478bd9Sstevel@tonic-gate jobflags = 0;
6437c478bd9Sstevel@tonic-gate do {
6447c478bd9Sstevel@tonic-gate jobflags |= pp->p_flags;
6457c478bd9Sstevel@tonic-gate pstatus = pp->p_flags & PALLSTATES;
6467c478bd9Sstevel@tonic-gate if (tp != pp && linp != linbuf && !(flag&FANCY) &&
6477c478bd9Sstevel@tonic-gate (pstatus == status && pp->p_reason == reason ||
64865b0c20eSnakanon !(flag&REASON)))
6497c478bd9Sstevel@tonic-gate printf(" ");
6507c478bd9Sstevel@tonic-gate else {
6517c478bd9Sstevel@tonic-gate if (tp != pp && linp != linbuf)
6527c478bd9Sstevel@tonic-gate printf("\n");
65365b0c20eSnakanon if (flag&NUMBER)
6547c478bd9Sstevel@tonic-gate if (pp == tp)
6557c478bd9Sstevel@tonic-gate printf("[%d]%s %c ", pp->p_index,
6567c478bd9Sstevel@tonic-gate pp->p_index < 10 ? " " : "",
65765b0c20eSnakanon pp == pcurrent ? '+' :
6587c478bd9Sstevel@tonic-gate (pp == pprevious ? (tchar) '-'
6597c478bd9Sstevel@tonic-gate : (tchar) ' '));
6607c478bd9Sstevel@tonic-gate else
6617c478bd9Sstevel@tonic-gate printf(" ");
6627c478bd9Sstevel@tonic-gate if (flag&FANCY)
6637c478bd9Sstevel@tonic-gate printf("%5d ", pp->p_pid);
6647c478bd9Sstevel@tonic-gate if (flag&(REASON|AREASON)) {
6657c478bd9Sstevel@tonic-gate if (flag&NAME)
6667c478bd9Sstevel@tonic-gate format = "%-21s";
6677c478bd9Sstevel@tonic-gate else
6687c478bd9Sstevel@tonic-gate format = "%s";
6697c478bd9Sstevel@tonic-gate if (pstatus == status)
6707c478bd9Sstevel@tonic-gate if (pp->p_reason == reason) {
6717c478bd9Sstevel@tonic-gate printf(format, "");
6727c478bd9Sstevel@tonic-gate goto prcomd;
6737c478bd9Sstevel@tonic-gate } else
6747c478bd9Sstevel@tonic-gate reason = pp->p_reason;
6757c478bd9Sstevel@tonic-gate else {
6767c478bd9Sstevel@tonic-gate status = pstatus;
6777c478bd9Sstevel@tonic-gate reason = pp->p_reason;
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate switch (status) {
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate case PRUNNING:
6827c478bd9Sstevel@tonic-gate printf(format, "Running ");
6837c478bd9Sstevel@tonic-gate break;
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate case PINTERRUPTED:
6867c478bd9Sstevel@tonic-gate case PSTOPPED:
6877c478bd9Sstevel@tonic-gate case PSIGNALED:
6887c478bd9Sstevel@tonic-gate if ((flag&(REASON|AREASON))
6897c478bd9Sstevel@tonic-gate && reason != SIGINT
6907c478bd9Sstevel@tonic-gate && reason != SIGPIPE)
6917c478bd9Sstevel@tonic-gate printf(format,
6927c478bd9Sstevel@tonic-gate strsignal(pp->p_reason));
6937c478bd9Sstevel@tonic-gate break;
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate case PNEXITED:
6967c478bd9Sstevel@tonic-gate case PAEXITED:
6977c478bd9Sstevel@tonic-gate if (flag & REASON)
6987c478bd9Sstevel@tonic-gate if (pp->p_reason)
6997c478bd9Sstevel@tonic-gate printf("Exit %-16d", pp->p_reason);
7007c478bd9Sstevel@tonic-gate else
7017c478bd9Sstevel@tonic-gate printf(format, "Done");
7027c478bd9Sstevel@tonic-gate break;
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate default:
7057c478bd9Sstevel@tonic-gate printf("BUG: status=%-9o", status);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate prcomd:
7107c478bd9Sstevel@tonic-gate if (flag&NAME) {
7117c478bd9Sstevel@tonic-gate printf("%t", pp->p_command);
7127c478bd9Sstevel@tonic-gate if (pp->p_flags & PPOU)
7137c478bd9Sstevel@tonic-gate printf(" |");
7147c478bd9Sstevel@tonic-gate if (pp->p_flags & PDIAG)
7157c478bd9Sstevel@tonic-gate printf("&");
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED)
7187c478bd9Sstevel@tonic-gate printf(" (core dumped)");
7197c478bd9Sstevel@tonic-gate if (tp == pp->p_friends) {
7207c478bd9Sstevel@tonic-gate if (flag&ERSAND)
7217c478bd9Sstevel@tonic-gate printf(" &");
7227c478bd9Sstevel@tonic-gate if (flag&JOBDIR &&
7237c478bd9Sstevel@tonic-gate !eq(tp->p_cwd->di_name, dcwd->di_name)) {
7247c478bd9Sstevel@tonic-gate printf(" (wd: ");
72565b0c20eSnakanon dtildepr(value(S_home /* "home" */), tp->p_cwd->di_name);
7267c478bd9Sstevel@tonic-gate printf(")");
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) {
7307c478bd9Sstevel@tonic-gate if (linp != linbuf)
7317c478bd9Sstevel@tonic-gate printf("\n\t");
7327c478bd9Sstevel@tonic-gate { static struct rusage zru;
73365b0c20eSnakanon prusage(&zru, &pp->p_rusage, &pp->p_etime,
7347c478bd9Sstevel@tonic-gate &pp->p_btime);
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate if (tp == pp->p_friends) {
7387c478bd9Sstevel@tonic-gate if (linp != linbuf)
7397c478bd9Sstevel@tonic-gate printf("\n");
7407c478bd9Sstevel@tonic-gate if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
7417c478bd9Sstevel@tonic-gate printf("(wd now: ");
7427c478bd9Sstevel@tonic-gate dtildepr(value(S_home /* "home" */), dcwd->di_name);
7437c478bd9Sstevel@tonic-gate printf(")\n");
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate } while ((pp = pp->p_friends) != tp);
7477c478bd9Sstevel@tonic-gate if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) {
7487c478bd9Sstevel@tonic-gate if (jobflags & NUMBER)
7497c478bd9Sstevel@tonic-gate printf(" ");
7507c478bd9Sstevel@tonic-gate ptprint(tp);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate return (jobflags);
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate
7556c02b4a4Smuffin void
ptprint(struct process * tp)7566c02b4a4Smuffin ptprint(struct process *tp)
7577c478bd9Sstevel@tonic-gate {
7587c478bd9Sstevel@tonic-gate struct timeval tetime, diff;
7597c478bd9Sstevel@tonic-gate static struct timeval ztime;
7607c478bd9Sstevel@tonic-gate struct rusage ru;
7617c478bd9Sstevel@tonic-gate static struct rusage zru;
7626c02b4a4Smuffin struct process *pp = tp;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate #ifdef TRACE
7657c478bd9Sstevel@tonic-gate tprintf("TRACE- ptprint()\n");
7667c478bd9Sstevel@tonic-gate #endif
7677c478bd9Sstevel@tonic-gate ru = zru;
7687c478bd9Sstevel@tonic-gate tetime = ztime;
7697c478bd9Sstevel@tonic-gate do {
7707c478bd9Sstevel@tonic-gate ruadd(&ru, &pp->p_rusage);
7717c478bd9Sstevel@tonic-gate tvsub(&diff, &pp->p_etime, &pp->p_btime);
7727c478bd9Sstevel@tonic-gate if (timercmp(&diff, &tetime, >))
7737c478bd9Sstevel@tonic-gate tetime = diff;
7747c478bd9Sstevel@tonic-gate } while ((pp = pp->p_friends) != tp);
7757c478bd9Sstevel@tonic-gate prusage(&zru, &ru, &tetime, &ztime);
7767c478bd9Sstevel@tonic-gate }
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate /*
7797c478bd9Sstevel@tonic-gate * dojobs - print all jobs
7807c478bd9Sstevel@tonic-gate */
7816c02b4a4Smuffin void
dojobs(tchar ** v)7826c02b4a4Smuffin dojobs(tchar **v)
7837c478bd9Sstevel@tonic-gate {
7846c02b4a4Smuffin struct process *pp;
7856c02b4a4Smuffin int flag = NUMBER|NAME|REASON;
7867c478bd9Sstevel@tonic-gate int i;
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate #ifdef TRACE
7897c478bd9Sstevel@tonic-gate tprintf("TRACE- dojobs()\n");
7907c478bd9Sstevel@tonic-gate #endif
7917c478bd9Sstevel@tonic-gate if (chkstop)
7927c478bd9Sstevel@tonic-gate chkstop = 2;
7937c478bd9Sstevel@tonic-gate if (*++v) {
79465b0c20eSnakanon if (v[1] || !eq(*v, S_DASHl /* "-l" */))
7957c478bd9Sstevel@tonic-gate error("Usage: jobs [ -l ]");
7967c478bd9Sstevel@tonic-gate flag |= FANCY|JOBDIR;
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate for (i = 1; i <= pmaxindex; i++)
7997c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp; pp = pp->p_next)
8007c478bd9Sstevel@tonic-gate if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
8017c478bd9Sstevel@tonic-gate pp->p_flags &= ~PNEEDNOTE;
8027c478bd9Sstevel@tonic-gate if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED)))
8037c478bd9Sstevel@tonic-gate pflush(pp);
8047c478bd9Sstevel@tonic-gate break;
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate /*
8097c478bd9Sstevel@tonic-gate * dofg - builtin - put the job into the foreground
8107c478bd9Sstevel@tonic-gate */
8116c02b4a4Smuffin void
dofg(tchar ** v)8126c02b4a4Smuffin dofg(tchar **v)
8137c478bd9Sstevel@tonic-gate {
8146c02b4a4Smuffin struct process *pp;
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate #ifdef TRACE
8177c478bd9Sstevel@tonic-gate tprintf("TRACE- dofg()\n");
8187c478bd9Sstevel@tonic-gate #endif
8197c478bd9Sstevel@tonic-gate okpcntl();
8207c478bd9Sstevel@tonic-gate ++v;
8217c478bd9Sstevel@tonic-gate do {
8227c478bd9Sstevel@tonic-gate pp = pfind(*v);
8237c478bd9Sstevel@tonic-gate pstart(pp, 1);
8247c478bd9Sstevel@tonic-gate pjwait(pp);
8257c478bd9Sstevel@tonic-gate } while (*v && *++v);
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate
8287c478bd9Sstevel@tonic-gate /*
8297c478bd9Sstevel@tonic-gate * %... - builtin - put the job into the foreground
8307c478bd9Sstevel@tonic-gate */
8316c02b4a4Smuffin void
dofg1(tchar ** v)8326c02b4a4Smuffin dofg1(tchar **v)
8337c478bd9Sstevel@tonic-gate {
8346c02b4a4Smuffin struct process *pp;
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate #ifdef TRACE
8377c478bd9Sstevel@tonic-gate tprintf("TRACE- untty()\n");
8387c478bd9Sstevel@tonic-gate #endif
8397c478bd9Sstevel@tonic-gate okpcntl();
8407c478bd9Sstevel@tonic-gate pp = pfind(v[0]);
8417c478bd9Sstevel@tonic-gate pstart(pp, 1);
8427c478bd9Sstevel@tonic-gate pjwait(pp);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate /*
8467c478bd9Sstevel@tonic-gate * dobg - builtin - put the job into the background
8477c478bd9Sstevel@tonic-gate */
8486c02b4a4Smuffin void
dobg(tchar ** v)8496c02b4a4Smuffin dobg(tchar **v)
8507c478bd9Sstevel@tonic-gate {
8516c02b4a4Smuffin struct process *pp;
8527c478bd9Sstevel@tonic-gate
8537c478bd9Sstevel@tonic-gate #ifdef TRACE
8547c478bd9Sstevel@tonic-gate tprintf("TRACE- dobg()\n");
8557c478bd9Sstevel@tonic-gate #endif
8567c478bd9Sstevel@tonic-gate okpcntl();
8577c478bd9Sstevel@tonic-gate ++v;
8587c478bd9Sstevel@tonic-gate do {
8597c478bd9Sstevel@tonic-gate pp = pfind(*v);
8607c478bd9Sstevel@tonic-gate pstart(pp, 0);
8617c478bd9Sstevel@tonic-gate } while (*v && *++v);
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate /*
8657c478bd9Sstevel@tonic-gate * %... & - builtin - put the job into the background
8667c478bd9Sstevel@tonic-gate */
8676c02b4a4Smuffin void
dobg1(tchar ** v)8686c02b4a4Smuffin dobg1(tchar **v)
8697c478bd9Sstevel@tonic-gate {
8706c02b4a4Smuffin struct process *pp;
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate #ifdef TRACE
8737c478bd9Sstevel@tonic-gate tprintf("TRACE- dobg1()\n");
8747c478bd9Sstevel@tonic-gate #endif
8757c478bd9Sstevel@tonic-gate pp = pfind(v[0]);
8767c478bd9Sstevel@tonic-gate pstart(pp, 0);
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate /*
8807c478bd9Sstevel@tonic-gate * dostop - builtin - stop the job
8817c478bd9Sstevel@tonic-gate */
8826c02b4a4Smuffin void
dostop(tchar ** v)8836c02b4a4Smuffin dostop(tchar **v)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate #ifdef TRACE
8877c478bd9Sstevel@tonic-gate tprintf("TRACE- dostop()\n");
8887c478bd9Sstevel@tonic-gate #endif
8897c478bd9Sstevel@tonic-gate pkill(++v, SIGSTOP);
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate /*
8937c478bd9Sstevel@tonic-gate * dokill - builtin - superset of kill (1)
8947c478bd9Sstevel@tonic-gate */
8956c02b4a4Smuffin void
dokill(tchar ** v)8966c02b4a4Smuffin dokill(tchar **v)
8977c478bd9Sstevel@tonic-gate {
8986c02b4a4Smuffin int signum;
8996c02b4a4Smuffin tchar *name;
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate #ifdef TRACE
9027c478bd9Sstevel@tonic-gate tprintf("TRACE- dokill()\n");
9037c478bd9Sstevel@tonic-gate #endif
9047c478bd9Sstevel@tonic-gate v++;
9057c478bd9Sstevel@tonic-gate if (v[0] && v[0][0] == '-') {
9067c478bd9Sstevel@tonic-gate if (v[0][1] == 'l') {
9077c478bd9Sstevel@tonic-gate for (signum = 1; signum <= NSIG-1; signum++) {
9087c478bd9Sstevel@tonic-gate char sbuf[BUFSIZ];
9097c478bd9Sstevel@tonic-gate if (sig2str(signum, sbuf) == 0)
9107c478bd9Sstevel@tonic-gate printf("%s ", sbuf);
9117c478bd9Sstevel@tonic-gate if (signum % 8 == 0)
9127c478bd9Sstevel@tonic-gate Putchar('\n');
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate Putchar('\n');
9157c478bd9Sstevel@tonic-gate return;
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate if (digit(v[0][1])) {
91870a587ddSchin if (chkalldigit_(v[0]+1) != 0) {
91970a587ddSchin setname(v[0]+1);
92070a587ddSchin bferr("Unknown signal; kill -l lists signals");
92170a587ddSchin }
9227c478bd9Sstevel@tonic-gate signum = atoi_(v[0]+1);
9237c478bd9Sstevel@tonic-gate if (signum < 0 || signum > NSIG)
9247c478bd9Sstevel@tonic-gate bferr("Bad signal number");
9257c478bd9Sstevel@tonic-gate } else {
9267c478bd9Sstevel@tonic-gate int signo;
9277c478bd9Sstevel@tonic-gate char sbuf[BUFSIZ];
9287c478bd9Sstevel@tonic-gate name = &v[0][1];
9297c478bd9Sstevel@tonic-gate tstostr(sbuf, name);
9307c478bd9Sstevel@tonic-gate if (str2sig(sbuf, &signo) == 0) {
9317c478bd9Sstevel@tonic-gate signum = signo;
9327c478bd9Sstevel@tonic-gate goto gotsig;
9337c478bd9Sstevel@tonic-gate }
93465b0c20eSnakanon if (eq(name, S_IOT /* "IOT" */)) {
9357c478bd9Sstevel@tonic-gate signum = SIGABRT;
9367c478bd9Sstevel@tonic-gate goto gotsig;
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate setname(name);
9397c478bd9Sstevel@tonic-gate bferr("Unknown signal; kill -l lists signals");
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate gotsig:
9427c478bd9Sstevel@tonic-gate v++;
9437c478bd9Sstevel@tonic-gate } else
9447c478bd9Sstevel@tonic-gate signum = SIGTERM;
9457c478bd9Sstevel@tonic-gate pkill(v, signum);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9486c02b4a4Smuffin void
pkill(tchar ** v,int signum)9496c02b4a4Smuffin pkill(tchar **v, int signum)
9507c478bd9Sstevel@tonic-gate {
9516c02b4a4Smuffin struct process *pp, *np;
9526c02b4a4Smuffin int jobflags = 0;
9537c478bd9Sstevel@tonic-gate int omask, pid, err = 0;
9547c478bd9Sstevel@tonic-gate tchar *cp;
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate #ifdef TRACE
9577c478bd9Sstevel@tonic-gate tprintf("TRACE- pkill()\n");
9587c478bd9Sstevel@tonic-gate #endif
9597c478bd9Sstevel@tonic-gate omask = sigmask(SIGCHLD);
9607c478bd9Sstevel@tonic-gate if (setintr)
9617c478bd9Sstevel@tonic-gate omask |= sigmask(SIGINT);
9627c478bd9Sstevel@tonic-gate omask = sigblock(omask) & ~omask;
9637c478bd9Sstevel@tonic-gate while (*v) {
9647c478bd9Sstevel@tonic-gate cp = globone(*v);
9657c478bd9Sstevel@tonic-gate if (*cp == '%') {
9667c478bd9Sstevel@tonic-gate np = pp = pfind(cp);
9677c478bd9Sstevel@tonic-gate do
9687c478bd9Sstevel@tonic-gate jobflags |= np->p_flags;
9697c478bd9Sstevel@tonic-gate while ((np = np->p_friends) != pp);
9707c478bd9Sstevel@tonic-gate switch (signum) {
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate case SIGSTOP:
9737c478bd9Sstevel@tonic-gate case SIGTSTP:
9747c478bd9Sstevel@tonic-gate case SIGTTIN:
9757c478bd9Sstevel@tonic-gate case SIGTTOU:
9767c478bd9Sstevel@tonic-gate if ((jobflags & PRUNNING) == 0) {
9777c478bd9Sstevel@tonic-gate /* %s -> %t */
9787c478bd9Sstevel@tonic-gate printf("%t: Already stopped\n", cp);
9797c478bd9Sstevel@tonic-gate err++;
9807c478bd9Sstevel@tonic-gate goto cont;
9817c478bd9Sstevel@tonic-gate }
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate if (killpg(pp->p_jobid, signum) < 0) {
9847c478bd9Sstevel@tonic-gate /* %s -> %t */
9857c478bd9Sstevel@tonic-gate printf("%t: ", cp);
9867c478bd9Sstevel@tonic-gate printf("%s\n", strerror(errno));
9877c478bd9Sstevel@tonic-gate err++;
9887c478bd9Sstevel@tonic-gate }
9897c478bd9Sstevel@tonic-gate if (signum == SIGTERM || signum == SIGHUP)
9907c478bd9Sstevel@tonic-gate (void) killpg(pp->p_jobid, SIGCONT);
9917c478bd9Sstevel@tonic-gate } else if (!(digit(*cp) || *cp == '-'))
9927c478bd9Sstevel@tonic-gate bferr("Arguments should be jobs or process id's");
9937c478bd9Sstevel@tonic-gate else {
9947c478bd9Sstevel@tonic-gate pid = atoi_(cp);
9957c478bd9Sstevel@tonic-gate if (kill(pid, signum) < 0) {
9967c478bd9Sstevel@tonic-gate printf("%d: ", pid);
9977c478bd9Sstevel@tonic-gate printf("%s\n", strerror(errno));
9987c478bd9Sstevel@tonic-gate err++;
9997c478bd9Sstevel@tonic-gate goto cont;
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate if (signum == SIGTERM || signum == SIGHUP)
10027c478bd9Sstevel@tonic-gate (void) kill(pid, SIGCONT);
10037c478bd9Sstevel@tonic-gate }
10047c478bd9Sstevel@tonic-gate cont:
10057c478bd9Sstevel@tonic-gate xfree(cp);
10067c478bd9Sstevel@tonic-gate v++;
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
10097c478bd9Sstevel@tonic-gate if (err)
10107c478bd9Sstevel@tonic-gate error(NULL);
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate /*
10147c478bd9Sstevel@tonic-gate * pstart - start the job in foreground/background
10157c478bd9Sstevel@tonic-gate */
10166c02b4a4Smuffin void
pstart(struct process * pp,int foregnd)10176c02b4a4Smuffin pstart(struct process *pp, int foregnd)
10187c478bd9Sstevel@tonic-gate {
10196c02b4a4Smuffin struct process *np;
10207c478bd9Sstevel@tonic-gate int omask, jobflags = 0;
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate #ifdef TRACE
10237c478bd9Sstevel@tonic-gate tprintf("TRACE- pstart()\n");
10247c478bd9Sstevel@tonic-gate #endif
10257c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
10267c478bd9Sstevel@tonic-gate np = pp;
10277c478bd9Sstevel@tonic-gate do {
10287c478bd9Sstevel@tonic-gate jobflags |= np->p_flags;
10297c478bd9Sstevel@tonic-gate if (np->p_flags&(PRUNNING|PSTOPPED)) {
10307c478bd9Sstevel@tonic-gate np->p_flags |= PRUNNING;
10317c478bd9Sstevel@tonic-gate np->p_flags &= ~PSTOPPED;
10327c478bd9Sstevel@tonic-gate if (foregnd)
10337c478bd9Sstevel@tonic-gate np->p_flags |= PFOREGND;
10347c478bd9Sstevel@tonic-gate else
10357c478bd9Sstevel@tonic-gate np->p_flags &= ~PFOREGND;
10367c478bd9Sstevel@tonic-gate }
103765b0c20eSnakanon } while ((np = np->p_friends) != pp);
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate if (foregnd)
10407c478bd9Sstevel@tonic-gate pclrcurr(pp);
10417c478bd9Sstevel@tonic-gate else
10427c478bd9Sstevel@tonic-gate {
104365b0c20eSnakanon if (pprevious && (pprevious->p_flags & PSTOPPED))
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate pcurrent = pprevious;
10467c478bd9Sstevel@tonic-gate pprevious = pgetcurr(PNULL);
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate else
104965b0c20eSnakanon {
10507c478bd9Sstevel@tonic-gate pcurrent = pgetcurr(pp);
105165b0c20eSnakanon if (!pcurrent || (pcurrent->p_flags & PRUNNING))
10527c478bd9Sstevel@tonic-gate pcurrent = pp;
10537c478bd9Sstevel@tonic-gate else
10547c478bd9Sstevel@tonic-gate pprevious = pp;
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND);
10587c478bd9Sstevel@tonic-gate if (foregnd)
10597c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid);
10607c478bd9Sstevel@tonic-gate if (jobflags&PSTOPPED)
10617c478bd9Sstevel@tonic-gate (void) killpg(pp->p_jobid, SIGCONT);
10627c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate
10656c02b4a4Smuffin void
panystop(int neednl)10666c02b4a4Smuffin panystop(int neednl)
10677c478bd9Sstevel@tonic-gate {
10686c02b4a4Smuffin struct process *pp;
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate #ifdef TRACE
10717c478bd9Sstevel@tonic-gate tprintf("TRACE- panystop()\n");
10727c478bd9Sstevel@tonic-gate #endif
10737c478bd9Sstevel@tonic-gate chkstop = 2;
10747c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp; pp = pp->p_next)
10757c478bd9Sstevel@tonic-gate if (pp->p_flags & PSTOPPED)
10767c478bd9Sstevel@tonic-gate error("\nThere are stopped jobs" + 1 - neednl);
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate struct process *
pfind(tchar * cp)10806c02b4a4Smuffin pfind(tchar *cp)
10817c478bd9Sstevel@tonic-gate {
10826c02b4a4Smuffin struct process *pp, *np;
10837c478bd9Sstevel@tonic-gate
10847c478bd9Sstevel@tonic-gate #ifdef TRACE
10857c478bd9Sstevel@tonic-gate tprintf("TRACE- pfind()\n");
10867c478bd9Sstevel@tonic-gate #endif
108765b0c20eSnakanon if (cp == 0 || cp[1] == 0 || eq(cp, S_PARCENTPARCENT /* "%%" */) ||
108865b0c20eSnakanon eq(cp, S_PARCENTPLUS /* "%+" */)) {
10897c478bd9Sstevel@tonic-gate if (pcurrent == PNULL)
109065b0c20eSnakanon if ((pcurrent = pgetcurr(PNULL)) == PNULL)
10917c478bd9Sstevel@tonic-gate bferr("No current job");
10927c478bd9Sstevel@tonic-gate return (pcurrent);
10937c478bd9Sstevel@tonic-gate }
109465b0c20eSnakanon if (eq(cp, S_PARCENTMINUS /* "%-" */) ||
109565b0c20eSnakanon eq(cp, S_PARCENTSHARP /* "%#" */)) {
10967c478bd9Sstevel@tonic-gate if (pprevious == PNULL)
10977c478bd9Sstevel@tonic-gate bferr("No previous job");
10987c478bd9Sstevel@tonic-gate return (pprevious);
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate if (digit(cp[1])) {
11017c478bd9Sstevel@tonic-gate int index = atoi_(cp+1);
11027c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp; pp = pp->p_next)
11037c478bd9Sstevel@tonic-gate if (pp->p_index == index && pp->p_pid == pp->p_jobid)
11047c478bd9Sstevel@tonic-gate return (pp);
11057c478bd9Sstevel@tonic-gate bferr("No such job");
11067c478bd9Sstevel@tonic-gate }
11077c478bd9Sstevel@tonic-gate np = PNULL;
11087c478bd9Sstevel@tonic-gate for (pp = proclist.p_next; pp; pp = pp->p_next)
11097c478bd9Sstevel@tonic-gate if (pp->p_pid == pp->p_jobid) {
11107c478bd9Sstevel@tonic-gate if (cp[1] == '?') {
11116c02b4a4Smuffin tchar *dp;
11127c478bd9Sstevel@tonic-gate for (dp = pp->p_command; *dp; dp++) {
11137c478bd9Sstevel@tonic-gate if (*dp != cp[2])
11147c478bd9Sstevel@tonic-gate continue;
11157c478bd9Sstevel@tonic-gate if (prefix(cp+2, dp))
11167c478bd9Sstevel@tonic-gate goto match;
11177c478bd9Sstevel@tonic-gate }
11187c478bd9Sstevel@tonic-gate } else if (prefix(cp+1, pp->p_command)) {
11197c478bd9Sstevel@tonic-gate match:
11207c478bd9Sstevel@tonic-gate if (np)
11217c478bd9Sstevel@tonic-gate bferr("Ambiguous");
11227c478bd9Sstevel@tonic-gate np = pp;
11237c478bd9Sstevel@tonic-gate }
11247c478bd9Sstevel@tonic-gate }
11257c478bd9Sstevel@tonic-gate if (np)
11267c478bd9Sstevel@tonic-gate return (np);
11277c478bd9Sstevel@tonic-gate if (cp[1] == '?')
11287c478bd9Sstevel@tonic-gate bferr("No job matches pattern");
11297c478bd9Sstevel@tonic-gate else
11307c478bd9Sstevel@tonic-gate bferr("No such job");
11317c478bd9Sstevel@tonic-gate /*NOTREACHED*/
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate /*
11357c478bd9Sstevel@tonic-gate * pgetcurr - find most recent job that is not pp, preferably stopped
11367c478bd9Sstevel@tonic-gate */
11377c478bd9Sstevel@tonic-gate struct process *
pgetcurr(struct process * pp)11386c02b4a4Smuffin pgetcurr(struct process *pp)
11397c478bd9Sstevel@tonic-gate {
11406c02b4a4Smuffin struct process *np;
11416c02b4a4Smuffin struct process *xp = PNULL;
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate #ifdef TRACE
11447c478bd9Sstevel@tonic-gate tprintf("TRACE- pgetcurr()\n");
11457c478bd9Sstevel@tonic-gate #endif
11467c478bd9Sstevel@tonic-gate for (np = proclist.p_next; np; np = np->p_next)
11477c478bd9Sstevel@tonic-gate if (np != pcurrent && np != pp && np->p_pid &&
11487c478bd9Sstevel@tonic-gate np->p_pid == np->p_jobid) {
11497c478bd9Sstevel@tonic-gate if (np->p_flags & PSTOPPED)
11507c478bd9Sstevel@tonic-gate return (np);
11517c478bd9Sstevel@tonic-gate if (xp == PNULL)
11527c478bd9Sstevel@tonic-gate xp = np;
11537c478bd9Sstevel@tonic-gate }
11547c478bd9Sstevel@tonic-gate return (xp);
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate /*
11587c478bd9Sstevel@tonic-gate * donotify - flag the job so as to report termination asynchronously
11597c478bd9Sstevel@tonic-gate */
11606c02b4a4Smuffin void
donotify(tchar ** v)11616c02b4a4Smuffin donotify(tchar **v)
11627c478bd9Sstevel@tonic-gate {
11636c02b4a4Smuffin struct process *pp;
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate #ifdef TRACE
11667c478bd9Sstevel@tonic-gate tprintf("TRACE- donotify()\n");
11677c478bd9Sstevel@tonic-gate #endif
11687c478bd9Sstevel@tonic-gate pp = pfind(*++v);
11697c478bd9Sstevel@tonic-gate pp->p_flags |= PNOTIFY;
11707c478bd9Sstevel@tonic-gate }
11717c478bd9Sstevel@tonic-gate
11727c478bd9Sstevel@tonic-gate /*
11737c478bd9Sstevel@tonic-gate * Do the fork and whatever should be done in the child side that
11747c478bd9Sstevel@tonic-gate * should not be done if we are not forking at all (like for simple builtin's)
11757c478bd9Sstevel@tonic-gate * Also do everything that needs any signals fiddled with in the parent side
11767c478bd9Sstevel@tonic-gate *
11777c478bd9Sstevel@tonic-gate * Wanttty tells whether process and/or tty pgrps are to be manipulated:
11787c478bd9Sstevel@tonic-gate * -1: leave tty alone; inherit pgrp from parent
11797c478bd9Sstevel@tonic-gate * 0: already have tty; manipulate process pgrps only
11807c478bd9Sstevel@tonic-gate * 1: want to claim tty; manipulate process and tty pgrps
11817c478bd9Sstevel@tonic-gate * It is usually just the value of tpgrp.
11826c02b4a4Smuffin *
11836c02b4a4Smuffin * argument:
11846c02b4a4Smuffin * t: command we are forking for
11857c478bd9Sstevel@tonic-gate */
11866c02b4a4Smuffin int
pfork(struct command * t,int wanttty)11876c02b4a4Smuffin pfork(struct command *t, int wanttty)
11887c478bd9Sstevel@tonic-gate {
11896c02b4a4Smuffin int pid;
11907c478bd9Sstevel@tonic-gate bool ignint = 0;
11917c478bd9Sstevel@tonic-gate int pgrp, omask;
11927c478bd9Sstevel@tonic-gate int child_pid;
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate #ifdef TRACE
11957c478bd9Sstevel@tonic-gate tprintf("TRACE- pfork()\n");
11967c478bd9Sstevel@tonic-gate #endif
11977c478bd9Sstevel@tonic-gate /*
11987c478bd9Sstevel@tonic-gate * A child will be uninterruptible only under very special
11997c478bd9Sstevel@tonic-gate * conditions. Remember that the semantics of '&' is
12007c478bd9Sstevel@tonic-gate * implemented by disconnecting the process from the tty so
12017c478bd9Sstevel@tonic-gate * signals do not need to ignored just for '&'.
12027c478bd9Sstevel@tonic-gate * Thus signals are set to default action for children unless:
12037c478bd9Sstevel@tonic-gate * we have had an "onintr -" (then specifically ignored)
12047c478bd9Sstevel@tonic-gate * we are not playing with signals (inherit action)
12057c478bd9Sstevel@tonic-gate */
12067c478bd9Sstevel@tonic-gate if (setintr)
12077c478bd9Sstevel@tonic-gate ignint = (tpgrp == -1 && (t->t_dflg&FINT))
120865b0c20eSnakanon || (gointr && eq(gointr, S_MINUS /* "-" */));
12097c478bd9Sstevel@tonic-gate /*
12107c478bd9Sstevel@tonic-gate * Hold SIGCHLD until we have the process installed in our table.
12117c478bd9Sstevel@tonic-gate */
12127c478bd9Sstevel@tonic-gate omask = sigblock(sigmask(SIGCHLD));
12137c478bd9Sstevel@tonic-gate while ((pid = fork()) < 0)
12147c478bd9Sstevel@tonic-gate if (setintr == 0)
12157c478bd9Sstevel@tonic-gate sleep(FORKSLEEP);
12167c478bd9Sstevel@tonic-gate else {
12177c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
12187c478bd9Sstevel@tonic-gate error("Fork failed");
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate * setup the process group
12237c478bd9Sstevel@tonic-gate */
12247c478bd9Sstevel@tonic-gate if (pid == 0)
12257c478bd9Sstevel@tonic-gate child_pid = getpid();
12267c478bd9Sstevel@tonic-gate else
12277c478bd9Sstevel@tonic-gate child_pid = pid;
12287c478bd9Sstevel@tonic-gate pgrp = pcurrjob ? pcurrjob->p_jobid : child_pid;
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gate if (pid == 0) {
12317c478bd9Sstevel@tonic-gate int sigttou;
12327c478bd9Sstevel@tonic-gate settimes();
12337c478bd9Sstevel@tonic-gate pflushall();
12347c478bd9Sstevel@tonic-gate pcurrjob = PNULL;
12357c478bd9Sstevel@tonic-gate child++;
12367c478bd9Sstevel@tonic-gate if (setintr) {
12377c478bd9Sstevel@tonic-gate setintr = 0; /* until I think otherwise */
12387c478bd9Sstevel@tonic-gate /*
12397c478bd9Sstevel@tonic-gate * Children just get blown away on SIGINT, SIGQUIT
12407c478bd9Sstevel@tonic-gate * unless "onintr -" seen.
12417c478bd9Sstevel@tonic-gate */
12427c478bd9Sstevel@tonic-gate (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
12437c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
12447c478bd9Sstevel@tonic-gate if (wanttty >= 0) {
12457c478bd9Sstevel@tonic-gate /* make stoppable */
12467c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL);
12477c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_DFL);
12487c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_DFL);
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm);
12517c478bd9Sstevel@tonic-gate } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
12527c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN);
12537c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN);
12547c478bd9Sstevel@tonic-gate }
12557c478bd9Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0)
12567c478bd9Sstevel@tonic-gate (void) setpgid(0, pgrp);
12577c478bd9Sstevel@tonic-gate if (wanttty > 0) {
125865b0c20eSnakanon sigttou = sigblock(sigmask(SIGTTOU) |
125965b0c20eSnakanon sigmask(SIGTTIN) |
12607c478bd9Sstevel@tonic-gate sigmask(SIGTSTP));
12617c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp);
126265b0c20eSnakanon sigsetmask(sigttou);
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate if (tpgrp > 0)
12657c478bd9Sstevel@tonic-gate tpgrp = 0; /* gave tty away */
12667c478bd9Sstevel@tonic-gate /*
12677c478bd9Sstevel@tonic-gate * Nohup and nice apply only to TCOM's but it would be
12687c478bd9Sstevel@tonic-gate * nice (?!?) if you could say "nohup (foo;bar)"
12697c478bd9Sstevel@tonic-gate * Then the parser would have to know about nice/nohup/time
12707c478bd9Sstevel@tonic-gate */
12717c478bd9Sstevel@tonic-gate if (t->t_dflg & FNOHUP)
12727c478bd9Sstevel@tonic-gate (void) signal(SIGHUP, SIG_IGN);
12737c478bd9Sstevel@tonic-gate if (t->t_dflg & FNICE)
12747c478bd9Sstevel@tonic-gate (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
12757c478bd9Sstevel@tonic-gate } else {
12767c478bd9Sstevel@tonic-gate if (wanttty >= 0 && tpgrp >= 0)
12777c478bd9Sstevel@tonic-gate setpgid(pid, pgrp);
12787c478bd9Sstevel@tonic-gate palloc(pid, t);
12797c478bd9Sstevel@tonic-gate (void) sigsetmask(omask);
12807c478bd9Sstevel@tonic-gate }
12817c478bd9Sstevel@tonic-gate
12827c478bd9Sstevel@tonic-gate return (pid);
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate
12856c02b4a4Smuffin void
okpcntl(void)12866c02b4a4Smuffin okpcntl(void)
12877c478bd9Sstevel@tonic-gate {
12887c478bd9Sstevel@tonic-gate #ifdef TRACE
12897c478bd9Sstevel@tonic-gate tprintf("TRACE- okpcntl()\n");
12907c478bd9Sstevel@tonic-gate #endif
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate if (tpgrp == -1)
12937c478bd9Sstevel@tonic-gate error("No job control in this shell");
12947c478bd9Sstevel@tonic-gate if (tpgrp == 0)
12957c478bd9Sstevel@tonic-gate error("No job control in subshells");
12967c478bd9Sstevel@tonic-gate }
12972b51d29aSmg
12982b51d29aSmg void
hupforegnd(void)12992b51d29aSmg hupforegnd(void)
13002b51d29aSmg {
13012b51d29aSmg struct process *pp;
13022b51d29aSmg int omask;
13032b51d29aSmg
13042b51d29aSmg omask = sigblock(sigmask(SIGCHLD));
13052b51d29aSmg for (pp = (&proclist)->p_next; pp != PNULL; pp = pp->p_next)
13062b51d29aSmg if (pp->p_pid > 0) {
13072b51d29aSmg if (pp->p_flags & PFOREGND)
13082b51d29aSmg (void) kill(pp->p_pid, SIGHUP);
13092b51d29aSmg }
13102b51d29aSmg (void) sigsetmask(omask);
13112b51d29aSmg }
1312