📄 cmds.c
字号:
/* Display some brief help for specified commands, or a list of commands. */
void
HelpCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
CommandPtr c;
int showall = 0, helpall = 0;
int i, j, k, n;
int nRows, nCols;
int nCmds2Print;
int screenColumns;
int len, widestName;
char *cp, spec[16];
const char *cmdnames[64];
ARGSUSED(gUnusedArg);
assert(gNumCommands < (sizeof(cmdnames) / sizeof(char *)));
if (argc == 2) {
showall = (strcmp(argv[1], "showall") == 0);
helpall = (strcmp(argv[1], "helpall") == 0);
}
if (argc == 1 || showall) {
(void) printf("\
Commands may be abbreviated. 'help showall' shows hidden and unsupported \n\
commands. 'help <command>' gives a brief description of <command>.\n\n");
/* First, see how many commands we will be printing to the screen.
* Unless 'showall' was given, we won't be printing the hidden
* (i.e. not very useful to the end-user) commands.
*/
c = gCommands;
nCmds2Print = 0;
for (n = 0; n < (int) gNumCommands; c++, n++)
if ((!iscntrl((int) c->name[0])) && (!(c->flags & kCmdHidden) || showall))
nCmds2Print++;
(void) memset((char *) cmdnames, 0, sizeof(cmdnames));
/* Now form the list we'll be printing, and noting what the maximum
* length of a command name was, so we can use that when determining
* how to print in columns.
*/
c = gCommands;
i = 0;
widestName = 0;
for (n = 0; n < (int) gNumCommands; c++, n++) {
if ((!iscntrl((int) c->name[0])) && (!(c->flags & kCmdHidden) || showall)) {
cmdnames[i++] = c->name;
len = (int) strlen(c->name);
if (len > widestName)
widestName = len;
}
}
if ((cp = (char *) getenv("COLUMNS")) == NULL)
screenColumns = 80;
else
screenColumns = atoi(cp);
/* Leave an extra bit of whitespace for the margins between columns. */
widestName += 2;
nCols = (screenColumns + 0) / widestName;
nRows = nCmds2Print / nCols;
if ((nCmds2Print % nCols) > 0)
nRows++;
for (i = 0; i < nRows; i++) {
for (j = 0; j < nCols; j++) {
k = nRows * j + i;
if (k < nCmds2Print) {
(void) sprintf(spec, "%%-%ds",
(j < nCols - 1) ? widestName : widestName - 2
);
(void) printf(spec, cmdnames[k]);
}
}
(void) printf("\n");
}
} else if (helpall) {
/* Really intended for me, so I can debug the help strings. */
for (c = gCommands, n = 0; n < (int) gNumCommands; c++, n++) {
PrintCmdHelp(c);
PrintCmdUsage(c);
}
} else {
/* For each command name specified, print its help stuff. */
for (i=1; i<argc; i++) {
c = GetCommandByName(argv[i], 0);
if (c == kAmbiguousCommand) {
(void) printf("%s: ambiguous command name.\n", argv[i]);
} else if (c == kNoCommand) {
(void) printf("%s: no such command.\n", argv[i]);
} else {
if (i > 1)
(void) printf("\n");
PrintCmdHelp(c);
PrintCmdUsage(c);
}
}
}
} /* HelpCmd */
/* Displays the list of saved bookmarks, so that the user can then choose
* one by name.
*/
static int
PrintHosts(void)
{
FILE *bookmarks;
FILE *pager;
int nbm = 0;
Bookmark bm;
char url[128];
#ifdef SIGPIPE
sigproc_t osigpipe;
#endif
bookmarks = OpenBookmarkFile(NULL);
if (bookmarks == NULL)
return (0);
#ifdef SIGPIPE
osigpipe = (sigproc_t) NcSignal(SIGPIPE, SIG_IGN);
#endif
pager = OpenPager();
while (GetNextBookmark(bookmarks, &bm) == 0) {
nbm++;
if (nbm == 1) {
/* header */
(void) fprintf(pager, "--BOOKMARK----------URL--------------------------------------------------------\n");
}
BookmarkToURL(&bm, url, sizeof(url));
(void) fprintf(pager, " %-16s %s\n", bm.bookmarkName, url);
}
ClosePager(pager);
CloseBookmarkFile(bookmarks);
#ifdef SIGPIPE
(void) NcSignal(SIGPIPE, osigpipe);
#endif
return (nbm);
} /* PrintHosts */
static int
RunBookmarkEditor(char *selectedBmName, size_t dsize)
{
#if defined(WIN32) || defined(_WINDOWS)
char ncftpbookmarks[260];
const char *prog;
int winExecResult;
HANDLE hMailSlot;
char msg[kNcFTPBookmarksMailslotMsgSize];
DWORD dwRead;
BOOL rc;
if (selectedBmName != NULL)
memset(selectedBmName, 0, dsize);
if (gOurInstallationPath[0] == '\0') {
(void) fprintf(stderr, "Cannot find path to %s. Please re-run Setup.\n", "ncftpbookmarks.exe");
return (-1);
}
prog = ncftpbookmarks;
OurInstallationPath(ncftpbookmarks, sizeof(ncftpbookmarks), "ncftpbookmarks.exe");
hMailSlot = CreateMailslot(kNcFTPBookmarksMailslot, kNcFTPBookmarksMailslotMsgSize, MAILSLOT_WAIT_FOREVER, NULL);
if (hMailSlot == INVALID_HANDLE_VALUE) {
SysPerror("CreateMailslot");
(void) fprintf(stderr, "Could not create communication channel with %s.\n", "ncftpbookmarks.exe");
(void) fprintf(stderr, "%s", "This means if you select a bookmark to connect to that NcFTP\n");
(void) fprintf(stderr, "%s", "will not get the message from %s.\n", "ncftpbookmarks.exe");
}
winExecResult = WinExec(prog, SW_SHOWNORMAL);
if (winExecResult <= 31) switch (winExecResult) {
case ERROR_BAD_FORMAT:
fprintf(stderr, "Could not run %s: %s\n", prog, "The .EXE file is invalid");
return (-1);
case ERROR_FILE_NOT_FOUND:
fprintf(stderr, "Could not run %s: %s\n", prog, "The specified file was not found.");
return (-1);
case ERROR_PATH_NOT_FOUND:
fprintf(stderr, "Could not run %s: %s\n", prog, "The specified path was not found.");
return (-1);
default:
fprintf(stderr, "Could not run %s: Unknown error #%d.\n", prog, winExecResult);
return (-1);
}
if (hMailSlot != INVALID_HANDLE_VALUE) {
fprintf(stdout, "Waiting for %s to exit...\n", "ncftpbookmarks.exe");
ZeroMemory(msg, sizeof(msg));
dwRead = 0;
rc = ReadFile(
hMailSlot,
msg,
sizeof(msg),
&dwRead,
NULL
);
if (!rc) {
SysPerror("ReadFile");
} else {
msg[sizeof(msg) - 1] = '\0';
Strncpy(selectedBmName, msg, dsize);
Trace(0, "Selected bookmark from editor: [%s]\n", selectedBmName);
}
CloseHandle(hMailSlot);
}
return (0);
#else
#ifdef BINDIR
char ncftpbookmarks[256];
char *av[8];
int pid;
int status;
char bmSelectionFile[256];
char pidStr[32];
FILE *fp;
if (selectedBmName != NULL)
memset(selectedBmName, 0, dsize);
STRNCPY(ncftpbookmarks, BINDIR);
STRNCAT(ncftpbookmarks, "/");
STRNCAT(ncftpbookmarks, "ncftpbookmarks");
STRNCPY(bmSelectionFile, "view");
if ((selectedBmName != NULL) && (gOurDirectoryPath[0] != '\0')) {
sprintf(pidStr, ".%u", (unsigned int) getpid());
OurDirectoryPath(bmSelectionFile, sizeof(bmSelectionFile), kOpenSelectedBookmarkFileName);
STRNCAT(bmSelectionFile, pidStr);
}
if (access(ncftpbookmarks, X_OK) == 0) {
pid = (int) fork();
if (pid < 0) {
return (-1);
} else if (pid == 0) {
/* child */
av[0] = (char *) "ncftpbookmarks";
av[1] = bmSelectionFile;
av[2] = NULL;
execv(ncftpbookmarks, av);
exit(1);
} else {
/* parent NcFTP */
for (;;) {
#ifdef HAVE_WAITPID
if ((waitpid(pid, &status, 0) < 0) && (errno != EINTR))
break;
#else
if ((wait(&status) < 0) && (errno != EINTR))
break;
#endif
if (WIFEXITED(status) || WIFSIGNALED(status))
break; /* done */
}
if (strcmp(bmSelectionFile, "view") != 0) {
fp = fopen(bmSelectionFile, FOPEN_READ_TEXT);
if (fp != NULL) {
(void) FGets(selectedBmName, dsize, fp);
(void) fclose(fp);
(void) unlink(bmSelectionFile);
Trace(0, "Selected bookmark from editor: [%s]\n", selectedBmName);
}
}
return (0);
}
}
return (-1);
#else /* BINDIR */
/* Not installed. */
return (-1);
#endif /* BINDIR */
#endif /* Windows */
} /* RunBookmarkEditor */
/* This just shows the list of saved bookmarks. */
void
HostsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
const char *av[3];
char bm[128];
ARGSUSED(gUnusedArg);
/* Skip visual mode if "-l". */
if ((argc == 1) && (RunBookmarkEditor(bm, sizeof(bm)) == 0)) {
if (bm[0] != '\0') {
av[0] = "open";
av[1] = bm;
av[2] = NULL;
OpenCmd(2, av, (CommandPtr) 0, (ArgvInfoPtr) 0);
}
return;
}
if (PrintHosts() <= 0) {
(void) printf("You haven't bookmarked any FTP sites.\n");
(void) printf("Before closing a site, you can use the \"bookmark\" command to save the current\nhost and directory for next time.\n");
} else {
(void) printf("\nTo use a bookmark, use the \"open\" command with the name of the bookmark.\n");
}
} /* HostsCmd */
/* Show active background ncftp (ncftpbatch) jobs. */
void
JobsCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
ARGSUSED(gUnusedArg);
Jobs();
} /* JobsCmd */
/* Do a "ls" on the remote system and display the directory contents to our
* user. This command handles "dir" (ls -l), "ls", and "nlist" (ls -1).
*/
void
ListCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
volatile int i;
int j;
char options[32];
char option[2];
volatile int listmode;
FILE *volatile stream;
volatile int paging;
#if defined(WIN32) || defined(_WINDOWS)
#else
int sj;
vsigproc_t osigpipe, osigint;
#endif
ARGSUSED(gUnusedArg);
stream = stdout;
paging = 0;
if (argv[0][0] == 'd') {
/* dir */
listmode = 'l';
} else if (argv[0][0] == 'n') {
/* nlist */
listmode = '1';
} else if (argv[0][0] == 'p') {
/* pager */
paging = 1;
if (argv[0][1] == 'd') {
/* dir */
listmode = 'l';
} else if (argv[0][1] == 'n') {
/* nlist */
listmode = '1';
} else {
/* ls */
listmode = 'C';
}
} else {
/* ls */
listmode = 'C';
}
options[0] = '\0';
option[1] = '\0';
for (i=1; i<argc; i++) {
if (argv[i][0] != '-')
break;
if (argv[i][1] == '-') {
if (argv[i][2] == '\0') {
/* end of options. */
++i;
break;
} else {
/* GNU-esque long --option? */
PrintCmdUsage(cmdp);
}
} else {
for (j=1; ; j++) {
option[0] = argv[i][j];
if (argv[i][j] == '\0')
break;
switch (argv[i][j]) {
case 'l':
listmode = 'l';
break;
case '1':
listmode = '1';
break;
case 'C':
listmode = 'C';
break;
default:
(void) STRNCAT(options, option);
break;
}
}
}
}
if (paging != 0) {
stream = OpenPager();
if (stream == NULL) {
return;
}
#if defined(WIN32) || defined(_WINDOWS)
#elif defined(HAVE_SIGSETJMP)
osigpipe = osigint = (sigproc_t) 0;
sj = sigsetjmp(gCancelJmp, 1);
#else /* HAVE_SIGSETJMP */
osigpipe = osigint = (sigproc_t) 0;
sj = setjmp(gCancelJmp);
#endif /* HAVE_SIGSETJMP */
#if defined(WIN32) || defined(_WINDOWS)
#else
if (sj != 0) {
/* Caught a signal. */
(void) NcSignal(SIGPIPE, (FTPSigProc) SIG_IGN);
ClosePager(stream);
(void) NcSignal(SIGPIPE, osigpipe);
(void) NcSignal(SIGINT, osigint);
Trace(0, "Canceled because of signal %d.\n", gGotSig);
(void) fprintf(stderr, "Canceled.\n");
gMayCancelJmp = 0;
return;
} else {
osigpipe = NcSignal(SIGPIPE, Cancel);
osigint = NcSignal(SIGINT, Cancel);
gMayCancelJmp = 1;
}
#endif
}
if (argv[i] == NULL) {
/* No directory specified, use cwd. */
Ls(NULL, listmode, options, stream);
} else {
/* List each item. */
for ( ; i<argc; i++) {
Ls(argv[i], listmode, options, stream);
}
}
if (paging != 0) {
ClosePager(stream);
#if defined(WIN32) || defined(_WINDOWS)
#else
(void) NcSignal(SIGPIPE, osigpipe);
(void) NcSignal(SIGINT, osigint);
#endif
}
gMayCancelJmp = 0;
} /* ListCmd */
/* Does a change of working directory on the local host. */
void
LocalChdirCmd(const int argc, const char **const argv, const CommandPtr cmdp, const ArgvInfoPtr aip)
{
int result;
const char *dir;
char buf[512];
ARGSUSED(gUnusedArg);
dir = ((argc < 2) ? gHome : argv[1]);
if ((dir[0] == '-') && (dir[1] == '\0')) {
if (gPrevLocalCWD[0] == '\0') {
(void) fprintf(stderr, "No previous local working directory to switch to.\n");
return;
} else {
dir = gPrevLocalCWD;
}
} else if (dir[0] == '~') {
if (dir[1] == '\0') {
dir = gHome;
} else if (dir[1] == '/') {
(void) STRNCPY(buf, gHome);
dir = STRNCAT(buf, dir + 1);
}
}
result = chdir(dir);
if (result < 0) {
perror(dir);
} else {
(void) STRNCPY(gPrevLocalCWD, gLocalCWD);
(void) FTPGetLocalCWD(gLocalCWD, sizeof(gLocalCWD));
}
} /* LocalChdirCmd */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -