From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from euclid.skiles.gatech.edu (list@euclid.skiles.gatech.edu [130.207.146.50]) by melb.werple.net.au (8.7.5/8.7.3/2) with ESMTP id TAA05039 for ; Thu, 11 Jul 1996 19:33:04 +1000 (EST) Received: (from list@localhost) by euclid.skiles.gatech.edu (8.7.3/8.7.3) id FAA16772; Thu, 11 Jul 1996 05:08:32 -0400 (EDT) Resent-Date: Thu, 11 Jul 1996 05:08:32 -0400 (EDT) Message-Id: <199607110907.LAA02994@hydra.ifh.de> To: zsh-workers@math.gatech.edu (Zsh hackers list) Subject: Printjobs alternative patch In-reply-to: "pws@ifh.de"'s message of "Fri, 31 May 1996 14:07:50 MET." <199605311207.OAA13596@hydra.ifh.de> Date: Thu, 11 Jul 1996 11:07:29 +0200 From: Peter Stephenson Resent-Message-ID: <"9jJLx3.0.-54.FICvn"@euclid> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/1606 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu A few weeks ago I sent a one-line patch which would prevent printjobs() from unnecessarily trashing the terminal. The symptom was that a `jobs' executed inside a completion function (called with the compctl -K mechanism) unnecessarily redrew the terminal, because it didn't bother finding out where the output was going. I made the following patch, then had second thoughts because the previous patch would fix the vast majority of incorrect behaviour without introducing any incompatibilities. I suppose I might as well now submit the alternative patch with comments so other people can decide which is better. (If you don't make your own comments, Zoltan will simply decide on his own.) Just possibly the patch doesn't apply cleanly any more. I wrote: > A better fix would be to tell printjob() when it's being run > synchronously. That would also allow you a flag to print to stdout on > a genuine call to jobs, which would be more natural (and more > compatible). If that change is made, probably remaining printjob's > should go directly to the terminal output `shout', rather than stderr > which might be redirected. This all ought to be easy, I'm just > feeling a bit overpatched at the moment. I'm assuming that scanjobs() and waitjob[s]() are always called synchronously, so don't need to worry about the state of the terminal. No doubt someone will tell me if I'm wrong. I've also made "(pwd now:...)" information messages go to the shell terminal rather than whatever stdout happens to be. Incompatibility Warning: output from `jobs' now goes to stdout. Before it went to stderr. This is now compatible with ksh, but if you've got scripts with things like `jobs 2>jobfile' they'll need changing. (I always wrote `jobs >& jobfile' since I thought `some day, someone's going to fix this'.) You now can't redirect output from `fg' or `bg'. Would anybody ever want to? My philosophy was that they're purely informational messages which therefore go direct to the terminal. (You can't change where the output of the job you're operating on is going anyway.) An alternative approach would be to simplify the patch so that all synchronous output goes to stdout and asynchronous directly to the terminal. I suppose somebody might argue that if you're making a transcript of a session with stderr redirected to catch error messages, then you want everything to be redirectable. In that case, my previous patch will do (although `jobs' output should really still go to stdout). *** Src/builtin.c.sigzle Fri May 31 15:15:05 1996 --- Src/builtin.c Fri May 31 15:21:03 1996 *************** *** 537,543 **** (ops['r'] && ops['s']) || (ops['r'] && !(jobtab[job].stat & STAT_STOPPED)) || (ops['s'] && jobtab[job].stat & STAT_STOPPED)) ! printjob(job + jobtab, lng); } return 0; } else { /* Must be BIN_WAIT, so wait for all jobs */ --- 537,543 ---- (ops['r'] && ops['s']) || (ops['r'] && !(jobtab[job].stat & STAT_STOPPED)) || (ops['s'] && jobtab[job].stat & STAT_STOPPED)) ! printjob(job + jobtab, lng, 2); } return 0; } else { /* Must be BIN_WAIT, so wait for all jobs */ *************** *** 599,612 **** } if (func != BIN_WAIT) /* for bg and fg -- show the job we are operating on */ ! printjob(jobtab + job, (stopped) ? -1 : 0); if (func != BIN_BG) { /* fg or wait */ if (strcmp(jobtab[job].pwd, pwd)) { ! printf("(pwd : "); ! fprintdir(jobtab[job].pwd, stdout); ! printf(")\n"); } ! fflush(stdout); if (func != BIN_WAIT) { /* fg */ thisjob = job; attachtty(jobtab[job].gleader); --- 599,612 ---- } if (func != BIN_WAIT) /* for bg and fg -- show the job we are operating on */ ! printjob(jobtab + job, (stopped) ? -1 : 0, 1); if (func != BIN_BG) { /* fg or wait */ if (strcmp(jobtab[job].pwd, pwd)) { ! fprintf(shout, "(pwd : "); ! fprintdir(jobtab[job].pwd, shout); ! fprintf(shout, ")\n"); } ! fflush(shout); if (func != BIN_WAIT) { /* fg */ thisjob = job; attachtty(jobtab[job].gleader); *************** *** 625,631 **** } break; case BIN_JOBS: ! printjob(job + jobtab, lng); break; case BIN_DISOWN: { --- 625,631 ---- } break; case BIN_JOBS: ! printjob(job + jobtab, lng, 2); break; case BIN_DISOWN: { *** Src/exec.c.sigzle Fri May 31 15:16:42 1996 --- Src/exec.c Fri May 31 15:24:06 1996 *************** *** 652,658 **** jn->stat &= ~(STAT_DONE | STAT_NOPRINT); jn->stat |= STAT_STOPPED | STAT_CHANGED; ! printjob(jn, !!isset(LONGLISTJOBS)); } else deletejob(jn); --- 652,658 ---- jn->stat &= ~(STAT_DONE | STAT_NOPRINT); jn->stat |= STAT_STOPPED | STAT_CHANGED; ! printjob(jn, !!isset(LONGLISTJOBS), 1); } else deletejob(jn); *** Src/jobs.c.sigzle Mon May 6 16:08:58 1996 --- Src/jobs.c Fri May 31 15:24:53 1996 *************** *** 190,196 **** curjob = job; } if ((isset(NOTIFY) || job == thisjob) && (jn->stat & STAT_LOCKED)) { ! printjob(jn, !!isset(LONGLISTJOBS)); if (zleactive) refresh(); } --- 190,196 ---- curjob = job; } if ((isset(NOTIFY) || job == thisjob) && (jn->stat & STAT_LOCKED)) { ! printjob(jn, !!isset(LONGLISTJOBS), 0); if (zleactive) refresh(); } *************** *** 227,241 **** /* lng = 0 means jobs * * lng = 1 means jobs -l * ! * lng = 2 means jobs -p */ /**/ void ! printjob(Job jn, int lng) { Process pn; int job = jn - jobtab, len = 9, sig, sflag = 0, llen; int conted = 0, lineleng = columns, skip = 0, doputnl = 0; if (jn->stat & STAT_NOPRINT) return; --- 227,247 ---- /* lng = 0 means jobs * * lng = 1 means jobs -l * ! * lng = 2 means jobs -p ! * ! * synch = 0 means asynchronous ! * synch = 1 means synchronous ! * synch = 2 means called synchronously from jobs ! */ /**/ void ! printjob(Job jn, int lng, int synch) { Process pn; int job = jn - jobtab, len = 9, sig, sflag = 0, llen; int conted = 0, lineleng = columns, skip = 0, doputnl = 0; + FILE *fout = (synch == 2) ? stdout : shout; if (jn->stat & STAT_NOPRINT) return; *************** *** 285,293 **** int len2, fline = 1; Process qn; ! trashzle(); ! if (doputnl) ! putc('\n', stderr); for (pn = jn->procs; pn;) { len2 = ((job == thisjob) ? 5 : 10) + len; /* 2 spaces */ if (lng) --- 291,300 ---- int len2, fline = 1; Process qn; ! if (!synch) ! trashzle(); ! if (doputnl && !synch) ! putc('\n', fout); for (pn = jn->procs; pn;) { len2 = ((job == thisjob) ? 5 : 10) + len; /* 2 spaces */ if (lng) *************** *** 302,364 **** } if (job != thisjob) if (fline) ! fprintf(stderr, "[%ld] %c ", (long)(jn - jobtab), (job == curjob) ? '+' : (job == prevjob) ? '-' : ' '); else ! fprintf(stderr, (job > 9) ? " " : " "); else ! fprintf(stderr, "zsh: "); if (lng) if (lng == 1) ! fprintf(stderr, "%ld ", (long) pn->pid); else { pid_t x = jn->gleader; ! fprintf(stderr, "%ld ", (long) x); do skip++; while ((x /= 10)); skip++; lng = 0; } else ! fprintf(stderr, "%*s", skip, ""); if (pn->status == SP_RUNNING) if (!conted) ! fprintf(stderr, "running%*s", len - 7 + 2, ""); else ! fprintf(stderr, "continued%*s", len - 9 + 2, ""); else if (WIFEXITED(pn->status)) if (WEXITSTATUS(pn->status)) ! fprintf(stderr, "exit %-4d%*s", WEXITSTATUS(pn->status), len - 9 + 2, ""); else ! fprintf(stderr, "done%*s", len - 4 + 2, ""); else if (WIFSTOPPED(pn->status)) ! fprintf(stderr, "%-*s", len + 2, sigmsg[WSTOPSIG(pn->status)]); else if (WCOREDUMP(pn->status)) ! fprintf(stderr, "%s (core dumped)%*s", sigmsg[WTERMSIG(pn->status)], (int)(len - 14 + 2 - strlen(sigmsg[WTERMSIG(pn->status)])), ""); else ! fprintf(stderr, "%-*s", len + 2, sigmsg[WTERMSIG(pn->status)]); for (; pn != qn; pn = pn->next) ! fprintf(stderr, (pn->next) ? "%s | " : "%s", pn->text); ! putc('\n', stderr); fline = 0; } ! } else if (doputnl && interact) ! putc('\n', stderr); ! fflush(stderr); /* print "(pwd now: foo)" messages */ if (interact && job == thisjob && strcmp(jn->pwd, pwd)) { ! printf("(pwd now: "); ! fprintdir(pwd, stdout); ! printf(")\n"); ! fflush(stdout); } /* delete job if done */ --- 309,371 ---- } if (job != thisjob) if (fline) ! fprintf(fout, "[%ld] %c ", (long)(jn - jobtab), (job == curjob) ? '+' : (job == prevjob) ? '-' : ' '); else ! fprintf(fout, (job > 9) ? " " : " "); else ! fprintf(fout, "zsh: "); if (lng) if (lng == 1) ! fprintf(fout, "%ld ", (long) pn->pid); else { pid_t x = jn->gleader; ! fprintf(fout, "%ld ", (long) x); do skip++; while ((x /= 10)); skip++; lng = 0; } else ! fprintf(fout, "%*s", skip, ""); if (pn->status == SP_RUNNING) if (!conted) ! fprintf(fout, "running%*s", len - 7 + 2, ""); else ! fprintf(fout, "continued%*s", len - 9 + 2, ""); else if (WIFEXITED(pn->status)) if (WEXITSTATUS(pn->status)) ! fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status), len - 9 + 2, ""); else ! fprintf(fout, "done%*s", len - 4 + 2, ""); else if (WIFSTOPPED(pn->status)) ! fprintf(fout, "%-*s", len + 2, sigmsg[WSTOPSIG(pn->status)]); else if (WCOREDUMP(pn->status)) ! fprintf(fout, "%s (core dumped)%*s", sigmsg[WTERMSIG(pn->status)], (int)(len - 14 + 2 - strlen(sigmsg[WTERMSIG(pn->status)])), ""); else ! fprintf(fout, "%-*s", len + 2, sigmsg[WTERMSIG(pn->status)]); for (; pn != qn; pn = pn->next) ! fprintf(fout, (pn->next) ? "%s | " : "%s", pn->text); ! putc('\n', fout); fline = 0; } ! } else if (doputnl && interact && !synch) ! putc('\n', fout); ! fflush(fout); /* print "(pwd now: foo)" messages */ if (interact && job == thisjob && strcmp(jn->pwd, pwd)) { ! fprintf(shout, "(pwd now: "); ! fprintdir(pwd, shout); ! fprintf(shout, ")\n"); ! fflush(shout); } /* delete job if done */ *************** *** 513,519 **** if (jn->procs) { /* if any forks were done */ jn->stat |= STAT_LOCKED; if (jn->stat & STAT_CHANGED) ! printjob(jn, !!isset(LONGLISTJOBS)); while (!errflag && jn->stat && !(jn->stat & STAT_DONE) && !(interact && (jn->stat & STAT_STOPPED))) { --- 520,526 ---- if (jn->procs) { /* if any forks were done */ jn->stat |= STAT_LOCKED; if (jn->stat & STAT_CHANGED) ! printjob(jn, !!isset(LONGLISTJOBS), 1); while (!errflag && jn->stat && !(jn->stat & STAT_DONE) && !(interact && (jn->stat & STAT_STOPPED))) { *************** *** 550,556 **** for (p = jn->procs; p; p = p->next) p->status = sj->procs->status; curjob = jn - jobtab; ! printjob(jn, !!isset(LONGLISTJOBS)); break; } } --- 557,563 ---- for (p = jn->procs; p; p = p->next) p->status = sj->procs->status; curjob = jn - jobtab; ! printjob(jn, !!isset(LONGLISTJOBS), 1); break; } } *************** *** 823,829 **** for (i = 1; i < MAXJOB; i++) if (jobtab[i].stat & STAT_CHANGED) ! printjob(jobtab + i, 0); } /* check to see if user has jobs running/stopped */ --- 830,836 ---- for (i = 1; i < MAXJOB; i++) if (jobtab[i].stat & STAT_CHANGED) ! printjob(jobtab + i, 0, 1); } /* check to see if user has jobs running/stopped */ -- Peter Stephenson Tel: +49 33762 77366 WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77330 Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen DESY-IfH, 15735 Zeuthen, Germany.