Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Printjobs alternative patch



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 <pws@xxxxxx>       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.




Messages sorted by: Reverse Date, Date, Thread, Author