home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
ncftp-2.3.0-src.tgz
/
tar.out
/
contrib
/
ncftp
/
Main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
23KB
|
950 lines
/* Main.c */
#define _main_c_ 1
/* This is copyrighted software. Read the entire ``COPYRIGHT.h'' file
* before compiling or using!
*/
#include "COPYRIGHT.h"
#include "Sys.h"
#if (LOCK_METHOD == 2)
# ifdef HAVE_SYS_FILE_H
# include <sys/file.h>
# endif
#endif
#ifdef SYSLOG
# include <syslog.h>
#endif
#include <pwd.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include "Util.h"
#include "Main.h"
#include "Cmds.h"
#include "Open.h"
#include "Cmdline.h"
#include "DateSize.h"
#include "Bookmark.h"
#include "Prefs.h"
#include "FTP.h"
#include "Glob.h"
#include "Getopt.h"
#include "Xfer.h"
#include "Complete.h"
#include "Tips.h"
#include "Version.h"
/* We need to know our fully qualified hostname. That way we can give
* a complete email address as a password for anonymous logins.
*/
string gOurHostName;
/* The user's full email address, which we use for the password on
* anonymous logins.
*/
string gEmailAddress;
/* This is what we'll actually use for the anonymous password.
* We keep an unmodified copy of gEmailAddress, and let the user
* change the variable below if they want to.
*/
string gAnonPassword;
/* Since we create a bunch of files, instead of making them all
* .dot files in the home directory, we have our own .dot directory
* and keep all our stuff in there.
*/
string gOurDirectoryPath;
/* We keep some basic information about the user. Most of the structure
* is just a copy of the user's password file entry. Instead of keeping
* just that pointer from getpwnam(), we make our own copy so we can
* use getpwnam() again later.
*/
UserInfo gUserInfo;
/* Boolean indicating whether input is coming from a live user or
* a file.
*/
int gIsFromTTY;
/* Boolean indicating whether output is going to the screen or to
* a file.
*/
int gIsToTTY;
/* Boolean indicating whether input is coming from a script file.
* This is really just a copy of gIsFromTTY.
*/
int gDoingScript;
/* A FILE pointer to the user's usage log, or NULL if we're not
* logging anything.
*/
FILE *gLogFile = NULL;
/* We can optionally log all the debugging information to a separate
* log file.
*/
FILE *gTraceLogFile = NULL;
/* Full pathname of the user's usage log file, in our .dot directory. */
longstring gLogFileName;
/* Maximum size we will let the log grow to before making it smaller.
* If this is zero, there is no limit.
*/
int gMaxLogSize = 10240;
/* Boolean indicating whether the user wanted to keep a usage log. */
int gLogging = USERLOG;
/* Full pathname of the user's pager. Maybe be just "more" if the user
* doesn't have a PAGER environment variable, or didn't set it explicitly.
*/
longstring gPager;
int gVisualMode;
int gDefaultVisualMode = VISUAL;
/* If another ncftp process is running, we don't want to overwrite the
* the files in our directory. We will only read them to prevent the
* user losing changes made in the first process.
*/
int gOtherSessionRunning = 0;
/* We track the number of times the user has run the program. We may
* use that information for something else later.
*/
int gTotalRuns = 0;
/* Types of startup messages user wants us to print when we first run. */
int gStartupMsgs = (kStartupMsg | kTips);
string gVersion;
/* If this user variable is set, we will change directory to the last
* local directory the user was in when the user exited.
*/
int gRememberLCWD = 0;
/* If this user variable is set, we will always chdir to this value each
* time we run the program.
*/
longstring gDownloadDir = "";
jmp_buf gMainJmp;
/* We save previously entered commands between sessions, so the user can
* use the history.
*/
LineList gCmdHistory;
/* Name of the file we use to tell if another ncftp process is running. */
longstring gLockFileName = "";
/* Boolean telling whether the splash-screen and interactive startup stuff
* has been done.
*/
int gStartup = 0;
extern int gStdout, gRealStdout;
extern char *getlogin(void);
extern longstring gLocalCWD;
extern time_t gMailBoxTime;
extern int gWinInit, gOptErr, gTrace, gDebug;
extern char *gSprintfBuf;
extern jmp_buf gCmdLoopJmp;
extern LineList gRedir;
/* This looks up the user's password entry, trying to look by the username.
* We have a couple of extra hacks in place to increase the probability
* that we can get the username.
*/
static
struct passwd *GetPwByName(void)
{
char *cp;
struct passwd *pw;
cp = getlogin();
if (cp == NULL) {
cp = (char *) getenv("LOGNAME");
if (cp == NULL)
cp = (char *) getenv("USER");
}
pw = NULL;
if (cp != NULL)
pw = getpwnam(cp);
return (pw);
} /* GetPwByName */
void GetUserInfo(void)
{
register char *cp;
struct passwd *pw;
string str;
struct stat st;
pw = NULL;
errno = 0;
#ifdef USE_GETPWUID
/* Try to use getpwuid(), but if we have to, fall back to getpwnam(). */
if ((pw = getpwuid(getuid())) == NULL)
pw = GetPwByName(); /* Oh well, try getpwnam() then. */
#else
/* Try to use getpwnam(), but if we have to, fall back to getpwuid(). */
if ((pw = GetPwByName()) == NULL)
pw = getpwuid(getuid()); /* Try getpwnam() then. */
#endif
if (pw != NULL) {
gUserInfo.uid = pw->pw_uid;
(void) STRNCPY(gUserInfo.userName, pw->pw_name);
gUserInfo.shell = StrDup(pw->pw_shell);
if ((cp = (char *) getenv("HOME")) != NULL)
gUserInfo.home = StrDup(cp);
else
gUserInfo.home = StrDup(pw->pw_dir);
} else {
/* Couldn't get information about this user. Since this isn't
* the end of the world as far as I'm concerned, make up
* some stuff that might work good enough.
*/
Error(kDoPerror, "Could not get your passwd entry!");
sleep(1);
if ((cp = (char *) getenv("LOGNAME")) == NULL)
cp = "nobody";
(void) STRNCPY(gUserInfo.userName, cp);
gUserInfo.shell = StrDup("/bin/sh");
if ((cp = (char *) getenv("HOME")) == NULL)
cp = ".";
gUserInfo.home = StrDup(cp);
gUserInfo.uid = 999;
}
cp = (char *) getenv("MAIL");
if (cp == NULL)
cp = (char *) getenv("mail");
if (cp != NULL) {
/* We do have a Mail environment variable. */
(void) STRNCPY(str, cp);
cp = str;
/* Mail variable may be like MAIL=(28 /usr/mail/me /usr/mail/you),
* so try to find the first mail path.
*/
while ((*cp != '/') && (*cp != 0))
cp++;
gUserInfo.mail = StrDup(cp);
if ((cp = strchr(gUserInfo.mail, ' ')) != NULL)
*cp = '\0';
} else {
/* Guess between /usr/mail and /usr/spool/mail as
* possible directories. We'll just choose /usr/spool/mail
* if we have to.
*/
(void) sprintf(str, "/usr/mail/%s", gUserInfo.userName);
if (stat(str, &st) < 0)
(void) sprintf(str, "/usr/spool/mail/%s", gUserInfo.userName);
gUserInfo.mail = StrDup(str);
}
DebugMsg("GetOurHostName returned %d, %s.\n",
GetOurHostName(gOurHostName, sizeof(gOurHostName)),
gOurHostName
);
STRNCPY(gEmailAddress, gUserInfo.userName);
STRNCAT(gEmailAddress, "@");
STRNCAT(gEmailAddress, gOurHostName);
STRNCPY(gAnonPassword, gEmailAddress);
} /* GetUserInfo */
/* Setup the malloc library, if we're using one. */
static void InitMalloc(void)
{
#ifdef DEBUG
# if (LIBMALLOC == FAST_MALLOC)
FILE *malloclog;
mallopt(M_DEBUG, 1);
mallopt(M_LOG, 1); /* turn on/off malloc/realloc/free logging */
/* set the file to use for logging */
if ((malloclog = fopen("malloc.log", "w")) != NULL)
mallopt(M_LOGFILE, fileno(malloclog));
# endif
#endif
#if (LIBMALLOC == DEBUG_MALLOC)
/* Thanks to Conor Cahill for making something like this possible! */
union dbmalloptarg m;
# if 1
m.i = 1;
dbmallopt(MALLOC_CKCHAIN, &m);
# endif
# if 1
m.i = M_HANDLE_IGNORE;
dbmallopt(MALLOC_WARN, &m);
# endif
# if 0 /* If 0, stderr. */
m.str = "malloc.log";
dbmallopt(MALLOC_ERRFILE, &m);
# endif
#endif
} /* InitMalloc */
void OpenTraceLog(void)
{
string traceLogPath;
string traceLog2Path;
string traceLogTmpPath;
string line;
FILE *f1, *f2, *f3;
int i, lim;
time_t now;
if (gOtherSessionRunning != 0)
return;
if (gTraceLogFile != NULL)
return; /* Already open. */
if (gOurDirectoryPath[0] == '\0')
return; /* Don't create in root directory. */
OurDirectoryPath(traceLogPath, sizeof(traceLogPath), kTraceLogName);
if (access(traceLogPath, F_OK) == 0) {
/* Need to prepend last session's log to the master debug log. */
OurDirectoryPath(traceLog2Path, sizeof(traceLog2Path), kTraceLog2Name);
OurDirectoryPath(traceLogTmpPath, sizeof(traceLogTmpPath), kTraceLogTmpName);
f1 = fopen(traceLogTmpPath, "w");
if (f1 == NULL) {
Error(kDoPerror, "Can't open %s for writing.\n", traceLogTmpPath);
return;
}
f2 = fopen(traceLogPath, "r");
if (f2 == NULL) {
Error(kDoPerror, "Can't open %s for reading.\n", traceLogPath);
return;
}
lim = kMaxTraceLogLines - 1;
for (i=0; i<lim; i++) {
if (fgets(line, ((int) sizeof(line)) - 1, f2) == NULL)
break;
fputs(line, f1);
}
if (i + 2 < lim) {
fputs("\n\n", f1);
i += 2;
}
(void) fclose(f2);
f3 = fopen(traceLog2Path, "r");
if (f3 != NULL) {
for (; i<lim; i++) {
if (fgets(line, ((int) sizeof(line)) - 1, f3) == NULL)
break;
fputs(line, f1);
}
(void) fclose(f3);
}
if (i >= lim)
fputs("...Remaining lines omitted...\n", f1);
(void) fclose(f1);
(void) UNLINK(traceLogPath);
(void) UNLINK(traceLog2Path);
(void) rename(traceLogTmpPath, traceLog2Path);
}
gTraceLogFile = fopen(traceLogPath, "w");
if (gTraceLogFile == NULL) {
Error(kDoPerror, "Can't open %s for writing.\n", traceLogPath);
} else {
time(&now);
fprintf(
gTraceLogFile,
"SESSION STARTED at %s%s\n\n",
ctime(&now),
"-----------------------------------------------"
);
}
} /* OpenTraceLog */
void OpenLogs(void)
{
/* First try open the user's private log, unless the user
* has this option turned off.
*/
OurDirectoryPath(gLogFileName, sizeof(gLogFileName), kLogName);
gLogFile = NULL;
if (gOtherSessionRunning == 0) {
if ((gLogging) && (gMaxLogSize > 0))
gLogFile = fopen(gLogFileName, "a");
if (gTrace == kTracingOn)
OpenTraceLog();
}
/* Open a port to the system log, if you're hellbent on knowing
* everything users do with the program.
*/
#ifdef SYSLOG
# ifdef LOG_LOCAL3
openlog ("NcFTP", LOG_PID, LOG_LOCAL3);
# else
openlog ("NcFTP", LOG_PID);
# endif
#endif /* SYSLOG */
} /* OpenLogs */
/* Create, if necessary, a directory in the user's home directory to
* put our incredibly important stuff in.
*/
void InitOurDirectory(void)
{
struct stat st;
char *cp;
cp = getenv("NCFTPDIR");
if (cp != NULL) {
STRNCPY(gOurDirectoryPath, cp);
} else if (STREQ(gUserInfo.home, "/")) {
/* Don't create it if you're root and your home directory
* is the root directory.
*/
gOurDirectoryPath[0] = '\0';
return;
} else {
(void) Path(gOurDirectoryPath,
sizeof(gOurDirectoryPath),
gUserInfo.home,
kOurDirectoryName
);
}
if (stat(gOurDirectoryPath, &st) < 0) {
(void) mkdir(gOurDirectoryPath, 00755);
}
} /* InitOurDirectory */
/* There would be problems if we had multiple ncftp's going. They would
* each try to update the files in ~/.ncftp. Whichever program exited
* last would have its stuff written, and the others which may have made
* changes, would lose the changes they made.
*
* This checks to see if another ncftp is running. To do that we try
* to lock a special file. If we could make the lock, then we are the first
* ncftp running and our changes will be written. Other ncftps that may
* start will not be able to save their changes.
*
* No matter what locking method in use, whenever we Exit() we try to
* remove the lock file if we had the lock. For the first two methods,
* exiting releases the lock automatically.
*/
static
void CheckForOtherSessions(void)
{
int fd;
char pidbuf[64];
time_t now;
#if (LOCK_METHOD == 1)
struct flock l;
int err;
l.l_type = F_WRLCK;
l.l_start = 0;
l.l_whence = SEEK_SET;
l.l_len = 1;
OurDirectoryPath(gLockFileName, sizeof(gLockFileName), kLockFileName);
if ((fd = open(gLockFileName, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
Error(kDoPerror, "Could not open lock file %s.\n", gLockFileName);
sleep(5);
/* Try to save data anyway. */
gOtherSessionRunning = 0;
} else {
err = fcntl(fd, F_SETLK, &l);
if (err == 0) {
/* We now have a lock set on the first byte. */
gOtherSessionRunning = 0;
time(&now);
sprintf(pidbuf, "%5d %s", (int) getpid(), ctime(&now));
write(fd, pidbuf, strlen(pidbuf) + 1);
} else {
/* Could not lock; maybe another ncftp process has
* already locked it.
*/
gOtherSessionRunning = 1;
}
}
#endif /* (LOCK_METHOD == 1) */
#if (LOCK_METHOD == 2) /* BSD's flock */
int err;
OurDirectoryPath(gLockFileName, sizeof(gLockFileName), kLockFileName);
if ((fd = open(gLockFileName, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
Error(kDoPerror, "Could not open lock file %s.\n", gLockFileName);
sleep(5);
/* Try to save data anyway. */
gOtherSessionRunning = 0;
} else {
err = flock(fd, LOCK_EX | LOCK_NB);
if (err == 0) {
/* We now have a lock set on the whole file. */
gOtherSessionRunning = 0;
time(&now);
sprintf(pidbuf, "%5d %s", (int) getpid(), ctime(&now));
write(fd, pidbuf, strlen(pidbuf) + 1);
} else {
/* Could not lock; maybe another ncftp process has
* already locked it.
*/
gOtherSessionRunning = 1;
}
}
#endif /* (LOCK_METHOD == 2) */
#if (LOCK_METHOD == 3) /* Cheezy lock */
/* For this locking mechanism, we consider it locked if another
* process had already created the lockfile. Unfortunately we
* aren't guaranteed to get the lock file removed if the program
* crashes somewhere without explicitly removing the lockfile.
*/
OurDirectoryPath(gLockFileName, sizeof(gLockFileName), kLockFileName);
if ((fd = open(gLockFileName, O_CREAT | O_EXCL | O_WRONLY, S_IWUSR)) < 0) {
gOtherSessionRunning = 1;
} else {
gOtherSessionRunning = 0;
/* Unlike the other two methods, we don't need to keep the file
* open.
*/
close(fd);
}
#endif /* (LOCK_METHOD == 3) */
} /* CheckForOtherSessions */
void Init(void)
{
char *cp;
gRealStdout = gStdout = 1;
InitMalloc();
InitXferBuffer();
gSprintfBuf = (char *) malloc((size_t) 4096);
if (gSprintfBuf == NULL)
OutOfMemory();
#if (kAlpha > 0)
sprintf(gVersion, "%s Alpha %d (%s)",
kVersion,
kAlpha,
kVersionDate
);
#else
# if (kBeta > 0)
sprintf(gVersion, "%s Beta %d (%s)",
kVersion,
kBeta,
kVersionDate
);
# else
sprintf(gVersion, "%s (%s)",
kVersion,
kVersionDate
);
# endif
#endif
srand((unsigned int) time(NULL));
GetUserInfo();
InitDefaultFTPPort();
if ((cp = (char *) getenv("PAGER")) != NULL)
STRNCPY(gPager, cp);
else {
#ifdef MORE
STRNCPY(gPager, MORE);
#else
gPager[0] = '\0';
#endif
}
gIsFromTTY = gDoingScript = isatty(0);
gIsToTTY = isatty(1);
(void) UserLoggedIn(); /* Init parent-death detection. */
/* Init the mailbox checking code. */
(void) time(&gMailBoxTime);
/* Clear the redir buffer. */
InitLineList(&gRedir);
(void) GetCWD(gLocalCWD, sizeof(gLocalCWD));
/* Compute our own private directory's name, and create it
* if we have to. Stuff that depends on this will need
* to follow (duh).
*/
(void) InitOurDirectory();
(void) CheckForOtherSessions();
ReadPrefs();
OpenLogs();
ReadBookmarkFile();
ReadMacroFile();
InitCommandAndMacroNameList();
++gTotalRuns;
} /* Init */
void CloseTraceLog(void)
{
time_t now;
if (gTraceLogFile != NULL) {
time(&now);
fprintf(
gTraceLogFile,
"\nSESSION ENDED at %s",
ctime(&now)
);
(void) fclose(gTraceLogFile);
gTraceLogFile = NULL;
}
} /* CloseTraceLog */
void CloseLogs(void)
{
FILE *new, *old;
struct stat st;
long fat;
string str;
longstring tmpLog;
#ifdef SYSLOG
/* Close system log first. */
closelog();
#endif
/* Close the debugging log next. */
CloseTraceLog();
/* The rest is for the user's log. */
if (!gLogging)
return;
CloseFile(&gLogFile);
if (gOurDirectoryPath[0] == '\0')
return; /* Don't create in root directory. */
/* If the user wants to, s/he can specify the maximum size of the log file,
* so it doesn't waste too much disk space. If the log is too fat, trim the
* older lines (at the top) until we're under the limit.
*/
if ((gMaxLogSize < 0) || (stat(gLogFileName, &st) < 0) ||
((old = fopen(gLogFileName, "r")) == NULL))
return; /* Never trim, or no log. */
if (st.st_size < (size_t)gMaxLogSize)
return; /* Log size not over limit yet. */
/* Want to make it so we're about 30% below capacity.
* That way we won't trim the log each time we run the program.
*/
fat = st.st_size - gMaxLogSize + (long) (0.30 * gMaxLogSize);
DebugMsg("%s was over %ld limit; trimming at least %ld...\n",
gLogFileName,
gMaxLogSize,
fat
);
while (fat > 0L) {
if (fgets(str, (int) sizeof(str), old) == NULL)
return;
fat -= (long) strlen(str);
}
/* skip lines until a new site was opened */
while (1) {
if (fgets(str, (int) sizeof(str), old) == NULL) {
(void) fclose(old);
(void) UNLINK(gLogFileName);
return; /* Nothing left, start anew next time. */
}
if (! isspace(*str))
break;
}
/* Copy the remaining lines in "old" to "new" */
OurDirectoryPath(tmpLog, sizeof(tmpLog), kTmpLogName);
if ((new = fopen(tmpLog, "w")) == NULL) {
(void) Error(kDoPerror, "Could not open %s.\n", tmpLog);
return;
}
(void) fputs(str, new);
while (fgets(str, (int) sizeof(str), old) != NULL)
(void) fputs(str, new);
(void) fclose(old);
(void) fclose(new);
if (UNLINK(gLogFileName) < 0)
(void) Error(kDoPerror, "Could not delete %s.\n", gLogFileName);
if (rename(tmpLog, gLogFileName) < 0)
(void) Error(kDoPerror, "Could not rename %s to %s.\n",
tmpLog, gLogFileName);
} /* CloseLogs */
void SaveHistory(void)
{
string histFileName;
FILE *fp;
LinePtr lp;
int i;
if (gWinInit) {
if (gOurDirectoryPath[0] == '\0')
return; /* Don't create in root directory. */
lp = gCmdHistory.last;
OurDirectoryPath(histFileName, sizeof(histFileName), kHistoryName);
fp = fopen(histFileName, "w");
if ((fp != NULL) && (lp != NULL)) {
for (i = 1 ; (lp->prev != NULL) && (i < kMaxHistorySaveLines); i++)
lp = lp->prev;
for ( ; lp != NULL; lp = lp->next)
fprintf(fp, "%s\n", lp->line);
fclose(fp);
}
}
} /* SaveHistory */
void LoadHistory(void)
{
string histFileName;
string str;
FILE *fp;
InitLineList(&gCmdHistory);
OurDirectoryPath(histFileName, sizeof(histFileName), kHistoryName);
fp = fopen(histFileName, "r");
if (fp != NULL) {
while (FGets(str, sizeof(str), fp) != NULL)
AddLine(&gCmdHistory, str);
}
} /* LoadHistory */
void StartupMsgs(void)
{
char curLocalCWD[512];
if ((gStartupMsgs & kStartupMsg) != 0) {
#if (kAlpha > 0) || (kBeta > 0)
if (gWinInit == 0)
PrintF("NcFTP %s, by Mike Gleason, NCEMRSoft.\n", gVersion);
BoldPrintF(
"This pre-release is for testing only. Please do not archive.\n\n");
BoldPrintF(
"Check the CHANGELOG file for changes between betas.\n\n");
#else
if (gWinInit == 0)
PrintF("NcFTP %s, by Mike Gleason, NCEMRSoft.\n", gVersion);
#endif
}
if (gTotalRuns < 2) {
PrintF("%s%s%s\n", gCopyright1 + 5, gCopyright2, gCopyright3);
} else if ((gStartupMsgs & kTips) != 0) {
PrintRandomTip();
}
if (gOtherSessionRunning) {
BoldPrintF("Note: Another session is running. Changes made to the\n");
BoldPrintF(" prefs, bookmarks, and trace files will not be saved.\n\n");
}
(void) GetCWD(curLocalCWD, sizeof(curLocalCWD));
if (gDownloadDir[0] != '\0') {
/* If set, always try to cd there. */
ExpandTilde(gDownloadDir, sizeof(gDownloadDir));
(void) chdir(gDownloadDir); /* May not succeed. */
} else if (gRememberLCWD) {
/* Try restoring the last local directory we were in.
* gLocalCWD may be set when the prefs are read in.
*/
if (gLocalCWD[0] != '\0')
(void) chdir(gLocalCWD); /* May not succeed. */
}
/* Print a message if we changed the directory. */
(void) GetCWD(gLocalCWD, sizeof(gLocalCWD));
if (strcmp(curLocalCWD, gLocalCWD))
PrintF("Current local directory is %s.\n", gLocalCWD);
} /* StartupMsg */
void Startup(void)
{
if (gStartup == 0) {
gStartup = 1;
InitWindows();
StartupMsgs();
(void) RunPrefixedMacro("start.", "ncftp");
InitReadline();
}
} /* Startup */
/*ARGSUSED*/
static void
SigIntMain(int sigNum)
{
SIGNAL(SIGINT, SigIntMain);
alarm(0);
EPrintF("\n*Interrupt*\n");
longjmp(gMainJmp, 1);
} /* SigIntMain */
void main(int argc, char **argv)
{
int opt, result;
OpenOptions openopt;
Init();
RunStartupScript();
GetoptReset();
gOptErr = 0;
if (GetOpenOptions(argc, argv, &openopt, 1) == kUsageErr)
goto usage;
gOptErr = 1;
GetoptReset();
gVisualMode = gDefaultVisualMode;
/* Note that we getopt on three sets of options, one for open,
* one for get, and one for the program. That means that these
* commands' flags and the program must use mutually exclusive
* sets of flags.
*/
while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:zDLVH")) >= 0) {
if (strchr("aiup:rd:g:cmCfGRn:z", opt) == NULL) {
switch (opt) {
case 'D':
gDebug = kDebuggingOn;
gTrace = kTracingOn;
break;
case 'L': gVisualMode = 0; break;
case 'V': gVisualMode = 1; break;
case 'H': VersionCmd(0, NULL); Exit(kExitNoErr); break;
default:
usage:
EPrintF(
"Usage: ncftp [options] [hostname[:path]]\n");
EPrintF("Program options:\n\
-D : Turn debug mode and trace mode on.\n\
-L : Don't use visual mode (use line mode).\n\
-V : Use visual mode.\n\
-H : Dump the version information.\n");
EPrintF("Command-line open options:\n\
-a : Open anonymously.\n\
-u : Open with username and password prompt.\n\
-p X : Use port number X when opening.\n\
-r : Redial until connected.\n\
-d X : Redial, delaying X seconds between tries.\n\
-g X : Give up after X redials without connection.\n");
EPrintF("Command-line retrieve options:\n\
-C : Force continuation (reget).\n\
-f : Force overwrite.\n\
-G : Don't use wildcard matching.\n\
-R : Recursive. Useful for fetching whole directories.\n\
-n X : Get selected files only if X days old or newer.\n");
Exit(kExitUsageErr);
}
}
}
result = kNoErr;
if (openopt.hostname[0] != '\0') {
if (setjmp(gMainJmp)) {
result = kNoErr;
} else {
SIGNAL(SIGINT, SigIntMain);
SIGNAL(SIGPIPE, SIG_IGN);
if (setjmp(gCmdLoopJmp)) {
/* May have lost connection during Open. */
result = kCmdErr;
} else {
result = Open(&openopt);
}
}
}
if (result == kNoErr) {
Startup(); /* Init the interactive shell. */
CommandShell();
DoQuit(kExitNoErr);
}
DoQuit(kExitColonModeFail);
/*NOTREACHED*/
Exit(kExitNoErr);
} /* main */
/* eof Main.c */