From: alsaggaf@athena.mit.edu (M. Saggaf)
Subject: Graphic Zmodem (Was: How to make curses write to stderr?)
Organization: Massachusetts Institute of Technology
Date: Thu, 1 Oct 1992 22:45:38 GMT

In article <1992Sep30.224730.18173@athena.mit.edu> alsaggaf@athena.mit.edu (M. Saggaf) writes:
>
>Well, I was trying to make a front end to zmodem using curses (you
>know, bars and stuff like in the DOS comm programs). Things went
>rather smoothly consdering that this is the first time I use curses.
>However, I have one problem: How can I make curses write to the
>standard error instead of the standard output? (since if writes to the
>standard output it is useless for something like 'rz < /devttys1 >
>dev/ttys1' ..etc.). Any help would be greaty appreciated.
>
>                                        - M. Saggaf

(I'm answering myself). No, there seems to be no way to do that. The
following is a patch that makes a graphic zmodem (something like gsz
in DOS) of the stock zmodem. Apply the patch, define MODEM in the
makefile, then run 'make rz' to make it. To use it in xcomm, type '! rz
-vv' (not '$ rz'). To use it in minicom, do Ctl-A J, then type 'rz
-vv' at the shell. It needs no redirection of stdin/stdout. 

I won't be uploading any binaries since I'm not sure of what the
zmodem copyright entails (i.e. wither it allows any modifications to
the code), so use it at your own reponsibility. The patch is a quick
and somewhat dirty hack and is also not very complete. Enjoy!

------------------------------8<------------------------------
diff -crN czmodem/Makefile zmodem/Makefile
*** czmodem/Makefile	Sun Dec 15 15:35:56 1991
--- zmodem/Makefile	Thu Oct  1 17:41:32 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 -crN 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 -crN czmodem/rz.c zmodem/rz.c
*** czmodem/rz.c	Wed Oct 30 19:57:48 1991
--- zmodem/rz.c	Thu Oct  1 18:14:16 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,149 ----
  int errors;
  int Restricted=0;	/* restricted; no /.. or ../ in filenames */
  
+ #define TDIS 30
+ struct tms tdummy;
+ long btime, ttime;
+ 
  #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,177 ****
--- 178,184 ----
  
  int tryzhdrtype=ZRINIT;	/* Header type to send corresponding to Last rx close */
  
+ WINDOW *win, *bwin;
  
  /* called by signal interrupt or terminate to clean things up */
  bibi(n)
***************
*** 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);
--- 253,272 ----
  	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(16, 54, 5, 12);
! 		bwin = newwin(16, 55, 5, 12);
! 		leaveok(win, FALSE);
! 
! 		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);
  }
  
--- 286,297 ----
  		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;
--- 330,336 ----
  
  	if (Batch || argc==0) {
  		Crcflg=1;
! 		wprintw(win, rbmsg, Progname, Nozmodem?"sb":"sz");
  		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);
- 		}
  	}
  
  
--- 593,602 ----
  		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;
  	}
  
  
***************
*** 988,993 ****
--- 1004,1017 ----
  {
  	register c;
  
+ 	wclear(win);
+ 	box(bwin, '|', '-');
+ 	zmessage("Waiting for files");	
+ 	wrefresh(win);
+ 	wrefresh(bwin);
+ 
+ 	ttime = times(&tdummy);
+ 
  	for (;;) {
  		switch (c = rzfile()) {
  		case ZEOF:
***************
*** 1016,1021 ****
--- 1040,1046 ----
  rzfile()
  {
  	register c, n;
+ 	char Fname[40];
  
  	Eofseen=FALSE;
  	n = 20; rxbytes = 0l;
***************
*** 1024,1029 ****
--- 1049,1086 ----
  		return (tryzhdrtype = c);
  	}
  
+ 	if (strlen(secbuf) > 14) {
+ 	  strncpy(Fname, secbuf, 11);
+ 	  Fname[11] = NULL;
+ 	  strcat(Fname, "...");
+ 	}
+ 	else
+ 	  strcpy(Fname, secbuf);
+ 
+ 	mvwaddstr(win, 14, 12, "Receiving files OK         ");
+ 	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, "Thruput :");
+ 	mvwaddstr(win, 14, 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, "Thruput :");
+ 	
+ 	mvwaddstr(win, 7, 2, "This File:");
+ 	mvwaddstr(win, 8, 2, "+-----------+------------+------------+-----------+");
+ 	mvwaddstr(win, 9, 2, "0%         25%          50%          75%       100%");
+ 	mvwaddstr(win, 10, 2, "Total:");
+ 	mvwaddstr(win, 11, 2, "+-----------+------------+------------+-----------+");
+ 	mvwaddstr(win, 12, 2, "0%         25%          50%          75%       100%");
+ 	wmove(win, 1, 1);
+ 	wrefresh(win);
+ 
+ 	btime = times(&tdummy);
+ 
  	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);
--- 1177,1184 ----
  			}
  moredata:
  			if (Verbose>1)
! 			  show_info();
! 
  #ifdef SEGMENTS
  			if (chinseg >= (1024 * SEGMENTS)) {
  				putsec(secbuf, chinseg);
diff -crN czmodem/show_info.c zmodem/show_info.c
*** czmodem/show_info.c
--- zmodem/show_info.c	Thu Oct  1 17:41:35 1992
***************
*** 0 ****
--- 1,58 ----
+ #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()
+ {
+   int perc, tperc, bytesthru, totalthru, i;
+   long rxtotal, curtime;
+   struct tms tdummy;
+ 
+ #define DIS 10
+ #define TDIS 30
+ 
+   rxtotal = GTotalleft-Totalleft+rxbytes;
+   perc = 100*rxbytes/Bytesleft;
+   tperc = 100*rxtotal/GTotalleft;
+ 
+   curtime = times(&tdummy);
+   bytesthru = rxbytes*100/(curtime-btime);
+   totalthru = rxtotal*100/(curtime-ttime);
+ 
+ 
+ /*  wstandout(win);*/
+   mvwprintw(win, 2, 4+DIS, "%dk", rxbytes/1024);
+   mvwprintw(win, 4, 4+DIS, "%d%%", perc);
+   mvwprintw(win, 5, 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, "%d cps", totalthru);
+ /*  wstandend(win);*/
+ 
+   wstandout(win);
+   for(i=0; i<=perc/2; i++)
+ 	mvwaddstr(win, 8, 2+i, " ");
+   for(i=0; i<=tperc/2; i++)
+ 	mvwaddstr(win, 11, 2+i, " ");
+   wstandend(win);  
+ 
+   /*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;
+ {
+   wmove(win, 14, 12);
+   wclrtoeol(win);
+   waddstr(win, msg);
+   wrefresh(win);
+ }


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