X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f58943be0bb3ef87ab57a0464b8d22bc0d6acbe7..2c5d7f0d9c585d802fda462dedefa62250eeb73d:/usr/src/usr.bin/ftp/cmds.c diff --git a/usr/src/usr.bin/ftp/cmds.c b/usr/src/usr.bin/ftp/cmds.c index d830852106..56cc42806f 100644 --- a/usr/src/usr.bin/ftp/cmds.c +++ b/usr/src/usr.bin/ftp/cmds.c @@ -2,21 +2,37 @@ * Copyright (c) 1985, 1989 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. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef lint -static char sccsid[] = "@(#)cmds.c 5.18 (Berkeley) %G%"; +static char sccsid[] = "@(#)cmds.c 5.26 (Berkeley) 3/5/91"; #endif /* not lint */ /* @@ -35,24 +51,59 @@ static char sccsid[] = "@(#)cmds.c 5.18 (Berkeley) %G%"; #include #include #include +#include #include "ftp_var.h" #include "pathnames.h" extern char *globerr; -extern char **glob(); +extern char **ftpglob(); extern char *home; extern char *remglob(); extern char *getenv(); extern char *index(); extern char *rindex(); -extern int allbinary; +extern char *strerror(); +extern int errno; +extern off_t restart_point; extern char reply_string[]; 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. + */ +another(pargc, pargv, prompt) + int *pargc; + char ***pargv; + char *prompt; +{ + int len = strlen(line), ret; + extern sig_t intr(); + + 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. @@ -62,7 +113,7 @@ setpeer(argc, argv) char *argv[]; { char *host, *hookup(); - int port; + short port; if (connected) { printf("Already connected to %s, use close first.\n", @@ -70,15 +121,9 @@ setpeer(argc, argv) 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; @@ -99,6 +144,15 @@ setpeer(argc, argv) int overbose; connected = 1; + /* + * 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]); @@ -110,7 +164,6 @@ setpeer(argc, argv) overbose = verbose; if (debug == 0) verbose = -1; - allbinary = 0; if (command("SYST") == COMPLETE && overbose) { register char *cp, c; cp = index(reply_string+4, ' '); @@ -129,14 +182,29 @@ setpeer(argc, argv) *cp = c; } if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { - setbinary(); - allbinary = 1; + 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 (overbose && - !strncmp(reply_string, "215 TOPS20", 10)) { - printf( + } 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; @@ -162,6 +230,7 @@ struct types { * Set transfer type. */ settype(argc, argv) + int argc; char *argv[]; { register struct types *p; @@ -174,8 +243,7 @@ settype(argc, argv) sep = " "; for (p = types; p->t_name; p++) { printf("%s%s", sep, p->t_name); - if (*sep == ' ') - sep = " | "; + sep = " | "; } printf(" ]\n"); code = -1; @@ -200,48 +268,77 @@ settype(argc, argv) 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() +changetype(newtype, show) + int newtype, show; { + register 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*/ -setascii() +setbinary() { - - call(settype, "type", "ascii", 0); + stype[1] = "binary"; + settype(2, stype); } /* - * Set tenex transfer type. + * Set ascii transfer type. */ /*VARARGS*/ -settenex() +setascii() { - - call(settype, "type", "tenex", 0); + stype[1] = "ascii"; + settype(2, stype); } /* - * Set ebcdic transfer type. + * Set tenex transfer type. */ /*VARARGS*/ -setebcdic() +settenex() { - - call(settype, "type", "ebcdic", 0); + stype[1] = "tenex"; + settype(2, stype); } /* @@ -249,6 +346,7 @@ setebcdic() */ /*ARGSUSED*/ setmode(argc, argv) + int argc; char *argv[]; { @@ -261,6 +359,7 @@ setmode(argc, argv) */ /*ARGSUSED*/ setform(argc, argv) + int argc; char *argv[]; { @@ -273,6 +372,7 @@ setform(argc, argv) */ /*ARGSUSED*/ setstruct(argc, argv) + int argc; char *argv[]; { @@ -296,30 +396,14 @@ put(argc, argv) 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: - printf("usage:%s local-file remote-file\n", argv[0]); + printf("usage: %s local-file remote-file\n", argv[0]); 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]; oldargv2 = argv[2]; if (!globulize(&argv[1])) { @@ -348,23 +432,18 @@ usage: * Send multiple files. */ mput(argc, argv) - char *argv[]; + int argc; + char **argv; { - register int i; - int ointer, (*oldintr)(), mabort(); extern jmp_buf jabort; + register int i; + sig_t oldintr; + int ointer; char *tp; + void mabort(); - 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; } @@ -441,12 +520,12 @@ mput(argc, argv) } continue; } - gargs = glob(argv[i]); + gargs = ftpglob(argv[i]); if (globerr != NULL) { printf("%s\n", globerr); if (gargs) { blkfree(gargs); - free(gargs); + free((char *)gargs); } continue; } @@ -468,19 +547,34 @@ mput(argc, argv) } if (gargs != NULL) { blkfree(gargs); - free(gargs); + free((char *)gargs); } } (void) signal(SIGINT, oldintr); mflag = 0; } +reget(argc, argv) + int argc; + char *argv[]; +{ + (void) getit(argc, argv, 1, "r+w"); +} + +get(argc, argv) + int argc; + char *argv[]; +{ + (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); +} /* * Receive one file. */ -get(argc, argv) +getit(argc, argv, restartit, mode) + int argc; char *argv[]; + char *mode; { int loc = 0; char *oldargv1, *oldargv2; @@ -490,35 +584,19 @@ get(argc, argv) 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; - return; - } - if (argc < 3) { - (void) strcat(line, " "); - printf("(local-file) "); - (void) gets(&line[strlen(line)]); - makeargv(); - argc = margc; - argv = margv; + return (0); } - if (argc < 3) - goto usage; oldargv1 = argv[1]; oldargv2 = argv[2]; if (!globulize(&argv[2])) { code = -1; - return; + return (0); } if (loc && mcase) { char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; @@ -543,9 +621,68 @@ usage: argv[2] = dotrans(argv[2]); if (loc && mapflag) argv[2] = domap(argv[2]); - recvrequest("RETR", argv[2], argv[1], "w"); + if (restartit) { + struct stat stbuf; + int ret; + + ret = stat(argv[2], &stbuf); + if (restartit == 1) { + if (ret < 0) { + fprintf(stderr, "local: %s: %s\n", argv[2], + strerror(errno)); + return (0); + } + restart_point = stbuf.st_size; + } else { + if (ret == 0) { + int overbose; + + overbose = verbose; + if (debug == 0) + 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 { + printf("%s\n", reply_string); + verbose = overbose; + return (0); + } + } + } + } + + recvrequest("RETR", argv[2], argv[1], mode, + argv[1] != oldargv1 || argv[2] != oldargv2); + restart_point = 0; + return (0); } +void mabort() { int ointer; @@ -570,22 +707,17 @@ mabort() * Get multiple files. */ mget(argc, argv) - char *argv[]; + int argc; + char **argv; { - char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; - int ointer, (*oldintr)(), mabort(); extern jmp_buf jabort; + sig_t oldintr; + int ointer; + char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; + void mabort(); - 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; } @@ -713,6 +845,7 @@ onoff(bool) */ /*ARGSUSED*/ status(argc, argv) + int argc; char *argv[]; { int i; @@ -857,6 +990,7 @@ setglob() */ /*VARARGS*/ setdebug(argc, argv) + int argc; char *argv[]; { int val; @@ -884,19 +1018,12 @@ setdebug(argc, argv) * on remote machine. */ cd(argc, argv) + int argc; 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; } @@ -912,14 +1039,16 @@ cd(argc, argv) * on local machine. */ lcd(argc, argv) + int argc; char *argv[]; { char buf[MAXPATHLEN]; + extern char *getwd(); 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; } @@ -928,7 +1057,7 @@ lcd(argc, argv) return; } if (chdir(argv[1]) < 0) { - perror(argv[1]); + fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); code = -1; return; } @@ -940,19 +1069,12 @@ lcd(argc, argv) * Delete a single file. */ delete(argc, argv) + int argc; 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; } @@ -963,22 +1085,17 @@ delete(argc, argv) * Delete multiple files. */ mdelete(argc, argv) - char *argv[]; + int argc; + char **argv; { - char *cp; - int ointer, (*oldintr)(), mabort(); extern jmp_buf jabort; + sig_t oldintr; + int ointer; + char *cp; + void mabort(); - 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; } @@ -1011,33 +1128,18 @@ mdelete(argc, argv) * Rename a remote file. */ renamefile(argc, argv) + int argc; 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; } - 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]); } @@ -1047,6 +1149,7 @@ usage: * of remote files. */ ls(argc, argv) + int argc; char *argv[]; { char *cmd; @@ -1078,37 +1181,28 @@ ls(argc, argv) * of multiple remote files. */ mls(argc, argv) - char *argv[]; + int argc; + char **argv; { - char *cmd, mode[1], *dest; - int ointer, i, (*oldintr)(), mabort(); extern jmp_buf jabort; + sig_t oldintr; + int ointer, i; + char *cmd, mode[1], *dest; + void mabort(); - 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 != '|') - if (!globulize(&dest) || !confirm("output to local-file:", dest)) { + if (!globulize(&dest) || + !confirm("output to local-file:", dest)) { code = -1; return; } @@ -1138,9 +1232,11 @@ mls(argc, argv) */ /*ARGSUSED*/ shell(argc, argv) - char *argv[]; + int argc; + char **argv; { - int pid, (*old1)(), (*old2)(); + int pid; + sig_t old1, old2; char shellnam[40], *shell, *namep; union wait status; @@ -1176,7 +1272,7 @@ shell(argc, argv) exit(1); } if (pid > 0) - while (wait(&status) != pid) + while (wait((int *)&status) != pid) ; (void) signal(SIGINT, old1); (void) signal(SIGQUIT, old2); @@ -1200,15 +1296,9 @@ user(argc, argv) char acct[80], *getpass(); 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; return (0); @@ -1262,18 +1352,11 @@ pwd() * Make a directory. */ makedir(argc, argv) + int argc; 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; @@ -1289,18 +1372,11 @@ makedir(argc, argv) * Remove a directory. */ removedir(argc, argv) + int argc; 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; @@ -1316,64 +1392,56 @@ removedir(argc, argv) * Send a line, verbatim, to the remote machine. */ quote(argc, argv) + int argc; 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) { + if (argc < 2 && !another(&argc, &argv, "command line to send")) { 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]); - } - if (command(buf) == PRELIM) { - while (getreply(0) == PRELIM); - } + quote1("", argc, argv); } /* * Send a SITE command to the remote machine. The line - * is sent almost verbatim to the remote machine, the - * first argument is changed to SITE. + * is sent verbatim to the remote machine, except that the + * word "SITE" is added at the front. */ - site(argc, argv) + int argc; char *argv[]; { - int i; - char buf[BUFSIZ]; - if (argc < 2) { - (void) strcat(line, " "); - printf("(arguments to SITE command) "); - (void) gets(&line[strlen(line)]); - makeargv(); - argc = margc; - argv = margv; - } - if (argc < 2) { + if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { printf("usage: %s line-to-send\n", argv[0]); code = -1; return; } - (void) strcpy(buf, "SITE "); - (void) strcat(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. + */ +quote1(initial, argc, argv) + char *initial; + int argc; + char **argv; +{ + register 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) { while (getreply(0) == PRELIM); @@ -1381,30 +1449,23 @@ site(argc, argv) } do_chmod(argc, argv) + int argc; char *argv[]; { - if (argc == 2) { - printf("usage: %s mode file-name\n", argv[0]); - code = -1; - return; - } - if (argc < 3) { - (void) strcat(line, " "); - printf("(mode and file-name) "); - (void) gets(&line[strlen(line)]); - makeargv(); - argc = margc; - argv = margv; - } - if (argc != 3) { + + 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) command("SITE CHMOD %s %s", argv[1], argv[2]); } do_umask(argc, argv) + int argc; char *argv[]; { int oldverbose = verbose; @@ -1415,6 +1476,7 @@ do_umask(argc, argv) } idle(argc, argv) + int argc; char *argv[]; { int oldverbose = verbose; @@ -1428,6 +1490,7 @@ idle(argc, argv) * Ask the other side for help. */ rmthelp(argc, argv) + int argc; char *argv[]; { int oldverbose = verbose; @@ -1484,7 +1547,8 @@ confirm(cmd, file) 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'); } @@ -1509,12 +1573,12 @@ globulize(cpp) if (!doglob) return (1); - globbed = glob(*cpp); + globbed = ftpglob(*cpp); if (globerr != NULL) { printf("%s: %s\n", *cpp, globerr); if (globbed) { blkfree(globbed); - free(globbed); + free((char *)globbed); } return (0); } @@ -1523,7 +1587,7 @@ globulize(cpp) /* don't waste too much memory */ if (*globbed) { blkfree(globbed); - free(globbed); + free((char *)globbed); } } return (1); @@ -1555,6 +1619,7 @@ account(argc,argv) jmp_buf abortprox; +void proxabort() { extern int proxy; @@ -1576,22 +1641,15 @@ doproxy(argc,argv) int argc; char *argv[]; { - int (*oldintr)(), proxabort(); - register struct cmd *c; - struct cmd *getcmd(); extern struct cmd cmdtab[]; extern jmp_buf abortprox; + register struct cmd *c; + struct cmd *getcmd(); + sig_t oldintr; + void proxabort(); - 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; } @@ -1715,15 +1773,7 @@ setnmap(argc, argv) 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; @@ -1936,6 +1986,20 @@ cdup() } } +/* restart transfer at specific point */ +restart(argc, 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. %s\n", restart_point, + "execute get, put or append to initiate transfer"); + } +} /* show remote system type */ syst() @@ -1955,15 +2019,7 @@ macdef(argc, argv) 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; @@ -2015,19 +2071,12 @@ macdef(argc, argv) * get size of file on remote machine */ sizecmd(argc, argv) + int argc; 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; } @@ -2038,20 +2087,13 @@ sizecmd(argc, argv) * get last modification time of file on remote machine */ modtime(argc, argv) + int argc; 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; } @@ -2066,15 +2108,28 @@ modtime(argc, argv) 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; } /* - * show status on remote machine + * show status on reomte machine */ rmtstatus(argc, argv) + int argc; char *argv[]; { (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); } + +/* + * get file if modtime is more recent than current file + */ +newer(argc, argv) + int argc; + char *argv[]; +{ + if (getit(argc, argv, -1, "w")) + printf("Local file \"%s\" is newer than remote file \"%s\"\n", + argv[1], argv[2]); +}