📄 cmds.c
字号:
/* $Id: cmds.c,v 1.14 1998/02/14 15:38:29 steve Exp $ */
/* $NetBSD: cmds.c,v 1.30.2.1 1997/11/18 00:58:26 mellon Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Portions copyright (c) 1999, 2000
* Intel Corporation.
* All rights reserved.
*
* 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, Intel Corporation, and its contributors.
*
* 4. Neither the name of University, Intel Corporation, or their respective
* 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, INTEL CORPORATION 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,
* INTEL CORPORATION 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.
*
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
#else
__RCSID("$Id: cmds.c,v 1.14 1998/02/14 15:38:29 steve Exp $");
__RCSID_SOURCE("$NetBSD: cmds.c,v 1.30.2.1 1997/11/18 00:58:26 mellon Exp $");
#endif
#endif /* not lint */
/*
* FTP User Program -- Command Routines.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#if !EFI32 && !EFI64
#include <sys/wait.h> /* EFI port: not used */
#endif
#include <arpa/ftp.h>
#include <ctype.h>
#include <err.h>
#if EFI32 || EFI64
#include "efimisc.h"
#endif /* EFI32 || EFI64 */
#include <glob.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ftp_var.h"
#include "pathnames.h"
jmp_buf jabort;
char *mname;
char *home = "/";
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 },
{ NULL }
};
/*
* Set transfer type.
*/
void
settype(argc, argv)
int argc;
char *argv[];
{
struct types *p;
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 = " | ";
}
puts(" ]");
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.
*/
void
changetype(newtype, show)
int newtype, show;
{
struct types *p;
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) {
warnx("internal error: unknown type %d.", 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*/
void
setbinary(argc, argv)
int argc;
char *argv[];
{
stype[1] = "binary";
settype(2, stype);
}
/*
* Set ascii transfer type.
*/
/*VARARGS*/
void
setascii(argc, argv)
int argc;
char *argv[];
{
stype[1] = "ascii";
settype(2, stype);
}
/*
* Set tenex transfer type.
*/
/*VARARGS*/
void
settenex(argc, argv)
int argc;
char *argv[];
{
stype[1] = "tenex";
settype(2, stype);
}
/*
* Set file transfer mode.
*/
/*ARGSUSED*/
void
setftmode(argc, argv)
int argc;
char *argv[];
{
printf("We only support %s mode, sorry.\n", modename);
code = -1;
}
/*
* Set file transfer format.
*/
/*ARGSUSED*/
void
setform(argc, argv)
int argc;
char *argv[];
{
printf("We only support %s format, sorry.\n", formname);
code = -1;
}
/*
* Set file transfer structure.
*/
/*ARGSUSED*/
void
setstruct(argc, argv)
int argc;
char *argv[];
{
printf("We only support %s structure, sorry.\n", structname);
code = -1;
}
/*
* Send a single file.
*/
void
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;
if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
usage:
printf("usage: %s local-file [ remote-file ]\n", argv[0]);
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);
if (oldargv1 != argv[1]) /* free up after globulize() */
free(argv[1]);
}
/*
* Send multiple files.
*/
void
mput(argc, argv)
int argc;
char *argv[];
{
int i;
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];
while ((cp = remglob(argv, 0, NULL)) != NULL) {
if (*cp == '\0') {
mflag = 0;
continue;
}
if (mflag && confirm(argv[0], cp)) {
tp = cp;
if (mcase) {
while (*tp && !islower((unsigned char)*tp)) {
tp++;
}
if (!*tp) {
tp = cp;
tp2 = tmpbuf;
while ((*tp2 = *tp) != '\0') {
if (isupper((unsigned char)*tp2))
*tp2 = tolower((unsigned char)*tp2);
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;
if (confirm("Continue with", "mput")) {
mflag++;
}
interactive = ointer;
}
}
}
(void)signal(SIGINT, oldintr);
mflag = 0;
return;
}
for (i = 1; i < argc; i++) {
char **cpp;
glob_t gl;
int flags;
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;
if (confirm("Continue with", "mput")) {
mflag++;
}
interactive = ointer;
}
}
continue;
}
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);
continue;
}
for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
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;
if (confirm("Continue with", "mput")) {
mflag++;
}
interactive = ointer;
}
}
}
globfree(&gl);
}
(void)signal(SIGINT, oldintr);
mflag = 0;
}
void
reget(argc, argv)
int argc;
char *argv[];
{
(void)getit(argc, argv, 1, "r+w");
}
void
get(argc, argv)
int argc;
char *argv[];
{
(void)getit(argc, argv, 0, restart_point ? "r+w" : "w" );
}
/*
* Receive one file.
*/
int
getit(argc, argv, restartit, mode)
int argc;
char *argv[];
int restartit;
const char *mode;
{
int loc = 0;
int rval = 0;
char *oldargv1, *oldargv2, *globargv2;
if (argc == 2) {
argc++;
argv[2] = argv[1];
loc++;
}
if (argc < 2 && !another(&argc, &argv, "remote-file"))
goto usage;
if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
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);
}
globargv2 = argv[2];
if (loc && mcase) {
char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
while (*tp && !islower((unsigned char)*tp)) {
tp++;
}
if (!*tp) {
tp = argv[2];
tp2 = tmpbuf;
while ((*tp2 = *tp) != '\0') {
if (isupper((unsigned char)*tp2)) {
*tp2 = tolower((unsigned char)*tp2);
}
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) {
warn("local: %s", argv[2]);
goto freegetit;
}
restart_point = stbuf.st_size;
} else {
if (ret == 0) {
time_t mtime;
mtime = remotemodtime(argv[1], 0);
if (mtime == -1)
goto freegetit;
if (stbuf.st_mtime >= mtime) {
rval = 1;
goto freegetit;
}
}
}
}
recvrequest("RETR", argv[2], argv[1], mode,
argv[1] != oldargv1 || argv[2] != oldargv2, loc);
restart_point = 0;
freegetit:
if (oldargv2 != globargv2) /* free up after globulize() */
free(globargv2);
return (rval);
}
/* ARGSUSED */
void
mabort(signo)
int signo;
{
int ointer, oconf;
alarmtimer(0);
putchar('\n');
(void)fflush(stdout);
if (mflag && fromatty) {
ointer = interactive;
oconf = confirmrest;
interactive = 1;
confirmrest = 0;
if (confirm("Continue with", mname)) {
interactive = ointer;
confirmrest = oconf;
longjmp(jabort, 0);
}
interactive = ointer;
confirmrest = oconf;
}
mflag = 0;
longjmp(jabort, 0);
}
/*
* Get multiple files.
*/
void
mget(argc, argv)
int argc;
char *argv[];
{
sig_t oldintr;
int ch, ointer;
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;
oldintr = signal(SIGINT, mabort);
(void)setjmp(jabort);
while ((cp = remglob(argv, proxy, NULL)) != NULL) {
if (*cp == '\0') {
mflag = 0;
continue;
}
if (mflag && confirm(argv[0], cp)) {
tp = cp;
if (mcase) {
for (tp2 = tmpbuf; (ch = *tp++) != 0; )
*tp2++ = isupper((unsigned char)ch) ?
tolower((unsigned char)ch) :
ch;
*tp2 = '\0';
tp = tmpbuf;
}
if (ntflag) {
tp = dotrans(tp);
}
if (mapflag) {
tp = domap(tp);
}
recvrequest("RETR", tp, cp, "w",
tp != cp || !interactive, 1);
if (!mflag && fromatty) {
ointer = interactive;
interactive = 1;
if (confirm("Continue with", "mget")) {
mflag++;
}
interactive = ointer;
}
}
}
(void)signal(SIGINT, oldintr);
mflag = 0;
}
char *
onoff(bool)
int bool;
{
return (bool ? "on" : "off");
}
/*
* Show status.
*/
/*ARGSUSED*/
void
status(argc, argv)
int argc;
char *argv[];
{
int i;
if (connected)
printf("Connected %sto %s.\n",
connected == -1 ? "and logged in" : "", hostname);
else
puts("Not connected.");
if (!proxy) {
pswitch(1);
if (connected) {
printf("Connected for proxy commands to %s.\n",
hostname);
}
else {
puts("No proxy connection.");
}
pswitch(0);
}
printf("Gate ftp: %s, server %s, port %d.\n", onoff(gatemode),
*gateserver ? gateserver : "(none)", ntohs(gateport));
printf("Passive mode: %s.\n", onoff(passivemode));
printf("Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
modename, typename, formname, structname);
printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
onoff(verbose), onoff(bell), onoff(interactive),
onoff(doglob));
printf("Store unique: %s; Receive unique: %s.\n", onoff(sunique),
onoff(runique));
printf("Preserve modification times: %s.\n", onoff(preserve));
printf("Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
if (ntflag) {
printf("Ntrans: (in) %s (out) %s\n", ntin, ntout);
}
else {
puts("Ntrans: off.");
}
if (mapflag) {
printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
}
else {
puts("Nmap: off.");
}
printf("Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
onoff(hash), mark, onoff(progress));
printf("Use of PORT cmds: %s.\n", onoff(sendport));
#ifndef SMALL
printf("Command line editing: %s.\n", onoff(editing));
#endif /* !SMALL */
if (macnum > 0) {
puts("Macros:");
for (i=0; i<macnum; i++) {
printf("\t%s\n", macros[i].mac_name);
}
}
code = 0;
}
/*
* 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);
}
if (mesg)
printf("%s %s.\n", mesg, onoff(*var));
return (*var);
}
/*
* Set beep on cmd completed mode.
*/
/*VARARGS*/
void
setbell(argc, argv)
int argc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -