prettyness police
[unix-history] / usr / src / usr.bin / ftp / cmds.c
index 00dea2d..af860ff 100644 (file)
@@ -1,67 +1,83 @@
 /*
 /*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)cmds.c     5.13 (Berkeley) %G%";
+static char sccsid[] = "@(#)cmds.c     8.2 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
  * FTP User Program -- Command Routines.
  */
 #endif /* not lint */
 
 /*
  * FTP User Program -- Command Routines.
  */
-#include "ftp_var.h"
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
-
+#include <netinet/in.h>
 #include <arpa/ftp.h>
 
 #include <arpa/ftp.h>
 
+#include <ctype.h>
+#include <err.h>
+#include <netdb.h>
 #include <signal.h>
 #include <stdio.h>
 #include <signal.h>
 #include <stdio.h>
-#include <errno.h>
-#include <netdb.h>
-#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #include <time.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/param.h>
+#include <unistd.h>
 
 
+#include "ftp_var.h"
+#include "pathnames.h"
 
 
-extern char *globerr;
-extern char **glob();
-extern char *home;
-extern char *remglob();
-extern char *getenv();
-extern char *index();
-extern char *rindex();
-extern off_t restart_point;
-extern char reply_string[];
+jmp_buf        jabort;
+char   *mname;
 
 
-char *mname;
-jmp_buf jabort;
-char *dotrans(), *domap();
+/*
+ * `Another' gets another argument, and stores the new argc and argv.
+ * It reverts to the top level (via main.c's intr()) on EOF/error.
+ *
+ * Returns false if no new arguments have been added.
+ */
+int
+another(pargc, pargv, prompt)
+       int *pargc;
+       char ***pargv;
+       char *prompt;
+{
+       int len = strlen(line), ret;
+
+       if (len >= sizeof(line) - 3) {
+               printf("sorry, arguments too long\n");
+               intr();
+       }
+       printf("(%s) ", prompt);
+       line[len++] = ' ';
+       if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
+               intr();
+       len += strlen(&line[len]);
+       if (len > 0 && line[len - 1] == '\n')
+               line[len - 1] = '\0';
+       makeargv();
+       ret = margc > *pargc;
+       *pargc = margc;
+       *pargv = margv;
+       return (ret);
+}
 
 /*
  * Connect to peer server and
  * auto-login, if possible.
  */
 
 /*
  * Connect to peer server and
  * auto-login, if possible.
  */
+void
 setpeer(argc, argv)
        int argc;
        char *argv[];
 {
 setpeer(argc, argv)
        int argc;
        char *argv[];
 {
-       char *host, *hookup();
-       int port;
+       char *host;
+       short port;
 
        if (connected) {
                printf("Already connected to %s, use close first.\n",
 
        if (connected) {
                printf("Already connected to %s, use close first.\n",
@@ -69,15 +85,9 @@ setpeer(argc, argv)
                code = -1;
                return;
        }
                code = -1;
                return;
        }
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(to) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc > 3) {
+       if (argc < 2)
+               (void) another(&argc, &argv, "to");
+       if (argc < 2 || argc > 3) {
                printf("usage: %s host-name [port]\n", argv[0]);
                code = -1;
                return;
                printf("usage: %s host-name [port]\n", argv[0]);
                code = -1;
                return;
@@ -95,45 +105,74 @@ setpeer(argc, argv)
        }
        host = hookup(argv[1], port);
        if (host) {
        }
        host = hookup(argv[1], port);
        if (host) {
+               int overbose;
+
                connected = 1;
                connected = 1;
-               if (autologin) {
-                       int overbose;
+               /*
+                * Set up defaults for FTP.
+                */
+               (void) strcpy(typename, "ascii"), type = TYPE_A;
+               curtype = TYPE_A;
+               (void) strcpy(formname, "non-print"), form = FORM_N;
+               (void) strcpy(modename, "stream"), mode = MODE_S;
+               (void) strcpy(structname, "file"), stru = STRU_F;
+               (void) strcpy(bytename, "8"), bytesize = 8;
+               if (autologin)
                        (void) login(argv[1]);
                        (void) login(argv[1]);
+
 #if defined(unix) && NBBY == 8
 /*
  * this ifdef is to keep someone form "porting" this to an incompatible
  * system and not checking this out. This way they have to think about it.
  */
 #if defined(unix) && NBBY == 8
 /*
  * this ifdef is to keep someone form "porting" this to an incompatible
  * system and not checking this out. This way they have to think about it.
  */
-                       overbose = verbose, verbose = -1;
-                       if (command("SYST") == COMPLETE && overbose) {
-                               register char *cp, c;
-                               cp = index(reply_string+4, ' ');
-                               if (cp == NULL)
-                                       cp = index(reply_string+4, '\r');
-                               if (cp) {
-                                       if (cp[-1] == '.')
-                                               cp--;
-                                       c = *cp;
-                                       *cp = '\0';
-                               }
-
-                               printf("Remote system type is %s.\n",
-                                       reply_string+4);
-                               if (cp)
-                                       *cp = c;
-                       }
-                       if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
-                               setbinary();
-                               if (overbose)
-                                       printf("Using %s mode to transfer files.\n",
-                                               typename);
-                       } else if (overbose && 
-                           !strncmp(reply_string, "215 TOPS20", 10)) {
-                               printf("Remember to set tenex mode when transfering binary files from this machine.\n");
+               overbose = verbose;
+               if (debug == 0)
+                       verbose = -1;
+               if (command("SYST") == COMPLETE && overbose) {
+                       char *cp, c;
+                       cp = strchr(reply_string+4, ' ');
+                       if (cp == NULL)
+                               cp = strchr(reply_string+4, '\r');
+                       if (cp) {
+                               if (cp[-1] == '.')
+                                       cp--;
+                               c = *cp;
+                               *cp = '\0';
                        }
                        }
-                       verbose = overbose;
-#endif /* unix */
+
+                       printf("Remote system type is %s.\n",
+                               reply_string+4);
+                       if (cp)
+                               *cp = c;
                }
                }
+               if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+                       if (proxy)
+                               unix_proxy = 1;
+                       else
+                               unix_server = 1;
+                       /*
+                        * Set type to 0 (not specified by user),
+                        * meaning binary by default, but don't bother
+                        * telling server.  We can use binary
+                        * for text files unless changed by the user.
+                        */
+                       type = 0;
+                       (void) strcpy(typename, "binary");
+                       if (overbose)
+                           printf("Using %s mode to transfer files.\n",
+                               typename);
+               } else {
+                       if (proxy)
+                               unix_proxy = 0;
+                       else
+                               unix_server = 0;
+                       if (overbose && 
+                           !strncmp(reply_string, "215 TOPS20", 10))
+                               printf(
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+               }
+               verbose = overbose;
+#endif /* unix */
        }
 }
 
        }
 }
 
@@ -148,16 +187,18 @@ struct    types {
        { "image",      "I",    TYPE_I, 0 },
        { "ebcdic",     "E",    TYPE_E, 0 },
        { "tenex",      "L",    TYPE_L, bytename },
        { "image",      "I",    TYPE_I, 0 },
        { "ebcdic",     "E",    TYPE_E, 0 },
        { "tenex",      "L",    TYPE_L, bytename },
-       0
+       { NULL }
 };
 
 /*
  * Set transfer type.
  */
 };
 
 /*
  * Set transfer type.
  */
+void
 settype(argc, argv)
 settype(argc, argv)
+       int argc;
        char *argv[];
 {
        char *argv[];
 {
-       register struct types *p;
+       struct types *p;
        int comret;
 
        if (argc > 2) {
        int comret;
 
        if (argc > 2) {
@@ -167,8 +208,7 @@ settype(argc, argv)
                sep = " ";
                for (p = types; p->t_name; p++) {
                        printf("%s%s", sep, p->t_name);
                sep = " ";
                for (p = types; p->t_name; p++) {
                        printf("%s%s", sep, p->t_name);
-                       if (*sep == ' ')
-                               sep = " | ";
+                       sep = " | ";
                }
                printf(" ]\n");
                code = -1;
                }
                printf(" ]\n");
                code = -1;
@@ -193,55 +233,99 @@ settype(argc, argv)
                comret = command("TYPE %s", p->t_mode);
        if (comret == COMPLETE) {
                (void) strcpy(typename, p->t_name);
                comret = command("TYPE %s", p->t_mode);
        if (comret == COMPLETE) {
                (void) strcpy(typename, p->t_name);
-               type = p->t_type;
+               curtype = type = p->t_type;
        }
 }
 
 /*
        }
 }
 
 /*
- * Set binary transfer type.
+ * Internal form of settype; changes current type in use with server
+ * without changing our notion of the type for data transfers.
+ * Used to change to and from ascii for listings.
  */
  */
-/*VARARGS*/
-setbinary()
+void
+changetype(newtype, show)
+       int newtype, show;
 {
 {
+       struct types *p;
+       int comret, oldverbose = verbose;
 
 
-       call(settype, "type", "binary", 0);
+       if (newtype == 0)
+               newtype = TYPE_I;
+       if (newtype == curtype)
+               return;
+       if (debug == 0 && show == 0)
+               verbose = 0;
+       for (p = types; p->t_name; p++)
+               if (newtype == p->t_type)
+                       break;
+       if (p->t_name == 0) {
+               printf("ftp: internal error: unknown type %d\n", newtype);
+               return;
+       }
+       if (newtype == TYPE_L && bytename[0] != '\0')
+               comret = command("TYPE %s %s", p->t_mode, bytename);
+       else
+               comret = command("TYPE %s", p->t_mode);
+       if (comret == COMPLETE)
+               curtype = newtype;
+       verbose = oldverbose;
 }
 
 }
 
+char *stype[] = {
+       "type",
+       "",
+       0
+};
+
 /*
 /*
- * Set ascii transfer type.
+ * Set binary transfer type.
  */
 /*VARARGS*/
  */
 /*VARARGS*/
-setascii()
+void
+setbinary(argc, argv)
+       int argc;
+       char **argv;
 {
 
 {
 
-       call(settype, "type", "ascii", 0);
+       stype[1] = "binary";
+       settype(2, stype);
 }
 
 /*
 }
 
 /*
- * Set tenex transfer type.
+ * Set ascii transfer type.
  */
 /*VARARGS*/
  */
 /*VARARGS*/
-settenex()
+void
+setascii(argc, argv)
+       int argc;
+       char *argv[];
 {
 
 {
 
-       call(settype, "type", "tenex", 0);
+       stype[1] = "ascii";
+       settype(2, stype);
 }
 
 /*
 }
 
 /*
- * Set ebcdic transfer type.
+ * Set tenex transfer type.
  */
 /*VARARGS*/
  */
 /*VARARGS*/
-setebcdic()
+void
+settenex(argc, argv)
+       int argc;
+       char *argv[];
 {
 
 {
 
-       call(settype, "type", "ebcdic", 0);
+       stype[1] = "tenex";
+       settype(2, stype);
 }
 
 /*
  * Set file transfer mode.
  */
 /*ARGSUSED*/
 }
 
 /*
  * Set file transfer mode.
  */
 /*ARGSUSED*/
-setmode(argc, argv)
+void
+setftmode(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
@@ -253,7 +337,9 @@ setmode(argc, argv)
  * Set file transfer format.
  */
 /*ARGSUSED*/
  * Set file transfer format.
  */
 /*ARGSUSED*/
+void
 setform(argc, argv)
 setform(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
@@ -265,7 +351,9 @@ setform(argc, argv)
  * Set file transfer structure.
  */
 /*ARGSUSED*/
  * Set file transfer structure.
  */
 /*ARGSUSED*/
+void
 setstruct(argc, argv)
 setstruct(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
@@ -276,44 +364,30 @@ setstruct(argc, argv)
 /*
  * Send a single file.
  */
 /*
  * Send a single file.
  */
+void
 put(argc, argv)
        int argc;
        char *argv[];
 {
        char *cmd;
        int loc = 0;
 put(argc, argv)
        int argc;
        char *argv[];
 {
        char *cmd;
        int loc = 0;
-       char *oldargv1;
+       char *oldargv1, *oldargv2;
 
        if (argc == 2) {
                argc++;
                argv[2] = argv[1];
                loc++;
        }
 
        if (argc == 2) {
                argc++;
                argv[2] = argv[1];
                loc++;
        }
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(local-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
+       if (argc < 2 && !another(&argc, &argv, "local-file"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "remote-file")) {
 usage:
 usage:
-               printf("usage:%s local-file remote-file\n", argv[0]);
+               printf("usage: %s local-file remote-file\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
-       if (argc < 3) {
-               (void) strcat(line, " ");
-               printf("(remote-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 3) 
-               goto usage;
        oldargv1 = argv[1];
        oldargv1 = argv[1];
+       oldargv2 = argv[2];
        if (!globulize(&argv[1])) {
                code = -1;
                return;
        if (!globulize(&argv[1])) {
                code = -1;
                return;
@@ -332,30 +406,25 @@ usage:
        if (loc && mapflag) {
                argv[2] = domap(argv[2]);
        }
        if (loc && mapflag) {
                argv[2] = domap(argv[2]);
        }
-       sendrequest(cmd, argv[1], argv[2]);
+       sendrequest(cmd, argv[1], argv[2],
+           argv[1] != oldargv1 || argv[2] != oldargv2);
 }
 
 /*
  * Send multiple files.
  */
 }
 
 /*
  * Send multiple files.
  */
+void
 mput(argc, argv)
 mput(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
-       register int i;
-       int ointer, (*oldintr)(), mabort();
-       extern jmp_buf jabort;
+       int i;
+       sig_t oldintr;
+       int ointer;
        char *tp;
 
        char *tp;
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(local-files) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s local-files\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "local-files")) {
+               printf("usage: %s local-files\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -396,7 +465,8 @@ mput(argc, argv)
                                if (mapflag) {
                                        tp = domap(tp);
                                }
                                if (mapflag) {
                                        tp = domap(tp);
                                }
-                               sendrequest((sunique) ? "STOU" : "STOR", cp,tp);
+                               sendrequest((sunique) ? "STOU" : "STOR",
+                                   cp, tp, cp != tp || !interactive);
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
@@ -412,14 +482,14 @@ mput(argc, argv)
                return;
        }
        for (i = 1; i < argc; i++) {
                return;
        }
        for (i = 1; i < argc; i++) {
-               register char **cpp, **gargs;
+               char **cpp, **gargs;
 
                if (!doglob) {
                        if (mflag && confirm(argv[0], argv[i])) {
                                tp = (ntflag) ? dotrans(argv[i]) : argv[i];
                                tp = (mapflag) ? domap(tp) : tp;
                                sendrequest((sunique) ? "STOU" : "STOR",
 
                if (!doglob) {
                        if (mflag && confirm(argv[0], argv[i])) {
                                tp = (ntflag) ? dotrans(argv[i]) : argv[i];
                                tp = (mapflag) ? domap(tp) : tp;
                                sendrequest((sunique) ? "STOU" : "STOR",
-                                           argv[i], tp);
+                                   argv[i], tp, tp != argv[i] || !interactive);
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
@@ -431,12 +501,12 @@ mput(argc, argv)
                        }
                        continue;
                }
                        }
                        continue;
                }
-               gargs = glob(argv[i]);
+               gargs = ftpglob(argv[i]);
                if (globerr != NULL) {
                        printf("%s\n", globerr);
                        if (gargs) {
                                blkfree(gargs);
                if (globerr != NULL) {
                        printf("%s\n", globerr);
                        if (gargs) {
                                blkfree(gargs);
-                               free(gargs);
+                               free((char *)gargs);
                        }
                        continue;
                }
                        }
                        continue;
                }
@@ -445,7 +515,7 @@ mput(argc, argv)
                                tp = (ntflag) ? dotrans(*cpp) : *cpp;
                                tp = (mapflag) ? domap(tp) : tp;
                                sendrequest((sunique) ? "STOU" : "STOR",
                                tp = (ntflag) ? dotrans(*cpp) : *cpp;
                                tp = (mapflag) ? domap(tp) : tp;
                                sendrequest((sunique) ? "STOU" : "STOR",
-                                          *cpp, tp);
+                                   *cpp, tp, *cpp != tp || !interactive);
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
                                if (!mflag && fromatty) {
                                        ointer = interactive;
                                        interactive = 1;
@@ -458,66 +528,44 @@ mput(argc, argv)
                }
                if (gargs != NULL) {
                        blkfree(gargs);
                }
                if (gargs != NULL) {
                        blkfree(gargs);
-                       free(gargs);
+                       free((char *)gargs);
                }
        }
        (void) signal(SIGINT, oldintr);
        mflag = 0;
 }
 
                }
        }
        (void) signal(SIGINT, oldintr);
        mflag = 0;
 }
 
-reget(argc, argv)
-       char *argv[];
-{
-       (void) getit(argc, argv, 1, "r+w");
-}
-
-get(argc, argv)
-       char *argv[];
-{
-       (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
-}
+void
 
 
+void
 /*
  * Receive one file.
  */
 /*
  * Receive one file.
  */
-getit(argc, argv, restartit, mode)
+int
+get(argc, argv)
        char *argv[];
        char *argv[];
-       char *mode;
 {
        int loc = 0;
 {
        int loc = 0;
+       char *oldargv1, *oldargv2;
 
        if (argc == 2) {
                argc++;
                argv[2] = argv[1];
                loc++;
        }
 
        if (argc == 2) {
                argc++;
                argv[2] = argv[1];
                loc++;
        }
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
+       if (argc < 2 && !another(&argc, &argv, "remote-file"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "local-file")) {
 usage:
                printf("usage: %s remote-file [ local-file ]\n", argv[0]);
                code = -1;
 usage:
                printf("usage: %s remote-file [ local-file ]\n", argv[0]);
                code = -1;
-               return 0;
-       }
-       if (argc < 3) {
-               (void) strcat(line, " ");
-               printf("(local-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
+               return;
        }
        }
-       if (argc < 3) 
-               goto usage;
+       oldargv1 = argv[1];
+       oldargv2 = argv[2];
        if (!globulize(&argv[2])) {
                code = -1;
        if (!globulize(&argv[2])) {
                code = -1;
-               return 0;
+               return;
        }
        if (loc && mcase) {
                char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
        }
        if (loc && mcase) {
                char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
@@ -538,71 +586,19 @@ usage:
                        argv[2] = tmpbuf;
                }
        }
                        argv[2] = tmpbuf;
                }
        }
-       if (loc && ntflag) {
+       if (loc && ntflag)
                argv[2] = dotrans(argv[2]);
                argv[2] = dotrans(argv[2]);
-       }
-       if (loc && mapflag) {
+       if (loc && mapflag)
                argv[2] = domap(argv[2]);
                argv[2] = domap(argv[2]);
-       }
-       if (restartit) {
-               struct stat stbuf;
-               int ret;
-               ret = stat(argv[2], &stbuf);
-               if (restartit == 1) {
-                       if (ret < 0) {
-                               perror(argv[2]);
-                               return 0;
-                       }
-                       restart_point = stbuf.st_size;
-               } else {
-                       if (ret == 0) {
-                               int overbose;
-                               overbose = verbose; verbose = -1;
-                               if (command("MDTM %s", argv[1]) == COMPLETE) {
-                                       int yy, mo, day, hour, min, sec;
-                                       struct tm *tm;
-                                       verbose = overbose;
-                                       sscanf(reply_string,
-                                           "%*s %04d%02d%02d%02d%02d%02d",
-                                           &yy, &mo, &day, &hour, &min, &sec);
-                                       tm = gmtime(&stbuf.st_mtime);
-                                       tm->tm_mon++;
-                                       if (tm->tm_year > yy%100)
-                                               return 1;
-                                       else if (tm->tm_year == yy%100) {
-                                               if (tm->tm_mon > mo)
-                                                       return 1;
-                                       } else if (tm->tm_mon == mo) {
-                                               if (tm->tm_mday > day)
-                                                       return 1;
-                                       } else if (tm->tm_mday == day) {
-                                               if (tm->tm_hour > hour)
-                                                       return 1;
-                                       } else if (tm->tm_hour == hour) {
-                                               if (tm->tm_min > min)
-                                                       return 1;
-                                       } else if (tm->tm_min == min) {
-                                               if (tm->tm_sec > sec)
-                                                       return 1;
-                                       }
-                               } else {
-                                       fputs(reply_string, stdout);
-                                       verbose = overbose;
-                                       return 0;
-                               }
-                       }
-               }
-       }
-
-       recvrequest("RETR", argv[2], argv[1], mode);
-       restart_point = 0;
-       return 0;
+       recvrequest("RETR", argv[2], argv[1], "w");
 }
 
 }
 
-mabort()
+/* ARGSUSED */
+void
+mabort(signo)
+       int signo;
 {
        int ointer;
 {
        int ointer;
-       extern jmp_buf jabort;
 
        printf("\n");
        (void) fflush(stdout);
 
        printf("\n");
        (void) fflush(stdout);
@@ -622,29 +618,23 @@ mabort()
 /*
  * Get multiple files.
  */
 /*
  * Get multiple files.
  */
+void
 mget(argc, argv)
 mget(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
+       sig_t oldintr;
+       int ch, ointer;
        char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
        char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
-       int ointer, (*oldintr)(), mabort();
-       extern jmp_buf jabort;
 
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-files) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s remote-files\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+               printf("usage: %s remote-files\n", argv[0]);
                code = -1;
                return;
        }
        mname = argv[0];
        mflag = 1;
                code = -1;
                return;
        }
        mname = argv[0];
        mflag = 1;
-       oldintr = signal(SIGINT,mabort);
+       oldintr = signal(SIGINT, mabort);
        (void) setjmp(jabort);
        while ((cp = remglob(argv,proxy)) != NULL) {
                if (*cp == '\0') {
        (void) setjmp(jabort);
        while ((cp = remglob(argv,proxy)) != NULL) {
                if (*cp == '\0') {
@@ -654,20 +644,8 @@ mget(argc, argv)
                if (mflag && confirm(argv[0], cp)) {
                        tp = cp;
                        if (mcase) {
                if (mflag && confirm(argv[0], cp)) {
                        tp = cp;
                        if (mcase) {
-                               while (*tp && !islower(*tp)) {
-                                       tp++;
-                               }
-                               if (!*tp) {
-                                       tp = cp;
-                                       tp2 = tmpbuf;
-                                       while ((*tp2 = *tp) != NULL) {
-                                               if (isupper(*tp2)) {
-                                                       *tp2 = 'a' + *tp2 - 'A';
-                                               }
-                                               tp++;
-                                               tp2++;
-                                       }
-                               }
+                               for (tp2 = tmpbuf; ch = *tp++;)
+                                       *tp2++ = isupper(ch) ? tolower(ch) : ch;
                                tp = tmpbuf;
                        }
                        if (ntflag) {
                                tp = tmpbuf;
                        }
                        if (ntflag) {
@@ -676,7 +654,8 @@ mget(argc, argv)
                        if (mapflag) {
                                tp = domap(tp);
                        }
                        if (mapflag) {
                                tp = domap(tp);
                        }
-                       recvrequest("RETR", tp, cp, "w");
+                       recvrequest("RETR", tp, cp, "w",
+                           tp != cp || !interactive);
                        if (!mflag && fromatty) {
                                ointer = interactive;
                                interactive = 1;
                        if (!mflag && fromatty) {
                                ointer = interactive;
                                interactive = 1;
@@ -713,7 +692,7 @@ remglob(argv,doswitch)
                                ftemp = NULL;
                        }
                }
                                ftemp = NULL;
                        }
                }
-               return(NULL);
+               return (NULL);
        }
        if (!doglob) {
                if (args == NULL)
        }
        if (!doglob) {
                if (args == NULL)
@@ -723,7 +702,7 @@ remglob(argv,doswitch)
                return (cp);
        }
        if (ftemp == NULL) {
                return (cp);
        }
        if (ftemp == NULL) {
-               (void) strcpy(temp, "/tmp/ftpXXXXXX");
+               (void) strcpy(temp, _PATH_TMP);
                (void) mktemp(temp);
                oldverbose = verbose, verbose = 0;
                oldhash = hash, hash = 0;
                (void) mktemp(temp);
                oldverbose = verbose, verbose = 0;
                oldhash = hash, hash = 0;
@@ -731,7 +710,7 @@ remglob(argv,doswitch)
                        pswitch(!proxy);
                }
                for (mode = "w"; *++argv != NULL; mode = "a")
                        pswitch(!proxy);
                }
                for (mode = "w"; *++argv != NULL; mode = "a")
-                       recvrequest ("NLST", temp, *argv, mode);
+                       recvrequest ("NLST", temp, *argv, mode, 0);
                if (doswitch) {
                        pswitch(!proxy);
                }
                if (doswitch) {
                        pswitch(!proxy);
                }
@@ -747,7 +726,7 @@ remglob(argv,doswitch)
                (void) fclose(ftemp), ftemp = NULL;
                return (NULL);
        }
                (void) fclose(ftemp), ftemp = NULL;
                return (NULL);
        }
-       if ((cp = index(buf, '\n')) != NULL)
+       if ((cp = strchr(buf, '\n')) != NULL)
                *cp = '\0';
        return (buf);
 }
                *cp = '\0';
        return (buf);
 }
@@ -764,7 +743,9 @@ onoff(bool)
  * Show status.
  */
 /*ARGSUSED*/
  * Show status.
  */
 /*ARGSUSED*/
+void
 status(argc, argv)
 status(argc, argv)
+       int argc;
        char *argv[];
 {
        int i;
        char *argv[];
 {
        int i;
@@ -818,7 +799,10 @@ status(argc, argv)
  * Set beep on cmd completed mode.
  */
 /*VARARGS*/
  * Set beep on cmd completed mode.
  */
 /*VARARGS*/
-setbell()
+void
+setbell(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        bell = !bell;
 {
 
        bell = !bell;
@@ -830,7 +814,10 @@ setbell()
  * Turn on packet tracing.
  */
 /*VARARGS*/
  * Turn on packet tracing.
  */
 /*VARARGS*/
-settrace()
+void
+settrace(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        trace = !trace;
 {
 
        trace = !trace;
@@ -842,14 +829,17 @@ settrace()
  * Toggle hash mark printing during transfers.
  */
 /*VARARGS*/
  * Toggle hash mark printing during transfers.
  */
 /*VARARGS*/
-sethash()
+void
+sethash(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        hash = !hash;
        printf("Hash mark printing %s", onoff(hash));
        code = hash;
        if (hash)
 {
 
        hash = !hash;
        printf("Hash mark printing %s", onoff(hash));
        code = hash;
        if (hash)
-               printf(" (%d bytes/hash mark)", BUFSIZ);
+               printf(" (%d bytes/hash mark)", 1024);
        printf(".\n");
 }
 
        printf(".\n");
 }
 
@@ -857,7 +847,10 @@ sethash()
  * Turn on printing of server echo's.
  */
 /*VARARGS*/
  * Turn on printing of server echo's.
  */
 /*VARARGS*/
-setverbose()
+void
+setverbose(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        verbose = !verbose;
 {
 
        verbose = !verbose;
@@ -869,7 +862,10 @@ setverbose()
  * Toggle PORT cmd use before each data connection.
  */
 /*VARARGS*/
  * Toggle PORT cmd use before each data connection.
  */
 /*VARARGS*/
-setport()
+void
+setport(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        sendport = !sendport;
 {
 
        sendport = !sendport;
@@ -882,7 +878,10 @@ setport()
  * during mget, mput, and mdelete.
  */
 /*VARARGS*/
  * during mget, mput, and mdelete.
  */
 /*VARARGS*/
-setprompt()
+void
+setprompt(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        interactive = !interactive;
 {
 
        interactive = !interactive;
@@ -895,7 +894,10 @@ setprompt()
  * on local file names.
  */
 /*VARARGS*/
  * on local file names.
  */
 /*VARARGS*/
-setglob()
+void
+setglob(argc, argv)
+       int argc;
+       char *argv[];
 {
        
        doglob = !doglob;
 {
        
        doglob = !doglob;
@@ -908,7 +910,9 @@ setglob()
  * set level of debugging.
  */
 /*VARARGS*/
  * set level of debugging.
  */
 /*VARARGS*/
+void
 setdebug(argc, argv)
 setdebug(argc, argv)
+       int argc;
        char *argv[];
 {
        int val;
        char *argv[];
 {
        int val;
@@ -935,31 +939,31 @@ setdebug(argc, argv)
  * Set current working directory
  * on remote machine.
  */
  * Set current working directory
  * on remote machine.
  */
+void
 cd(argc, argv)
 cd(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-directory) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s remote-directory\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
+               printf("usage: %s remote-directory\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
-       (void) command("CWD %s", argv[1]);
+       if (command("CWD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("CWD command not recognized, trying XCWD\n");
+               (void) command("XCWD %s", argv[1]);
+       }
 }
 
 /*
  * Set current working directory
  * on local machine.
  */
 }
 
 /*
  * Set current working directory
  * on local machine.
  */
+void
 lcd(argc, argv)
 lcd(argc, argv)
+       int argc;
        char *argv[];
 {
        char buf[MAXPATHLEN];
        char *argv[];
 {
        char buf[MAXPATHLEN];
@@ -967,7 +971,7 @@ lcd(argc, argv)
        if (argc < 2)
                argc++, argv[1] = home;
        if (argc != 2) {
        if (argc < 2)
                argc++, argv[1] = home;
        if (argc != 2) {
-               printf("usage:%s local-directory\n", argv[0]);
+               printf("usage: %s local-directory\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -976,7 +980,7 @@ lcd(argc, argv)
                return;
        }
        if (chdir(argv[1]) < 0) {
                return;
        }
        if (chdir(argv[1]) < 0) {
-               perror(argv[1]);
+               warn("local: %s", argv[1]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -987,20 +991,14 @@ lcd(argc, argv)
 /*
  * Delete a single file.
  */
 /*
  * Delete a single file.
  */
+void
 delete(argc, argv)
 delete(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s remote-file\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+               printf("usage: %s remote-file\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -1010,23 +1008,17 @@ delete(argc, argv)
 /*
  * Delete multiple files.
  */
 /*
  * Delete multiple files.
  */
+void
 mdelete(argc, argv)
 mdelete(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
+       sig_t oldintr;
+       int ointer;
        char *cp;
        char *cp;
-       int ointer, (*oldintr)(), mabort();
-       extern jmp_buf jabort;
 
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-files) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s remote-files\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+               printf("usage: %s remote-files\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -1058,34 +1050,20 @@ mdelete(argc, argv)
 /*
  * Rename a remote file.
  */
 /*
  * Rename a remote file.
  */
+void
 renamefile(argc, argv)
 renamefile(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(from-name) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
+       if (argc < 2 && !another(&argc, &argv, "from-name"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "to-name")) {
 usage:
                printf("%s from-name to-name\n", argv[0]);
                code = -1;
                return;
        }
 usage:
                printf("%s from-name to-name\n", argv[0]);
                code = -1;
                return;
        }
-       if (argc < 3) {
-               (void) strcat(line, " ");
-               printf("(to-name) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 3) 
-               goto usage;
        if (command("RNFR %s", argv[1]) == CONTINUE)
                (void) command("RNTO %s", argv[2]);
 }
        if (command("RNFR %s", argv[1]) == CONTINUE)
                (void) command("RNTO %s", argv[2]);
 }
@@ -1094,7 +1072,9 @@ usage:
  * Get a directory listing
  * of remote files.
  */
  * Get a directory listing
  * of remote files.
  */
+void
 ls(argc, argv)
 ls(argc, argv)
+       int argc;
        char *argv[];
 {
        char *cmd;
        char *argv[];
 {
        char *cmd;
@@ -1118,56 +1098,46 @@ ls(argc, argv)
                        code = -1;
                        return;
        }
                        code = -1;
                        return;
        }
-       recvrequest(cmd, argv[2], argv[1], "w");
+       recvrequest(cmd, argv[2], argv[1], "w", 0);
 }
 
 /*
  * Get a directory listing
  * of multiple remote files.
  */
 }
 
 /*
  * Get a directory listing
  * of multiple remote files.
  */
+void
 mls(argc, argv)
 mls(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
+       sig_t oldintr;
+       int ointer, i;
        char *cmd, mode[1], *dest;
        char *cmd, mode[1], *dest;
-       int ointer, i, (*oldintr)(), mabort();
-       extern jmp_buf jabort;
 
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(remote-files) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 3) {
-               (void) strcat(line, " ");
-               printf("(local-file) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 3) {
-               printf("usage:%s remote-files local-file\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "remote-files"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+               printf("usage: %s remote-files local-file\n", argv[0]);
                code = -1;
                return;
        }
        dest = argv[argc - 1];
        argv[argc - 1] = NULL;
        if (strcmp(dest, "-") && *dest != '|')
                code = -1;
                return;
        }
        dest = argv[argc - 1];
        argv[argc - 1] = NULL;
        if (strcmp(dest, "-") && *dest != '|')
-               if (!globulize(&dest) || !confirm("output to local-file:", dest)) {
+               if (!globulize(&dest) ||
+                   !confirm("output to local-file:", dest)) {
                        code = -1;
                        return;
        }
                        code = -1;
                        return;
        }
-       cmd = argv[0][1] == 'n' ? "NLST" : "LIST";
+       cmd = argv[0][1] == 'l' ? "NLST" : "LIST";
        mname = argv[0];
        mflag = 1;
        oldintr = signal(SIGINT, mabort);
        (void) setjmp(jabort);
        for (i = 1; mflag && i < argc-1; ++i) {
                *mode = (i == 1) ? 'w' : 'a';
        mname = argv[0];
        mflag = 1;
        oldintr = signal(SIGINT, mabort);
        (void) setjmp(jabort);
        for (i = 1; mflag && i < argc-1; ++i) {
                *mode = (i == 1) ? 'w' : 'a';
-               recvrequest(cmd, dest, argv[i], mode);
+               recvrequest(cmd, dest, argv[i], mode, 0);
                if (!mflag && fromatty) {
                        ointer = interactive;
                        interactive = 1;
                if (!mflag && fromatty) {
                        ointer = interactive;
                        interactive = 1;
@@ -1185,10 +1155,13 @@ mls(argc, argv)
  * Do a shell escape
  */
 /*ARGSUSED*/
  * Do a shell escape
  */
 /*ARGSUSED*/
+void
 shell(argc, argv)
 shell(argc, argv)
-       char *argv[];
+       int argc;
+       char **argv;
 {
 {
-       int pid, (*old1)(), (*old2)();
+       pid_t pid;
+       sig_t old1, old2;
        char shellnam[40], *shell, *namep; 
        union wait status;
 
        char shellnam[40], *shell, *namep; 
        union wait status;
 
@@ -1201,8 +1174,8 @@ shell(argc, argv)
                (void) signal(SIGQUIT, SIG_DFL);
                shell = getenv("SHELL");
                if (shell == NULL)
                (void) signal(SIGQUIT, SIG_DFL);
                shell = getenv("SHELL");
                if (shell == NULL)
-                       shell = "/bin/sh";
-               namep = rindex(shell,'/');
+                       shell = _PATH_BSHELL;
+               namep = strrchr(shell,'/');
                if (namep == NULL)
                        namep = shell;
                (void) strcpy(shellnam,"-");
                if (namep == NULL)
                        namep = shell;
                (void) strcpy(shellnam,"-");
@@ -1219,47 +1192,41 @@ shell(argc, argv)
                else {
                        execl(shell,shellnam,(char *)0);
                }
                else {
                        execl(shell,shellnam,(char *)0);
                }
-               perror(shell);
+               warn("%s", shell);
                code = -1;
                exit(1);
                code = -1;
                exit(1);
-               }
+       }
        if (pid > 0)
        if (pid > 0)
-               while (wait(&status) != pid)
+               while (wait((int *)&status) != pid)
                        ;
        (void) signal(SIGINT, old1);
        (void) signal(SIGQUIT, old2);
        if (pid == -1) {
                        ;
        (void) signal(SIGINT, old1);
        (void) signal(SIGQUIT, old2);
        if (pid == -1) {
-               perror("Try again later");
+               warn("%s", "Try again later");
                code = -1;
        }
        else {
                code = 0;
        }
                code = -1;
        }
        else {
                code = 0;
        }
-       return (0);
 }
 
 /*
  * Send new user information (re-login)
  */
 }
 
 /*
  * Send new user information (re-login)
  */
+void
 user(argc, argv)
        int argc;
        char **argv;
 {
 user(argc, argv)
        int argc;
        char **argv;
 {
-       char acct[80], *getpass();
+       char acct[80];
        int n, aflag = 0;
 
        int n, aflag = 0;
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(username) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc > 4) {
+       if (argc < 2)
+               (void) another(&argc, &argv, "username");
+       if (argc < 2 || argc > 4) {
                printf("usage: %s username [password] [account]\n", argv[0]);
                code = -1;
                printf("usage: %s username [password] [account]\n", argv[0]);
                code = -1;
-               return (0);
+               return;
        }
        n = command("USER %s", argv[1]);
        if (n == CONTINUE) {
        }
        n = command("USER %s", argv[1]);
        if (n == CONTINUE) {
@@ -1279,106 +1246,188 @@ user(argc, argv)
        }
        if (n != COMPLETE) {
                fprintf(stdout, "Login failed.\n");
        }
        if (n != COMPLETE) {
                fprintf(stdout, "Login failed.\n");
-               return (0);
+               return;
        }
        if (!aflag && argc == 4) {
                (void) command("ACCT %s", argv[3]);
        }
        }
        if (!aflag && argc == 4) {
                (void) command("ACCT %s", argv[3]);
        }
-       return (1);
 }
 
 /*
  * Print working directory.
  */
 /*VARARGS*/
 }
 
 /*
  * Print working directory.
  */
 /*VARARGS*/
-pwd()
+void
+pwd(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+       int oldverbose = verbose;
 
 
-       (void) command("PWD");
+       /*
+        * If we aren't verbose, this doesn't do anything!
+        */
+       verbose = 1;
+       if (command("PWD") == ERROR && code == 500) {
+               printf("PWD command not recognized, trying XPWD\n");
+               (void) command("XPWD");
+       }
+       verbose = oldverbose;
 }
 
 /*
  * Make a directory.
  */
 }
 
 /*
  * Make a directory.
  */
+void
 makedir(argc, argv)
 makedir(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(directory-name) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
+       if (argc < 2 && !another(&argc, &argv, "directory-name")) {
                printf("usage: %s directory-name\n", argv[0]);
                code = -1;
                return;
        }
                printf("usage: %s directory-name\n", argv[0]);
                code = -1;
                return;
        }
-       (void) command("MKD %s", argv[1]);
+       if (command("MKD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("MKD command not recognized, trying XMKD\n");
+               (void) command("XMKD %s", argv[1]);
+       }
 }
 
 /*
  * Remove a directory.
  */
 }
 
 /*
  * Remove a directory.
  */
+void
 removedir(argc, argv)
 removedir(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(directory-name) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
+       if (argc < 2 && !another(&argc, &argv, "directory-name")) {
                printf("usage: %s directory-name\n", argv[0]);
                code = -1;
                return;
        }
                printf("usage: %s directory-name\n", argv[0]);
                code = -1;
                return;
        }
-       (void) command("RMD %s", argv[1]);
+       if (command("RMD %s", argv[1]) == ERROR && code == 500) {
+               if (verbose)
+                       printf("RMD command not recognized, trying XRMD\n");
+               (void) command("XRMD %s", argv[1]);
+       }
 }
 
 /*
  * Send a line, verbatim, to the remote machine.
  */
 }
 
 /*
  * Send a line, verbatim, to the remote machine.
  */
+void
 quote(argc, argv)
 quote(argc, argv)
+       int argc;
        char *argv[];
 {
        char *argv[];
 {
-       int i;
-       char buf[BUFSIZ];
 
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(command line to send) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
+       if (argc < 2 && !another(&argc, &argv, "command line to send")) {
+               printf("usage: %s line-to-send\n", argv[0]);
+               code = -1;
+               return;
        }
        }
-       if (argc < 2) {
+       quote1("", argc, argv);
+}
+
+/*
+ * Send a SITE command to the remote machine.  The line
+ * is sent verbatim to the remote machine, except that the
+ * word "SITE" is added at the front.
+ */
+void
+site(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
                printf("usage: %s line-to-send\n", argv[0]);
                code = -1;
                return;
        }
                printf("usage: %s line-to-send\n", argv[0]);
                code = -1;
                return;
        }
-       (void) strcpy(buf, argv[1]);
-       for (i = 2; i < argc; i++) {
-               (void) strcat(buf, " ");
-               (void) strcat(buf, argv[i]);
+       quote1("SITE ", argc, argv);
+}
+
+/*
+ * Turn argv[1..argc) into a space-separated string, then prepend initial text.
+ * Send the result as a one-line command and get response.
+ */
+void
+quote1(initial, argc, argv)
+       char *initial;
+       int argc;
+       char **argv;
+{
+       int i, len;
+       char buf[BUFSIZ];               /* must be >= sizeof(line) */
+
+       (void) strcpy(buf, initial);
+       if (argc > 1) {
+               len = strlen(buf);
+               len += strlen(strcpy(&buf[len], argv[1]));
+               for (i = 2; i < argc; i++) {
+                       buf[len++] = ' ';
+                       len += strlen(strcpy(&buf[len], argv[i]));
+               }
        }
        if (command(buf) == PRELIM) {
        }
        if (command(buf) == PRELIM) {
-               while (getreply(0) == PRELIM);
+               while (getreply(0) == PRELIM)
+                       continue;
        }
 }
 
        }
 }
 
+void
+do_chmod(argc, argv)
+       int argc;
+       char *argv[];
+{
+
+       if (argc < 2 && !another(&argc, &argv, "mode"))
+               goto usage;
+       if (argc < 3 && !another(&argc, &argv, "file-name")) {
+usage:
+               printf("usage: %s mode file-name\n", argv[0]);
+               code = -1;
+               return;
+       }
+       (void) command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void
+do_umask(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       verbose = 1;
+       (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+       verbose = oldverbose;
+}
+
+void
+idle(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int oldverbose = verbose;
+
+       verbose = 1;
+       (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
+       verbose = oldverbose;
+}
+
 /*
  * Ask the other side for help.
  */
 /*
  * Ask the other side for help.
  */
+void
 rmthelp(argc, argv)
 rmthelp(argc, argv)
+       int argc;
        char *argv[];
 {
        int oldverbose = verbose;
        char *argv[];
 {
        int oldverbose = verbose;
@@ -1392,14 +1441,17 @@ rmthelp(argc, argv)
  * Terminate session and exit.
  */
 /*VARARGS*/
  * Terminate session and exit.
  */
 /*VARARGS*/
-quit()
+void
+quit(argc, argv)
+       int argc;
+       char *argv[];
 {
 
        if (connected)
 {
 
        if (connected)
-               disconnect();
+               disconnect(0, 0);
        pswitch(1);
        if (connected) {
        pswitch(1);
        if (connected) {
-               disconnect();
+               disconnect(0, 0);
        }
        exit(0);
 }
        }
        exit(0);
 }
@@ -1407,10 +1459,11 @@ quit()
 /*
  * Terminate session, but don't exit.
  */
 /*
  * Terminate session, but don't exit.
  */
-disconnect()
+void
+disconnect(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
-       extern FILE *cout;
-       extern int data;
 
        if (!connected)
                return;
 
        if (!connected)
                return;
@@ -1426,6 +1479,7 @@ disconnect()
        }
 }
 
        }
 }
 
+int
 confirm(cmd, file)
        char *cmd, *file;
 {
 confirm(cmd, file)
        char *cmd, *file;
 {
@@ -1435,16 +1489,17 @@ confirm(cmd, file)
                return (1);
        printf("%s %s? ", cmd, file);
        (void) fflush(stdout);
                return (1);
        printf("%s %s? ", cmd, file);
        (void) fflush(stdout);
-       (void) gets(line);
+       if (fgets(line, sizeof line, stdin) == NULL)
+               return (0);
        return (*line != 'n' && *line != 'N');
 }
 
        return (*line != 'n' && *line != 'N');
 }
 
+void
 fatal(msg)
        char *msg;
 {
 
 fatal(msg)
        char *msg;
 {
 
-       fprintf(stderr, "ftp: %s\n", msg);
-       exit(1);
+       errx(1, "%s", msg);
 }
 
 /*
 }
 
 /*
@@ -1453,6 +1508,7 @@ fatal(msg)
  * Can't control multiple values being expanded
  * from the expression, we return only the first.
  */
  * Can't control multiple values being expanded
  * from the expression, we return only the first.
  */
+int
 globulize(cpp)
        char **cpp;
 {
 globulize(cpp)
        char **cpp;
 {
@@ -1460,26 +1516,27 @@ globulize(cpp)
 
        if (!doglob)
                return (1);
 
        if (!doglob)
                return (1);
-       globbed = glob(*cpp);
+       globbed = ftpglob(*cpp);
        if (globerr != NULL) {
                printf("%s: %s\n", *cpp, globerr);
                if (globbed) {
                        blkfree(globbed);
        if (globerr != NULL) {
                printf("%s: %s\n", *cpp, globerr);
                if (globbed) {
                        blkfree(globbed);
-                       free(globbed);
+                       free((char *)globbed);
                }
                return (0);
        }
        if (globbed) {
                *cpp = *globbed++;
                /* don't waste too much memory */
                }
                return (0);
        }
        if (globbed) {
                *cpp = *globbed++;
                /* don't waste too much memory */
-               if (*globbed) {
+               if (globbed) {
                        blkfree(globbed);
                        blkfree(globbed);
-                       free(globbed);
+                       free((char *)*globbed);
                }
        }
        return (1);
 }
 
                }
        }
        return (1);
 }
 
+void
 account(argc,argv)
        int argc;
        char **argv;
 account(argc,argv)
        int argc;
        char **argv;
@@ -1506,9 +1563,9 @@ account(argc,argv)
 
 jmp_buf abortprox;
 
 
 jmp_buf abortprox;
 
+void
 proxabort()
 {
 proxabort()
 {
-       extern int proxy;
 
        if (!proxy) {
                pswitch(1);
 
        if (!proxy) {
                pswitch(1);
@@ -1523,26 +1580,16 @@ proxabort()
        longjmp(abortprox,1);
 }
 
        longjmp(abortprox,1);
 }
 
-doproxy(argc,argv)
+void
+doproxy(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-       int (*oldintr)(), proxabort();
-       register struct cmd *c;
-       struct cmd *getcmd();
-       extern struct cmd cmdtab[];
-       extern jmp_buf abortprox;
+       struct cmd *c;
+       sig_t oldintr;
 
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(command) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s command\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "command")) {
+               printf("usage: %s command\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -1590,20 +1637,29 @@ doproxy(argc,argv)
        (void) signal(SIGINT, oldintr);
 }
 
        (void) signal(SIGINT, oldintr);
 }
 
-setcase()
+void
+setcase(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+
        mcase = !mcase;
        printf("Case mapping %s.\n", onoff(mcase));
        code = mcase;
 }
 
        mcase = !mcase;
        printf("Case mapping %s.\n", onoff(mcase));
        code = mcase;
 }
 
-setcr()
+void
+setcr(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+
        crflag = !crflag;
        printf("Carriage Return stripping %s.\n", onoff(crflag));
        code = crflag;
 }
 
        crflag = !crflag;
        printf("Carriage Return stripping %s.\n", onoff(crflag));
        code = crflag;
 }
 
+void
 setntrans(argc,argv)
        int argc;
        char *argv[];
 setntrans(argc,argv)
        int argc;
        char *argv[];
@@ -1632,9 +1688,10 @@ dotrans(name)
 {
        static char new[MAXPATHLEN];
        char *cp1, *cp2 = new;
 {
        static char new[MAXPATHLEN];
        char *cp1, *cp2 = new;
-       register int i, ostop, found;
+       int i, ostop, found;
 
 
-       for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++);
+       for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
+               continue;
        for (cp1 = name; *cp1; cp1++) {
                found = 0;
                for (i = 0; *(ntin + i) && i < 16; i++) {
        for (cp1 = name; *cp1; cp1++) {
                found = 0;
                for (i = 0; *(ntin + i) && i < 16; i++) {
@@ -1651,9 +1708,10 @@ dotrans(name)
                }
        }
        *cp2 = '\0';
                }
        }
        *cp2 = '\0';
-       return(new);
+       return (new);
 }
 
 }
 
+void
 setnmap(argc, argv)
        int argc;
        char *argv[];
 setnmap(argc, argv)
        int argc;
        char *argv[];
@@ -1666,30 +1724,24 @@ setnmap(argc, argv)
                code = mapflag;
                return;
        }
                code = mapflag;
                return;
        }
-       if (argc < 3) {
-               (void) strcat(line, " ");
-               printf("(mapout) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 3) {
+       if (argc < 3 && !another(&argc, &argv, "mapout")) {
                printf("Usage: %s [mapin mapout]\n",argv[0]);
                code = -1;
                return;
        }
        mapflag = 1;
        code = 1;
                printf("Usage: %s [mapin mapout]\n",argv[0]);
                code = -1;
                return;
        }
        mapflag = 1;
        code = 1;
-       cp = index(altarg, ' ');
+       cp = strchr(altarg, ' ');
        if (proxy) {
        if (proxy) {
-               while(*++cp == ' ');
+               while(*++cp == ' ')
+                       continue;
                altarg = cp;
                altarg = cp;
-               cp = index(altarg, ' ');
+               cp = strchr(altarg, ' ');
        }
        *cp = '\0';
        (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
        }
        *cp = '\0';
        (void) strncpy(mapin, altarg, MAXPATHLEN - 1);
-       while (*++cp == ' ');
+       while (*++cp == ' ')
+               continue;
        (void) strncpy(mapout, cp, MAXPATHLEN - 1);
 }
 
        (void) strncpy(mapout, cp, MAXPATHLEN - 1);
 }
 
@@ -1698,7 +1750,7 @@ domap(name)
        char *name;
 {
        static char new[MAXPATHLEN];
        char *name;
 {
        static char new[MAXPATHLEN];
-       register char *cp1 = name, *cp2 = mapin;
+       char *cp1 = name, *cp2 = mapin;
        char *tp[9], *te[9];
        int i, toks[9], toknum = 0, match = 1;
 
        char *tp[9], *te[9];
        int i, toks[9], toknum = 0, match = 1;
 
@@ -1804,7 +1856,7 @@ LOOP:
                                        }
                                        if (!*cp2) {
                                                printf("nmap: unbalanced brackets\n");
                                        }
                                        if (!*cp2) {
                                                printf("nmap: unbalanced brackets\n");
-                                               return(name);
+                                               return (name);
                                        }
                                        match = 1;
                                        cp2--;
                                        }
                                        match = 1;
                                        cp2--;
@@ -1817,7 +1869,7 @@ LOOP:
                                        }
                                        if (!*cp2) {
                                                printf("nmap: unbalanced brackets\n");
                                        }
                                        if (!*cp2) {
                                                printf("nmap: unbalanced brackets\n");
-                                               return(name);
+                                               return (name);
                                        }
                                        break;
                                }
                                        }
                                        break;
                                }
@@ -1858,52 +1910,59 @@ LOOP:
        }
        *cp1 = '\0';
        if (!*new) {
        }
        *cp1 = '\0';
        if (!*new) {
-               return(name);
+               return (name);
        }
        }
-       return(new);
+       return (new);
 }
 
 }
 
-setsunique()
+void
+setsunique(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+
        sunique = !sunique;
        printf("Store unique %s.\n", onoff(sunique));
        code = sunique;
 }
 
        sunique = !sunique;
        printf("Store unique %s.\n", onoff(sunique));
        code = sunique;
 }
 
-setrunique()
+void
+setrunique(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+
        runique = !runique;
        printf("Receive unique %s.\n", onoff(runique));
        code = runique;
 }
 
 /* change directory to perent directory */
        runique = !runique;
        printf("Receive unique %s.\n", onoff(runique));
        code = runique;
 }
 
 /* change directory to perent directory */
-cdup()
-{
-       (void) command("CDUP");
-}
-
-/* restart transfer at specific point */
-restart(argc, argv)
+void
+cdup(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-       extern long atol();
-       if (argc != 2)
-               printf("restart: offset not specified\n");
-       else {
-               restart_point = atol(argv[1]);
-               printf("restarting at %ld. execute get, put or append to initiate transfer\n",
-                       restart_point);
+
+       if (command("CDUP") == ERROR && code == 500) {
+               if (verbose)
+                       printf("CDUP command not recognized, trying XCUP\n");
+               (void) command("XCUP");
        }
 }
 
        }
 }
 
+
 /* show remote system type */
 /* show remote system type */
-syst()
+void
+syst(argc, argv)
+       int argc;
+       char *argv[];
 {
 {
+
        (void) command("SYST");
 }
 
        (void) command("SYST");
 }
 
+void
 macdef(argc, argv)
        int argc;
        char *argv[];
 macdef(argc, argv)
        int argc;
        char *argv[];
@@ -1916,15 +1975,7 @@ macdef(argc, argv)
                code = -1;
                return;
        }
                code = -1;
                return;
        }
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(macro name) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc != 2) {
+       if (argc < 2 && !another(&argc, &argv, "macro name")) {
                printf("Usage: %s macro_name\n",argv[0]);
                code = -1;
                return;
                printf("Usage: %s macro_name\n",argv[0]);
                code = -1;
                return;
@@ -1975,20 +2026,14 @@ macdef(argc, argv)
 /*
  * get size of file on remote machine
  */
 /*
  * get size of file on remote machine
  */
+void
 sizecmd(argc, argv)
 sizecmd(argc, argv)
+       int argc;
        char *argv[];
 {
 
        char *argv[];
 {
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(filename) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s filename\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "filename")) {
+               printf("usage: %s filename\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
@@ -1998,25 +2043,21 @@ sizecmd(argc, argv)
 /*
  * get last modification time of file on remote machine
  */
 /*
  * get last modification time of file on remote machine
  */
+void
 modtime(argc, argv)
 modtime(argc, argv)
+       int argc;
        char *argv[];
 {
        int overbose;
 
        char *argv[];
 {
        int overbose;
 
-       if (argc < 2) {
-               (void) strcat(line, " ");
-               printf("(filename) ");
-               (void) gets(&line[strlen(line)]);
-               makeargv();
-               argc = margc;
-               argv = margv;
-       }
-       if (argc < 2) {
-               printf("usage:%s filename\n", argv[0]);
+       if (argc < 2 && !another(&argc, &argv, "filename")) {
+               printf("usage: %s filename\n", argv[0]);
                code = -1;
                return;
        }
                code = -1;
                return;
        }
-       overbose = verbose; verbose = -1;
+       overbose = verbose;
+       if (debug == 0)
+               verbose = -1;
        if (command("MDTM %s", argv[1]) == COMPLETE) {
                int yy, mo, day, hour, min, sec;
                sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
        if (command("MDTM %s", argv[1]) == COMPLETE) {
                int yy, mo, day, hour, min, sec;
                sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
@@ -2025,26 +2066,18 @@ modtime(argc, argv)
                printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
                        mo, day, yy, hour, min, sec);
        } else
                printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
                        mo, day, yy, hour, min, sec);
        } else
-               fputs(reply_string, stdout);
+               printf("%s\n", reply_string);
        verbose = overbose;
 }
 
 /*
        verbose = overbose;
 }
 
 /*
- * show status on reomte machine
+ * show status on remote machine
  */
  */
+void
 rmtstatus(argc, argv)
 rmtstatus(argc, argv)
+       int argc;
        char *argv[];
 {
        char *argv[];
 {
-       (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
-}
 
 
-/*
- * get file if modtime is more recent than current file
- */
-newer(argc, argv)
-       char *argv[];
-{
-       if (getit(argc, argv, -1, "w"))
-               printf("Local file \"%s\" is newer than remote file \"%s\"\n",
-                       argv[1], argv[2]);
+       (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
 }
 }