summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/exec.c87
-rw-r--r--Src/jobs.c77
-rw-r--r--Src/signals.c5
-rw-r--r--Src/utils.c8
-rw-r--r--Src/zsh.h1
5 files changed, 123 insertions, 55 deletions
diff --git a/Src/exec.c b/Src/exec.c
index 289c7b1fd..bcd0e93bb 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -318,7 +318,7 @@ execcursh(Estate state, int do_exec)
{
Wordcode end = state->pc + WC_CURSH_SKIP(state->pc[-1]);
- if (!list_pipe && thisjob != list_pipe_job)
+ if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob))
deletejob(jobtab + thisjob);
cmdpush(CS_CURSH);
execlist(state, 1, do_exec);
@@ -1054,7 +1054,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
curjob = newjob;
DPUTS(!list_pipe_pid, "invalid list_pipe_pid");
- addproc(list_pipe_pid, list_pipe_text);
+ addproc(list_pipe_pid, list_pipe_text, 0);
/* If the super-job contains only the sub-shell, the
sub-shell is the group leader. */
@@ -1088,13 +1088,13 @@ execpline(Estate state, wordcode slcode, int how, int last1)
makerunning(jn);
}
if (!(jn->stat & STAT_LOCKED)) {
- updated = !!jobtab[thisjob].procs;
+ updated = hasprocs(thisjob);
waitjobs();
child_block();
} else
updated = 0;
if (!updated &&
- list_pipe_job && jobtab[list_pipe_job].procs &&
+ list_pipe_job && hasprocs(list_pipe_job) &&
!(jobtab[list_pipe_job].stat & STAT_STOPPED)) {
child_unblock();
child_block();
@@ -1143,7 +1143,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
jn->stat |= STAT_SUBJOB | STAT_NOPRINT;
jn->other = pid;
}
- if ((list_pipe || last1) && jobtab[list_pipe_job].procs)
+ if ((list_pipe || last1) && hasprocs(list_pipe_job))
killpg(jobtab[list_pipe_job].gleader, SIGSTOP);
break;
}
@@ -1251,7 +1251,7 @@ execpline2(Estate state, wordcode pcode,
char dummy, *text;
text = getjobtext(state->prog, state->pc);
- addproc(pid, text);
+ addproc(pid, text, 0);
close(synch[1]);
read(synch[0], &dummy, 1);
close(synch[0]);
@@ -1388,13 +1388,19 @@ closemn(struct multio **mfds, int fd)
struct multio *mn = mfds[fd];
char buf[TCBUFSIZE];
int len, i;
+ pid_t pid;
- if (zfork()) {
+ if ((pid = zfork())) {
for (i = 0; i < mn->ct; i++)
zclose(mn->fds[i]);
zclose(mn->pipe);
+ if (pid == -1) {
+ mfds[fd] = NULL;
+ return;
+ }
mn->ct = 1;
mn->fds[0] = fd;
+ addproc(pid, NULL, 1);
return;
}
/* pid == 0 */
@@ -2054,7 +2060,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
3 : WC_ASSIGN_NUM(ac) + 2);
}
}
- addproc(pid, text);
+ addproc(pid, text, 0);
opts[AUTOCONTINUE] = oautocont;
return;
}
@@ -2946,38 +2952,28 @@ getproc(char *cmd)
Eprog prog;
int out = *cmd == Inang;
char *pnam;
+ pid_t pid;
+
#ifndef PATH_DEV_FD
int fd;
-#else
- int pipes[2];
-#endif
if (thisjob == -1)
return NULL;
-#ifndef PATH_DEV_FD
if (!(pnam = namedpipe()))
return NULL;
-#else
- pnam = hcalloc(strlen(PATH_DEV_FD) + 6);
-#endif
if (!(prog = parsecmd(cmd)))
return NULL;
-#ifndef PATH_DEV_FD
if (!jobtab[thisjob].filelist)
jobtab[thisjob].filelist = znewlinklist();
zaddlinknode(jobtab[thisjob].filelist, ztrdup(pnam));
- if (zfork()) {
-#else
- mpipe(pipes);
- if (zfork()) {
- sprintf(pnam, "%s/%d", PATH_DEV_FD, pipes[!out]);
- zclose(pipes[out]);
- fdtable[pipes[!out]] = 2;
-#endif
+ if ((pid = zfork())) {
+ if (pid == -1)
+ return NULL;
+ if (!out)
+ addproc(pid, NULL, 1);
return pnam;
}
-#ifndef PATH_DEV_FD
closem(0);
fd = open(pnam, out ? O_WRONLY | O_NOCTTY : O_RDONLY | O_NOCTTY);
if (fd == -1) {
@@ -2986,11 +2982,37 @@ getproc(char *cmd)
}
entersubsh(Z_ASYNC, 1, 0, 0);
redup(fd, out);
-#else
+#else /* PATH_DEV_FD */
+ int pipes[2];
+
+ if (thisjob == -1)
+ return NULL;
+ pnam = hcalloc(strlen(PATH_DEV_FD) + 6);
+ if (!(prog = parsecmd(cmd)))
+ return NULL;
+ mpipe(pipes);
+ if ((pid = zfork())) {
+ sprintf(pnam, "%s/%d", PATH_DEV_FD, pipes[!out]);
+ zclose(pipes[out]);
+ if (pid == -1)
+ {
+ zclose(pipes[!out]);
+ return NULL;
+ }
+ fdtable[pipes[!out]] = 2;
+ if (!out)
+ {
+ addproc(pid, NULL, 1);
+ fprintf(stderr, "Proc %d added\n", pid);
+ fflush(stderr);
+ }
+ return pnam;
+ }
entersubsh(Z_ASYNC, 1, 0, 0);
redup(pipes[out], out);
closem(0); /* this closes pipes[!out] as well */
-#endif
+#endif /* PATH_DEV_FD */
+
cmdpush(CS_CMDSUBST);
execode(prog, 0, 1);
cmdpop();
@@ -3008,12 +3030,18 @@ getpipe(char *cmd)
{
Eprog prog;
int pipes[2], out = *cmd == Inang;
+ pid_t pid;
if (!(prog = parsecmd(cmd)))
return -1;
mpipe(pipes);
- if (zfork()) {
+ if ((pid = zfork())) {
zclose(pipes[out]);
+ if (pid == -1) {
+ zclose(pipes[!out]);
+ return -1;
+ }
+ addproc(pid, NULL, 1);
return pipes[!out];
}
entersubsh(Z_ASYNC, 1, 0, 0);
@@ -3226,13 +3254,14 @@ execshfunc(Shfunc shf, LinkList args)
if (errflag)
return;
- if (!list_pipe && thisjob != list_pipe_job) {
+ if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob)) {
/* Without this deletejob the process table *
* would be filled by a recursive function. */
last_file_list = jobtab[thisjob].filelist;
jobtab[thisjob].filelist = NULL;
deletejob(jobtab + thisjob);
}
+
if (isset(XTRACE)) {
LinkNode lptr;
printprompt4();
diff --git a/Src/jobs.c b/Src/jobs.c
index 359e1564e..c94f694ee 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -130,22 +130,36 @@ makerunning(Job jn)
/**/
int
-findproc(pid_t pid, Job *jptr, Process *pptr)
+findproc(pid_t pid, Job *jptr, Process *pptr, int aux)
{
Process pn;
int i;
for (i = 1; i < MAXJOB; i++)
- for (pn = jobtab[i].procs; pn; pn = pn->next)
+ {
+ for (pn = aux ? jobtab[i].auxprocs : jobtab[i].procs;
+ pn; pn = pn->next)
if (pn->pid == pid) {
*pptr = pn;
*jptr = jobtab + i;
return 1;
}
+ }
return 0;
}
+/* Does the given job number have any processes? */
+
+/**/
+int
+hasprocs(int job)
+{
+ Job jn = jobtab + job;
+
+ return jn->procs || jn->auxprocs;
+}
+
/* Find the super-job of a sub-job. */
/**/
@@ -168,7 +182,7 @@ handle_sub(int job, int fg)
{
Job jn = jobtab + job, sj = jobtab + jn->other;
- if ((sj->stat & STAT_DONE) || !sj->procs) {
+ if ((sj->stat & STAT_DONE) || (!sj->procs && !sj->auxprocs)) {
struct process *p;
for (p = sj->procs; p; p = p->next)
@@ -257,6 +271,10 @@ update_job(Job jn)
int val = 0, status = 0;
int somestopped = 0, inforeground = 0;
+ for (pn = jn->auxprocs; pn; pn = pn->next)
+ if (pn->status == SP_RUNNING)
+ return;
+
for (pn = jn->procs; pn; pn = pn->next) {
if (pn->status == SP_RUNNING) /* some processes in this job are running */
return; /* so no need to update job table entry */
@@ -806,6 +824,13 @@ freejob(Job jn, int deleting)
zfree(pn, sizeof(struct process));
}
+ pn = jn->auxprocs;
+ jn->auxprocs = NULL;
+ for (; pn; pn = nx) {
+ nx = pn->next;
+ zfree(pn, sizeof(struct process));
+ }
+
if (jn->ty)
zfree(jn->ty, sizeof(struct ttyinfo));
if (jn->pwd)
@@ -819,7 +844,6 @@ freejob(Job jn, int deleting)
}
jn->gleader = jn->other = 0;
jn->stat = jn->stty_in_env = 0;
- jn->procs = NULL;
jn->filelist = NULL;
jn->ty = NULL;
}
@@ -842,13 +866,19 @@ deletejob(Job jn)
freejob(jn, 1);
}
-/* add a process to the current job */
+/*
+ * Add a process to the current job.
+ * The third argument is 1 if we are adding a process which is not
+ * part of the main pipeline but an auxiliary process used for
+ * handling MULTIOS or process substitution. We will wait for it
+ * but not display job information about it.
+ */
/**/
void
-addproc(pid_t pid, char *text)
+addproc(pid_t pid, char *text, int aux)
{
- Process pn;
+ Process pn, *pnlist;
struct timezone dummy_tz;
pn = (Process) zcalloc(sizeof *pn);
@@ -857,25 +887,30 @@ addproc(pid_t pid, char *text)
strcpy(pn->text, text);
else
*pn->text = '\0';
- gettimeofday(&pn->bgtime, &dummy_tz);
pn->status = SP_RUNNING;
pn->next = NULL;
- /* if this is the first process we are adding to *
- * the job, then it's the group leader. */
- if (!jobtab[thisjob].gleader)
- jobtab[thisjob].gleader = pid;
+ if (!aux)
+ {
+ gettimeofday(&pn->bgtime, &dummy_tz);
+ /* if this is the first process we are adding to *
+ * the job, then it's the group leader. */
+ if (!jobtab[thisjob].gleader)
+ jobtab[thisjob].gleader = pid;
+ /* attach this process to end of process list of current job */
+ pnlist = &jobtab[thisjob].procs;
+ }
+ else
+ pnlist = &jobtab[thisjob].auxprocs;
- /* attach this process to end of process list of current job */
- if (jobtab[thisjob].procs) {
+ if (*pnlist) {
Process n;
- for (n = jobtab[thisjob].procs; n->next; n = n->next);
- pn->next = NULL;
+ for (n = *pnlist; n->next; n = n->next);
n->next = pn;
} else {
/* first process for this job */
- jobtab[thisjob].procs = pn;
+ *pnlist = pn;
}
/* If the first process in the job finished before any others were *
* added, maybe STAT_DONE got set incorrectly. This can happen if *
@@ -938,7 +973,7 @@ zwaitjob(int job, int sig)
dont_queue_signals();
child_block(); /* unblocked during child_suspend() */
- if (jn->procs) { /* if any forks were done */
+ if (jn->procs || jn->auxprocs) { /* if any forks were done */
jn->stat |= STAT_LOCKED;
if (jn->stat & STAT_CHANGED)
printjob(jn, !!isset(LONGLISTJOBS), 1);
@@ -978,7 +1013,7 @@ waitjobs(void)
{
Job jn = jobtab + thisjob;
- if (jn->procs)
+ if (jn->procs || jn->auxprocs)
zwaitjob(thisjob, 0);
else {
deletejob(jn);
@@ -1075,7 +1110,7 @@ spawnjob(void)
fflush(stderr);
}
}
- if (!jobtab[thisjob].procs)
+ if (!hasprocs(thisjob))
deletejob(jobtab + thisjob);
else
jobtab[thisjob].stat |= STAT_LOCKED;
@@ -1373,7 +1408,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
Job j;
Process p;
- if (findproc(pid, &j, &p))
+ if (findproc(pid, &j, &p, 0))
waitforpid(pid);
else
zwarnnam(name, "pid %d is not a child of this shell", 0, pid);
diff --git a/Src/signals.c b/Src/signals.c
index 8b1b9775c..86a5de748 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -487,9 +487,12 @@ zhandler(int sig)
}
/* Find the process and job containing this pid and update it. */
- if (findproc(pid, &jn, &pn)) {
+ if (findproc(pid, &jn, &pn, 0)) {
update_process(pn, status);
update_job(jn);
+ } else if (findproc(pid, &jn, &pn, 1)) {
+ pn->status = status;
+ update_job(jn);
} else {
/* If not found, update the shell record of time spent by
* children in sub processes anyway: otherwise, this
diff --git a/Src/utils.c b/Src/utils.c
index 5e9fbfb82..92d97bc5c 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -988,10 +988,10 @@ adjustwinsize(int from)
ttyrows = shttyinfo.winsize.ws_row;
ttycols = shttyinfo.winsize.ws_col;
} else {
- /* Set to unknown on failure */
- shttyinfo.winsize.ws_row = 0;
- shttyinfo.winsize.ws_col = 0;
- resetzle = 1;
+ /* Set to value from environment on failure */
+ shttyinfo.winsize.ws_row = lines;
+ shttyinfo.winsize.ws_col = columns;
+ resetzle = (from == 1);
}
#else
resetzle = from == 1;
diff --git a/Src/zsh.h b/Src/zsh.h
index bcde57bb4..033005dfc 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -697,6 +697,7 @@ struct job {
char *pwd; /* current working dir of shell when *
* this job was spawned */
struct process *procs; /* list of processes */
+ struct process *auxprocs; /* auxiliary processes e.g multios */
LinkList filelist; /* list of files to delete when done */
int stty_in_env; /* if STTY=... is present */
struct ttyinfo *ty; /* the modes specified by STTY */