From: alsaggaf@athena.mit.edu (M. Saggaf)
Subject: Re: Graphic Zmodem (Was: How to make curses write to stderr?)
Organization: Massachusetts Institute of Technology
Date: Fri, 2 Oct 1992 20:55:28 GMT

OK, several people have contacted me regarding the patches. I sent the
patches to a few people by mail, but I can no longer do that since I
received more requests that I thought I would get. Hence, I'm posting the
patches here for eveybody's benefit. If you sent me mail and didn't
hear from me, I hope you will find your reading of this post to be
sufficient.


Please do the following:
1) Patch the stock zmodem sources with included patches.
   (check oak.oakland.edu pub/unix-c/xyzmodem)
2) define MODEM at the top of the makefile.
3) Compile with the command 'make rz'.
4) Use it as follows:
	* in the shell (bash, tcsh ..etc) type 'rz -vv'.
	* in xcomm type '! rz -vv'.
	* in minicom do Ctl-A J, then 'rz -vv' in the shell.
	(i.e. no redirection of stdio)
5) If you like it, let me know.

Note: this is for rz only, not sz (i.e. receiving only).

                                        -- Muhammad


---------- One Graphical Zmodem Coming Up .... ----------
diff -cNr czmodem/Makefile zmodem/Makefile
*** czmodem/Makefile	Sun Dec 15 15:35:56 1991
--- zmodem/Makefile	Fri Oct  2 14:08:36 1992
***************
*** 1,7 ****
  # Makefile for Unix/Xenix rz and sz programs
  # the makefile is not too well tested yet
! CC=cc
! OFLAG= -O
  
  
  ARCFILES= README rbsb.c gz *.t minirb.c zmodem.h \
--- 1,7 ----
  # Makefile for Unix/Xenix rz and sz programs
  # the makefile is not too well tested yet
! CC=gcc
! OFLAG= -O6 -w -DHVM -DMODEM=\"/dev/ttys1\"
  
  
  ARCFILES= README rbsb.c gz *.t minirb.c zmodem.h \
***************
*** 88,133 ****
  
  .PRECIOUS:rz sz
  
! xenix:
! 	$(CC) $(CFLAGS) $(OFLAG) -M0 -K -i -DTXBSIZE=16384 -DNFGVMIN -DREADCHECK sz.c -lx -o sz
! 	size sz
! 	-ln sz sb
! 	-ln sz sx
! 	-ln sz zcommand
! 	-ln sz zcommandi
! 	$(CC) $(CFLAGS) $(OFLAG) -M0 -K -i -DMD rz.c -o rz
! 	size rz
! 	-ln rz rb
! 	-ln rz rx
! 	-ln rz rc
! 
! x386:
! 	$(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! 	size rz
! 	-ln rz rb
! 	-ln rz rx
! 	$(CC) $(CFLAGS) $(OFLAG) -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -lx -o sz
! 	size sz
! 	-ln sz sb
! 	-ln sz sx
! 	-ln sz zcommand
! 	-ln sz zcommandi
! 
! sysv:
! 	$(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! 	size rz
! 	-ln rz rb
! 	-ln rz rx
! 	-ln rz rc
! 	$(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN sz.c -o sz
! 	size sz
! 	-ln sz sb
! 	-ln sz sx
! 	-ln sz zcommand
! 	-ln sz zcommandi
! 
! sysvr3:
! 	$(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
  	size rz
  	-ln rz rb
  	-ln rz rx
--- 88,94 ----
  
  .PRECIOUS:rz sz
  
! sysvr3: rz
  	size rz
  	-ln rz rb
  	-ln rz rx
***************
*** 139,224 ****
  	-ln sz zcommand
  	-ln sz zcommandi
  
- sysvr4:
- 	$(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
- 	size rz
- 	-ln rz rb
- 	-ln rz rx
- 	-ln rz rc
- 	$(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 sz.c -o sz
- 	size sz
- 	-ln sz sb
- 	-ln sz sx
- 	-ln sz zcommand
- 	-ln sz zcommandi
- 
- odt:
- 	cc -Za -n -DMD=2 rz.c -o rz
- 	size rz
- 	-ln rz rb
- 	-ln rz rx
- 	-ln rz rc
- 	cc -Za -n -DSV -DTXBSIZE=32768 sz.c -o sz
- 	size sz
- 	-ln sz sb
- 	-ln sz sx
- 	-ln sz zcommand
- 	-ln sz zcommandi
- 
- bsd:
- 	$(CC) $(CFLAGS) $(OFLAG) -DMD=2 -Dstrchr=index -DV7 rz.c -o rz
- 	size rz
- 	-ln rz rb
- 	-ln rz rx
- 	-ln rz rc
- 	$(CC) $(CFLAGS) $(OFLAG) -DV7 -DTXBSIZE=32768 -DNFGVMIN sz.c -o sz
- 	size sz
- 	-ln sz sb
- 	-ln sz sx
- 	-ln sz zcommand
- 	-ln sz zcommandi
- 
- tandy:
- 	$(CC) $(CFLAGS) $(OFLAGS) -n -DMD -DT6K sz.c -lx -o sz
- 	size sz
- 	-ln sz sb
- 	-ln sz sx
- 	-ln sz zcommand
- 	-ln sz zcommandi
- 	$(CC) $(CFLAGS) $(OFLAGS) -n -DMD -DT6K rz.c -lx -o rz
- 	size rz
- 	-ln rz rb
- 	-ln rz rx
- 	-ln rz rc
  
! dnix:
! 	$(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! 	size rz
! 	-ln rz rb
! 	-ln rz rx
! 	-ln rz rc
! 	$(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -o sz
! 	size sz
! 	-ln sz sb
! 	-ln sz sx
! 	-ln sz zcommand
! 	-ln sz zcommandi
  
! dnix5r3:
! 	$(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
! 	size rz
! 	-ln rz rb
! 	-ln rz rx
! 	-ln rz rc
! 	$(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -o sz
! 	size sz
! 	-ln sz sb
! 	-ln sz sx
! 	-ln sz zcommand
! 	-ln sz zcommandi
  
  
  sz: nothing
  sb: nothing
- rz: nothing
  rb: nothing
--- 100,117 ----
  	-ln sz zcommand
  	-ln sz zcommandi
  
  
! rz: rz.o show_info.o
! 	$(CC) $(CFLAGS) $(OFLAG) -o rz rz.o show_info.o -lcurses -ltermcap
! #	install -c -s rz /usr/bin
  
! rz.o: rz.c rbsb.c
! 	$(CC) $(CFLAGS) $(OFLAG) -DDSZ -DMD=2 -c rz.c
  
+ show_info.o: show_info.c
+ 	$(CC) $(CFLAGS) $(OFLAG) -c show_info.c
  
  sz: nothing
  sb: nothing
  rb: nothing
+ 
diff -cNr czmodem/rbsb.c zmodem/rbsb.c
*** czmodem/rbsb.c	Wed Oct 30 19:59:16 1991
--- zmodem/rbsb.c	Thu Oct  1 17:23:21 1992
***************
*** 336,345 ****
  /* Initialize tty device for serial file xfer */
  inittty()
  {
! 	Tty = open("/dev/tty", 2);
  	if (Tty < 0) {
! 		perror("/dev/tty");  exit(2);
  	}
  	Ttystream = fdopen(Tty, "w");
  	setbuf(Ttystream, xXbuf);		
  }
--- 336,349 ----
  /* Initialize tty device for serial file xfer */
  inittty()
  {
! #ifdef HVM
! 	Tty = open(MODEM, 2);
  	if (Tty < 0) {
! 		perror(MODEM);  exit(2);
  	}
+ #else
+ 	Tty = 1;
+ #endif
  	Ttystream = fdopen(Tty, "w");
  	setbuf(Ttystream, xXbuf);		
  }
***************
*** 387,393 ****
  #endif
  		Lleft = 0;
  		if (Verbose>1)
! 			fprintf(stderr, "Readline:TIMEOUT\n");
  		return TIMEOUT;
  	}
  	signal(SIGALRM, alrm); alarm(n);
--- 391,397 ----
  #endif
  		Lleft = 0;
  		if (Verbose>1)
! 			zmessage("Readline:TIMEOUT");
  		return TIMEOUT;
  	}
  	signal(SIGALRM, alrm); alarm(n);
diff -cNr czmodem/rz.c zmodem/rz.c
*** czmodem/rz.c	Wed Oct 30 19:57:48 1991
--- zmodem/rz.c	Fri Oct  2 13:37:12 1992
***************
*** 63,72 ****
  
  
  #define LOGFILE "/tmp/rzlog"
! #include <stdio.h>
  #include <signal.h>
  #include <ctype.h>
  #include <errno.h>
  extern int errno;
  FILE *popen();
  
--- 63,73 ----
  
  
  #define LOGFILE "/tmp/rzlog"
! #include <curses.h>
  #include <signal.h>
  #include <ctype.h>
  #include <errno.h>
+ #include <sys/times.h>
  extern int errno;
  FILE *popen();
  
***************
*** 133,143 ****
--- 134,152 ----
  int errors;
  int Restricted=0;	/* restricted; no /.. or ../ in filenames */
  
+ #define TDIS 30
+ long btime, ttime;
+ char sdummy[80];
+ struct tms tdummy;
+ WINDOW *win, *bwin;
+ char version[15]="version 0.2";
+ 
  #define DEFBYTL 2000000000L	/* default rx file size */
  long Bytesleft;		/* number of bytes of incoming file left */
  long Modtime;		/* Unix style mod time for incoming file */
  int Filemode;		/* Unix style mode for incoming file */
  long Totalleft;
+ long GTotalleft = 0;
  long Filesleft;
  char Pathname[PATHLEN];
  char *Progname;		/* the name by which we were called */
***************
*** 172,178 ****
  
  int tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
  
- 
  /* called by signal interrupt or terminate to clean things up */
  bibi(n)
  {
--- 181,186 ----
***************
*** 246,257 ****
  	if (Batch && npats)
  		usage();
  	if (Verbose) {
  		if (freopen(LOGFILE, "a", stderr)==NULL) {
  			printf("Can't open log file %s\n",LOGFILE);
  			exit(2);
  		}
  		setbuf(stderr, NULL);
! 		fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
  	}
  	vfile("%s %s for %s\n", Progname, VERSION, OS);
  	mode(1);
--- 254,276 ----
  	if (Batch && npats)
  		usage();
  	if (Verbose) {
+ #ifndef HVM
  		if (freopen(LOGFILE, "a", stderr)==NULL) {
  			printf("Can't open log file %s\n",LOGFILE);
  			exit(2);
  		}
+ #endif
  		setbuf(stderr, NULL);
! 
! 		initscr();
! 		win = newwin(18, 54, 4, 12);
! 		bwin = newwin(18, 55, 4, 12);
! 		leaveok(win, FALSE);
! /*		cbreak();*/
! 		noecho();
! 		nonl();
! 
! 		mvwprintw(win, 13, 10, "argv[0]=%s Progname=%s\n", virgin, Progname);
  	}
  	vfile("%s %s for %s\n", Progname, VERSION, OS);
  	mode(1);
***************
*** 271,278 ****
  		canit();
  	if (endmsg[0])
  		printf("  %s: %s\r\n", Progname, endmsg);
! 	printf("%s %s finished.\r\n", Progname, VERSION);
  	fflush(stdout);
  	exit(exitcode != 0);
  }
  
--- 290,301 ----
  		canit();
  	if (endmsg[0])
  		printf("  %s: %s\r\n", Progname, endmsg);
! 	zmessage("Transfer complete");
  	fflush(stdout);
+ 	wrefresh(win);
+ 	move(1, 1);
+ 	refresh();
+ 	endwin();
  	exit(exitcode != 0);
  }
  
***************
*** 311,317 ****
  
  	if (Batch || argc==0) {
  		Crcflg=1;
! 		fprintf(stderr, rbmsg, Progname, Nozmodem?"sb":"sz");
  		if (c=tryz()) {
  			if (c == ZCOMPL)
  				return OK;
--- 334,341 ----
  
  	if (Batch || argc==0) {
  		Crcflg=1;
! 		sprintf(sdummy, rbmsg, Progname, Nozmodem?"sb":"sz");
! 		zmessage(sdummy);
  		if (c=tryz()) {
  			if (c == ZCOMPL)
  				return OK;
***************
*** 574,586 ****
  		sscanf(p, "%ld%lo%o%lo%d%ld%d%d",
  		  &Bytesleft, &Modtime, &Filemode,
  		  &dummy, &Filesleft, &Totalleft, &dummy, &dummy);
  		if (Filemode & UNIXFILE)
  			++Thisbinary;
- 		if (Verbose) {
- 			fprintf(stderr,  "Incoming: %s %ld %lo %o\n",
- 			  name, Bytesleft, Modtime, Filemode);
- 			fprintf(stderr,  "YMODEM header: %s\n", p);
- 		}
  	}
  
  
--- 598,607 ----
  		sscanf(p, "%ld%lo%o%lo%d%ld%d%d",
  		  &Bytesleft, &Modtime, &Filemode,
  		  &dummy, &Filesleft, &Totalleft, &dummy, &dummy);
+ 		if (GTotalleft < Totalleft)
+ 		  GTotalleft = Totalleft;
  		if (Filemode & UNIXFILE)
  			++Thisbinary;
  	}
  
  
***************
*** 811,821 ****
  zperr(s,p,u)
  char *s, *p, *u;
  {
  	if (Verbose <= 0)
  		return;
! 	fprintf(stderr, "Retry %d: ", errors);
! 	fprintf(stderr, s, p, u);
! 	fprintf(stderr, "\n");
  }
  
  report(sct)
--- 832,845 ----
  zperr(s,p,u)
  char *s, *p, *u;
  {
+   char sdummy2[80];
+   
  	if (Verbose <= 0)
  		return;
!   sprintf(sdummy, "Retry %d: ", errors);
!   sprintf(sdummy2, s, p, u);
!   strcat(sdummy, sdummy2);
!   zmessage(sdummy);
  }
  
  report(sct)
***************
*** 988,993 ****
--- 1012,1019 ----
  {
  	register c;
  
+ 	ttime = times(&tdummy);
+ 
  	for (;;) {
  		switch (c = rzfile()) {
  		case ZEOF:
***************
*** 1016,1029 ****
--- 1042,1099 ----
  rzfile()
  {
  	register c, n;
+ 	char Fname[40];
  
  	Eofseen=FALSE;
  	n = 20; rxbytes = 0l;
  
+ 	btime = times(&tdummy);
+ 
+ 	wclear(win);
+ /*	box(bwin, '|', '-');*/
+ 	box(bwin, '.', '.');
+ 	zmessage("Waiting for file");	
+ 	wrefresh(win);
+ 	wrefresh(bwin);
+ 
  	if (c = procheader(secbuf)) {
  		return (tryzhdrtype = c);
  	}
  
+ 	if (strlen(secbuf) > 14) {
+ 	  strncpy(Fname, secbuf, 11);
+ 	  Fname[11] = NULL;
+ 	  strcat(Fname, "...");
+ 	}
+ 	else
+ 	  strcpy(Fname, secbuf);
+ 
+ 	mvwprintw(win, 1, 2, "This File: %s", Fname);
+ 	mvwaddstr(win, 2, 4, "Received:");
+ 	mvwprintw(win, 3, 4, "Expected: %dk", Bytesleft/1024);
+ 	mvwaddstr(win, 4, 4, "Percent :");
+ 	mvwaddstr(win, 5, 4, "T. Elpsd:");
+ 	mvwaddstr(win, 6, 4, "T. Left :");
+ 	mvwaddstr(win, 7, 4, "Thruput :");
+ 	mvwaddstr(win, 16, 2, "Messages:");
+ 
+ 	mvwprintw(win, 1, TDIS+2, "Total: %d files left", Filesleft);
+ 	mvwaddstr(win, 2, TDIS+4, "Received:");
+ 	mvwprintw(win, 3, TDIS+4, "Expected: %dk", GTotalleft/1024);
+ 	mvwaddstr(win, 4, TDIS+4, "Percent :");
+ 	mvwaddstr(win, 5, TDIS+4, "T. Elpsd:");
+ 	mvwaddstr(win, 6, TDIS+4, "T. Left :");
+ 	mvwaddstr(win, 7, TDIS+4, "Thruput :");
+ 	
+ 	mvwaddstr(win, 9, 2, "This File:");
+ 	mvwaddstr(win, 10, 2, "+-----------+------------+------------+-----------+");
+ 	mvwaddstr(win, 11, 2, "0%         25%          50%          75%       100%");
+ 	mvwaddstr(win, 12, 2, "Total:");
+ 	mvwaddstr(win, 13, 2, "+-----------+------------+------------+-----------+");
+ 	mvwaddstr(win, 14, 2, "0%         25%          50%          75%       100%");
+ 	wmove(win, 1, 1);
+ 	wrefresh(win);
+ 
  	for (;;) {
  #ifdef SEGMENTS
  		chinseg = 0;
***************
*** 1120,1127 ****
  			}
  moredata:
  			if (Verbose>1)
! 				fprintf(stderr, "\r%7ld ZMODEM%s    ",
! 				  rxbytes, Crc32r?" CRC-32":"");
  #ifdef SEGMENTS
  			if (chinseg >= (1024 * SEGMENTS)) {
  				putsec(secbuf, chinseg);
--- 1190,1197 ----
  			}
  moredata:
  			if (Verbose>1)
! 			  show_info();
! 
  #ifdef SEGMENTS
  			if (chinseg >= (1024 * SEGMENTS)) {
  				putsec(secbuf, chinseg);
diff -cNr czmodem/show_info.c zmodem/show_info.c
*** czmodem/show_info.c
--- zmodem/show_info.c	Fri Oct  2 11:20:14 1992
***************
*** 0 ****
--- 1,72 ----
+ #include <curses.h>
+ #include <sys/times.h>
+ 
+ extern int Crc32r;
+ extern long rxbytes, Bytesleft, Filesleft, Totalleft, GTotalleft;
+ extern long btime, ttime;
+ extern WINDOW *win;
+ 
+ int show_info()
+ {
+   long rxtotal, curtime;
+   long btelpsd, btleft, ttelpsd, ttleft;
+   int perc, tperc, bytesthru, totalthru;
+   int i;
+   struct tms tdummy;
+ 
+ #define DIS 10
+ #define TDIS 30
+ 
+   rxtotal = GTotalleft-Totalleft+rxbytes;
+   perc = 100*rxbytes/Bytesleft;
+   tperc = 100*rxtotal/GTotalleft;
+ 
+   curtime = times(&tdummy);
+   btelpsd = (curtime-btime)>100 ? (curtime-btime)/100 : 1;
+   ttelpsd = (curtime-ttime)>100 ? (curtime-ttime)/100 : 1;
+   btleft = rxbytes>100 ? (Bytesleft-rxbytes)*1.0/rxbytes*btelpsd : 0 ;
+   ttleft = rxtotal>100 ? (Totalleft-rxbytes)*1.0/rxtotal*ttelpsd : 0 ;
+   bytesthru = rxbytes/btelpsd;
+   totalthru = rxtotal/ttelpsd;
+ 
+ /*  wstandout(win);*/
+   mvwprintw(win, 2, 4+DIS, "%dk  ", rxbytes/1024);
+   mvwprintw(win, 4, 4+DIS, "%d%%  ", perc);
+   mvwprintw(win, 5, 4+DIS, "%02d\:%02d", btelpsd/60, btelpsd%60);
+   mvwprintw(win, 6, 4+DIS, "%02d\:%02d", btleft/60, btleft%60);
+   mvwprintw(win, 7, 4+DIS, "%d cps ", bytesthru);
+ 
+   mvwprintw(win, 2, TDIS+4+DIS, "%dk  ", rxtotal/1024);
+   mvwprintw(win, 4, TDIS+4+DIS, "%d%%  ", tperc);
+   mvwprintw(win, 5, TDIS+4+DIS, "%02d\:%02d", ttelpsd/60, ttelpsd%60);
+   mvwprintw(win, 6, TDIS+4+DIS, "%02d\:%02d", ttleft/60, ttleft%60);
+   mvwprintw(win, 7, TDIS+4+DIS, "%d cps ", totalthru);
+ /*  wstandend(win);*/
+ 
+   wstandout(win);
+   for(i=0; i<=perc/2; i++)
+ 	mvwaddstr(win, 10, 2+i, " ");
+   for(i=0; i<=tperc/2; i++)
+ 	mvwaddstr(win, 13, 2+i, " ");
+   wstandend(win);  
+ 
+   zmessage("Receiving file OK");
+   
+ /*mvwprintw(win, 3, 1, "\r< %d%% >< %dk of %dk >< %df = %dk >< %s >      \r",
+ 		  100*rxbytes/Bytesleft, rxbytes/1024, Bytesleft/1024,
+ 		  Filesleft, Totalleft/1024, Crc32r?"CRC-32":"");*/
+ 
+   wmove(win, 1, 1);
+   wrefresh(win);
+ }
+ 
+ zmessage(msg)
+ char *msg;
+ {
+   if (strlen(msg) > 40)
+ 	msg[40] = NULL;
+   wmove(win, 16, 12);
+   wclrtoeol(win);
+   waddstr(win, msg);
+   wrefresh(win);
+ }

----------------------------------------
--
/M. Saggaf
 alsaggaf@athena.mit.edu