[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
/* $NetBSD: cmds.c,v 1.18 1997/02/01 10:44:54 lukem Exp $ */
|
1995-09-08 05:05:59 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-08-25 07:47:50 +04:00
|
|
|
* Copyright (c) 1985, 1989, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* 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
|
1995-09-08 05:05:59 +04:00
|
|
|
#if 0
|
|
|
|
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
|
|
|
|
#else
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
static char rcsid[] = "$NetBSD: cmds.c,v 1.18 1997/02/01 10:44:54 lukem Exp $";
|
1995-09-08 05:05:59 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FTP User Program -- Command Routines.
|
|
|
|
*/
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <sys/types.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <sys/socket.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/wait.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <arpa/ftp.h>
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include <glob.h>
|
|
|
|
#include <netdb.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <stdio.h>
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#include "ftp_var.h"
|
|
|
|
#include "pathnames.h"
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
jmp_buf jabort;
|
|
|
|
char *mname;
|
|
|
|
char *home = "/";
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
struct types {
|
|
|
|
char *t_name;
|
|
|
|
char *t_mode;
|
|
|
|
int t_type;
|
|
|
|
char *t_arg;
|
|
|
|
} types[] = {
|
|
|
|
{ "ascii", "A", TYPE_A, 0 },
|
|
|
|
{ "binary", "I", TYPE_I, 0 },
|
|
|
|
{ "image", "I", TYPE_I, 0 },
|
|
|
|
{ "ebcdic", "E", TYPE_E, 0 },
|
|
|
|
{ "tenex", "L", TYPE_L, bytename },
|
1994-08-25 07:47:50 +04:00
|
|
|
{ NULL }
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set transfer type.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
settype(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
struct types *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
int comret;
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
char *sep;
|
|
|
|
|
|
|
|
printf("usage: %s [", argv[0]);
|
|
|
|
sep = " ";
|
|
|
|
for (p = types; p->t_name; p++) {
|
|
|
|
printf("%s%s", sep, p->t_name);
|
|
|
|
sep = " | ";
|
|
|
|
}
|
|
|
|
printf(" ]\n");
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (argc < 2) {
|
|
|
|
printf("Using %s mode to transfer files.\n", typename);
|
|
|
|
code = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (p = types; p->t_name; p++)
|
|
|
|
if (strcmp(argv[1], p->t_name) == 0)
|
|
|
|
break;
|
|
|
|
if (p->t_name == 0) {
|
|
|
|
printf("%s: unknown mode\n", argv[1]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
|
|
|
|
comret = command ("TYPE %s %s", p->t_mode, p->t_arg);
|
|
|
|
else
|
|
|
|
comret = command("TYPE %s", p->t_mode);
|
|
|
|
if (comret == COMPLETE) {
|
|
|
|
(void) strcpy(typename, p->t_name);
|
|
|
|
curtype = type = p->t_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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
changetype(newtype, show)
|
|
|
|
int newtype, show;
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
struct types *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
int comret, oldverbose = verbose;
|
|
|
|
|
|
|
|
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 binary transfer type.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setbinary(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
stype[1] = "binary";
|
|
|
|
settype(2, stype);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set ascii transfer type.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setascii(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
stype[1] = "ascii";
|
|
|
|
settype(2, stype);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set tenex transfer type.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
settenex(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
stype[1] = "tenex";
|
|
|
|
settype(2, stype);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set file transfer mode.
|
|
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setftmode(argc, argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("We only support %s mode, sorry.\n", modename);
|
|
|
|
code = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set file transfer format.
|
|
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
setform(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("We only support %s format, sorry.\n", formname);
|
|
|
|
code = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set file transfer structure.
|
|
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
setstruct(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
printf("We only support %s structure, sorry.\n", structname);
|
|
|
|
code = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send a single file.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
put(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char *cmd;
|
|
|
|
int loc = 0;
|
|
|
|
char *oldargv1, *oldargv2;
|
|
|
|
|
|
|
|
if (argc == 2) {
|
|
|
|
argc++;
|
|
|
|
argv[2] = argv[1];
|
|
|
|
loc++;
|
|
|
|
}
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "local-file"))
|
|
|
|
goto usage;
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
|
1993-03-21 12:45:37 +03:00
|
|
|
usage:
|
1996-11-25 08:13:18 +03:00
|
|
|
printf("usage: %s local-file [ remote-file ]\n", argv[0]);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
oldargv1 = argv[1];
|
|
|
|
oldargv2 = argv[2];
|
|
|
|
if (!globulize(&argv[1])) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If "globulize" modifies argv[1], and argv[2] is a copy of
|
|
|
|
* the old argv[1], make it a copy of the new argv[1].
|
|
|
|
*/
|
|
|
|
if (argv[1] != oldargv1 && argv[2] == oldargv1) {
|
|
|
|
argv[2] = argv[1];
|
|
|
|
}
|
|
|
|
cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
|
|
|
|
if (loc && ntflag) {
|
|
|
|
argv[2] = dotrans(argv[2]);
|
|
|
|
}
|
|
|
|
if (loc && mapflag) {
|
|
|
|
argv[2] = domap(argv[2]);
|
|
|
|
}
|
|
|
|
sendrequest(cmd, argv[1], argv[2],
|
|
|
|
argv[1] != oldargv1 || argv[2] != oldargv2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send multiple files.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
mput(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
int i;
|
1993-03-21 12:45:37 +03:00
|
|
|
sig_t oldintr;
|
|
|
|
int ointer;
|
|
|
|
char *tp;
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "local-files")) {
|
|
|
|
printf("usage: %s local-files\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mname = argv[0];
|
|
|
|
mflag = 1;
|
|
|
|
oldintr = signal(SIGINT, mabort);
|
|
|
|
(void) setjmp(jabort);
|
|
|
|
if (proxy) {
|
|
|
|
char *cp, *tp2, tmpbuf[MAXPATHLEN];
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
while ((cp = remglob(argv, 0)) != NULL) {
|
1997-01-19 17:19:02 +03:00
|
|
|
if (*cp == '\0') {
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tp = tmpbuf;
|
|
|
|
}
|
|
|
|
if (ntflag) {
|
|
|
|
tp = dotrans(tp);
|
|
|
|
}
|
|
|
|
if (mapflag) {
|
|
|
|
tp = domap(tp);
|
|
|
|
}
|
|
|
|
sendrequest((sunique) ? "STOU" : "STOR",
|
|
|
|
cp, tp, cp != tp || !interactive);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
1996-11-28 06:12:28 +03:00
|
|
|
if (confirm("Continue with", "mput")) {
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
mflag = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (i = 1; i < argc; i++) {
|
1996-11-25 08:13:18 +03:00
|
|
|
char **cpp;
|
1994-08-25 07:47:50 +04:00
|
|
|
glob_t gl;
|
|
|
|
int flags;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
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, tp != argv[i] || !interactive);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
1996-11-28 06:12:28 +03:00
|
|
|
if (confirm("Continue with", "mput")) {
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
|
|
|
|
memset(&gl, 0, sizeof(gl));
|
|
|
|
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
|
|
|
|
if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
|
|
|
|
warnx("%s: not found", argv[i]);
|
|
|
|
globfree(&gl);
|
1993-03-21 12:45:37 +03:00
|
|
|
continue;
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (mflag && confirm(argv[0], *cpp)) {
|
|
|
|
tp = (ntflag) ? dotrans(*cpp) : *cpp;
|
|
|
|
tp = (mapflag) ? domap(tp) : tp;
|
|
|
|
sendrequest((sunique) ? "STOU" : "STOR",
|
|
|
|
*cpp, tp, *cpp != tp || !interactive);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
1996-11-28 06:12:28 +03:00
|
|
|
if (confirm("Continue with", "mput")) {
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
globfree(&gl);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
mflag = 0;
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
reget(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) getit(argc, argv, 1, "r+w");
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
get(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Receive one file.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
getit(argc, argv, restartit, mode)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1994-08-25 07:47:50 +04:00
|
|
|
int restartit;
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *mode;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
int loc = 0;
|
|
|
|
char *oldargv1, *oldargv2;
|
|
|
|
|
|
|
|
if (argc == 2) {
|
|
|
|
argc++;
|
|
|
|
argv[2] = argv[1];
|
|
|
|
loc++;
|
|
|
|
}
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "remote-file"))
|
|
|
|
goto usage;
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
|
1993-03-21 12:45:37 +03:00
|
|
|
usage:
|
|
|
|
printf("usage: %s remote-file [ local-file ]\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
oldargv1 = argv[1];
|
|
|
|
oldargv2 = argv[2];
|
|
|
|
if (!globulize(&argv[2])) {
|
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (loc && mcase) {
|
|
|
|
char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
|
|
|
|
|
|
|
|
while (*tp && !islower(*tp)) {
|
|
|
|
tp++;
|
|
|
|
}
|
|
|
|
if (!*tp) {
|
|
|
|
tp = argv[2];
|
|
|
|
tp2 = tmpbuf;
|
|
|
|
while ((*tp2 = *tp) != NULL) {
|
|
|
|
if (isupper(*tp2)) {
|
|
|
|
*tp2 = 'a' + *tp2 - 'A';
|
|
|
|
}
|
|
|
|
tp++;
|
|
|
|
tp2++;
|
|
|
|
}
|
|
|
|
argv[2] = tmpbuf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (loc && ntflag)
|
|
|
|
argv[2] = dotrans(argv[2]);
|
|
|
|
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) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", argv[2]);
|
1993-03-21 12:45:37 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
restart_point = stbuf.st_size;
|
|
|
|
} else {
|
|
|
|
if (ret == 0) {
|
1996-11-28 06:12:28 +03:00
|
|
|
time_t mtime;
|
|
|
|
|
1996-12-29 07:05:29 +03:00
|
|
|
mtime = remotemodtime(argv[1], 0);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (mtime == -1)
|
1997-01-19 17:19:02 +03:00
|
|
|
return (0);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (stbuf.st_mtime >= mtime)
|
|
|
|
return (1);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
recvrequest("RETR", argv[2], argv[1], mode,
|
|
|
|
argv[1] != oldargv1 || argv[2] != oldargv2);
|
|
|
|
restart_point = 0;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
/* ARGSUSED */
|
1993-03-21 12:45:37 +03:00
|
|
|
void
|
1994-08-25 07:47:50 +04:00
|
|
|
mabort(signo)
|
|
|
|
int signo;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1996-11-28 06:12:28 +03:00
|
|
|
int ointer, oconf;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
alarmtimer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("\n");
|
|
|
|
(void) fflush(stdout);
|
|
|
|
if (mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
1996-11-28 06:12:28 +03:00
|
|
|
oconf = confirmrest;
|
1993-03-21 12:45:37 +03:00
|
|
|
interactive = 1;
|
1996-11-28 06:12:28 +03:00
|
|
|
confirmrest = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (confirm("Continue with", mname)) {
|
|
|
|
interactive = ointer;
|
1996-11-28 06:12:28 +03:00
|
|
|
confirmrest = oconf;
|
|
|
|
longjmp(jabort, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
interactive = ointer;
|
1996-11-28 06:12:28 +03:00
|
|
|
confirmrest = oconf;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
mflag = 0;
|
1996-11-28 06:12:28 +03:00
|
|
|
longjmp(jabort, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get multiple files.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
mget(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
sig_t oldintr;
|
1994-08-25 07:47:50 +04:00
|
|
|
int ch, ointer;
|
1993-03-21 12:45:37 +03:00
|
|
|
char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "remote-files")) {
|
|
|
|
printf("usage: %s remote-files\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mname = argv[0];
|
|
|
|
mflag = 1;
|
1994-08-25 07:47:50 +04:00
|
|
|
oldintr = signal(SIGINT, mabort);
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) setjmp(jabort);
|
1996-11-28 06:12:28 +03:00
|
|
|
while ((cp = remglob(argv, proxy)) != NULL) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (*cp == '\0') {
|
|
|
|
mflag = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (mflag && confirm(argv[0], cp)) {
|
|
|
|
tp = cp;
|
|
|
|
if (mcase) {
|
1996-11-25 08:13:18 +03:00
|
|
|
for (tp2 = tmpbuf; (ch = *tp++) != NULL; )
|
1994-08-25 07:47:50 +04:00
|
|
|
*tp2++ = isupper(ch) ? tolower(ch) : ch;
|
1994-12-15 11:58:44 +03:00
|
|
|
*tp2 = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
tp = tmpbuf;
|
|
|
|
}
|
|
|
|
if (ntflag) {
|
|
|
|
tp = dotrans(tp);
|
|
|
|
}
|
|
|
|
if (mapflag) {
|
|
|
|
tp = domap(tp);
|
|
|
|
}
|
|
|
|
recvrequest("RETR", tp, cp, "w",
|
|
|
|
tp != cp || !interactive);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
1996-11-28 06:12:28 +03:00
|
|
|
if (confirm("Continue with", "mget")) {
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
(void) signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
onoff(bool)
|
|
|
|
int bool;
|
|
|
|
{
|
|
|
|
|
|
|
|
return (bool ? "on" : "off");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Show status.
|
|
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
status(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (connected)
|
|
|
|
printf("Connected to %s.\n", hostname);
|
|
|
|
else
|
|
|
|
printf("Not connected.\n");
|
|
|
|
if (!proxy) {
|
|
|
|
pswitch(1);
|
|
|
|
if (connected) {
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Connected for proxy commands to %s.\n",
|
|
|
|
hostname);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("No proxy connection.\n");
|
|
|
|
}
|
|
|
|
pswitch(0);
|
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Passive mode: %s.\n", onoff(passivemode));
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
|
|
|
|
modename, typename, formname, structname);
|
1996-11-25 08:13:18 +03:00
|
|
|
printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
|
1993-03-21 12:45:37 +03:00
|
|
|
onoff(verbose), onoff(bell), onoff(interactive),
|
|
|
|
onoff(doglob));
|
|
|
|
printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
|
|
|
|
onoff(runique));
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Preserve modification times: %s\n", onoff(preserve));
|
|
|
|
printf("Case: %s; CR stripping: %s\n", onoff(mcase), onoff(crflag));
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ntflag) {
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Ntrans: (in) %s (out) %s\n", ntin, ntout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("Ntrans: off\n");
|
|
|
|
}
|
|
|
|
if (mapflag) {
|
|
|
|
printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("Nmap: off\n");
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
printf("Hash mark printing: %s; Mark count: %d; Progress bar: %s\n",
|
|
|
|
onoff(hash), mark, onoff(progress));
|
1996-11-25 08:13:18 +03:00
|
|
|
printf("Use of PORT cmds: %s\n", onoff(sendport));
|
1997-01-19 17:19:02 +03:00
|
|
|
#ifndef SMALLFTP
|
|
|
|
printf("Command line editing: %s\n", onoff(editing));
|
|
|
|
#endif /* !SMALLFTP */
|
1993-03-21 12:45:37 +03:00
|
|
|
if (macnum > 0) {
|
|
|
|
printf("Macros:\n");
|
|
|
|
for (i=0; i<macnum; i++) {
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("\t%s\n", macros[i].mac_name);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
code = 0;
|
|
|
|
}
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
/*
|
|
|
|
* Toggle a variable
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
togglevar(argc, argv, var, mesg)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
int *var;
|
|
|
|
const char *mesg;
|
|
|
|
{
|
|
|
|
if (argc < 2) {
|
|
|
|
*var = !*var;
|
|
|
|
} else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
|
|
|
|
*var = 1;
|
|
|
|
} else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
|
|
|
|
*var = 0;
|
|
|
|
} else {
|
|
|
|
printf("usage: %s [ on | off ]\n", argv[0]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("%s %s.\n", mesg, onoff(*var));
|
|
|
|
return *var;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Set beep on cmd completed mode.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setbell(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &bell, "Bell mode");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
#ifndef SMALLFTP
|
|
|
|
/*
|
|
|
|
* Set command line editing
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
|
|
|
void
|
|
|
|
setedit(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
code = togglevar(argc, argv, &editing, "Editing mode");
|
|
|
|
}
|
|
|
|
#endif /* !SMALLFTP */
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Turn on packet tracing.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
settrace(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &trace, "Packet tracing");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1996-11-25 08:13:18 +03:00
|
|
|
* Toggle hash mark printing during transfers, or set hash mark bytecount.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
sethash(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1996-11-28 06:12:28 +03:00
|
|
|
if (argc == 1)
|
1996-11-25 08:13:18 +03:00
|
|
|
hash = !hash;
|
1996-11-28 06:12:28 +03:00
|
|
|
else if (argc != 2) {
|
|
|
|
printf("usage: %s [ on | off | bytecount ]\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
} else if (strcasecmp(argv[1], "on") == 0)
|
|
|
|
hash = 1;
|
|
|
|
else if (strcasecmp(argv[1], "off") == 0)
|
|
|
|
hash = 0;
|
|
|
|
else {
|
1996-11-25 08:13:18 +03:00
|
|
|
int nmark = atol(argv[1]);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (nmark < 1) {
|
|
|
|
printf("%s: bad bytecount value\n", argv[1]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
1996-11-25 08:13:18 +03:00
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
mark = nmark;
|
|
|
|
hash = 1;
|
1996-11-25 08:13:18 +03:00
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Hash mark printing %s", onoff(hash));
|
|
|
|
if (hash)
|
|
|
|
printf(" (%d bytes/hash mark)", mark);
|
|
|
|
printf(".\n");
|
|
|
|
code = hash;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Turn on printing of server echo's.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setverbose(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &verbose, "Verbose mode");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toggle PORT cmd use before each data connection.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setport(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &sendport, "Use of PORT cmds");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1996-12-06 05:06:46 +03:00
|
|
|
/*
|
|
|
|
* Toggle transfer progress bar.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
|
|
|
void
|
|
|
|
setprogress(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
code = togglevar(argc, argv, &progress, "Progress bar");
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Turn on interactive prompting
|
|
|
|
* during mget, mput, and mdelete.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setprompt(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &interactive, "Interactive mode");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toggle metacharacter interpretation
|
|
|
|
* on local file names.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setglob(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1996-11-25 08:13:18 +03:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &doglob, "Globbing");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toggle preserving modification times on retreived files.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
|
|
|
void
|
|
|
|
setpreserve(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
code = togglevar(argc, argv, &preserve, "Preserve modification times");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set debugging mode on/off and/or
|
|
|
|
* set level of debugging.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
setdebug(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if (argc > 2) {
|
|
|
|
printf("usage: %s [ on | off | debuglevel ]\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
} else if (argc == 2) {
|
|
|
|
if (strcasecmp(argv[1], "on") == 0)
|
|
|
|
debug = 1;
|
|
|
|
else if (strcasecmp(argv[1], "off") == 0)
|
|
|
|
debug = 0;
|
|
|
|
else {
|
|
|
|
val = atoi(argv[1]);
|
|
|
|
if (val < 0) {
|
|
|
|
printf("%s: bad debugging value.\n", argv[1]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
debug = val;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
} else
|
1996-12-06 05:06:46 +03:00
|
|
|
debug = !debug;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (debug)
|
|
|
|
options |= SO_DEBUG;
|
|
|
|
else
|
|
|
|
options &= ~SO_DEBUG;
|
|
|
|
printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
|
|
|
|
code = debug > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set current working directory
|
|
|
|
* on remote machine.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
cd(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1997-01-19 17:19:02 +03:00
|
|
|
int r;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
|
|
|
|
argc > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("usage: %s remote-directory\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1997-01-19 23:17:37 +03:00
|
|
|
r = command("CWD %s", argv[1]);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (r == ERROR && code == 500) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (verbose)
|
|
|
|
printf("CWD command not recognized, trying XCWD\n");
|
1997-01-19 17:19:02 +03:00
|
|
|
r = command("XCWD %s", argv[1]);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
if (r == COMPLETE)
|
|
|
|
dirchange = 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set current working directory
|
|
|
|
* on local machine.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
lcd(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char buf[MAXPATHLEN];
|
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
argc++, argv[1] = home;
|
|
|
|
if (argc != 2) {
|
|
|
|
printf("usage: %s local-directory\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!globulize(&argv[1])) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (chdir(argv[1]) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", argv[1]);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
if (getcwd(buf, sizeof(buf)) != NULL)
|
1994-08-25 07:47:50 +04:00
|
|
|
printf("Local directory now %s\n", buf);
|
|
|
|
else
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
warn("getcwd: %s", argv[1]);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete a single file.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
delete(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("usage: %s remote-file\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
(void) command("DELE %s", argv[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete multiple files.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
mdelete(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
sig_t oldintr;
|
|
|
|
int ointer;
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "remote-files")) {
|
|
|
|
printf("usage: %s remote-files\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mname = argv[0];
|
|
|
|
mflag = 1;
|
|
|
|
oldintr = signal(SIGINT, mabort);
|
|
|
|
(void) setjmp(jabort);
|
1996-11-28 06:12:28 +03:00
|
|
|
while ((cp = remglob(argv, 0)) != NULL) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (*cp == '\0') {
|
|
|
|
mflag = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (mflag && confirm(argv[0], cp)) {
|
|
|
|
(void) command("DELE %s", cp);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
|
|
|
if (confirm("Continue with", "mdelete")) {
|
|
|
|
mflag++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
mflag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rename a remote file.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
renamefile(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "from-name"))
|
|
|
|
goto usage;
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
|
1993-03-21 12:45:37 +03:00
|
|
|
usage:
|
|
|
|
printf("%s from-name to-name\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (command("RNFR %s", argv[1]) == CONTINUE)
|
|
|
|
(void) command("RNTO %s", argv[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a directory listing
|
|
|
|
* of remote files.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
ls(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *cmd;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
argc++, argv[1] = NULL;
|
|
|
|
if (argc < 3)
|
|
|
|
argc++, argv[2] = "-";
|
|
|
|
if (argc > 3) {
|
|
|
|
printf("usage: %s remote-directory local-file\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
cmd = strcmp(argv[0], "dir") == 0 ? "LIST" : "NLST";
|
1993-03-21 12:45:37 +03:00
|
|
|
if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (strcmp(argv[2], "-") && *argv[2] != '|')
|
1996-12-06 05:06:46 +03:00
|
|
|
if (!globulize(&argv[2]) || !confirm("output to local-file:",
|
|
|
|
argv[2])) {
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
recvrequest(cmd, argv[2], argv[1], "w", 0);
|
1996-11-25 08:13:18 +03:00
|
|
|
|
|
|
|
/* flush results in case commands are coming from a pipe */
|
|
|
|
fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a directory listing
|
|
|
|
* of multiple remote files.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
mls(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
sig_t oldintr;
|
|
|
|
int ointer, i;
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *cmd;
|
|
|
|
char mode[1], *dest;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
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)) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
cmd = strcmp(argv[0], "mls") == 0 ? "NLST" : "LIST";
|
1993-03-21 12:45:37 +03:00
|
|
|
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, 0);
|
|
|
|
if (!mflag && fromatty) {
|
|
|
|
ointer = interactive;
|
|
|
|
interactive = 1;
|
|
|
|
if (confirm("Continue with", argv[0])) {
|
|
|
|
mflag ++;
|
|
|
|
}
|
|
|
|
interactive = ointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
mflag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do a shell escape
|
|
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
shell(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
pid_t pid;
|
1993-03-21 12:45:37 +03:00
|
|
|
sig_t old1, old2;
|
1996-12-29 07:05:29 +03:00
|
|
|
char shellnam[MAXPATHLEN], *shell, *namep;
|
1993-03-21 12:45:37 +03:00
|
|
|
union wait status;
|
|
|
|
|
|
|
|
old1 = signal (SIGINT, SIG_IGN);
|
|
|
|
old2 = signal (SIGQUIT, SIG_IGN);
|
|
|
|
if ((pid = fork()) == 0) {
|
|
|
|
for (pid = 3; pid < 20; pid++)
|
|
|
|
(void) close(pid);
|
|
|
|
(void) signal(SIGINT, SIG_DFL);
|
|
|
|
(void) signal(SIGQUIT, SIG_DFL);
|
|
|
|
shell = getenv("SHELL");
|
|
|
|
if (shell == NULL)
|
|
|
|
shell = _PATH_BSHELL;
|
1996-11-28 06:12:28 +03:00
|
|
|
namep = strrchr(shell, '/');
|
1993-03-21 12:45:37 +03:00
|
|
|
if (namep == NULL)
|
|
|
|
namep = shell;
|
1996-12-29 07:05:29 +03:00
|
|
|
shellnam[0] = '-';
|
|
|
|
(void) strncpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (strcmp(namep, "sh") != 0)
|
|
|
|
shellnam[0] = '+';
|
|
|
|
if (debug) {
|
|
|
|
printf ("%s\n", shell);
|
|
|
|
(void) fflush (stdout);
|
|
|
|
}
|
|
|
|
if (argc > 1) {
|
1996-11-28 06:12:28 +03:00
|
|
|
execl(shell, shellnam, "-c", altarg, (char *)0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
else {
|
1996-11-28 06:12:28 +03:00
|
|
|
execl(shell, shellnam, (char *)0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("%s", shell);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
exit(1);
|
1994-08-25 07:47:50 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (pid > 0)
|
|
|
|
while (wait((int *)&status) != pid)
|
|
|
|
;
|
|
|
|
(void) signal(SIGINT, old1);
|
|
|
|
(void) signal(SIGQUIT, old2);
|
|
|
|
if (pid == -1) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("%s", "Try again later");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
code = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send new user information (re-login)
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
user(argc, argv)
|
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
char acct[80];
|
1993-03-21 12:45:37 +03:00
|
|
|
int n, aflag = 0;
|
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
(void) another(&argc, &argv, "username");
|
|
|
|
if (argc < 2 || argc > 4) {
|
|
|
|
printf("usage: %s username [password] [account]\n", argv[0]);
|
|
|
|
code = -1;
|
1994-08-25 07:47:50 +04:00
|
|
|
return;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
n = command("USER %s", argv[1]);
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
if (argc < 3 )
|
|
|
|
argv[2] = getpass("Password: "), argc++;
|
|
|
|
n = command("PASS %s", argv[2]);
|
|
|
|
}
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
if (argc < 4) {
|
|
|
|
printf("Account: "); (void) fflush(stdout);
|
|
|
|
(void) fgets(acct, sizeof(acct) - 1, stdin);
|
|
|
|
acct[strlen(acct) - 1] = '\0';
|
|
|
|
argv[3] = acct; argc++;
|
|
|
|
}
|
|
|
|
n = command("ACCT %s", argv[3]);
|
|
|
|
aflag++;
|
|
|
|
}
|
|
|
|
if (n != COMPLETE) {
|
|
|
|
fprintf(stdout, "Login failed.\n");
|
1994-08-25 07:47:50 +04:00
|
|
|
return;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (!aflag && argc == 4) {
|
|
|
|
(void) command("ACCT %s", argv[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1996-11-28 06:12:28 +03:00
|
|
|
* Print working directory on remote machine.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
pwd(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
int oldverbose = verbose;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
/*
|
|
|
|
* Print working directory on local machine.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
lpwd(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char buf[MAXPATHLEN];
|
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
if (getcwd(buf, sizeof(buf)) != NULL)
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("Local directory %s\n", buf);
|
|
|
|
else
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
warn("getcwd");
|
1996-11-28 06:12:28 +03:00
|
|
|
code = 0;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Make a directory.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
makedir(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
|
|
|
|
argc > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("usage: %s directory-name\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
removedir(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
|
|
|
|
argc > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("usage: %s directory-name\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
quote(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "command line to send")) {
|
|
|
|
printf("usage: %s line-to-send\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
quote1(initial, argc, argv)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *initial;
|
1993-03-21 12:45:37 +03:00
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
int i, len;
|
1993-03-21 12:45:37 +03:00
|
|
|
char buf[BUFSIZ]; /* must be >= sizeof(line) */
|
|
|
|
|
1996-12-29 07:05:29 +03:00
|
|
|
(void) strncpy(buf, initial, sizeof(buf));
|
1993-03-21 12:45:37 +03:00
|
|
|
if (argc > 1) {
|
|
|
|
len = strlen(buf);
|
1996-12-29 07:05:29 +03:00
|
|
|
len += strlen(strncpy(&buf[len], argv[1], sizeof(buf) - len));
|
1993-03-21 12:45:37 +03:00
|
|
|
for (i = 2; i < argc; i++) {
|
|
|
|
buf[len++] = ' ';
|
1996-12-29 07:05:29 +03:00
|
|
|
len += strlen(strncpy(&buf[len], argv[i],
|
|
|
|
sizeof(buf) - len));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (command(buf) == PRELIM) {
|
1994-08-25 07:47:50 +04:00
|
|
|
while (getreply(0) == PRELIM)
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
do_chmod(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "mode"))
|
|
|
|
goto usage;
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 3 && !another(&argc, &argv, "file-name")) || argc > 3) {
|
1993-03-21 12:45:37 +03:00
|
|
|
usage:
|
|
|
|
printf("usage: %s mode file-name\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
(void) command("SITE CHMOD %s %s", argv[1], argv[2]);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
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.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
rmthelp(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
int oldverbose = verbose;
|
|
|
|
|
|
|
|
verbose = 1;
|
|
|
|
(void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
|
|
|
|
verbose = oldverbose;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Terminate session and exit.
|
|
|
|
*/
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
quit(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
if (connected)
|
1994-08-25 07:47:50 +04:00
|
|
|
disconnect(0, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(1);
|
|
|
|
if (connected) {
|
1994-08-25 07:47:50 +04:00
|
|
|
disconnect(0, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Terminate session, but don't exit.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
disconnect(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
if (!connected)
|
|
|
|
return;
|
|
|
|
(void) command("QUIT");
|
|
|
|
if (cout) {
|
|
|
|
(void) fclose(cout);
|
|
|
|
}
|
|
|
|
cout = NULL;
|
|
|
|
connected = 0;
|
|
|
|
data = -1;
|
|
|
|
if (!proxy) {
|
|
|
|
macnum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1996-11-28 06:12:28 +03:00
|
|
|
account(argc, argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
int argc;
|
1996-11-28 06:12:28 +03:00
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1996-12-29 07:05:29 +03:00
|
|
|
char *ap;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-12-29 07:05:29 +03:00
|
|
|
if (argc > 2) {
|
|
|
|
printf("usage: %s [password]\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-12-29 07:05:29 +03:00
|
|
|
else if (argc == 2)
|
|
|
|
ap = argv[1];
|
|
|
|
else
|
1993-03-21 12:45:37 +03:00
|
|
|
ap = getpass("Account:");
|
|
|
|
(void) command("ACCT %s", ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
jmp_buf abortprox;
|
|
|
|
|
|
|
|
void
|
|
|
|
proxabort()
|
|
|
|
{
|
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
alarmtimer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (!proxy) {
|
|
|
|
pswitch(1);
|
|
|
|
}
|
|
|
|
if (connected) {
|
|
|
|
proxflag = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
proxflag = 0;
|
|
|
|
}
|
|
|
|
pswitch(0);
|
1996-11-28 06:12:28 +03:00
|
|
|
longjmp(abortprox, 1);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
doproxy(argc, argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
struct cmd *c;
|
1997-01-03 05:55:59 +03:00
|
|
|
int cmdpos;
|
1993-03-21 12:45:37 +03:00
|
|
|
sig_t oldintr;
|
|
|
|
|
|
|
|
if (argc < 2 && !another(&argc, &argv, "command")) {
|
|
|
|
printf("usage: %s command\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
c = getcmd(argv[1]);
|
|
|
|
if (c == (struct cmd *) -1) {
|
|
|
|
printf("?Ambiguous command\n");
|
|
|
|
(void) fflush(stdout);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (c == 0) {
|
|
|
|
printf("?Invalid command\n");
|
|
|
|
(void) fflush(stdout);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!c->c_proxy) {
|
|
|
|
printf("?Invalid proxy command\n");
|
|
|
|
(void) fflush(stdout);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (setjmp(abortprox)) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
oldintr = signal(SIGINT, proxabort);
|
|
|
|
pswitch(1);
|
|
|
|
if (c->c_conn && !connected) {
|
|
|
|
printf("Not connected\n");
|
|
|
|
(void) fflush(stdout);
|
|
|
|
pswitch(0);
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1997-01-03 05:55:59 +03:00
|
|
|
cmdpos = strcspn(line, " \t");
|
|
|
|
if (cmdpos > 0) /* remove leading "proxy " from input buffer */
|
|
|
|
memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
|
1993-03-21 12:45:37 +03:00
|
|
|
(*c->c_handler)(argc-1, argv+1);
|
|
|
|
if (connected) {
|
|
|
|
proxflag = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
proxflag = 0;
|
|
|
|
}
|
|
|
|
pswitch(0);
|
|
|
|
(void) signal(SIGINT, oldintr);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setcase(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &mcase, "Case mapping");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setcr(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1996-11-28 06:12:28 +03:00
|
|
|
setntrans(argc, argv)
|
1993-03-21 12:45:37 +03:00
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
if (argc == 1) {
|
|
|
|
ntflag = 0;
|
|
|
|
printf("Ntrans off.\n");
|
|
|
|
code = ntflag;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ntflag++;
|
|
|
|
code = ntflag;
|
|
|
|
(void) strncpy(ntin, argv[1], 16);
|
|
|
|
ntin[16] = '\0';
|
|
|
|
if (argc == 2) {
|
|
|
|
ntout[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
(void) strncpy(ntout, argv[2], 16);
|
|
|
|
ntout[16] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
dotrans(name)
|
|
|
|
char *name;
|
|
|
|
{
|
|
|
|
static char new[MAXPATHLEN];
|
|
|
|
char *cp1, *cp2 = new;
|
1994-08-25 07:47:50 +04:00
|
|
|
int i, ostop, found;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
for (cp1 = name; *cp1; cp1++) {
|
|
|
|
found = 0;
|
|
|
|
for (i = 0; *(ntin + i) && i < 16; i++) {
|
|
|
|
if (*cp1 == *(ntin + i)) {
|
|
|
|
found++;
|
|
|
|
if (i < ostop) {
|
|
|
|
*cp2++ = *(ntout + i);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
*cp2++ = *cp1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*cp2 = '\0';
|
1994-08-25 07:47:50 +04:00
|
|
|
return (new);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
setnmap(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if (argc == 1) {
|
|
|
|
mapflag = 0;
|
|
|
|
printf("Nmap off.\n");
|
|
|
|
code = mapflag;
|
|
|
|
return;
|
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) {
|
|
|
|
printf("Usage: %s [mapin mapout]\n", argv[0]);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mapflag = 1;
|
|
|
|
code = 1;
|
1994-08-25 07:47:50 +04:00
|
|
|
cp = strchr(altarg, ' ');
|
1993-03-21 12:45:37 +03:00
|
|
|
if (proxy) {
|
1994-08-25 07:47:50 +04:00
|
|
|
while(*++cp == ' ')
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
altarg = cp;
|
1994-08-25 07:47:50 +04:00
|
|
|
cp = strchr(altarg, ' ');
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
*cp = '\0';
|
|
|
|
(void) strncpy(mapin, altarg, MAXPATHLEN - 1);
|
1994-08-25 07:47:50 +04:00
|
|
|
while (*++cp == ' ')
|
|
|
|
continue;
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) strncpy(mapout, cp, MAXPATHLEN - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
domap(name)
|
|
|
|
char *name;
|
|
|
|
{
|
|
|
|
static char new[MAXPATHLEN];
|
1994-08-25 07:47:50 +04:00
|
|
|
char *cp1 = name, *cp2 = mapin;
|
1993-03-21 12:45:37 +03:00
|
|
|
char *tp[9], *te[9];
|
|
|
|
int i, toks[9], toknum = 0, match = 1;
|
|
|
|
|
|
|
|
for (i=0; i < 9; ++i) {
|
|
|
|
toks[i] = 0;
|
|
|
|
}
|
|
|
|
while (match && *cp1 && *cp2) {
|
|
|
|
switch (*cp2) {
|
|
|
|
case '\\':
|
|
|
|
if (*++cp2 != *cp1) {
|
|
|
|
match = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '$':
|
|
|
|
if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
|
|
|
|
if (*cp1 != *(++cp2+1)) {
|
|
|
|
toks[toknum = *cp2 - '1']++;
|
|
|
|
tp[toknum] = cp1;
|
|
|
|
while (*++cp1 && *(cp2+1)
|
|
|
|
!= *cp1);
|
|
|
|
te[toknum] = cp1;
|
|
|
|
}
|
|
|
|
cp2++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
if (*cp2 != *cp1) {
|
|
|
|
match = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (match && *cp1) {
|
|
|
|
cp1++;
|
|
|
|
}
|
|
|
|
if (match && *cp2) {
|
|
|
|
cp2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match && *cp1) /* last token mismatch */
|
|
|
|
{
|
|
|
|
toks[toknum] = 0;
|
|
|
|
}
|
|
|
|
cp1 = new;
|
|
|
|
*cp1 = '\0';
|
|
|
|
cp2 = mapout;
|
|
|
|
while (*cp2) {
|
|
|
|
match = 0;
|
|
|
|
switch (*cp2) {
|
|
|
|
case '\\':
|
|
|
|
if (*(cp2 + 1)) {
|
|
|
|
*cp1++ = *++cp2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
LOOP:
|
1996-11-25 08:13:18 +03:00
|
|
|
if (*++cp2 == '$' && isdigit(*(cp2+1))) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (*++cp2 == '0') {
|
|
|
|
char *cp3 = name;
|
|
|
|
|
|
|
|
while (*cp3) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
match = 1;
|
|
|
|
}
|
|
|
|
else if (toks[toknum = *cp2 - '1']) {
|
|
|
|
char *cp3 = tp[toknum];
|
|
|
|
|
|
|
|
while (cp3 != te[toknum]) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
match = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
1996-11-25 08:13:18 +03:00
|
|
|
while (*cp2 && *cp2 != ',' &&
|
1993-03-21 12:45:37 +03:00
|
|
|
*cp2 != ']') {
|
|
|
|
if (*cp2 == '\\') {
|
|
|
|
cp2++;
|
|
|
|
}
|
|
|
|
else if (*cp2 == '$' &&
|
|
|
|
isdigit(*(cp2+1))) {
|
|
|
|
if (*++cp2 == '0') {
|
|
|
|
char *cp3 = name;
|
|
|
|
|
|
|
|
while (*cp3) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (toks[toknum =
|
|
|
|
*cp2 - '1']) {
|
|
|
|
char *cp3=tp[toknum];
|
|
|
|
|
|
|
|
while (cp3 !=
|
|
|
|
te[toknum]) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (*cp2) {
|
|
|
|
*cp1++ = *cp2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!*cp2) {
|
1996-12-06 05:06:46 +03:00
|
|
|
printf("nmap: unbalanced "
|
|
|
|
"brackets\n");
|
1994-08-25 07:47:50 +04:00
|
|
|
return (name);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
match = 1;
|
|
|
|
cp2--;
|
|
|
|
}
|
|
|
|
if (match) {
|
|
|
|
while (*++cp2 && *cp2 != ']') {
|
|
|
|
if (*cp2 == '\\' && *(cp2 + 1)) {
|
|
|
|
cp2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!*cp2) {
|
1996-12-06 05:06:46 +03:00
|
|
|
printf("nmap: unbalanced "
|
|
|
|
"brackets\n");
|
1994-08-25 07:47:50 +04:00
|
|
|
return (name);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (*++cp2) {
|
|
|
|
case ',':
|
|
|
|
goto LOOP;
|
|
|
|
case ']':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cp2--;
|
|
|
|
goto LOOP;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '$':
|
|
|
|
if (isdigit(*(cp2 + 1))) {
|
|
|
|
if (*++cp2 == '0') {
|
|
|
|
char *cp3 = name;
|
|
|
|
|
|
|
|
while (*cp3) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (toks[toknum = *cp2 - '1']) {
|
|
|
|
char *cp3 = tp[toknum];
|
|
|
|
|
|
|
|
while (cp3 != te[toknum]) {
|
|
|
|
*cp1++ = *cp3++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* intentional drop through */
|
|
|
|
default:
|
|
|
|
*cp1++ = *cp2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cp2++;
|
|
|
|
}
|
|
|
|
*cp1 = '\0';
|
|
|
|
if (!*new) {
|
1994-08-25 07:47:50 +04:00
|
|
|
return (name);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
return (new);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 08:27:41 +04:00
|
|
|
void
|
|
|
|
setpassive(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &passivemode, "Passive mode");
|
1994-08-25 08:27:41 +04:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setsunique(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &sunique, "Store unique");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
setrunique(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
code = togglevar(argc, argv, &runique, "Receive unique");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/* change directory to parent directory */
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
cdup(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1997-01-19 17:19:02 +03:00
|
|
|
int r;
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
r = command("CDUP");
|
|
|
|
if (r == ERROR && code == 500) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (verbose)
|
|
|
|
printf("CDUP command not recognized, trying XCUP\n");
|
1997-01-19 17:19:02 +03:00
|
|
|
r = command("XCUP");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
if (r == COMPLETE)
|
|
|
|
dirchange = 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* restart transfer at specific point */
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
restart(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (argc != 2)
|
|
|
|
printf("restart: offset not specified\n");
|
|
|
|
else {
|
|
|
|
restart_point = atol(argv[1]);
|
1996-12-06 05:06:46 +03:00
|
|
|
printf("Restarting at %qd. Execute get, put or append to"
|
|
|
|
"initiate transfer\n", restart_point);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* show remote system type */
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
syst(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) command("SYST");
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
macdef(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
if (macnum == 16) {
|
|
|
|
printf("Limit of 16 macros have already been defined\n");
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
|
|
|
|
printf("Usage: %s macro_name\n", argv[0]);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (interactive) {
|
1996-12-06 05:06:46 +03:00
|
|
|
printf("Enter macro line by line, terminating it with a "
|
|
|
|
"null line\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
(void) strncpy(macros[macnum].mac_name, argv[1], 8);
|
|
|
|
if (macnum == 0) {
|
|
|
|
macros[macnum].mac_start = macbuf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
|
|
|
|
}
|
|
|
|
tmp = macros[macnum].mac_start;
|
|
|
|
while (tmp != macbuf+4096) {
|
|
|
|
if ((c = getchar()) == EOF) {
|
|
|
|
printf("macdef:end of file encountered\n");
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((*tmp = c) == '\n') {
|
|
|
|
if (tmp == macros[macnum].mac_start) {
|
|
|
|
macros[macnum++].mac_end = tmp;
|
|
|
|
code = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (*(tmp-1) == '\0') {
|
|
|
|
macros[macnum++].mac_end = tmp - 1;
|
|
|
|
code = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*tmp = '\0';
|
|
|
|
}
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
while (1) {
|
|
|
|
while ((c = getchar()) != '\n' && c != EOF)
|
|
|
|
/* LOOP */;
|
|
|
|
if (c == EOF || getchar() == '\n') {
|
|
|
|
printf("Macro not defined - 4k buffer exceeded\n");
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get size of file on remote machine
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
sizecmd(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1996-12-06 05:06:46 +03:00
|
|
|
off_t size;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
printf("usage: %s filename\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-29 07:05:29 +03:00
|
|
|
size = remotesize(argv[1], 1);
|
1996-12-06 05:06:46 +03:00
|
|
|
if (size != -1)
|
|
|
|
printf("%s\t%qd\n", argv[1], size);
|
|
|
|
code = size;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
/*
|
|
|
|
* get last modification time of file on remote machine
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
modtime(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
time_t mtime;
|
|
|
|
|
|
|
|
if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
|
|
|
|
printf("usage: %s filename\n", argv[0]);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-29 07:05:29 +03:00
|
|
|
mtime = remotemodtime(argv[1], 1);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (mtime != -1)
|
|
|
|
printf("%s\t%s", argv[1], asctime(localtime(&mtime)));
|
|
|
|
code = mtime;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1996-12-25 19:00:38 +03:00
|
|
|
* show status on remote machine
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
rmtstatus(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
(void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get file if modtime is more recent than current file
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
newer(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
if (getit(argc, argv, -1, "w"))
|
|
|
|
printf("Local file \"%s\" is newer than remote file \"%s\"\n",
|
1994-08-25 07:47:50 +04:00
|
|
|
argv[2], argv[1]);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|