📄 cmds.c
字号:
/* cmds.c
*
* Copyright (c) 1992-2001 by Mike Gleason.
* All rights reserved.
*
*/
#include "syshdrs.h"
#include "shell.h"
#include "util.h"
#include "ls.h"
#include "bookmark.h"
#include "cmds.h"
#include "main.h"
#include "trace.h"
#include "log.h"
#include "pref.h"
#include "spool.h"
#include "getline.h"
#include "readln.h"
#include "getopt.h"
/* This was the directory path when the user logged in. For anonymous users,
* this should be "/", but for real users, it should be their home directory.
* This variable is used later when we want to calculate a relative path
* from the starting directory.
*/
char gStartDir[512];
/* The pathname to the current working directory. This always needs to be
* current, so whenever a directory change is done this should be changed.
*/
char gRemoteCWD[512];
/* Same, but the previous directory the user was in, or empty string if
* there is none.
*/
char gPrevRemoteCWD[512];
/* Another buffer we use just temporarily when switching directories. */
char gScratchCWD[512];
/* The only reason we do this is to get gcc/lint to shut up
* about unused parameters.
*/
int gUnusedArg;
#define ARGSUSED(x) x = (argc != 0) || (argv != 0) || (cmdp != 0) || (aip != 0)
/* Used temporarily, but put it here because it's big. */
FTPConnectionInfo gTmpURLConn;
/* If the user doesn't want to be prompted for a batch of files,
* they can tell us to answer this answer for each item in the batch.
*/
int gResumeAnswerAll;
extern FTPLibraryInfo gLib;
extern FTPConnectionInfo gConn;
extern char gOurDirectoryPath[];
extern Command gCommands[];
extern char gVersion[];
extern size_t gNumCommands;
extern int gDebug, gDoneApplication;
extern char *gOptArg;
extern int gOptInd, gGotSig;
extern int gFirstTimeUser;
extern unsigned int gFirewallPort;
extern int gFirewallType;
extern char gFirewallHost[64];
extern char gFirewallUser[32];
extern char gFirewallPass[32];
extern char gFirewallExceptionList[];
extern char gPager[], gHome[], gShell[];
extern char gOS[];
extern int gAutoResume, gRedialDelay;
extern int gAutoSaveChangesToExistingBookmarks;
extern Bookmark gBm;
extern int gLoadedBm, gConfirmClose, gSavePasswords, gScreenColumns;
extern char gLocalCWD[512], gPrevLocalCWD[512], gOurInstallationPath[];
extern int gMayCancelJmp;
#if defined(WIN32) || defined(_WINDOWS)
#elif defined(HAVE_SIGSETJMP)
extern sigjmp_buf gCancelJmp;
#else /* HAVE_SIGSETJMP */
extern jmp_buf gCancelJmp;
#endif /* HAVE_SIGSETJMP */
/* Open the users $PAGER, or just return stdout. Make sure to use
* ClosePager(), and not fclose/pclose directly.
*/
static FILE *
OpenPager(void)
{
FILE *fp;
char *pprog;
(void) fflush(stdout);
pprog = gPager;
fp = popen((pprog[0] == '\0') ? "more" : pprog, "w");
if (fp == NULL)
return (stdout);
return (fp);
} /* OpenPager */
/* Close (maybe) a file previously created by OpenPager. */
static void
ClosePager(FILE *pagerfp)
{
#ifdef SIGPIPE
sigproc_t osigpipe;
#endif
if ((pagerfp != NULL) && (pagerfp != stdout)) {
#ifdef SIGPIPE
osigpipe = (sigproc_t) NcSignal(SIGPIPE, SIG_IGN);
#endif
(void) pclose(pagerfp);
#ifdef SIGPIPE
(void) NcSignal(SIGPIPE, osigpipe);
#endif
}
} /* ClosePager */
/* Fills in the bookmarkName field of the Bookmark. */
int
PromptForBookmarkName(BookmarkPtr bmp)
{
char dfltname[64];
char bmname[64];
DefaultBookmarkName(dfltname, sizeof(dfltname), gConn.host);
if (dfltname[0] == '\0') {
(void) printf("Enter a name for this bookmark: ");
} else {
(void) printf("Enter a name for this bookmark, or hit enter for \"%s\": ", dfltname);
}
fflush(stdin);
(void) FGets(bmname, sizeof(bmname), stdin);
if (bmname[0] != '\0') {
(void) STRNCPY(bmp->bookmarkName, bmname);
return (0);
} else if (dfltname[0] != '\0') {
(void) STRNCPY(bmp->bookmarkName, dfltname);
return (0);
}
return (-1);
} /* PromptForBookmarkName */
void
CurrentURL(char *dst, size_t dsize, int showpass)
{
Bookmark bm;
char dir[160];
memset(&bm, 0, sizeof(bm));
(void) STRNCPY(bm.name, gConn.host);
if ((gConn.user[0] != '\0') && (! STREQ(gConn.user, "anonymous")) && (! STREQ(gConn.user, "ftp"))) {
(void) STRNCPY(bm.user, gConn.user);
(void) STRNCPY(bm.pass, (showpass == 0) ? "PASSWORD" : gConn.pass);
(void) STRNCPY(bm.acct, gConn.acct);
}
bm.port = gConn.port;
/* We now save relative paths, because the pathname in URLs are
* relative by nature. This makes non-anonymous FTP URLs shorter
* because it doesn't have to include the pathname of their
* home directory.
*/
(void) STRNCPY(dir, gRemoteCWD);
AbsoluteToRelative(bm.dir, sizeof(bm.dir), dir, gStartDir, strlen(gStartDir));
BookmarkToURL(&bm, dst, dsize);
} /* CurrentURL */
/* Fills in the fields of the Bookmark structure, based on the FTP current
* session.
*/
void
FillBookmarkInfo(BookmarkPtr bmp)
{
char dir[160];
(void) STRNCPY(bmp->name, gConn.host);
if ((STREQ(gConn.user, "anonymous")) || (STREQ(gConn.user, "ftp"))) {
bmp->user[0] = '\0';
bmp->pass[0] = '\0';
bmp->acct[0] = '\0';
} else {
(void) STRNCPY(bmp->user, gConn.user);
(void) STRNCPY(bmp->pass, gConn.pass);
(void) STRNCPY(bmp->acct, gConn.acct);
}
/* We now save relative paths, because the pathname in URLs are
* relative by nature. This makes non-anonymous FTP URLs shorter
* because it doesn't have to include the pathname of their
* home directory.
*/
(void) STRNCPY(dir, gRemoteCWD);
AbsoluteToRelative(bmp->dir, sizeof(bmp->dir), dir, gStartDir, strlen(gStartDir));
bmp->port = gConn.port;
(void) time(&bmp->lastCall);
bmp->hasSIZE = gConn.hasSIZE;
bmp->hasMDTM = gConn.hasMDTM;
bmp->hasPASV = gConn.hasPASV;
bmp->hasUTIME = gConn.hasUTIME;
if (gFirewallType == kFirewallNotInUse)
(void) STRNCPY(bmp->lastIP, gConn.ip);
} /* FillBookmarkInfo */
/* Saves the current FTP session settings as a bookmark. */
void
SaveCurrentAsBookmark(void)
{
int saveBm;
char ans[64];
/* gBm.bookmarkName must already be set. */
FillBookmarkInfo(&gBm);
saveBm = gSavePasswords;
if (gLoadedBm != 0)
saveBm = 1;
if ((saveBm < 0) && (gBm.pass[0] != '\0')) {
(void) printf("\n\nYou logged into this site using a password.\nWould you like to save the password with this bookmark?\n\n");
(void) printf("Save? [no] ");
(void) memset(ans, 0, sizeof(ans));
fflush(stdin);
(void) fgets(ans, sizeof(ans) - 1, stdin);
if ((saveBm = StrToBool(ans)) == 0) {
(void) printf("\nNot saving the password.\n");
}
}
if (PutBookmark(&gBm, saveBm) < 0) {
(void) fprintf(stderr, "Could not save bookmark.\n");
} else {
/* Also marks whether we saved it. */
gLoadedBm = 1;
(void) printf("Bookmark \"%s\" saved.\n", gBm.bookmarkName);
ReCacheBookmarks();
}
} /* SaveCurrentAsBookmark */
/* If the user did not explicitly bookmark this site already, ask
* the user if they want to save one.
*/
void
SaveUnsavedBookmark(void)
{
char url[256];
char ans[64];
int c;
if ((gConfirmClose != 0) && (gLoadedBm == 0) && (gOurDirectoryPath[0] != '\0')) {
FillBookmarkInfo(&gBm);
BookmarkToURL(&gBm, url, sizeof(url));
(void) printf("\n\nYou have not saved a bookmark for this site.\n");
(void) sleep(1);
(void) printf("\nWould you like to save a bookmark to:\n\t%s\n\n", url);
for (;;) {
(void) printf("Save? (yes/no) ");
(void) memset(ans, 0, sizeof(ans));
fflush(stdin);
if (fgets(ans, sizeof(ans) - 1, stdin) == NULL) {
c = 'n';
break;
}
c = ans[0];
if ((c == 'n') || (c == 'y'))
break;
if (c == 'N') {
c = 'n';
break;
} else if (c == 'Y') {
c = 'y';
break;
}
}
if (c == 'n') {
(void) printf("Not saved. (If you don't want to be asked this, \"set confirm-close no\")\n\n\n");
} else if (PromptForBookmarkName(&gBm) < 0) {
(void) printf("Nevermind.\n");
} else {
SaveCurrentAsBookmark();
}
} else if ((gLoadedBm == 1) && (gOurDirectoryPath[0] != '\0') && (strcmp(gOurDirectoryPath, gBm.dir) != 0)) {
/* Bookmark has changed. */
if (gAutoSaveChangesToExistingBookmarks != 0) {
SaveCurrentAsBookmark();
}
}
} /* SaveUnsavedBookmark */
/* Save the current host session settings for later as a "bookmark", which
* will be referred to by a bookmark abbreviation name.
*/
void
BookmarkCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
/* The only reason we do this is to get gcc/lint to shut up
* about unused parameters.
*/
ARGSUSED(gUnusedArg);
if (gOurDirectoryPath[0] == '\0') {
(void) printf("Sorry, configuration information is not saved for this user.\n");
} else if ((argc <= 1) || (argv[1][0] == '\0')) {
/* No name specified on the command line. */
if (gBm.bookmarkName[0] == '\0') {
/* Not previously bookmarked. */
if (PromptForBookmarkName(&gBm) < 0) {
(void) printf("Nevermind.\n");
} else {
SaveCurrentAsBookmark();
}
} else {
/* User wants to update an existing bookmark. */
SaveCurrentAsBookmark();
}
} else {
(void) STRNCPY(gBm.bookmarkName, argv[1]);
SaveCurrentAsBookmark();
}
} /* BookmarkCmd */
/* Dump a remote file to the screen. */
void
CatCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int result;
int i;
ARGSUSED(gUnusedArg);
for (i=1; i<argc; i++) {
result = FTPGetOneFile2(&gConn, argv[i], NULL, kTypeAscii, STDOUT_FILENO, kResumeNo, kAppendNo);
FTPPerror(&gConn, result, kErrCouldNotStartDataTransfer, "cat", argv[i]);
}
} /* CatCmd */
static void
NcFTPCdResponseProc(const FTPCIPtr cipUNUSED, ResponsePtr rp)
{
LinePtr lp;
LineListPtr llp;
gUnusedArg = (cipUNUSED != NULL);
if ((rp->printMode & kResponseNoPrint) != 0)
return;
llp = &rp->msg;
for (lp = llp->first; lp != NULL; lp = lp->next) {
if ((lp == llp->first) && (rp->codeType == 2)) {
if (ISTRNCMP(lp->line, "CWD command", 11) == 0)
continue;
if (lp->line[0] == '"')
continue; /* "/pub/foo" is... */
}
(void) printf("%s\n", lp->line);
}
} /* NcFTPCdResponseProc */
/* Manually print a response obtained from the remote FTP user. */
void
PrintResp(LineListPtr llp)
{
LinePtr lp;
if (llp != NULL) {
for (lp = llp->first; lp != NULL; lp = lp->next) {
if ((lp == llp->first) && (ISTRNCMP(lp->line, "CWD command", 11) == 0))
continue;
(void) printf("%s\n", lp->line);
}
}
} /* PrintResp */
/* Do a chdir, and update our notion of the current directory.
* Some servers return it back as part of the CWD response,
* otherwise do a CWD command followed by a PWD.
*/
int
nFTPChdirAndGetCWD(const FTPCIPtr cip, const char *cdCwd, const int quietMode)
{
ResponsePtr rp;
size_t cdCwdLen;
int result;
#ifdef USE_WHAT_SERVER_SAYS_IS_CWD
int foundcwd;
char *l, *r;
#endif
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if ((cdCwd == NULL) || (cdCwd[0] == '\0')) {
result = kErrInvalidDirParam;
cip->errNo = kErrInvalidDirParam;
} else {
rp = InitResponse();
if (rp == NULL) {
result = kErrMallocFailed;
cip->errNo = kErrMallocFailed;
/* Error(cip, kDontPerror, "Malloc failed.\n"); */
} else {
cdCwdLen = strlen(cdCwd);
if (strcmp(cdCwd, "..") == 0) {
result = RCmd(cip, rp, "CDUP");
} else {
result = RCmd(cip, rp, "CWD %s", cdCwd);
}
if (result == 2) {
#ifdef USE_WHAT_SERVER_SAYS_IS_CWD
(void) STRNCPY(gScratchCWD, gRemoteCWD);
foundcwd = 0;
if ((r = strrchr(rp->msg.first->line, '"')) != NULL) {
/* "xxxx" is current directory.
* Strip out just the xxxx to copy into the remote cwd.
*
* This is nice because we didn't have to do a PWD.
*/
l = strchr(rp->msg.first->line, '"');
if ((l != NULL) && (l != r) && (l == rp->msg.first->line)) {
*r = '\0';
++l;
(void) Strncpy(gRemoteCWD, l, sizeof(gRemoteCWD));
*r = '"'; /* Restore, so response prints correctly. */
foundcwd = 1;
result = kNoErr;
}
}
if (quietMode)
rp->printMode |= kResponseNoPrint;
NcFTPCdResponseProc(cip, rp);
DoneWithResponse(cip, rp);
if (foundcwd == 0) {
result = FTPGetCWD(cip, gRemoteCWD, sizeof(gRemoteCWD));
if (result != kNoErr) {
PathCat(gRemoteCWD, sizeof(gRemoteCWD), gScratchCWD, cdCwd);
result = kNoErr;
}
}
#else /* USE_CLIENT_SIDE_CALCULATED_CWD */
if (quietMode)
rp->printMode |= kResponseNoPrint;
NcFTPCdResponseProc(cip, rp);
DoneWithResponse(cip, rp);
(void) STRNCPY(gScratchCWD, gRemoteCWD);
PathCat(gRemoteCWD, sizeof(gRemoteCWD), gScratchCWD, cdCwd);
result = kNoErr;
#endif
} else if (result > 0) {
result = kErrCWDFailed;
cip->errNo = kErrCWDFailed;
DoneWithResponse(cip, rp);
} else {
DoneWithResponse(cip, rp);
}
}
}
return (result);
} /* nFTPChdirAndGetCWD */
int
Chdirs(FTPCIPtr cip, const char *const cdCwd)
{
char *cp, *startcp;
int result;
int lastSubDir;
if (cip == NULL)
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
if (cdCwd == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -