--- Makefile
+++ Makefile	1994/03/15 22:08:09
@@ -0,0 +1,18 @@
+# Remove "-D__USE_READLINE__" and "-lreadline", if you do not 
+# want to have GNU readline and history support.
+# (Use cursor keys for the last ftp commands.)
+
+CFLAGS=-O2 -fomit-frame-pointer -m486 -I/usr/include/bsd -D__USE_READLINE__ \
+		-include /usr/include/bsd/bsd.h -Druserpass=x_ruserpass
+LDFLAGS=-v
+LDLIBS=-lbsd -lreadline
+
+ftp: cmds.o cmdtab.o domacro.o ftp.o glob.o main.o ruserpass.o
+
+install: ftp
+	install -s ftp /usr/bin
+	install -m644 ftp.1 /usr/man/man1
+
+clean:
+	rm -f *.o ftp
+
--- cmds.c
+++ cmds.c	1994/03/15 22:05:02
@@ -283,6 +283,7 @@
 {
 	register struct types *p;
 	int comret, oldverbose = verbose;
+	int oldtick = tick;
 
 	if (newtype == 0)
 		newtype = TYPE_I;
@@ -290,6 +291,7 @@
 		return;
 	if (debug == 0 && show == 0)
 		verbose = 0;
+	tick = 0;
 	for (p = types; p->t_name; p++)
 		if (newtype == p->t_type)
 			break;
@@ -304,6 +306,7 @@
 	if (comret == COMPLETE)
 		curtype = newtype;
 	verbose = oldverbose;
+	tick = oldtick;
 }
 
 char *stype[] = {
@@ -469,7 +472,7 @@
 					if (!*tp) {
 						tp = cp;
 						tp2 = tmpbuf;
-						while ((*tp2 = *tp) != NULL) {
+						while ((*tp2 = *tp) != '\0') {
 						     if (isupper(*tp2)) {
 						        *tp2 = 'a' + *tp2 - 'A';
 						     }
@@ -608,7 +611,7 @@
 		if (!*tp) {
 			tp = argv[2];
 			tp2 = tmpbuf;
-			while ((*tp2 = *tp) != NULL) {
+			while ((*tp2 = *tp) != '\0') {
 				if (isupper(*tp2)) {
 					*tp2 = 'a' + *tp2 - 'A';
 				}
@@ -650,24 +653,24 @@
 					    &yy, &mo, &day, &hour, &min, &sec);
 					tm = gmtime(&stbuf.st_mtime);
 					tm->tm_mon++;
+/* Indentation is misleading, but changes keep small. */
 					if (tm->tm_year > yy%100)
 						return (1);
-					else if (tm->tm_year == yy%100) {
+					else if (tm->tm_year == yy%100)
 						if (tm->tm_mon > mo)
 							return (1);
-					} else if (tm->tm_mon == mo) {
+					else if (tm->tm_mon == mo)
 						if (tm->tm_mday > day)
 							return (1);
-					} else if (tm->tm_mday == day) {
+					else if (tm->tm_mday == day)
 						if (tm->tm_hour > hour)
 							return (1);
-					} else if (tm->tm_hour == hour) {
+					else if (tm->tm_hour == hour)
 						if (tm->tm_min > min)
 							return (1);
-					} else if (tm->tm_min == min) {
+					else if (tm->tm_min == min)
 						if (tm->tm_sec > sec)
 							return (1);
-					}
 				} else {
 					printf("%s\n", reply_string);
 					verbose = overbose;
@@ -740,7 +743,7 @@
 				if (!*tp) {
 					tp = cp;
 					tp2 = tmpbuf;
-					while ((*tp2 = *tp) != NULL) {
+					while ((*tp2 = *tp) != '\0') {
 						if (isupper(*tp2)) {
 							*tp2 = 'a' + *tp2 - 'A';
 						}
@@ -887,6 +890,7 @@
 	}
 	printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
 		onoff(hash), onoff(sendport));
+	printf("Tick counter printing: %s\n", onoff(tick));
 	if (macnum > 0) {
 		printf("Macros:\n");
 		for (i=0; i<macnum; i++) {
@@ -928,6 +932,9 @@
 {
 
 	hash = !hash;
+	if (hash && tick)
+		settick();
+ 
 	printf("Hash mark printing %s", onoff(hash));
 	code = hash;
 	if (hash)
@@ -936,6 +943,22 @@
 }
 
 /*
+ * Toggle tick counter printing during transfers.
+ */
+/*VARARGS*/
+settick()
+{
+	tick = !tick;
+	if (hash && tick)
+		sethash();
+	printf("Tick counter printing %s", onoff(tick));
+	code = tick;
+	if (tick)
+		printf(" (%d bytes/tick increment)", TICKBYTES);
+	printf(".\n");
+}
+
+/*
  * Turn on printing of server echo's.
  */
 /*VARARGS*/
@@ -1069,7 +1092,7 @@
 /*
  * Delete a single file.
  */
-delete(argc, argv)
+delete_cmd(argc, argv)
 	int argc;
 	char *argv[];
 {
@@ -1476,7 +1499,7 @@
 	verbose = oldverbose;
 }
 
-idle(argc, argv)
+idle_cmd(argc, argv)
 	int argc;
 	char *argv[];
 {
@@ -2132,5 +2155,5 @@
 {
 	if (getit(argc, argv, -1, "w"))
 		printf("Local file \"%s\" is newer than remote file \"%s\"\n",
-			argv[1], argv[2]);
+			argv[2], argv[1]);
 }
--- cmdtab.c
+++ cmdtab.c	1994/03/15 22:05:02
@@ -42,11 +42,11 @@
  * User FTP -- Command Tables.
  */
 int	setascii(), setbell(), setbinary(), setdebug(), setform();
-int	setglob(), sethash(), setmode(), setpeer(), setport();
+int	setglob(), sethash(), settick(), setmode(), setpeer(), setport();
 int	setprompt(), setstruct();
 int	settenex(), settrace(), settype(), setverbose();
 int	disconnect(), restart(), reget(), syst();
-int	cd(), lcd(), delete(), mdelete(), user();
+int	cd(), lcd(), delete_cmd(), mdelete(), user();
 int	ls(), mls(), get(), mget(), help(), append(), put(), mput();
 int	quit(), renamefile(), status();
 int	quote(), rmthelp(), shell(), site();
@@ -54,7 +54,7 @@
 int	account(), doproxy(), reset(), setcase(), setntrans(), setnmap();
 int	setsunique(), setrunique(), cdup(), macdef(), domacro();
 int	sizecmd(), modtime(), newer(), rmtstatus();
-int	do_chmod(), do_umask(), idle();
+int	do_chmod(), do_umask(), idle_cmd();
 
 char	accounthelp[] =	"send account command to remote server";
 char	appendhelp[] =	"append to a file";
@@ -116,6 +116,7 @@
 char	suniquehelp[] = "toggle store unique on remote machine";
 char	systemhelp[] =  "show remote system type";
 char	tenexhelp[] =	"set tenex file transfer type";
+char	tickhelp[] =    "toggle printing byte counter during transfers";
 char	tracehelp[] =	"toggle packet tracing";
 char	typehelp[] =	"set file transfer type";
 char	umaskhelp[] =	"get (set) umask on remote side";
@@ -137,7 +138,7 @@
 	{ "chmod",	chmodhelp,	0,	1,	1,	do_chmod },
 	{ "close",	disconhelp,	0,	1,	1,	disconnect },
 	{ "cr",		crhelp,		0,	0,	0,	setcr },
-	{ "delete",	deletehelp,	0,	1,	1,	delete },
+	{ "delete",	deletehelp,	0,	1,	1,	delete_cmd },
 	{ "debug",	debughelp,	0,	0,	0,	setdebug },
 	{ "dir",	dirhelp,	1,	1,	1,	ls },
 	{ "disconnect",	disconhelp,	0,	1,	1,	disconnect },
@@ -146,7 +147,7 @@
 	{ "glob",	globhelp,	0,	0,	0,	setglob },
 	{ "hash",	hashhelp,	0,	0,	0,	sethash },
 	{ "help",	helphelp,	0,	0,	1,	help },
-	{ "idle",	idlehelp,	0,	1,	1,	idle },
+	{ "idle",	idlehelp,	0,	1,	1,	idle_cmd },
 	{ "image",	binaryhelp,	0,	1,	1,	setbinary },
 	{ "lcd",	lcdhelp,	0,	0,	0,	lcd },
 	{ "ls",		lshelp,		1,	1,	1,	ls },
@@ -188,6 +189,7 @@
 	{ "system",	systemhelp,	0,	1,	1,	syst },
 	{ "sunique",	suniquehelp,	0,	0,	1,	setsunique },
 	{ "tenex",	tenexhelp,	0,	1,	1,	settenex },
+	{ "tick",	tickhelp,	0,	0,	0,	settick },
 	{ "trace",	tracehelp,	0,	0,	0,	settrace },
 	{ "type",	typehelp,	0,	1,	1,	settype },
 	{ "user",	userhelp,	0,	1,	1,	user },
--- ftp.c
+++ ftp.c	1994/03/15 22:05:02
@@ -44,7 +44,6 @@
 #include <sys/file.h>
 
 #include <netinet/in.h>
-#include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <arpa/ftp.h>
 #include <arpa/telnet.h>
@@ -586,13 +585,23 @@
 				}
 				(void) fflush(stdout);
 			}
+			if (tick && (bytes >= hashbytes)) {
+				printf("\rBytes transferred: %d", bytes);
+				(void) fflush(stdout);
+				while (bytes >= hashbytes)
+					hashbytes += TICKBYTES;
+			}
 		}
-		if (hash && bytes > 0) {
+		if (hash && (bytes > 0)) {
 			if (bytes < HASHBYTES)
 				(void) putchar('#');
 			(void) putchar('\n');
 			(void) fflush(stdout);
 		}
+		if (tick) {
+			(void) printf("\rBytes transferred: %d\n", bytes);
+			(void) fflush(stdout);
+		}
 		if (c < 0)
 			fprintf(stderr, "local: %s: %s\n", local,
 				strerror(errno));
@@ -611,6 +620,13 @@
 					(void) fflush(stdout);
 					hashbytes += HASHBYTES;
 				}
+				if (tick && (bytes >= hashbytes)) {
+					(void) printf("\rBytes transferred: %d",
+						bytes);
+					(void) fflush(stdout);
+					while (bytes >= hashbytes)
+						hashbytes += TICKBYTES;
+				}
 				if (ferror(dout))
 					break;
 				(void) putc('\r', dout);
@@ -629,6 +645,10 @@
 			(void) putchar('\n');
 			(void) fflush(stdout);
 		}
+		if (tick) {
+			(void) printf("\rBytes transferred: %d\n", bytes);
+			(void) fflush(stdout);
+		}
 		if (ferror(fin))
 			fprintf(stderr, "local: %s: %s\n", local,
 				strerror(errno));
@@ -857,13 +877,20 @@
 			if ((d = write(fileno(fout), buf, c)) != c)
 				break;
 			bytes += c;
-			if (hash) {
+			if (hash && is_retr) {
 				while (bytes >= hashbytes) {
 					(void) putchar('#');
 					hashbytes += HASHBYTES;
 				}
 				(void) fflush(stdout);
 			}
+			if (tick && (bytes >= hashbytes) && is_retr) {
+				(void) printf("\rBytes transferred: %d",
+					bytes);
+				(void) fflush(stdout);
+				while (bytes >= hashbytes)
+					hashbytes += TICKBYTES;
+			}
 		}
 		if (hash && bytes > 0) {
 			if (bytes < HASHBYTES)
@@ -871,6 +898,10 @@
 			(void) putchar('\n');
 			(void) fflush(stdout);
 		}
+		if (tick && is_retr) {
+			(void) printf("\rBytes transferred: %d\n", bytes);
+			(void) fflush(stdout);
+		}
 		if (c < 0) {
 			if (errno != EPIPE)
 				perror("netin");
@@ -911,11 +942,19 @@
 			if (c == '\n')
 				bare_lfs++;
 			while (c == '\r') {
-				while (hash && (bytes >= hashbytes)) {
+				while (hash && (bytes >= hashbytes)
+					&& is_retr) {
 					(void) putchar('#');
 					(void) fflush(stdout);
 					hashbytes += HASHBYTES;
 				}
+				if (tick && (bytes >= hashbytes) && is_retr) {
+					(void) printf("\rBytes transferred: %d",
+						bytes);
+					(void) fflush(stdout);
+					while (bytes >= hashbytes)
+						hashbytes += TICKBYTES;
+				}
 				bytes++;
 				if ((c = getc(din)) != '\n' || tcrflag) {
 					if (ferror(fout))
@@ -934,16 +973,20 @@
 	contin2:	;
 		}
 break2:
-		if (bare_lfs) {
-			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
-			printf("File may not have transferred correctly.\n");
-		}
-		if (hash) {
+		if (hash && is_retr) {
 			if (bytes < hashbytes)
 				(void) putchar('#');
 			(void) putchar('\n');
 			(void) fflush(stdout);
 		}
+		if (tick && is_retr) {
+			(void) printf("\rBytes transferred: %d\n", bytes);
+			(void) fflush(stdout);
+		}
+		if (bare_lfs) {
+			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
+			printf("File may not have transferred correctly.\n");
+		}
 		if (ferror(din)) {
 			if (errno != EPIPE)
 				perror("netin");
@@ -1095,16 +1138,15 @@
 	struct timeval *t0, *t1;
 {
 	struct timeval td;
-	float s;
-	long bs;
+	float s, bs;
 
 	if (verbose) {
 		tvsub(&td, t1, t0);
 		s = td.tv_sec + (td.tv_usec / 1000000.);
 #define	nz(x)	((x) == 0 ? 1 : (x))
 		bs = bytes / nz(s);
-		printf("%ld bytes %s in %.3g secs (%ld bytes/sec)\n",
-		    bytes, direction, s, bs);
+		printf("%ld bytes %s in %.3g secs (%.2g Kbytes/sec)\n",
+		    bytes, direction, s, bs / 1024.0);
 	}
 }
 
--- ftp_var.h
+++ ftp_var.h	1994/03/15 22:05:02
@@ -39,10 +39,16 @@
  */
 
 /*
+ * Tick counter step size.
+ */
+#define TICKBYTES     10240
+
+/*
  * Options and other state info.
  */
 int	trace;			/* trace packets exchanged */
 int	hash;			/* print # for each buffer transferred */
+int	tick;			/* print byte counter during transfers */
 int	sendport;		/* use PORT cmd for each data connection */
 int	verbose;		/* print messages coming back from server */
 int	connected;		/* connected to server */
--- glob.c
+++ glob.c	1994/03/15 22:05:02
@@ -74,7 +74,7 @@
 
 static	int globcnt;
 
-char	*globchars = "`{[*?";
+static char	*globchars = "`{[*?";
 
 static	char *gpath, *gpathp, *lastgpathp;
 static	int globbed;
@@ -217,6 +217,10 @@
 	register struct dirent *dp;
 	DIR *dirp;
 
+#ifdef	__linux__
+	if (gpath == NULL || *gpath == '\0')
+		gpath = "./";
+#endif
 	dirp = opendir(gpath);
 	if (dirp == NULL) {
 		if (globbed)
--- main.c
+++ main.c	1994/03/15 22:05:02
@@ -58,6 +58,10 @@
 #include <ctype.h>
 #include <netdb.h>
 #include <pwd.h>
+#ifdef	__USE_READLINE__
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
 
 uid_t	getuid();
 void	intr(), lostpeer();
@@ -72,6 +76,8 @@
 	struct passwd *pw = NULL;
 	char homedir[MAXPATHLEN];
 
+	tick = 0;
+
 	sp = getservbyname("ftp", "tcp");
 	if (sp == 0) {
 		fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
@@ -221,16 +227,38 @@
 	register int l;
 	struct cmd *getcmd();
 	extern int help();
+#ifdef __USE_READLINE__
+	char *lineread;
+#endif
 
 	if (!top)
 		(void) putchar('\n');
 	for (;;) {
 		if (fromatty) {
+#ifdef __USE_READLINE__
+			lineread = readline("ftp> ");
+#else
 			printf("ftp> ");
 			(void) fflush(stdout);
+#endif
 		}
+#ifdef __USE_READLINE__
+		if (!fromatty) {
+			if (fgets(line, sizeof line, stdin) == NULL)
+				quit();
+		} else {
+			if (!lineread) {
+				quit();
+				break;
+			}
+			strcpy(line, lineread);
+			if (lineread[0]) add_history(lineread);
+			free(lineread);
+                }
+#else
 		if (fgets(line, sizeof line, stdin) == NULL)
 			quit();
+#endif
 		l = strlen(line);
 		if (l == 0)
 			break;