home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
ncftp-2.3.0-base.tgz
/
ncftp-2.3.0-base.tar
/
contrib
/
ncftp
/
List.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-26
|
11KB
|
489 lines
/* List.c */
#include "Sys.h"
#include <signal.h>
#include <setjmp.h>
#include "Util.h"
#include "RCmd.h"
#include "Xfer.h"
#include "Cmds.h"
#include "List.h"
#include "Glob.h"
#include "Bookmark.h"
#include "Complete.h"
jmp_buf gPDirJmp;
jmp_buf gLocalListJmp;
LineList gRedir;
extern int gStdout;
extern longstring gPager;
extern Bookmark gRmtInfo;
long ListGetProc(char *buf, size_t bufsize, XferSpecPtr xp)
{
long len;
len = (long) BufferGets(buf, bufsize, xp);
return (len);
} /* ListGetProc */
long ListPutProc(char *buf, size_t bufsize, XferSpecPtr xp)
{
long result;
char *cp;
int len;
longstring buf2;
if (isatty(xp->outStream)) {
MakeStringPrintable(buf2, (unsigned char *) buf, sizeof(buf2));
MultiLinePrintF("%s", buf2);
result = (long) bufsize;
} else {
result = (long) write(xp->outStream, buf, bufsize);
if (result != bufsize) {
return (-1L);
}
}
/* Save this output line for "redir". */
len = (int) strlen(buf);
cp = buf + len - 1;
if (*cp == '\n')
*cp = 0;
AddLine(&gRedir, buf);
CompleteParse(buf);
return (result);
} /* ListPutProc */
long ListToMemoryPutProc(char *buf, size_t bufsize, XferSpecPtr xp)
{
char *cp;
long len;
len = (long) strlen(buf);
cp = buf + len - 1;
if (*cp == '\n')
*cp = 0;
AddLine((LineListPtr) xp->miscPtr, buf);
return (len);
} /* ListToMemoryPutProc */
void ListToMemory(LineListPtr fileList, char *cmd, char *flags, char *what)
{
XferSpecPtr xp;
fileList->first = fileList->last = NULL;
/* Setup the parameter block for RDataCmd. Note that we purposely
* leave the other fields unset, since we don't use them, and
* being zeroed-out is okay.
*/
xp = InitXferSpec();
xp->netMode = kNetReading;
xp->getBlock = ListGetProc;
xp->putBlock = ListToMemoryPutProc;
xp->outStream = -1; /* Not used... */
xp->miscPtr = fileList;
SETASCII; /* Directory listings should be in ascii mode. */
if ((flags == NULL) || (gRmtInfo.isUnix == 0))
(void) RDataCmd(xp, "%s %s", cmd, what);
else
(void) RDataCmd(xp, "%s %s %s", cmd, flags, what);
DoneWithXferSpec(xp); /* Doesn't dispose miscPtr. */
} /* ListToMemory */
long FileListGetProc(char *buf, size_t bufsize, XferSpecPtr xp)
{
char *cp;
int len;
int c;
longstring str;
len = BufferGets(buf, bufsize, xp);
if (len < 1)
return (0L);
cp = buf;
/* Unix dependency: ls message */
if (strncmp(buf, "can not access", SZ(14)) == 0) {
EPrintF("%s", buf);
return (0L);
}
cp += len - 2; /* Want last char of name, but also have \n. */
if (gRmtInfo.isUnix) {
c = *cp;
switch(c) {
/* Unix dependency: ls -F format. */
case '/': c = 'd'; goto subt;
case '@': c = 'l'; goto subt;
case '*': c = '-'; goto subt;
/* No (supported) suffix, so treat it like a plain file. */
default: c = '-'; cp[1] = '\0'; break;
subt: *cp = '\0'; /* Remove suffix. */
}
} else {
/* For non unix, just have to assume file. */
c = '-';
cp[1] = '\0';
}
/* Just want the item names, no path prefixes. */
cp = strrchr(buf, '/');
if (cp != NULL) {
cp = Strncpy(str, cp + 1, sizeof(str));
} else {
cp = Strncpy(str, buf, sizeof(str));
}
/* We write the one-char file type, followed by the item name. */
*buf = c;
(void) Strncpy(buf + 1, str, bufsize - 1);
return ((long) len);
} /* FileListGetProc */
long FileListPutProc(char *buf, size_t bufsize, XferSpecPtr xp)
{
long len;
len = (long) strlen(buf);
AddLine((LineListPtr) xp->miscPtr, buf);
return (len);
} /* FileListPutProc */
void GetFileList(LineListPtr fileList, char *what)
{
XferSpecPtr xp;
fileList->first = fileList->last = NULL;
/* Setup the parameter block for RDataCmd. Note that we purposely
* leave the other fields unset, since we don't use them, and
* being zeroed-out is okay.
*/
xp = InitXferSpec();
xp->netMode = kNetReading;
xp->getBlock = FileListGetProc;
xp->putBlock = FileListPutProc;
xp->outStream = -1; /* Not used... */
xp->miscPtr = fileList;
SETASCII; /* Directory listings should be in ascii mode. */
if (gRmtInfo.isUnix)
(void) RDataCmd(xp, "NLST -F %s", what);
else
(void) RDataCmd(xp, "NLST %s", what);
DoneWithXferSpec(xp); /* Doesn't dispose miscPtr. */
} /* GetFileList */
int DoList(int argc, char **argv, char *lsMode)
{
char flags[64];
char flags2[64];
char *cmd;
char thingsToList[256];
int i, wildcards;
XferSpecPtr xp;
SETASCII; /* Directory listings should be in ascii mode. */
thingsToList[0] = '\0';
flags2[0] = '\0';
wildcards = 0;
if (STREQ(lsMode, kListLongMode)) {
cmd = "LIST";
CompleteSetFlags("-l");
flags[0] = '\0';
} else {
cmd = "NLST";
STRNCPY(flags, lsMode + 1);
CompleteSetFlags(lsMode);
}
/* Go through and find all the things that look like dash-flags,
* and combine them into one string. We do the same thing
* for the items to list, so we'll have to groups of things
* to hand to RDataCmd.
*/
for (i=1; i<argc; i++) {
CompleteSetFlags(argv[i]);
if (argv[i][0] == '-')
STRNCAT(flags2, argv[i] + 1);
else {
STRNCAT(thingsToList, " ");
STRNCAT(thingsToList, argv[i]);
if (GLOBCHARSINSTR(argv[i]))
wildcards = 1;
}
}
/* For some unknown reason, traditional servers can do "LIST -t *.tar"
* but not "NLST -t *.tar." This kludges around that limitation.
*/
if ((wildcards) && STREQ(cmd, "NLST")) {
if (flags2[0] == '\0') {
/* They didn't give any other flags, so use NLST, but without
* our usual -CF, but with the wildcard expression.
*/
flags[0] = '\0';
} else {
/* They gave some other flags, but print them a warning, and
* switch them over to LIST, and retain their flags.
*/
cmd = "LIST";
STRNCPY(flags, flags2);
BoldPrintF("Warning: cannot use both flags and wildcards with ls, using dir instead.\n");
}
} else {
/* Append their flags to the default flags. */
STRNCAT(flags, flags2);
}
/* Setup the parameter block for RDataCmd. Note that we purposely
* leave the other fields unset, since we don't use them, and
* being zeroed-out is okay.
*/
xp = InitXferSpec();
xp->netMode = kNetReading;
xp->getBlock = ListGetProc;
xp->putBlock = ListPutProc;
/* xp->inStream = gDataSocket; RDataCmd fills this in when it gets it. */
xp->outStream = gStdout;
/* The rest of the xp parameters can be left zeroed, since we won't
* be using them, and progress reports will not be activated, so
* they won't use them either.
*/
MultiLineInit();
/* Dispose previous buffer, and also be set up for a new one. */
DisposeLineListContents(&gRedir);
if ((flags[0]) && (gRmtInfo.isUnix != 0))
(void) RDataCmd(xp, "%s -%s%s", cmd, flags, thingsToList);
else
(void) RDataCmd(xp, "%s%s", cmd, thingsToList);
DoneWithXferSpec(xp);
return 0;
} /* DoList */
static
void PDirHandler(int ignored)
{
alarm(0);
longjmp(gPDirJmp, 1);
} /* PDirHandler */
/* Do a remote directory listing, to the screen (or file), or
* through your pager.
*/
int ListCmd(int argc, char **argv)
{
char *cp, *lsMode;
int result;
volatile int pageMode;
volatile FILE *pager;
volatile int saved;
volatile Sig_t si, sp;
result = kNoErr;
cp = argv[0];
pageMode = kNoPaging;
pager = NULL;
saved = -1;
lsMode = kListShortMode;
if (*cp == 'p') {
/* If the command started with 'p' we should be paging this. */
if (gPager[0] == '\0') {
EPrintF("You haven't specified a program to use as a pager.\n");
EPrintF("You can set this from the preferences screen (prefs command).\n");
return (-1);
}
++cp;
pageMode = kPageMode;
pager = (volatile FILE *) POpen(gPager, "w", 1);
if (pager == NULL) {
RestoreScreen(1);
Error(kDoPerror, "Could not open: %s\n", gPager);
return (-1);
}
/* Now replace our own stdout stream with the pager stream,
* so that writes go to the pager instead.
*/
saved = (volatile int) gStdout;
gStdout = fileno((FILE *) pager);
}
if (*cp == 'd')
lsMode = kListLongMode; /* i.e. "dir" or "pdir" */
CompleteStart(".");
if (setjmp(gPDirJmp) == 0) {
sp = SIGNAL(SIGPIPE, PDirHandler);
si = SIGNAL(SIGINT, PDirHandler);
result = DoList(argc, argv, lsMode);
}
CompleteFinish();
if (pageMode == kPageMode) {
/* Cleanup the mess we made. */
(void) SIGNAL(SIGPIPE, SIG_IGN);
(void) SIGNAL(SIGINT, SIG_IGN);
if (pager != NULL)
PClose((FILE *) pager);
gStdout = saved;
RestoreScreen(1);
}
(void) SIGNAL(SIGPIPE, sp);
(void) SIGNAL(SIGINT, si);
return (result);
} /* ListCmd */
/*ARGSUSED*/
static void SigLocalList(int sigNum)
{
alarm(0);
longjmp(gLocalListJmp, 1);
} /* SigLocalList */
/* Run ls on the local host. This is mostly useful for visual mode, where
* it is troublesome to spawn commands.
*/
int LocalListCmd(int argc, char **argv)
{
volatile FILE *fp;
VSig_t si, sp;
longstring str;
int i, cf;
si = (VSig_t) kNoSignalHandler;
sp = (VSig_t) kNoSignalHandler;
str[0] = '\0';
STRNCPY(str, LS);
cf = 1;
if (argc > 1) {
/* Look for "-l", and turn of -CF if we find it. */
for (i=1; (i < argc) && (argv[i][0] == '-'); i++) {
if (strchr(argv[i], 'l') != NULL) {
cf = 0;
break;
}
}
}
if (cf)
STRNCAT(str, " -CF");
for (i=1; i<argc; i++) {
STRNCAT(str, " ");
STRNCAT(str, argv[i]);
}
DebugMsg("%s\n", str);
fp = (volatile FILE *) POpen(str, "r", 0);
if (fp != NULL) {
if (setjmp(gLocalListJmp) == 0) {
/* Command was not interrupted. */
si = SIGNAL(SIGINT, SigLocalList);
sp = SIGNAL(SIGPIPE, SigLocalList);
MultiLineInit();
while (fgets(str, ((int) sizeof(str)) - 1, (FILE *)fp) != NULL)
MultiLinePrintF("%s", str);
}
(void) SIGNAL(SIGINT, SIG_IGN);
(void) SIGNAL(SIGPIPE, SIG_IGN);
PClose((FILE *) fp);
}
if (si != (VSig_t) kNoSignalHandler)
(void) SIGNAL(SIGINT, si);
if (sp != (VSig_t) kNoSignalHandler)
(void) SIGNAL(SIGPIPE, sp);
return (kNoErr);
} /* LocalListCmd */
int RedirCmd(int argc, char **argv)
{
LinePtr lp;
volatile FILE *pager;
VSig_t si, sp;
si = (VSig_t) kNoSignalHandler;
sp = (VSig_t) kNoSignalHandler;
if (argv[0][0] == 'p') {
/* If the command started with 'p' we should be paging this. */
if (gPager[0] == '\0') {
EPrintF("You haven't specified a program to use as a pager.\n");
EPrintF("You can set this from the preferences screen (prefs command).\n");
return (-1);
}
pager = (volatile FILE *) POpen(gPager, "w", 1);
if (pager == NULL) {
Error(kDoPerror, "Could not open: %s\n", gPager);
return (-1);
}
if (setjmp(gPDirJmp) == 0) {
/* Command was not interrupted. */
sp = SIGNAL(SIGPIPE, PDirHandler);
si = SIGNAL(SIGINT, PDirHandler);
for (lp = gRedir.first; lp != NULL; lp = lp->next)
fprintf((FILE *) pager, "%s\n", lp->line);
PClose((FILE *) pager);
RestoreScreen(1);
}
} else {
MultiLineInit();
for (lp = gRedir.first; lp != NULL; lp = lp->next)
MultiLinePrintF("%s\n", lp->line);
}
if (si != (VSig_t) kNoSignalHandler)
(void) SIGNAL(SIGINT, si);
if (sp != (VSig_t) kNoSignalHandler)
(void) SIGNAL(SIGPIPE, sp);
return (kNoErr);
} /* RedirCmd */