/*
- * Copyright (c) 1985 Regents of the University of California.
+ * 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 MERCHANTIBILITY 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.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)cmds.c 5.26 (Berkeley) 3/5/91";
#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 <arpa/ftp.h>
#include <errno.h>
#include <netdb.h>
#include <ctype.h>
-#include <sys/wait.h>
+#include <time.h>
+#include <netinet/in.h>
+#include "ftp_var.h"
+#include "pathnames.h"
extern char *globerr;
-extern char **glob();
+extern char **ftpglob();
extern char *home;
-extern short gflag;
extern char *remglob();
extern char *getenv();
extern char *index();
extern char *rindex();
+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.
char *argv[];
{
char *host, *hookup();
- int port;
+ short port;
if (connected) {
printf("Already connected to %s, use close first.\n",
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;
}
host = hookup(argv[1], port);
if (host) {
+ 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]);
+
+#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;
+ if (debug == 0)
+ 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)) {
+ 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 */
}
}
* Set transfer type.
*/
settype(argc, argv)
+ int argc;
char *argv[];
{
register struct types *p;
sep = " ";
for (p = types; p->t_name; p++) {
printf("%s%s", sep, p->t_name);
- if (*sep == ' ')
- sep = " | ";
+ sep = " | ";
}
printf(" ]\n");
code = -1;
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);
}
/*
*/
/*ARGSUSED*/
setmode(argc, argv)
+ int argc;
char *argv[];
{
*/
/*ARGSUSED*/
setform(argc, argv)
+ int argc;
char *argv[];
{
*/
/*ARGSUSED*/
setstruct(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) {
- (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])) {
code = -1;
return;
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.
*/
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;
}
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;
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;
}
continue;
}
- gargs = glob(argv[i]);
+ gargs = ftpglob(argv[i]);
if (globerr != NULL) {
printf("%s\n", globerr);
- if (gargs)
+ if (gargs) {
blkfree(gargs);
+ free((char *)gargs);
+ }
continue;
}
for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
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 (gargs != NULL)
+ if (gargs != NULL) {
blkfree(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;
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;
- 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];
argv[2] = tmpbuf;
}
}
- if (loc && ntflag) {
+ if (loc && ntflag)
argv[2] = dotrans(argv[2]);
- }
- if (loc && mapflag) {
+ if (loc && mapflag)
argv[2] = domap(argv[2]);
+ 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], "w");
+
+ recvrequest("RETR", argv[2], argv[1], mode,
+ argv[1] != oldargv1 || argv[2] != oldargv2);
+ restart_point = 0;
+ return (0);
}
+void
mabort()
{
int ointer;
* 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;
}
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;
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;
pswitch(!proxy);
}
for (mode = "w"; *++argv != NULL; mode = "a")
- recvrequest ("NLST", temp, *argv, mode);
+ recvrequest ("NLST", temp, *argv, mode, 0);
if (doswitch) {
pswitch(!proxy);
}
*/
/*ARGSUSED*/
status(argc, argv)
+ int argc;
char *argv[];
{
int i;
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");
}
*/
/*VARARGS*/
setdebug(argc, argv)
+ int argc;
char *argv[];
{
int val;
* 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;
}
- (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]);
+ }
}
/*
* 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;
}
return;
}
if (chdir(argv[1]) < 0) {
- perror(argv[1]);
+ fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno));
code = -1;
return;
}
* 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;
}
* 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;
}
* 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]);
}
* of remote files.
*/
ls(argc, argv)
+ int argc;
char *argv[];
{
char *cmd;
code = -1;
return;
}
- cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
+ cmd = argv[0][0] == 'n' ? "NLST" : "LIST";
if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
code = -1;
return;
code = -1;
return;
}
- recvrequest(cmd, argv[2], argv[1], "w");
+ recvrequest(cmd, argv[2], argv[1], "w", 0);
}
/*
* 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;
}
(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;
*/
/*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;
(void) signal(SIGQUIT, SIG_DFL);
shell = getenv("SHELL");
if (shell == NULL)
- shell = "/bin/sh";
+ shell = _PATH_BSHELL;
namep = rindex(shell,'/');
if (namep == NULL)
namep = shell;
exit(1);
}
if (pid > 0)
- while (wait(&status) != pid)
+ while (wait((int *)&status) != pid)
;
(void) signal(SIGINT, old1);
(void) signal(SIGQUIT, old2);
int argc;
char **argv;
{
- char acct[80], *mygetpass();
+ 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);
n = command("USER %s", argv[1]);
if (n == CONTINUE) {
if (argc < 3 )
- argv[2] = mygetpass("Password: "), argc++;
+ argv[2] = getpass("Password: "), argc++;
n = command("PASS %s", argv[2]);
}
if (n == CONTINUE) {
/*VARARGS*/
pwd()
{
+ 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.
*/
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;
}
- (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.
*/
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;
}
- (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.
*/
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 && !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.
+ */
+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;
}
- (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.
+ */
+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);
}
}
+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]);
+}
+
+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;
+}
+
+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.
*/
rmthelp(argc, argv)
+ int argc;
char *argv[];
{
int oldverbose = verbose;
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');
}
if (!doglob)
return (1);
- globbed = glob(*cpp);
+ globbed = ftpglob(*cpp);
if (globerr != NULL) {
printf("%s: %s\n", *cpp, globerr);
- if (globbed)
+ if (globbed) {
blkfree(globbed);
+ free((char *)globbed);
+ }
return (0);
}
if (globbed) {
*cpp = *globbed++;
/* don't waste too much memory */
- if (*globbed)
+ if (*globbed) {
blkfree(globbed);
+ free((char *)globbed);
+ }
}
return (1);
}
account(argc,argv)
-
int argc;
char **argv;
{
- char acct[50], *mygetpass(), *ap;
+ char acct[50], *getpass(), *ap;
if (argc > 1) {
++argv;
--argc;
(void) strncpy(acct,*argv,49);
- acct[50] = '\0';
+ acct[49] = '\0';
while (argc > 1) {
--argc;
++argv;
ap = acct;
}
else {
- ap = mygetpass("Account:");
+ ap = getpass("Account:");
}
(void) command("ACCT %s", ap);
}
jmp_buf abortprox;
+void
proxabort()
{
extern int proxy;
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;
}
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;
static char new[MAXPATHLEN];
register char *cp1 = name, *cp2 = mapin;
char *tp[9], *te[9];
- int i, toks[9], toknum, match = 1;
+ int i, toks[9], toknum = 0, match = 1;
for (i=0; i < 9; ++i) {
toks[i] = 0;
cp2++;
break;
}
- /* intentional drop through */
+ /* FALLTHROUGH */
default:
if (*cp2 != *cp1) {
match = 0;
}
break;
}
- if (*cp1) {
+ if (match && *cp1) {
cp1++;
}
- if (*cp2) {
+ if (match && *cp2) {
cp2++;
}
}
+ if (!match && *cp1) /* last token mismatch */
+ {
+ toks[toknum] = 0;
+ }
cp1 = new;
*cp1 = '\0';
cp2 = mapout;
/* change directory to perent directory */
cdup()
{
- (void) command("CDUP");
+ if (command("CDUP") == ERROR && code == 500) {
+ if (verbose)
+ printf("CDUP command not recognized, trying XCUP\n");
+ (void) command("XCUP");
+ }
+}
+
+/* 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()
+{
+ (void) command("SYST");
}
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;
tmp++;
}
while (1) {
- while ((c = getchar()) != '\n' && c != EOF);
+ while ((c = getchar()) != '\n' && c != EOF)
+ /* LOOP */;
if (c == EOF || getchar() == '\n') {
printf("Macro not defined - 4k buffer exceeded\n");
code = -1;
}
}
}
+
+/*
+ * get size of file on remote machine
+ */
+sizecmd(argc, argv)
+ int argc;
+ char *argv[];
+{
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ (void) command("SIZE %s", argv[1]);
+}
+
+/*
+ * get last modification time of file on remote machine
+ */
+modtime(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int overbose;
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ 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,
+ &day, &hour, &min, &sec);
+ /* might want to print this in local time */
+ printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
+ mo, day, yy, hour, min, sec);
+ } else
+ printf("%s\n", reply_string);
+ verbose = overbose;
+}
+
+/*
+ * 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]);
+}