diff options
Diffstat (limited to 'bin/sh/jobs.c')
-rw-r--r-- | bin/sh/jobs.c | 159 |
1 files changed, 101 insertions, 58 deletions
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 93553c1..765e6a2 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -118,6 +118,24 @@ static void showjob(struct job *, int); static int jobctl; #if JOBS +static void +jobctl_notty(void) +{ + if (ttyfd >= 0) { + close(ttyfd); + ttyfd = -1; + } + if (!iflag) { + setsignal(SIGTSTP); + setsignal(SIGTTOU); + setsignal(SIGTTIN); + jobctl = 1; + return; + } + out2fmt_flush("sh: can't access tty; job control turned off\n"); + mflag = 0; +} + void setjobctl(int on) { @@ -133,8 +151,10 @@ setjobctl(int on) while (i <= 2 && !isatty(i)) i++; if (i > 2 || - (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) - goto out; + (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) { + jobctl_notty(); + return; + } } if (ttyfd < 10) { /* @@ -142,9 +162,8 @@ setjobctl(int on) * the user's redirections. */ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) { - close(ttyfd); - ttyfd = -1; - goto out; + jobctl_notty(); + return; } close(ttyfd); ttyfd = i; @@ -152,11 +171,15 @@ setjobctl(int on) do { /* while we are in the background */ initialpgrp = tcgetpgrp(ttyfd); if (initialpgrp < 0) { -out: out2fmt_flush("sh: can't access tty; job control turned off\n"); - mflag = 0; + jobctl_notty(); return; } if (initialpgrp != getpgrp()) { + if (!iflag) { + initialpgrp = -1; + jobctl_notty(); + return; + } kill(0, SIGTTIN); continue; } @@ -168,9 +191,11 @@ out: out2fmt_flush("sh: can't access tty; job control turned off\n"); tcsetpgrp(ttyfd, rootpid); } else { /* turning job control off */ setpgid(0, initialpgrp); - tcsetpgrp(ttyfd, initialpgrp); - close(ttyfd); - ttyfd = -1; + if (ttyfd >= 0) { + tcsetpgrp(ttyfd, initialpgrp); + close(ttyfd); + ttyfd = -1; + } setsignal(SIGTSTP); setsignal(SIGTTOU); setsignal(SIGTTIN); @@ -195,7 +220,8 @@ fgcmd(int argc __unused, char **argv __unused) printjobcmd(jp); flushout(&output); pgrp = jp->ps[0].pid; - tcsetpgrp(ttyfd, pgrp); + if (ttyfd >= 0) + tcsetpgrp(ttyfd, pgrp); restartjob(jp); jp->foreground = 1; INTOFF; @@ -347,13 +373,13 @@ showjob(struct job *jp, int mode) strcat(statestr, " (core dumped)"); } - for (ps = jp->ps ; ; ps++) { /* for each process */ + for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */ if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) { out1fmt("%d\n", (int)ps->pid); - goto skip; + continue; } if (mode != SHOWJOBS_VERBOSE && ps != jp->ps) - goto skip; + continue; if (jobno == curr && ps == jp->ps) c = '+'; else if (jobno == prev && ps == jp->ps) @@ -384,8 +410,6 @@ showjob(struct job *jp, int mode) out1c('\n'); } else printjobcmd(jp); -skip: if (--procno <= 0) - break; } } @@ -568,23 +592,23 @@ getjob_nonotfound(const char *name) if (name == NULL) { #if JOBS -currentjob: if ((jp = getcurjob(NULL)) == NULL) - error("No current job"); - return (jp); + name = "%+"; #else error("No current job"); #endif - } else if (name[0] == '%') { + } + if (name[0] == '%') { if (is_digit(name[1])) { jobno = number(name + 1); if (jobno > 0 && jobno <= njobs && jobtab[jobno - 1].used != 0) return &jobtab[jobno - 1]; #if JOBS - } else if (name[1] == '%' && name[2] == '\0') { - goto currentjob; - } else if (name[1] == '+' && name[2] == '\0') { - goto currentjob; + } else if ((name[1] == '%' || name[1] == '+') && + name[2] == '\0') { + if ((jp = getcurjob(NULL)) == NULL) + error("No current job"); + return (jp); } else if (name[1] == '-' && name[2] == '\0') { if ((jp = getcurjob(NULL)) == NULL || (jp = getcurjob(jp)) == NULL) @@ -847,7 +871,8 @@ forkshell(struct job *jp, union node *n, int mode) pgrp = getpid(); else pgrp = jp->ps[0].pid; - if (setpgid(0, pgrp) == 0 && mode == FORK_FG) { + if (setpgid(0, pgrp) == 0 && mode == FORK_FG && + ttyfd >= 0) { /*** this causes superfluous TIOCSPGRPS ***/ if (tcsetpgrp(ttyfd, pgrp) < 0) error("tcsetpgrp failed, errno=%d", errno); @@ -1007,7 +1032,7 @@ waitforjob(struct job *jp, int *origstatus) dotrap(); #if JOBS if (jp->jobctl) { - if (tcsetpgrp(ttyfd, rootpid) < 0) + if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0) error("tcsetpgrp failed, errno=%d\n", errno); } if (jp->state == JOBSTOPPED) @@ -1263,13 +1288,43 @@ commandtext(union node *n) static void +cmdtxtdogroup(union node *n) +{ + cmdputs("; do "); + cmdtxt(n); + cmdputs("; done"); +} + + +static void +cmdtxtredir(union node *n, const char *op, int deffd) +{ + char s[2]; + + if (n->nfile.fd != deffd) { + s[0] = n->nfile.fd + '0'; + s[1] = '\0'; + cmdputs(s); + } + cmdputs(op); + if (n->type == NTOFD || n->type == NFROMFD) { + if (n->ndup.dupfd >= 0) + s[0] = n->ndup.dupfd + '0'; + else + s[0] = '-'; + s[1] = '\0'; + cmdputs(s); + } else { + cmdtxt(n->nfile.fname); + } +} + + +static void cmdtxt(union node *n) { union node *np; struct nodelist *lp; - const char *p; - int i; - char s[2]; if (n == NULL) return; @@ -1314,14 +1369,13 @@ cmdtxt(union node *n) break; case NWHILE: cmdputs("while "); - goto until; + cmdtxt(n->nbinary.ch1); + cmdtxtdogroup(n->nbinary.ch2); + break; case NUNTIL: cmdputs("until "); -until: cmdtxt(n->nbinary.ch1); - cmdputs("; do "); - cmdtxt(n->nbinary.ch2); - cmdputs("; done"); + cmdtxtdogroup(n->nbinary.ch2); break; case NFOR: cmdputs("for "); @@ -1356,36 +1410,25 @@ until: cmdputs(n->narg.text); break; case NTO: - p = ">"; i = 1; goto redir; + cmdtxtredir(n, ">", 1); + break; case NAPPEND: - p = ">>"; i = 1; goto redir; + cmdtxtredir(n, ">>", 1); + break; case NTOFD: - p = ">&"; i = 1; goto redir; + cmdtxtredir(n, ">&", 1); + break; case NCLOBBER: - p = ">|"; i = 1; goto redir; + cmdtxtredir(n, ">|", 1); + break; case NFROM: - p = "<"; i = 0; goto redir; + cmdtxtredir(n, "<", 0); + break; case NFROMTO: - p = "<>"; i = 0; goto redir; + cmdtxtredir(n, "<>", 0); + break; case NFROMFD: - p = "<&"; i = 0; goto redir; -redir: - if (n->nfile.fd != i) { - s[0] = n->nfile.fd + '0'; - s[1] = '\0'; - cmdputs(s); - } - cmdputs(p); - if (n->type == NTOFD || n->type == NFROMFD) { - if (n->ndup.dupfd >= 0) - s[0] = n->ndup.dupfd + '0'; - else - s[0] = '-'; - s[1] = '\0'; - cmdputs(s); - } else { - cmdtxt(n->nfile.fname); - } + cmdtxtredir(n, "<&", 0); break; case NHERE: case NXHERE: |