Logo Search packages:      
Sourcecode: ncftp2 version File versions  Download package

Open.c

/* Open.c */

#include "Sys.h"

#ifdef SYSLOG
#     include <syslog.h>
#endif

#include "Util.h"
#include "Open.h"
#include "GetPass.h"
#include "Cmds.h"
#include "RCmd.h"
#include "Bookmark.h"
#include "FTP.h"
#include "Get.h"
#include "Getopt.h"
#include "Macro.h"
#include "Hostwin.h"
#include "Main.h"
#include "Complete.h"

/* This is a preference setting specifying whether we use anonymous logins
 * by default (as opposed to user/passwd logins).
 */
int gAnonOpen = (UOPEN == 0);

/* A structure containing some extra information we've learned about
 * the remote host, so we don't need to find out the hard way each
 * time we do something.
 */
extern Bookmark gRmtInfo;

/* Name of the host we're connected to. */
string gHost;

/* We keep track if we've logged in to the host yet.  It's possible to
 * be connected but not authorized (authenticated, whatever) to do anything.
 */
int gLoggedIn = 0;

/* Need to know if we are trying to connect and login, so if we get
 * hangup during that, we will come back to the open without longjmp'ing
 * out.
 */
int gAttemptingConnection = 0;

/* Need to know if they did a 'open -r' so we don't use the built-in pager
 * for long site-connect messages.  Otherwise the program would stop to
 * wait for the user to hit <space> each time we connected to that site
 * which would sort of defeat the purpose of redialing.
 */
int gRedialModeEnabled = 0;

/* If we connect successfully, we'll want to save this port number
 * when we add a host file entry.
 */
int gPortNumberUsed;

int gSavePasswords = 0;

/* Open.c externs */
extern char *gOptArg;
extern int gOptInd, gIsToTTY;
extern unsigned int gFTPPort;
extern long gEventNumber;
extern char gRemoteCWD[256];
extern char gIPStr[32];
extern int gTransferType, gCurType, gRemoteServerType;
extern int gRmtInfoIsNew, gWantRmtInfoSaved;
extern int gConnected, gHasPASV, gVerbosity;
extern int gDoneApplication, gWinInit, gMode;
extern string gEmailAddress, gAnonPassword, gPager;
extern UserInfo gUserInfo;
extern FILE *gLogFile;
extern LineList gRedir;
extern void GetRemoteCWD(char *cdstub, ResponsePtr cwdrp);


/* This is used primarily for non-anonymous logins.  We'll have to ask
 * the user some questions, like their username, password, etc.
 */
int LoginQuestion(
      char *prompt,
      char *answer,
      size_t siz,
      char *defanswer,
      int noEcho)
{
      string prompt2;
      
      /* Only do this if we have an empty string as the answer. */
      if (*answer == '\0') {
            if (defanswer != NULL)
                  sprintf(prompt2, "%s [%s]: ", prompt, defanswer);
            else
                  sprintf(prompt2, "%s: ", prompt);
            GetAnswer(prompt2, answer, siz, noEcho);
            if ((*answer == '\0') && (defanswer != NULL))
                  Strncpy(answer, defanswer, siz);
      }
      return (*answer == '\0' ? (-1) : 0);
}     /* LoginQuestion */




int Login(char *u, char *p, char *a)
{
      string u2, p2, a2;
      ResponsePtr rp;
      int result = -1;
      int isAnonLogin = 1;

      STRNCPY(u2, u);
      STRNCPY(p2, p);
      STRNCPY(a2, a);
            
      rp = InitResponse();
      if (LoginQuestion("User", u2, sizeof(u2), "anonymous", 0) < 0)
            goto done;
      RCmd(rp, "USER %s", u2);

      for (;;) {
            /* Here's a mini finite-automaton for the login process.
             *
             * Originally, the FTP protocol was designed to be entirely
             * implementable from a FA.  It could be done, but I don't think
             * it's something an interactive process could be the most
             * effective with.
             */
            switch (rp->code) {
                  case 230:   /* 230 User logged in, proceed. */
                  case 202:   /* Command not implemented, superfluous at this site. */
                        goto okay;

                  case 421:   /* 421 Service not available, closing control connection. */
                        goto done;
                        
                  case 331:   /* 331 User name okay, need password. */
                        isAnonLogin =     STREQ("anonymous", u2) ||
                                                STREQ("ftp", u2);
                        if (isAnonLogin)
                              rp->printMode = kDontPrint;

                        ReInitResponse(rp);
                        (void) LoginQuestion(
                              "Password",
                              p2,
                              sizeof(p2),
                              isAnonLogin ? gAnonPassword : NULL,
                              1
                        );
                        RCmd(rp, "PASS %s", p2);
                        break;

            case 332:   /* 332 Need account for login. */
            case 532:   /* 532 Need account for storing files. */
                        ReInitResponse(rp);
                        (void) LoginQuestion("Account", a2, sizeof(a2), NULL, 1);
                        RCmd(rp, "ACCT %s", a2);
                        break;

                  case 501:   /* Syntax error in parameters or arguments. */
                  case 503:   /* Bad sequence of commands. */
                  case 530:   /* Not logged in. */
                  case 550:   /* Can't set guest privileges. */
                        goto done;
                        
                  default:
                        if (rp->msg.first == NULL) {
                              Error(kDontPerror, "Lost connection during login.\n");
                        } else {
                              Error(kDontPerror, "Unexpected response: %s\n",
                                    rp->msg.first->line
                              );
                        }
                        goto done;
            }
      }
okay:
      if (isAnonLogin) {
            gRmtInfo.user[0] = '\0';
            gRmtInfo.pass[0] = '\0';
            STRNCPY(gRmtInfo.acct, a2);
      } else {
            STRNCPY(gRmtInfo.user, u2);
            if (gSavePasswords) {
                  STRNCPY(gRmtInfo.pass, p2);
                  STRNCPY(gRmtInfo.acct, a2);
            }
      }

      result = 0;
done:
      DoneWithResponse(rp);
      return result;
}     /* Login */




/* After closing a site, set or restore some things to their original
 * states.
 */
void PostCloseStuff(void)
{
#ifdef SYSLOG
      syslog (LOG_INFO, "%s disconnected from %s.", gUserInfo.userName, gHost);
#endif
      if (gLoggedIn) {
            gRmtInfo.hasPASV = gHasPASV;
            gRmtInfo.port = gPortNumberUsed;
            gRmtInfo.nCalls++;
            time((time_t *) &gRmtInfo.lastCall);
            STRNCPY(gRmtInfo.lastIP, gIPStr);
            if (gEventNumber > 0L) {
                  /* Only do these if we were not in batch mode (colon-mode). */
                  if (gRmtInfo.noSaveDir == 0)
                              STRNCPY(gRmtInfo.dir, gRemoteCWD);
                  (void) RunPrefixedMacro("close.", gRmtInfo.bookmarkName);
                  (void) RunPrefixedMacro("close.", "any");
            } else {
                  /* Only do these if we are running colon mode. */
                  (void) RunPrefixedMacro("colon.close.", gRmtInfo.bookmarkName);
                  (void) RunPrefixedMacro("colon.close.", "any");
            }
            SaveCurHostBookmark(NULL);
      }
      gLoggedIn = 0;
      gRemoteCWD[0] = gHost[0] = '\0';
}     /* PostCloseStuff */




/* Close the connection to the remote host and cleanup. */
void DoClose(int tryQUIT)
{
      ResponsePtr rp;
      
      if (tryQUIT != 0) {
            rp = InitResponse();
            rp->eofOkay = 1;  /* We are expecting EOF after this cmd. */
            RCmd(rp, "QUIT");
            DoneWithResponse(rp);
      }
      
      CloseControlConnection();
      CloseDataConnection(1);
      PostCloseStuff();
}     /* DoClose */




int CloseCmd(void)
{
      DoClose(gConnected);
      if (gWinInit == 0)
                  SetScreenInfo();  /* Need for line mode. */
      return kNoErr;
}     /* CloseCmd */




/* Given a pointer to an OpenOptions (structure containing all variables
 * that can be set from the command line), this routine makes sure all
 * the variables have valid values by setting them to their defaults.
 */
 
void InitOpenOptions(OpenOptions *openopt)
{
      /* How do you want to open a site if neither -a or -u are given?
       * gAnonOpen is true (default to anonymous login), unless
       * Config.h was edited to set UOPEN to 0 instead.
       */
      openopt->openmode = gAnonOpen ? kOpenImplicitAnon : kOpenImplicitUser;

      /* Normally you don't want to ignore the entry in your netrc. */
      openopt->ignoreRC = 0;

      /* Set the default delay if the user specifies redial mode without
       * specifying the redial delay.
       */
      openopt->redialDelay = kRedialDelay;

      /* Normally, you only want to try once. If you specify redial mode,
       * this is changed.
       */
      openopt->maxDials = 1;
      
      /* You don't want to dump the file to stdout by default. */
      openopt->ftpcat = kNoFTPCat;

      /* We'll set this later, but we'll use 0 to mean that the port
       * is explicitly not set by the user.
       */
      openopt->port = kPortUnset;

      /* We are not in colon-mode (yet). */
      openopt->colonModePath[0] = 0;

      /* Set the hostname to a null string, since there is no default host. */
      openopt->hostname[0] = 0;
      
      /* Set the opening directory path to a null string. */
      openopt->cdpath[0] = 0;

      openopt->interactiveColonMode = 0;

      /* Since we're opening with a possible colon-mode item, we have to
       * track options for the GetCmd too.
       */
      InitGetOptions(&openopt->gopt);
}     /* InitOpenOptions */





/* This is responsible for parsing the command line and setting variables
 * in the OpenOptions structure according to the user's flags.
 */

int GetOpenOptions(int argc, char **argv, OpenOptions *openopt, int fromMain)
{
      int                           opt, www;
      char                    *cp, *hostp, *cpath;

      /* First setup the openopt variables. */
      InitOpenOptions(openopt);

      /* Tell Getopt() that we want to start over with a new command. */
      GetoptReset();
      while ((opt = Getopt(argc, argv, "aiup:rd:g:cmCfGRn:")) >= 0) {
            switch (opt) {          
                  case 'a':
                        /* User wants to open anonymously. */
                        openopt->openmode = kOpenExplicitAnon;
                        break;
                        
                  case 'u':
                        /* User wants to open with a login and password. */
                        openopt->openmode = kOpenExplicitUser;
                        break;

                  case 'i':
                        /* User wants to ignore the entry in the netrc. */
                        openopt->ignoreRC = 1;
                        break;

                  case 'p':
                        /* User supplied a port number different from the default
                         * ftp port.
                         */
                        openopt->port = atoi(gOptArg);
                        if (openopt->port <= 0) {
                              /* Probably never happen, but just in case. */
                              (void) PrintF("%s: bad port number (%s).\n", argv[0],
                                    gOptArg);
                              goto usage;
                        }
                        break;
                        
                  case 'd':
                        /* User supplied a delay (in seconds) that differs from
                         * the default.
                         */
                        openopt->redialDelay = atoi(gOptArg);
                        break;
                        
                  case 'g':
                        /* User supplied an upper-bound on the number of redials
                         * to try.
                         */
                        openopt->maxDials = atoi(gOptArg);
                        break;

                  case 'r':
                        openopt->maxDials = -1;
                        break;

                  case 'm':
                        /* ftpcat mode is only available from your shell command-line,
                         * not from the ncftp shell.  Do that yourself with 'more zz'.
                         */
                        if (gEventNumber == 0L) {
                              /* If gEventNumber is zero, then we were called directly
                               * from main(), and before the ftp shell has started.
                               */
                              openopt->ftpcat = kFTPMore;
                              /* ftpcat mode is really ftpmore mode. */
                              break;
                        } else {
                              PrintF(
"You can only use this form of colon-mode (-m) from your shell command line.\n\
Try 'ncftp -m wuarchive.wustl.edu:/README'\n");
                        }
                        goto usage;

                  case 'c':
                        /* ftpcat mode is only available from your shell command-line,
                         * not from the ncftp shell.  Do that yourself with 'get zz -'.
                         */
                        if (gEventNumber == 0L) {
                              /* If gEventNumber is zero, then we were called directly
                               * from main(), and before the ftp shell has started.
                               */
                              openopt->ftpcat = kFTPCat;
                              break;
                        } else {
                              PrintF(
"You can only use ftpcat/colon-mode from your shell command line.\n\
Try 'ncftp -c wuarchive.wustl.edu:/README > file.'\n");
                        }
                        goto usage;

                  /* These are options that can be passed to get. */
                  case 'C':
                  case 'f':
                  case 'G':
                  case 'R':
                  /* case 'z':  Note that we can't handle the rename here. */
                  case 'n':
                        if (fromMain) {
                              (void) SetGetOption(&openopt->gopt, opt, gOptArg);
                              break;
                        }
                        goto usage;

                  default:
                        if (fromMain)
                              break;
                              
                  usage:
                        return kUsageErr;
            }
      }

      if (argv[gOptInd] == NULL) {
            if (!fromMain) {
                  if (openopt->hostname[0] == 0)
                        goto usage;
            }
      } else {
            /* The user gave us a host to open.
             *
             * First, check to see if they gave us a colon-mode path
             * along with the hostname.  We also understand a WWW path,
             * like "ftp://bang.nta.no/pub/fm2html.v.0.8.4.tar.Z".
             */
            hostp = argv[gOptInd];
            cpath = NULL;
            if ((cp = strchr(hostp, ':')) != NULL) {
                  if (fromMain) {
                        *cp++ = '\0';
                        cpath = cp;
                        www = 0;    /* Is 0 or 1, depending on the type of path. */
                        if ((*cp == '/') && (cp[1] == '/')) {
                              /* First make sure the path was intended to be used
                               * with ftp and not one of the other URLs.
                               */
                              if (!ISTREQ(argv[gOptInd], "ftp")) {
                                    PrintF(
                                          "Bad URL '%s' -- WWW paths must be prefixed by 'ftp://'.\n",
                                          argv[gOptInd]
                                    );
                                    goto usage;
                              }
      
                              cp += 2;
                              hostp = cp;
                              cpath = NULL;     /* It could have been ftp://hostname only. */
      
                              if ((cp = strchr(hostp, '/')) != NULL) {
                                    *cp++ = '\0';
                                    cpath = cp;
                              }
                              www = 1;
                        }
                        if (cpath != NULL) {
                              (void) STRNCPY(openopt->colonModePath, www ? "/" : "");
                              (void) STRNCAT(openopt->colonModePath, cpath);
                              cp = openopt->colonModePath +
                                    strlen(openopt->colonModePath) - 1;
                              if (*cp == '/') {
                                    /* Colon-mode path ended in a slash, so you said it
                                     * was a directory.  That means we should start from
                                     * this directory when we open this site.
                                     */
                                    *cp = '\0';
                                    openopt->interactiveColonMode = 1;
                              }
                              DebugMsg("Colon-Mode Path = '%s'\n", openopt->colonModePath);
                        }

                  } else {
                        /* I may lift this restriction later. */
                        EPrintF("You can't use colon mode in the command shell.\n");
                        return kUsageErr;
                  }
            }
            (void) STRNCPY(openopt->hostname, hostp);

            if ((openopt->colonModePath[0] == '\0') &&
                  (openopt->ftpcat != kNoFTPCat))
            {
                  /* User specified ftpcat mode, but didn't supply
                   * the host:file.
                   */
                  EPrintF("You didn't use colon mode correctly.\n\
If you use -c or -m, you need to do something like this:\n\
ncftp -c wuarchive.wustl.edu:/pub/README (to cat this file to stdout).\n");
                  return kUsageErr;
            }

            GetBookmark(openopt->hostname, sizeof(openopt->hostname));
            if (openopt->port == kPortUnset) {
                  /* No port specified, so use same port as last time. */
                  if (gRmtInfo.port == kPortUnset)
                        openopt->port = gFTPPort;
                  else
                        openopt->port = gRmtInfo.port;
            }
      }
      return kNoErr;
}     /* GetOpenOptions */




void CheckRemoteSystemType(int force_binary)
{
      string remoteSys;

      if (gRmtInfoIsNew) {
            /* If first time here, check somethings while we can. */
            if (DoSystem(remoteSys, sizeof(remoteSys)) == 0)
                  gRmtInfo.isUnix = !strncmp(remoteSys, "UNIX", (size_t) 4);
      
            /* Set to binary mode if any of the following are true:
             * (a) The user is using colon-mode (force_binary; below);
             * (b) The reply-string from SYST said it was UNIX with 8-bit chars.
             */
            if (!strncmp(remoteSys, "UNIX Type: L8", (size_t) 13))
            {
                  gRmtInfo.xferType = 'I';
            }
      
            /* Print a warning for that (extremely) rare Tenex machine. */
            if (!strncmp(remoteSys, "TOPS20", (size_t) 6)) {
                  gRmtInfo.xferType = 'T';
                  (void) PrintF("Using tenex mode to transfer files.\n");
            }

            if (gRemoteServerType == kNcFTPd) {
                  /* This server correctly implements
                   * block transfer mode, so turn it
                   * on by default.
                   *
                   * Unfortunately, most servers don't
                   * support it, and those that do
                   * (AIX ftpd) don't do it correctly.
                   */
                  gRmtInfo.xferMode = 'B';
            }

      }
      gTransferType = gRmtInfo.xferType;
      
      /* Use binary mode if this site was last set using ascii mode,
       * and we are using colon-mode.
       */
      if ((force_binary) && (gTransferType == 'A'))
            gTransferType = 'I';

      if (SetMode(gRmtInfo.xferMode) < 0) {
            gRmtInfo.xferMode = gMode;
      }
}     /* CheckRemoteSystemType */



/* This is called if the user opened the host with a file appended to
 * the host's name, like "wuarchive.wustl.edu:/pub/readme," or
 * "wuarchive.wustl.edu:/pub."  In the former case, we open wuarchive,
 * and fetch "readme."  In the latter case, we open wuarchive, then set
 * the current remote directory to "/pub."  If we are fetching a file,
 * we can do some other tricks if "ftpcat mode" is enabled.  This mode
 * must be selected from your shell's command line, and this allows you
 * to use the program as a one-liner to pipe a remote file into something,
 * like "ncftp -c wu:/pub/README | wc."  If the user uses ftpcat mode,
 * the program immediately quits instead of going into its own command
 * shell.
 */
void ColonMode(OpenOptions *openopt)
{
      int result;

      /* Check for FTP-cat mode, so we call the appropriate
       * fetching routine.
       */
      if (openopt->ftpcat == kFTPCat) {
            InitGetOutputMode(&openopt->gopt, kDumpToStdout);
            openopt->gopt.rName = openopt->colonModePath;
            openopt->gopt.doReports = 0;
            result = DoGet(&openopt->gopt);
      } else if (openopt->ftpcat == kFTPMore) {
            result = DoPage(openopt->colonModePath);
      } else {
            /* Regular colon-mode, where we fetch the file, putting the
             * copy in the current local directory.
             */
            InitGetOutputMode(&openopt->gopt, kSaveToDisk);
            openopt->gopt.doReports = 0;
            openopt->gopt.rName = openopt->colonModePath;
            result = DoGetWithGlobbingAndRecursion(&openopt->gopt);
      }
      DoQuit(result == 0 ? result : kExitColonModeFail);
      /*NOTREACHED*/
}     /* ColonMode */




/* Now that we're logged in, do some other stuff prior to letting the
 * user type away at the shell.
 */
void PostLoginStuff(OpenOptions *openopt)
{
      time_t now;
      int wasColonMode;
      
      gLoggedIn = 1;

      /* Clear out the old redir buffer, since we are on a new site. */
      DisposeLineListContents(&gRedir);

      /* Since we're logged in okay, we know what we've collected so far
       * should be saved for next time.
       */
      gWantRmtInfoSaved = 1;
      
      /* The FTP module keeps its own note of whether the site has PASV
       * or not, and has already initialized it to true.  If the gRmtInfo
       * was fetched from our host file, we can tell FTP.c for sure if
       * PASV should even be attempted.  If this was a new gRmtInfo, we
       * will just be a little redundant, since new entries also assume
       * PASV is supported.
       */
      gHasPASV = gRmtInfo.hasPASV;
      
      /* Since we connected okay, save this port number for later. */
      gPortNumberUsed = openopt->port;

      /* When a new site is opened, ASCII type is assumed (by protocol),
       * as well as stream transfer mode.
       */
      gCurType = 'A';
      gMode = 'S';

      STRNCPY(gHost, openopt->hostname);
#ifdef SYSLOG
      syslog (LOG_INFO, "%s logged into %s.", gUserInfo.userName, gHost);
#endif
      if (gLogFile != NULL) {
            (void) time(&now);
            fprintf(gLogFile, "%s at %s", gHost, ctime(&now));
      }

      wasColonMode = openopt->colonModePath[0] != (char)0;

      /* We need to check for unix and see if we should set binary
       * mode automatically.
       */
      CheckRemoteSystemType(wasColonMode);

      if (wasColonMode) {
            if (openopt->interactiveColonMode) {
                  /* Interactive colon mode simply means that the thing they
                   * gave us was a directory, and we should just cd to that
                   * directory when we start up.
                   */
                  (void) DoChdir(openopt->colonModePath);
            } else {
                  /* Regular colon-mode is fetching a file by specifying the
                   * pathname of the file on the shell command line.
                   */
                  (void) GetRemoteCWD(kDidNotChdir, NULL);
                  ColonMode(openopt);           /* Does not return... */
            }
      } else if (gRmtInfo.dir[0]) {
            /* If we didn't have a colon-mode path, we try setting
             * the current remote directory to cdpath.  The .dir field is
             * (usually) the last directory we were in the previous
             * time we called this site.
             */
            (void) DoChdir(gRmtInfo.dir);
      } else {
            /* Freshen 'cwd' variable for the prompt. */
            (void) GetRemoteCWD(kDidNotChdir, NULL);
      }

      if (wasColonMode) {
            /* Run separate sets of macros for colon-mode opens and regular,
             * interactive opens.
             */
            (void) RunPrefixedMacro("colon.open.", "any");
            (void) RunPrefixedMacro("colon.open.", gRmtInfo.bookmarkName);
      } else {
            (void) RunPrefixedMacro("open.", "any");
            (void) RunPrefixedMacro("open.", gRmtInfo.bookmarkName);
            if (gWinInit == 0)
                        SetScreenInfo();  /* Need for line mode. */
            ClearDirCache();
      }
}     /* PostLoginStuff */





/* Given a properly set up OpenOptions, we try connecting to the site,
 * redialing if necessary, and do some initialization steps so the user
 * can send commands.
 */
int Open(OpenOptions *openopt)
{
      int                           hErr;
      int                           dials;
      char                    *user, *pass, *r_acct;  
      int                           loginResult;
      int                           openMode;

      gRedialModeEnabled = (openopt->maxDials != 1);
      if (ISEXPLICITOPEN(openopt->openmode)) {
            /* User specified an open mode explictly, like open -u,
             * so do what the user said in spite of what we may have had
             * in the gRmtInfo.
             */
            openMode = (ISANONOPEN(openopt->openmode)) ? 'a' : 'u';
      } else {
            if (gRmtInfoIsNew == 1) {
                  /* First time opening this site.  Open it anonymously
                   * unless you said not to with a -option.
                   */
                  openMode = (ISANONOPEN(openopt->openmode)) ? 'a' : 'u';
            } else {
                  /* We've been here before, so use what we had last time. */
                  openMode = 'r';
            }
      }

      if ((openMode == 'r') && (gRmtInfo.user[0] == '\0'))
            openMode = 'a';
      if (openMode == 'a') {
            user = "anonymous";
            pass = strchr(gRmtInfo.pass, '@') ? gRmtInfo.pass : gAnonPassword;
            r_acct = "";
      } else if (openMode == 'u') {
            user = "";
            pass = "";
            r_acct = "";
      } else {
            user = gRmtInfo.user;
            pass = gRmtInfo.pass;
            r_acct = gRmtInfo.acct;
      }

      if ((openopt->colonModePath[0]) && (!openopt->interactiveColonMode)) {
            /* If we're running from a shell script (or whatever)
             * don't dump any output.  If the user is doing this from
             * the shell, we will at least print the error messages.
             * We also don't want to "pollute" ftpcat mode, but since
             * error messages are printed to stderr, and we weren't
             * going to print anything but error messages anyway,
             * we're okay by using kErrorsOnly.
             */
            if (gIsToTTY != 0)
                  (void) SetVerbose(kErrorsOnly);
            else
                  (void) SetVerbose(kQuiet);
      } else {
            /* If we haven't already setup our interactive shell, which
             * would happen if you gave a host on the command line, then
             * we need to do that now because we want the remote host's
             * startup information to be displayed.
             */
            Startup();
      }

      
      PrintF("Trying to connect to %s...\n", openopt->hostname);
      for (
                  dials = 0;
                  openopt->maxDials < 0 || dials < openopt->maxDials;
                  dials++)
      {
            if (dials > 0) {
                  /* If this is the second dial or higher, sleep a bit. */
                  PrintF("Sleeping %u seconds...  ",
                        (unsigned) openopt->redialDelay);
                  FlushListWindow();
                  (void) sleep((unsigned) openopt->redialDelay);
                  PrintF("Retry Number: %d\n", dials + 1);
            }
            FlushListWindow();

            SetBar(NULL, "CONNECTING", NULL, 1, 1);
            gAttemptingConnection = 1;
            hErr = OpenControlConnection(openopt->hostname, openopt->port);
            if (hErr == kConnectErrFatal) {
                  /* Irrecoverable error, so don't bother redialing.
                   * The error message should have already been printed
                   * from OpenControlConnection().
                   */
                  DebugMsg("Cannot recover from open error %d.\n", hErr);
                  break;
            } else if (hErr == kConnectNoErr) {
                  /* We were hooked up successfully. */
                  
                  gRemoteCWD[0] = '\0';
      
                  /* This updates the status bar (for visual mode). */
                  SetBar(NULL, "LOGGING IN", NULL, 1, 1);
                  SetPostHangupOnServerProc(PostCloseStuff);
                  loginResult = Login(user, pass, r_acct);
                  
                  if (loginResult == 0) {
                        PostLoginStuff(openopt);
                        if (openopt->maxDials != 1) {
                              /* If they selected redial mode, beep at the user
                               * to get their attention.
                               */
                              Beep(1);
                        }
                        gAttemptingConnection = 0;    /* We are connected. */
                        gRedialModeEnabled = 0;       /* Not dialing any more. */
                        return(kNoErr);   /* Login okay, so done. */
                  }
                  /* Otherwise, an error during login occurred, so try again. */
            } else /* (hErr == kConnectErrReTryable), so redial. */ {
                  /* Display error now. */
                  FlushListWindow();
            }
            
            DoClose(gConnected);
            gAttemptingConnection = 0;
      }

      /* Display error now. */
      FlushListWindow();

      if ((openopt->colonModePath[0]) && (!openopt->interactiveColonMode)) {
            /* If we get here, we we're colon-moding and got a non-redialable
             * error or we ran out of attempts.
             */
            DoQuit(kExitColonModeFail);
      }
      return (kCmdErr);
}     /* Open */




int OpenCmd(int argc, char **argv)
{
      OpenOptions             openopt;
      int result;

      /* If there is already a site open, close that one so we can
       * open a new one.
       */
      DoClose(gConnected);

      if (argc < 2) {
            result = HostWindow();
      } else {
            if ((result = GetOpenOptions(argc, argv, &openopt, 0)) == kNoErr)
                  result = Open(&openopt);
      }
      return result;
}     /* OpenCmd */

/* Open.c */

Generated by  Doxygen 1.6.0   Back to index