Annotation of coherent/g/usr/lib/uucp/tay104/uucico.c.mwcbb, revision 1.1

1.1     ! root        1: /* uucico.c
        !             2:    This is the main UUCP communication program.
        !             3: 
        !             4:    Copyright (C) 1991, 1992 Ian Lance Taylor
        !             5: 
        !             6:    This file is part of the Taylor UUCP package.
        !             7: 
        !             8:    This program is free software; you can redistribute it and/or
        !             9:    modify it under the terms of the GNU General Public License as
        !            10:    published by the Free Software Foundation; either version 2 of the
        !            11:    License, or (at your option) any later version.
        !            12: 
        !            13:    This program is distributed in the hope that it will be useful, but
        !            14:    WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            16:    General Public License for more details.
        !            17: 
        !            18:    You should have received a copy of the GNU General Public License
        !            19:    along with this program; if not, write to the Free Software
        !            20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            21: 
        !            22:    The author of the program may be contacted at [email protected] or
        !            23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
        !            24:    */
        !            25: 
        !            26: #include "uucp.h"
        !            27: 
        !            28: #if USE_RCS_ID
        !            29: const char uucico_rcsid[] = "$Id: uucico.c,v 1.140 1993/01/18 05:03:06 ian Rel $";
        !            30: #endif
        !            31: 
        !            32: #include <ctype.h>
        !            33: 
        !            34: #if HAVE_LIMITS_H
        !            35: #include <limits.h>
        !            36: #else
        !            37: #define LONG_MAX 2147483647L
        !            38: #endif
        !            39: 
        !            40: #include "getopt.h"
        !            41: 
        !            42: #include "uudefs.h"
        !            43: #include "uuconf.h"
        !            44: #include "conn.h"
        !            45: #include "prot.h"
        !            46: #include "trans.h"
        !            47: #include "system.h"
        !            48: 
        !            49: /* The program name.  */
        !            50: char abProgram[] = "uucico";
        !            51: 
        !            52: /* Define the known protocols.  */
        !            53: 
        !            54: #define TCP_PROTO \
        !            55:   (UUCONF_RELIABLE_ENDTOEND \
        !            56:    | UUCONF_RELIABLE_RELIABLE \
        !            57:    | UUCONF_RELIABLE_EIGHT)
        !            58: 
        !            59: static const struct sprotocol asProtocols[] =
        !            60: {
        !            61:   { 't', TCP_PROTO, 1,
        !            62:       asTproto_params, ftstart, ftshutdown, ftsendcmd, ztgetspace,
        !            63:       ftsenddata, ftwait, ftfile },
        !            64:   { 'e', TCP_PROTO, 1,
        !            65:       asEproto_params, festart, feshutdown, fesendcmd, zegetspace,
        !            66:       fesenddata, fewait, fefile },
        !            67:   { 'i', UUCONF_RELIABLE_EIGHT, 7,
        !            68:       asIproto_params, fistart, fishutdown, fisendcmd, zigetspace,
        !            69:       fisenddata, fiwait, NULL },
        !            70:   { 'a', UUCONF_RELIABLE_EIGHT, 1,
        !            71:       asZproto_params, fzstart, fzshutdown, fzsendcmd, zzgetspace,
        !            72:       fzsenddata, fzwait, fzfile },
        !            73:   { 'g', UUCONF_RELIABLE_EIGHT, 1,
        !            74:       asGproto_params, fgstart, fgshutdown, fgsendcmd, zggetspace,
        !            75:       fgsenddata, fgwait, NULL },
        !            76:   { 'G', UUCONF_RELIABLE_EIGHT, 1,
        !            77:       asGproto_params, fbiggstart, fgshutdown, fgsendcmd, zggetspace,
        !            78:       fgsenddata, fgwait, NULL },
        !            79:   { 'j', UUCONF_RELIABLE_EIGHT, 7,
        !            80:       asIproto_params, fjstart, fjshutdown, fisendcmd, zigetspace,
        !            81:       fisenddata, fiwait, NULL },
        !            82:   { 'f', UUCONF_RELIABLE_RELIABLE, 1,
        !            83:       asFproto_params, ffstart, ffshutdown, ffsendcmd, zfgetspace,
        !            84:       ffsenddata, ffwait, fffile },
        !            85: };
        !            86: 
        !            87: #define CPROTOCOLS (sizeof asProtocols / sizeof asProtocols[0])
        !            88: 
        !            89: /* Locked system.  */
        !            90: static boolean fLocked_system;
        !            91: static struct uuconf_system sLocked_system;
        !            92: 
        !            93: /* Daemon structure holding information about the remote system (must
        !            94:    be global so the error handler can see it.  */
        !            95: static struct sdaemon sDaemon;
        !            96: 
        !            97: /* Open connection.  */
        !            98: static struct sconnection *qConn;
        !            99: 
        !           100: /* uuconf global pointer; need to close the connection after a fatal
        !           101:    error.  */
        !           102: static pointer pUuconf;
        !           103: 
        !           104: /* This structure is passed to iuport_lock via uuconf_find_port.  */
        !           105: struct spass
        !           106: {
        !           107:   boolean fmatched;
        !           108:   boolean flocked;
        !           109:   struct sconnection *qconn;
        !           110: };
        !           111: 
        !           112: /* Local functions.  */
        !           113: 
        !           114: static void uusage P((void));
        !           115: static void uabort P((void));
        !           116: static boolean fcall P((pointer puuconf,
        !           117:                        const struct uuconf_system *qsys,
        !           118:                        struct uuconf_port *qport, boolean fifwork,
        !           119:                        boolean fforce, boolean fdetach,
        !           120:                        boolean ftimewarn));
        !           121: static boolean fconn_call P((struct sdaemon *qdaemon,
        !           122:                             struct uuconf_port *qport,
        !           123:                             struct sstatus *qstat, int cretry,
        !           124:                             boolean *pfcalled));
        !           125: static boolean fdo_call P((struct sdaemon *qdaemon,
        !           126:                           struct sstatus *qstat,
        !           127:                           const struct uuconf_dialer *qdialer,
        !           128:                           boolean *pfcalled, enum tstatus_type *pterr));
        !           129: static int iuport_lock P((struct uuconf_port *qport, pointer pinfo));
        !           130: static boolean flogin_prompt P((pointer puuconf,
        !           131:                                struct sconnection *qconn));
        !           132: static boolean faccept_call P((pointer puuconf, const char *zlogin,
        !           133:                               struct sconnection *qconn,
        !           134:                               const char **pzsystem));
        !           135: static void uapply_proto_params P((pointer puuconf, int bproto,
        !           136:                                   struct uuconf_cmdtab *qcmds,
        !           137:                                   struct uuconf_proto_param *pas));
        !           138: static boolean fsend_uucp_cmd P((struct sconnection *qconn,
        !           139:                                 const char *z));
        !           140: static char *zget_uucp_cmd P((struct sconnection *qconn,
        !           141:                              boolean frequired));
        !           142: static char *zget_typed_line P((struct sconnection *qconn));
        !           143: 
        !           144: /* Long getopt options.  */
        !           145: static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } };
        !           146: 
        !           147: int
        !           148: main (argc, argv)
        !           149:      int argc;
        !           150:      char **argv;
        !           151: {
        !           152:   /* -c: Whether to warn if a call is attempted at a bad time.  */
        !           153:   boolean ftimewarn = TRUE;
        !           154:   /* -D: don't detach from controlling terminal.  */
        !           155:   boolean fdetach = TRUE;
        !           156:   /* -e: Whether to do an endless loop of accepting calls.  */
        !           157:   boolean fendless = FALSE;
        !           158:   /* -f: Whether to force a call despite status of previous call.  */
        !           159:   boolean fforce = FALSE;
        !           160:   /* -I file: configuration file name.  */
        !           161:   const char *zconfig = NULL;
        !           162:   /* -l: Whether to give a single login prompt.  */
        !           163:   boolean flogin = FALSE;
        !           164:   /* -P port: port to use; in master mode, call out on this port.  In
        !           165:      slave mode, accept logins on this port.  If port not specified,
        !           166:      then in master mode figure it out for each system, and in slave
        !           167:      mode use stdin and stdout.  */
        !           168:   const char *zport = NULL;
        !           169:   /* -q: Whether to start uuxqt when done.  */
        !           170:   boolean fuuxqt = TRUE;
        !           171:   /* -r1: Whether we are the master.  */
        !           172:   boolean fmaster = FALSE;
        !           173:   /* -s,-S system: system to call.  */
        !           174:   const char *zsystem = NULL;
        !           175:   /* -w: Whether to wait for a call after doing one.  */
        !           176:   boolean fwait = FALSE;
        !           177:   int iopt;
        !           178:   struct uuconf_port *qport;
        !           179:   struct uuconf_port sport;
        !           180:   boolean fret = TRUE;
        !           181:   pointer puuconf;
        !           182:   int iuuconf;
        !           183: #if DEBUG > 1
        !           184:   int iholddebug;
        !           185: #endif
        !           186: 
        !           187:   while ((iopt = getopt_long (argc, argv,
        !           188:                              "cDefI:lp:qr:s:S:u:x:X:w",
        !           189:                              asLongopts, (int *) NULL)) != EOF)
        !           190:     {
        !           191:       switch (iopt)
        !           192:        {
        !           193:        case 'c':
        !           194:          /* Don't warn if a call is attempted at a bad time.  */
        !           195:          ftimewarn = FALSE;
        !           196:          break;
        !           197: 
        !           198:        case 'D':
        !           199:          /* Don't detach from controlling terminal.  */
        !           200:          fdetach = FALSE;
        !           201:          break;
        !           202: 
        !           203:        case 'e':
        !           204:          /* Do an endless loop of accepting calls.  */
        !           205:          fendless = TRUE;
        !           206:          break;
        !           207: 
        !           208:        case 'f':
        !           209:          /* Force a call even if it hasn't been long enough since the last
        !           210:             failed call.  */
        !           211:          fforce = TRUE;
        !           212:          break;
        !           213: 
        !           214:        case 'I':
        !           215:          /* Set configuration file name (default is in sysdep.h).  */
        !           216:          if (fsysdep_other_config (optarg))
        !           217:            zconfig = optarg;
        !           218:          break;
        !           219: 
        !           220:        case 'l':
        !           221:          /* Prompt for login name and password.  */
        !           222:          flogin = TRUE;
        !           223:          break;
        !           224: 
        !           225:        case 'p':
        !           226:          /* Port to use  */
        !           227:          zport = optarg;
        !           228:          break;
        !           229: 
        !           230:        case 'q':
        !           231:          /* Don't start uuxqt.  */
        !           232:          fuuxqt = FALSE;
        !           233:          break;
        !           234: 
        !           235:        case 'r':
        !           236:          /* Set mode: -r1 for master, -r0 for slave (default)  */
        !           237:          if (strcmp (optarg, "1") == 0)
        !           238:            fmaster = TRUE;
        !           239:          else if (strcmp (optarg, "0") == 0)
        !           240:            fmaster = FALSE;
        !           241:          else
        !           242:            uusage ();
        !           243:          break;
        !           244:     
        !           245:        case 's':
        !           246:          /* Set system name  */
        !           247:          zsystem = optarg;
        !           248:          fmaster = TRUE;
        !           249:          break;
        !           250: 
        !           251:        case 'S':
        !           252:          /* Set system name and force call like -f  */
        !           253:          zsystem = optarg;
        !           254:          fforce = TRUE;
        !           255:          fmaster = TRUE;
        !           256:          break;
        !           257: 
        !           258:        case 'u':
        !           259:          /* Some versions of uucpd invoke uucico with a -u argument
        !           260:             specifying the login name.  I'm told it is safe to ignore
        !           261:             this value, although perhaps we should use it rather than
        !           262:             zsysdep_login_name ().  */
        !           263:          break;
        !           264: 
        !           265:        case 'x':
        !           266:        case 'X':
        !           267: #if DEBUG > 1
        !           268:          /* Set debugging level  */
        !           269:          iDebug |= idebug_parse (optarg);
        !           270: #endif
        !           271:          break;
        !           272: 
        !           273:        case 'w':
        !           274:          /* Call out and then wait for a call in  */
        !           275:          fwait = TRUE;
        !           276:          break;
        !           277: 
        !           278:        case 0:
        !           279:          /* Long option found, and flag value set.  */
        !           280:          break;
        !           281: 
        !           282:        default:
        !           283:          uusage ();
        !           284:          break;
        !           285:        }
        !           286:     }
        !           287: 
        !           288:   if (optind != argc)
        !           289:     uusage ();
        !           290: 
        !           291:   if (fwait && zport == NULL)
        !           292:     {
        !           293:       ulog (LOG_ERROR, "-w requires -e");
        !           294:       uusage ();
        !           295:     }
        !           296: 
        !           297:   iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig);
        !           298:   if (iuuconf != UUCONF_SUCCESS)
        !           299:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           300:   pUuconf = puuconf;
        !           301: 
        !           302: #if DEBUG > 1
        !           303:   {
        !           304:     const char *zdebug;
        !           305: 
        !           306:     iuuconf = uuconf_debuglevel (puuconf, &zdebug);
        !           307:     if (iuuconf != UUCONF_SUCCESS)
        !           308:       ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           309:     if (zdebug != NULL)
        !           310:       iDebug |= idebug_parse (zdebug);
        !           311:   }
        !           312: #endif
        !           313: 
        !           314:   /* If a port was named, get its information.  */
        !           315:   if (zport == NULL)
        !           316:     qport = NULL;
        !           317:   else
        !           318:     {
        !           319:       iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
        !           320:                                  (int (*) P((struct uuconf_port *,
        !           321:                                              pointer))) NULL,
        !           322:                                  (pointer) NULL, &sport);
        !           323:       if (iuuconf == UUCONF_NOT_FOUND)
        !           324:        ulog (LOG_FATAL, "%s: Port not found", zport);
        !           325:       else if (iuuconf != UUCONF_SUCCESS)
        !           326:        ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           327:       qport = &sport;
        !           328:     }
        !           329: 
        !           330: #ifdef SIGINT
        !           331:   usysdep_signal (SIGINT);
        !           332: #endif
        !           333: #ifdef SIGHUP
        !           334:   usysdep_signal (SIGHUP);
        !           335: #endif
        !           336: #ifdef SIGQUIT
        !           337:   usysdep_signal (SIGQUIT);
        !           338: #endif
        !           339: #ifdef SIGTERM
        !           340:   usysdep_signal (SIGTERM);
        !           341: #endif
        !           342: #ifdef SIGPIPE
        !           343:   usysdep_signal (SIGPIPE);
        !           344: #endif
        !           345: 
        !           346:   usysdep_initialize (puuconf, INIT_SUID);
        !           347: 
        !           348:   ulog_to_file (puuconf, TRUE);
        !           349:   ulog_fatal_fn (uabort);
        !           350: 
        !           351:   if (fmaster)
        !           352:     {
        !           353:       if (zsystem != NULL)
        !           354:        {
        !           355:          /* A system was named.  Call it.  */
        !           356:          iuuconf = uuconf_system_info (puuconf, zsystem,
        !           357:                                        &sLocked_system);
        !           358:          if (iuuconf == UUCONF_NOT_FOUND)
        !           359:            ulog (LOG_FATAL, "%s: System not found", zsystem);
        !           360:          else if (iuuconf != UUCONF_SUCCESS)
        !           361:            ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           362: 
        !           363:          /* Detach from the controlling terminal for the call.  This
        !           364:             probably makes sense only on Unix.  We want the modem
        !           365:             line to become the controlling terminal.  */
        !           366:          if (fdetach &&
        !           367:              (qport == NULL
        !           368:               || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
        !           369:            usysdep_detach ();
        !           370: 
        !           371:          ulog_system (sLocked_system.uuconf_zname);
        !           372: 
        !           373: #if DEBUG > 1
        !           374:          iholddebug = iDebug;
        !           375:          if (sLocked_system.uuconf_zdebug != NULL)
        !           376:            iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
        !           377: #endif
        !           378: 
        !           379:          if (! fsysdep_lock_system (&sLocked_system))
        !           380:            {
        !           381:              ulog (LOG_ERROR, "System already locked");
        !           382:              fret = FALSE;
        !           383:            }
        !           384:          else
        !           385:            {
        !           386:              fLocked_system = TRUE;
        !           387:              fret = fcall (puuconf, &sLocked_system, qport, FALSE,
        !           388:                            fforce, fdetach, ftimewarn);
        !           389:              if (fLocked_system)
        !           390:                {
        !           391:                  (void) fsysdep_unlock_system (&sLocked_system);
        !           392:                  fLocked_system = FALSE;
        !           393:                }
        !           394:            }
        !           395: #if DEBUG > 1
        !           396:          iDebug = iholddebug;
        !           397: #endif
        !           398:          ulog_system ((const char *) NULL);
        !           399:          (void) uuconf_system_free (puuconf, &sLocked_system);
        !           400:        }
        !           401:       else
        !           402:        {
        !           403:          char **pznames, **pz;
        !           404:          int c, i;
        !           405:          boolean fdidone;
        !           406: 
        !           407:          /* Call all systems which have work to do.  */
        !           408:          fret = TRUE;
        !           409:          fdidone = FALSE;
        !           410: 
        !           411:          iuuconf = uuconf_system_names (puuconf, &pznames, 0);
        !           412:          if (iuuconf != UUCONF_SUCCESS)
        !           413:            ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           414: 
        !           415:          /* Randomize the order in which we call the systems.  */
        !           416:          c = 0;
        !           417:          for (pz = pznames; *pz != NULL; pz++)
        !           418:            c++;
        !           419: 
        !           420:          srand ((unsigned int) ixsysdep_time ((long *) NULL));
        !           421:          for (i = c - 1; i > 0; i--)
        !           422:            {
        !           423:              int iuse;
        !           424:              char *zhold;
        !           425: 
        !           426:              iuse = rand () % (i + 1);
        !           427:              zhold = pznames[i];
        !           428:              pznames[i] = pznames[iuse];
        !           429:              pznames[iuse] = zhold;
        !           430:            }
        !           431: 
        !           432:          for (pz = pznames; *pz != NULL && ! FGOT_SIGNAL (); pz++)
        !           433:            {
        !           434:              iuuconf = uuconf_system_info (puuconf, *pz,
        !           435:                                            &sLocked_system);
        !           436:              if (iuuconf != UUCONF_SUCCESS)
        !           437:                {
        !           438:                  ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !           439:                  xfree ((pointer) *pz);
        !           440:                  continue;
        !           441:                }
        !           442: 
        !           443:              if (fsysdep_has_work (&sLocked_system))
        !           444:                {
        !           445:                  fdidone = TRUE;
        !           446: 
        !           447:                  /* Detach from the controlling terminal.  On Unix
        !           448:                     this means that we will wind up forking a new
        !           449:                     process for each system we call.  */
        !           450:                  if (fdetach
        !           451:                      && (qport == NULL
        !           452:                          || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN))
        !           453:                    usysdep_detach ();
        !           454: 
        !           455:                  ulog_system (sLocked_system.uuconf_zname);
        !           456: 
        !           457: #if DEBUG > 1
        !           458:                  iholddebug = iDebug;
        !           459:                  if (sLocked_system.uuconf_zdebug != NULL)
        !           460:                    iDebug |= idebug_parse (sLocked_system.uuconf_zdebug);
        !           461: #endif
        !           462: 
        !           463:                  if (! fsysdep_lock_system (&sLocked_system))
        !           464:                    {
        !           465:                      ulog (LOG_ERROR, "System already locked");
        !           466:                      fret = FALSE;
        !           467:                    }
        !           468:                  else
        !           469:                    {
        !           470:                      fLocked_system = TRUE;
        !           471:                      if (! fcall (puuconf, &sLocked_system, qport, TRUE,
        !           472:                                   fforce, fdetach, ftimewarn))
        !           473:                        fret = FALSE;
        !           474: 
        !           475:                      /* Now ignore any SIGHUP that we got.  */
        !           476:                      afSignal[INDEXSIG_SIGHUP] = FALSE;
        !           477: 
        !           478:                      if (fLocked_system)
        !           479:                        {
        !           480:                          (void) fsysdep_unlock_system (&sLocked_system);
        !           481:                          fLocked_system = FALSE;
        !           482:                        }
        !           483:                    }
        !           484: #if DEBUG > 1
        !           485:                  iDebug = iholddebug;
        !           486: #endif
        !           487:                  ulog_system ((const char *) NULL);
        !           488:                }
        !           489: 
        !           490:              (void) uuconf_system_free (puuconf, &sLocked_system);
        !           491:              xfree ((pointer) *pz);
        !           492:            }
        !           493: 
        !           494:          xfree ((pointer) pznames);
        !           495: 
        !           496:          if (! fdidone)
        !           497:            ulog (LOG_NORMAL, "No work");
        !           498:        }
        !           499: 
        !           500:       /* If requested, wait for calls after dialing out.  */
        !           501:       if (fwait)
        !           502:        {
        !           503:          fendless = TRUE;
        !           504:          fmaster = FALSE;
        !           505:        }
        !           506:     }
        !           507: 
        !           508:   if (! fmaster)
        !           509:     {
        !           510:       struct sconnection sconn;
        !           511:       boolean flocked;
        !           512: 
        !           513:       /* If a port was specified by name, we go into endless loop
        !           514:         mode.  In this mode, we wait for calls and prompt them with
        !           515:         "login:" and "Password:", so that they think we are a regular
        !           516:         UNIX system.  If we aren't in endless loop mode, we have been
        !           517:         called by some other system.  If flogin is TRUE, we prompt
        !           518:         with "login:" and "Password:" a single time.  */
        !           519: 
        !           520:       fret = TRUE;
        !           521:       zsystem = NULL;
        !           522: 
        !           523:       if (! fconn_init (qport, &sconn))
        !           524:        fret = FALSE;
        !           525: 
        !           526:       if (qport != NULL)
        !           527:        {
        !           528:          /* We are not using standard input.  Detach from the
        !           529:             controlling terminal, so that the port we are about to
        !           530:             use becomes our controlling terminal.  */
        !           531:          if (fdetach
        !           532:              && qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)
        !           533:            usysdep_detach ();
        !           534: 
        !           535:          /* If a port was given, we loop forever.  */
        !           536:          fendless = TRUE;
        !           537:        }
        !           538: 
        !           539:       if (fconn_lock (&sconn, TRUE))
        !           540:        flocked = TRUE;
        !           541:       else
        !           542:        {
        !           543:          flocked = FALSE;
        !           544:          ulog (LOG_ERROR, "%s: Port already locked",
        !           545:                qport->uuconf_zname);
        !           546:          fret = FALSE;
        !           547:        }
        !           548: 
        !           549:       if (fret)
        !           550:        {
        !           551:          if (! fconn_open (&sconn, (long) 0, (long) 0, TRUE))
        !           552:            fret = FALSE;
        !           553:          qConn = &sconn;
        !           554:        }
        !           555: 
        !           556:       if (fret)
        !           557:        {
        !           558:          if (fendless)
        !           559:            {
        !           560:              while (! FGOT_SIGNAL ()
        !           561:                     && flogin_prompt (puuconf, &sconn))
        !           562:                {
        !           563:                  /* Now ignore any SIGHUP that we got.  */
        !           564:                  afSignal[INDEXSIG_SIGHUP] = FALSE;
        !           565: 
        !           566:                  if (fLocked_system)
        !           567:                    {
        !           568:                      (void) fsysdep_unlock_system (&sLocked_system);
        !           569:                      fLocked_system = FALSE;
        !           570:                    }
        !           571:                  if (! fconn_reset (&sconn))
        !           572:                    break;
        !           573:                }
        !           574:              fret = FALSE;
        !           575:            }
        !           576:          else
        !           577:            {
        !           578:              if (flogin)
        !           579:                fret = flogin_prompt (puuconf, &sconn);
        !           580:              else
        !           581:                {
        !           582: #if DEBUG > 1
        !           583:                  iholddebug = iDebug;
        !           584: #endif
        !           585:                  fret = faccept_call (puuconf, zsysdep_login_name (),
        !           586:                                       &sconn, &zsystem);
        !           587: #if DEBUG > 1
        !           588:                  iDebug = iholddebug;
        !           589: #endif
        !           590:                }
        !           591:            }
        !           592:        }
        !           593: 
        !           594:       if (qConn != NULL)
        !           595:        {
        !           596:          if (! fconn_close (&sconn, puuconf, (struct uuconf_dialer *) NULL,
        !           597:                             fret))
        !           598:            fret = FALSE;
        !           599:          qConn = NULL;
        !           600:        }
        !           601: 
        !           602:       if (flocked)
        !           603:        (void) fconn_unlock (&sconn);
        !           604: 
        !           605:       if (fLocked_system)
        !           606:        {
        !           607:          (void) fsysdep_unlock_system (&sLocked_system);
        !           608:          fLocked_system = FALSE;
        !           609:        }
        !           610: 
        !           611:       uconn_free (&sconn);
        !           612:     }
        !           613: 
        !           614:   ulog_close ();
        !           615:   ustats_close ();
        !           616: 
        !           617:   /* If we got a SIGTERM, perhaps because the system is going down,
        !           618:      don't run uuxqt.  We go ahead and run it for any other signal,
        !           619:      since I think they indicate more temporary conditions.  */
        !           620:   if (afSignal[INDEXSIG_SIGTERM])
        !           621:     fuuxqt = FALSE;
        !           622: 
        !           623:   if (fuuxqt)
        !           624:     {
        !           625:       /* Detach from the controlling terminal before starting up uuxqt,
        !           626:         so that it runs as a true daemon.  */
        !           627:       if (fdetach)
        !           628:        usysdep_detach ();
        !           629:       if (zsystem == NULL)
        !           630:        {
        !           631:          if (! fsysdep_run ("uuxqt", (const char *) NULL,
        !           632:                             (const char *) NULL))
        !           633:            fret = FALSE;
        !           634:        }
        !           635:       else
        !           636:        {
        !           637:          if (! fsysdep_run ("uuxqt", "-s", zsystem))
        !           638:            fret = FALSE;
        !           639:        }
        !           640:     }
        !           641: 
        !           642:   usysdep_exit (fret);
        !           643: 
        !           644:   /* Avoid complaints about not returning.  */
        !           645:   return 0;
        !           646: }
        !           647: 
        !           648: /* Print out a usage message.  */
        !           649: 
        !           650: static void
        !           651: uusage ()
        !           652: {
        !           653:   fprintf (stderr,
        !           654:           "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
        !           655:           VERSION);
        !           656:   fprintf (stderr,
        !           657:           "Usage: uucico [options]\n");
        !           658:   fprintf (stderr,
        !           659:           " -s,-S system: Call system (-S implies -f)\n");
        !           660:   fprintf (stderr,
        !           661:           " -f: Force call despite system status\n");
        !           662:   fprintf (stderr,
        !           663:           " -r state: 1 for master, 0 for slave (default)\n");
        !           664:   fprintf (stderr,
        !           665:           " -p port: Specify port (implies -e)\n");
        !           666:   fprintf (stderr,
        !           667:           " -l: prompt for login name and password\n");
        !           668:   fprintf (stderr,
        !           669:           " -e: Endless loop of login prompts and daemon execution\n");
        !           670:   fprintf (stderr,
        !           671:           " -w: After calling out, wait for incoming calls\n");
        !           672:   fprintf (stderr,
        !           673:           " -q: Don't start uuxqt when done\n");
        !           674:   fprintf (stderr,
        !           675:           " -x,-X debug: Set debugging level\n");
        !           676: #if HAVE_TAYLOR_CONFIG
        !           677:   fprintf (stderr,
        !           678:           " -I file: Set configuration file to use\n");
        !           679: #endif /* HAVE_TAYLOR_CONFIG */
        !           680: 
        !           681:   exit (EXIT_FAILURE);
        !           682: }
        !           683: 
        !           684: /* This function is called when a LOG_FATAL error occurs.  */
        !           685: 
        !           686: static void
        !           687: uabort ()
        !           688: {
        !           689:   if (fLocked_system)
        !           690:     ufailed (&sDaemon);
        !           691: 
        !           692:   ulog_user ((const char *) NULL);
        !           693: 
        !           694:   if (qConn != NULL)
        !           695:     {
        !           696:       (void) fconn_close (qConn, pUuconf, (struct uuconf_dialer *) NULL,
        !           697:                          FALSE);
        !           698:       (void) fconn_unlock (qConn);
        !           699:       uconn_free (qConn);
        !           700:     }
        !           701: 
        !           702:   if (fLocked_system)
        !           703:     {
        !           704:       (void) fsysdep_unlock_system (&sLocked_system);
        !           705:       fLocked_system = FALSE;
        !           706:     }
        !           707: 
        !           708:   ulog_system ((const char *) NULL);
        !           709: 
        !           710:   ulog_close ();
        !           711:   ustats_close ();
        !           712: 
        !           713:   usysdep_exit (FALSE);
        !           714: }
        !           715: 
        !           716: /* Call another system, trying all the possible sets of calling
        !           717:    instructions.  The qsys argument is the system to call.  The qport
        !           718:    argument is the port to use, and may be NULL.  If the fifwork
        !           719:    argument is TRUE, the call is only placed if there is work to be
        !           720:    done.  If the fforce argument is TRUE, a call is forced even if not
        !           721:    enough time has passed since the last failed call.  If the
        !           722:    ftimewarn argument is TRUE (the normal case), then a warning is
        !           723:    given if calls are not permitted at this time.  */
        !           724: 
        !           725: static boolean
        !           726: fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
        !           727:      pointer puuconf;
        !           728:      const struct uuconf_system *qorigsys;
        !           729:      struct uuconf_port *qport;
        !           730:      boolean fifwork;
        !           731:      boolean fforce;
        !           732:      boolean fdetach;
        !           733:      boolean ftimewarn;
        !           734: {
        !           735:   struct sstatus sstat;
        !           736:   long inow;
        !           737:   boolean fbadtime, fnevertime;
        !           738:   const struct uuconf_system *qsys;
        !           739: 
        !           740:   if (! fsysdep_get_status (qorigsys, &sstat, (boolean *) NULL))
        !           741:     return FALSE;
        !           742: 
        !           743:   /* Make sure it's been long enough since the last failed call, and
        !           744:      that we haven't exceeded the maximum number of retries.  Even if
        !           745:      we are over the limit on retries, we permit a call to be made if
        !           746:      24 hours have passed.  This 24 hour limit is still controlled by
        !           747:      the retry time.  */
        !           748:   inow = ixsysdep_time ((long *) NULL);
        !           749:   if (! fforce)
        !           750:     {
        !           751:       if (qorigsys->uuconf_cmax_retries > 0
        !           752:          && sstat.cretries >= qorigsys->uuconf_cmax_retries
        !           753:          && sstat.ilast + 24 * 60 * 60 < inow)
        !           754:        {
        !           755:          ulog (LOG_ERROR, "Too many retries");
        !           756:          return FALSE;
        !           757:        }
        !           758: 
        !           759:       if (sstat.ttype == STATUS_COMPLETE
        !           760:          ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow
        !           761:          : sstat.ilast + sstat.cwait > inow)
        !           762:        {
        !           763:          ulog (LOG_NORMAL, "Retry time not reached");
        !           764:          return FALSE;
        !           765:        }
        !           766:     }
        !           767: 
        !           768:   sDaemon.puuconf = puuconf;
        !           769:   sDaemon.qsys = NULL;
        !           770:   sDaemon.zlocalname = NULL;
        !           771:   sDaemon.qconn = NULL;
        !           772:   sDaemon.qproto = NULL;
        !           773:   sDaemon.clocal_size = -1;
        !           774:   sDaemon.cremote_size = -1;
        !           775:   sDaemon.cmax_ever = -2;
        !           776:   sDaemon.cmax_receive = -1;
        !           777:   sDaemon.ifeatures = 0;
        !           778:   sDaemon.frequest_hangup = FALSE;
        !           779:   sDaemon.fhangup_requested = FALSE;
        !           780:   sDaemon.fhangup = FALSE;
        !           781:   sDaemon.fmaster = TRUE;
        !           782:   sDaemon.fcaller = TRUE;
        !           783:   sDaemon.ireliable = 0;
        !           784:   sDaemon.bgrade = '\0';
        !           785: 
        !           786:   fbadtime = TRUE;
        !           787:   fnevertime = TRUE;
        !           788: 
        !           789:   for (qsys = qorigsys; qsys != NULL; qsys = qsys->uuconf_qalternate)
        !           790:     {
        !           791:       int cretry;
        !           792:       boolean fany, fret, fcalled;
        !           793: 
        !           794:       if (FGOT_SIGNAL ())
        !           795:        return FALSE;
        !           796: 
        !           797:       if (! qsys->uuconf_fcall || qsys->uuconf_qtimegrade == NULL)
        !           798:        continue;
        !           799: 
        !           800:       fnevertime = FALSE;
        !           801: 
        !           802:       /* Make sure this is a legal time to call.  */
        !           803:       if (! ftimespan_match (qsys->uuconf_qtimegrade, (long *) NULL,
        !           804:                             &cretry))
        !           805:        continue;
        !           806: 
        !           807:       sDaemon.qsys = qsys;
        !           808: 
        !           809:       /* Queue up any work there is to do.  */
        !           810:       if (! fqueue (&sDaemon, &fany))
        !           811:        return FALSE;
        !           812: 
        !           813:       /* If we are only supposed to call if there is work, and there
        !           814:         isn't any work, check the next alternates.  We can't give up
        !           815:         at this point because there might be some other alternates
        !           816:         with fewer restrictions on grade or file transfer size.  */
        !           817:       if (fifwork && ! fany)
        !           818:        {
        !           819:          uclear_queue (&sDaemon);
        !           820:          continue;
        !           821:        }
        !           822: 
        !           823:       fbadtime = FALSE;
        !           824: 
        !           825:       fret = fconn_call (&sDaemon, qport, &sstat, cretry, &fcalled);
        !           826: 
        !           827:       uclear_queue (&sDaemon);
        !           828: 
        !           829:       if (fret)
        !           830:        return TRUE;
        !           831:       if (fcalled)
        !           832:        return FALSE;
        !           833: 
        !           834:       /* Now we have to dump that port so that we can aquire a new
        !           835:         one.  On Unix this means that we will fork and get a new
        !           836:         process ID, so we must unlock and relock the system.  */
        !           837:       if (fdetach)
        !           838:        {
        !           839:          (void) fsysdep_unlock_system (&sLocked_system);
        !           840:          fLocked_system = FALSE;
        !           841:          usysdep_detach ();
        !           842:          if (! fsysdep_lock_system (&sLocked_system))
        !           843:            return FALSE;
        !           844:          fLocked_system = TRUE;
        !           845:        }
        !           846:     }
        !           847: 
        !           848:   if (fbadtime && ftimewarn)
        !           849:     {
        !           850:       ulog (LOG_NORMAL, "Wrong time to call");
        !           851: 
        !           852:       /* Update the status, unless the system can never be called.  If
        !           853:         the system can never be called, there is little point to
        !           854:         putting in a ``wrong time to call'' message.  We don't change
        !           855:         the number of retries, although we do set the wait until the
        !           856:         next retry to 0.  */
        !           857:       if (! fnevertime)
        !           858:        {
        !           859:          sstat.ttype = STATUS_WRONG_TIME;
        !           860:          sstat.ilast = inow;
        !           861:          sstat.cwait = 0;
        !           862:          (void) fsysdep_set_status (qorigsys, &sstat);
        !           863:        }
        !           864:     }
        !           865: 
        !           866:   return FALSE;
        !           867: }
        !           868: 
        !           869: /* Find a port to use when calling a system, open a connection, and
        !           870:    dial the system.  The actual call is done in fdo_call.  This
        !           871:    routine is responsible for opening and closing the connection.  */
        !           872: 
        !           873: static boolean
        !           874: fconn_call (qdaemon, qport, qstat, cretry, pfcalled)
        !           875:      struct sdaemon *qdaemon;
        !           876:      struct uuconf_port *qport;
        !           877:      struct sstatus *qstat;
        !           878:      int cretry;
        !           879:      boolean *pfcalled;
        !           880: {
        !           881:   pointer puuconf;
        !           882:   const struct uuconf_system *qsys;
        !           883:   struct uuconf_port sport;
        !           884:   struct sconnection sconn;
        !           885:   enum tstatus_type terr;
        !           886:   boolean fret;
        !           887: 
        !           888:   puuconf = qdaemon->puuconf;
        !           889:   qsys = qdaemon->qsys;
        !           890: 
        !           891:   *pfcalled = FALSE;
        !           892: 
        !           893:   /* Ignore any SIGHUP signal we may have received up to this point.
        !           894:      This is needed on Unix because we may have gotten one from the
        !           895:      shell before we detached from the controlling terminal.  */
        !           896:   afSignal[INDEXSIG_SIGHUP] = FALSE;
        !           897: 
        !           898:   /* If no port was specified on the command line, use any port
        !           899:      defined for the system.  To select the system port: 1) see if
        !           900:      port information was specified directly; 2) see if a port was
        !           901:      named; 3) get an available port given the baud rate.  We don't
        !           902:      change the system status if a port is unavailable; i.e. we don't
        !           903:      force the system to wait for the retry time.  */
        !           904:   if (qport == NULL)
        !           905:     qport = qsys->uuconf_qport;
        !           906:   if (qport != NULL)
        !           907:     {
        !           908:       if (! fconn_init (qport, &sconn))
        !           909:        return FALSE;
        !           910:       if (! fconn_lock (&sconn, FALSE))
        !           911:        {
        !           912:          ulog (LOG_ERROR, "%s: Port already locked",
        !           913:                qport->uuconf_zname);
        !           914:          return FALSE;
        !           915:        }
        !           916:     }
        !           917:   else
        !           918:     {
        !           919:       struct spass s;
        !           920:       int iuuconf;
        !           921: 
        !           922:       s.fmatched = FALSE;
        !           923:       s.flocked = FALSE;
        !           924:       s.qconn = &sconn;
        !           925:       iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport,
        !           926:                                  qsys->uuconf_ibaud,
        !           927:                                  qsys->uuconf_ihighbaud,
        !           928:                                  iuport_lock, (pointer) &s,
        !           929:                                  &sport);
        !           930:       if (iuuconf == UUCONF_NOT_FOUND)
        !           931:        {
        !           932:          if (s.fmatched)
        !           933:            ulog (LOG_ERROR, "All matching ports in use");
        !           934:          else
        !           935:            ulog (LOG_ERROR, "No matching ports");
        !           936:          return FALSE;
        !           937:        }
        !           938:       else if (iuuconf != UUCONF_SUCCESS)
        !           939:        {
        !           940:          ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !           941:          if (s.flocked)
        !           942:            {
        !           943:              (void) fconn_unlock (&sconn);
        !           944:              uconn_free (&sconn);
        !           945:            }
        !           946:          return FALSE;
        !           947:        }
        !           948:     }
        !           949: 
        !           950:   if (! fconn_open (&sconn, qsys->uuconf_ibaud, qsys->uuconf_ihighbaud,
        !           951:                    FALSE))
        !           952:     {
        !           953:       terr = STATUS_PORT_FAILED;
        !           954:       fret = FALSE;
        !           955:     }
        !           956:   else
        !           957:     {
        !           958:       struct uuconf_dialer *qdialer;
        !           959:       struct uuconf_dialer sdialer;
        !           960:       enum tdialerfound tdialer;
        !           961: 
        !           962:       if (qsys->uuconf_zalternate == NULL)
        !           963:        ulog (LOG_NORMAL, "Calling system %s (port %s)", qsys->uuconf_zname,
        !           964:              zLdevice == NULL ? (char *) "unknown" : zLdevice);
        !           965:       else
        !           966:        ulog (LOG_NORMAL, "Calling system %s (alternate %s, port %s)",
        !           967:              qsys->uuconf_zname, qsys->uuconf_zalternate,
        !           968:          zLdevice == NULL ? (char *) "unknown" : zLdevice);
        !           969: 
        !           970:       qdialer = NULL;
        !           971: 
        !           972:       if (! fconn_dial (&sconn, puuconf, qsys, qsys->uuconf_zphone,
        !           973:                        &sdialer, &tdialer))
        !           974:        {
        !           975:          terr = STATUS_DIAL_FAILED;
        !           976:          fret = FALSE;
        !           977:        }
        !           978:       else
        !           979:        {
        !           980:          qdaemon->qconn = &sconn;
        !           981:          if (tdialer == DIALERFOUND_FALSE)
        !           982:            qdialer = NULL;
        !           983:          else
        !           984:            qdialer = &sdialer;
        !           985:          fret = fdo_call (qdaemon, qstat, qdialer, pfcalled, &terr);
        !           986:        }
        !           987: 
        !           988:       (void) fconn_close (&sconn, puuconf, qdialer, fret);
        !           989: 
        !           990:       if (tdialer == DIALERFOUND_FREE)
        !           991:        (void) uuconf_dialer_free (puuconf, &sdialer);
        !           992:     }
        !           993: 
        !           994:   if (! fret)
        !           995:     {
        !           996:       DEBUG_MESSAGE2 (DEBUG_HANDSHAKE, "Call failed: %d (%s)",
        !           997:                      (int) terr, azStatus[(int) terr]);
        !           998:       qstat->ttype = terr;
        !           999:       qstat->cretries++;
        !          1000:       qstat->ilast = ixsysdep_time ((long *) NULL);
        !          1001:       if (cretry == 0)
        !          1002:        qstat->cwait = CRETRY_WAIT (qstat->cretries);
        !          1003:       else
        !          1004:        qstat->cwait = cretry * 60;
        !          1005:       (void) fsysdep_set_status (qsys, qstat);
        !          1006:     }
        !          1007: 
        !          1008:   (void) fconn_unlock (&sconn);
        !          1009:   uconn_free (&sconn);
        !          1010: 
        !          1011:   if (qport == NULL)
        !          1012:     (void) uuconf_port_free (puuconf, &sport);
        !          1013: 
        !          1014:   return fret;
        !          1015: }
        !          1016: 
        !          1017: /* Do the actual work of calling another system.  The qsys argument is
        !          1018:    the system to call, the qconn argument is the connection to use,
        !          1019:    the qstat argument holds the current status of the ssystem, and the
        !          1020:    qdialer argument holds the dialer being used (it may be NULL).  If
        !          1021:    we log in successfully, set *pfcalled to TRUE; this is used to
        !          1022:    distinguish a failed dial from a failure during the call.  If an
        !          1023:    error occurs *pterr is set to the status type to record.  */
        !          1024: 
        !          1025: static boolean
        !          1026: fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
        !          1027:      struct sdaemon *qdaemon;
        !          1028:      struct sstatus *qstat;
        !          1029:      const struct uuconf_dialer *qdialer;
        !          1030:      boolean *pfcalled;
        !          1031:      enum tstatus_type *pterr;
        !          1032: {
        !          1033:   pointer puuconf;
        !          1034:   const struct uuconf_system *qsys;
        !          1035:   struct sconnection *qconn;
        !          1036:   const char *zport;
        !          1037:   int iuuconf;
        !          1038:   char *zstr;
        !          1039:   long istart_time;
        !          1040:   char *zlog;
        !          1041: 
        !          1042:   puuconf = qdaemon->puuconf;
        !          1043:   qsys = qdaemon->qsys;
        !          1044:   qconn = qdaemon->qconn;
        !          1045: 
        !          1046:   *pterr = STATUS_LOGIN_FAILED;
        !          1047: 
        !          1048:   if (qconn->qport == NULL)
        !          1049:     zport = "unknown";
        !          1050:   else
        !          1051:     zport = qconn->qport->uuconf_zname;
        !          1052:   if (! fchat (qconn, puuconf, &qsys->uuconf_schat, qsys,
        !          1053:               (const struct uuconf_dialer *) NULL,
        !          1054:               (const char *) NULL, FALSE, zport,
        !          1055:               iconn_baud (qconn)))
        !          1056:     return FALSE;
        !          1057: 
        !          1058:   *pfcalled = TRUE;
        !          1059:   istart_time = ixsysdep_time ((long *) NULL);
        !          1060: 
        !          1061:   *pterr = STATUS_HANDSHAKE_FAILED;
        !          1062: 
        !          1063:   /* We should now see "Shere" from the other system.  Newer systems
        !          1064:      send "Shere=foo" where foo is the remote name.  */
        !          1065:   zstr = zget_uucp_cmd (qconn, TRUE);
        !          1066:   if (zstr == NULL)
        !          1067:     return FALSE;
        !          1068: 
        !          1069:   if (strncmp (zstr, "Shere", 5) != 0)
        !          1070:     {
        !          1071:       ulog (LOG_ERROR, "Bad initialization string");
        !          1072:       ubuffree (zstr);
        !          1073:       return FALSE;
        !          1074:     }
        !          1075: 
        !          1076:   ulog (LOG_NORMAL, "Login successful");
        !          1077: 
        !          1078:   qstat->ttype = STATUS_TALKING;
        !          1079:   qstat->ilast = ixsysdep_time ((long *) NULL);
        !          1080:   qstat->cretries = 0;
        !          1081:   qstat->cwait = 0;
        !          1082:   if (! fsysdep_set_status (qsys, qstat))
        !          1083:     return FALSE;
        !          1084: 
        !          1085:   if (zstr[5] == '=')
        !          1086:     {
        !          1087:       const char *zheresys;
        !          1088:       size_t clen;
        !          1089:       int icmp;
        !          1090: 
        !          1091:       /* Some UUCP packages only provide seven characters in the Shere
        !          1092:         machine name.  Others only provide fourteen.  */
        !          1093:       zheresys = zstr + 6;
        !          1094:       clen = strlen (zheresys);
        !          1095:       if (clen == 7 || clen == 14)
        !          1096:        icmp = strncmp (zheresys, qsys->uuconf_zname, clen);
        !          1097:       else
        !          1098:        icmp = strcmp (zheresys, qsys->uuconf_zname);
        !          1099:       if (icmp != 0)
        !          1100:        {
        !          1101:          if (qsys->uuconf_pzalias != NULL)
        !          1102:            {
        !          1103:              char **pz;
        !          1104: 
        !          1105:              for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++)
        !          1106:                {
        !          1107:                  if (clen == 7 || clen == 14)
        !          1108:                    icmp = strncmp (zheresys, *pz, clen);
        !          1109:                  else
        !          1110:                    icmp = strcmp (zheresys, *pz);
        !          1111:                  if (icmp == 0)
        !          1112:                    break;
        !          1113:                }
        !          1114:            }
        !          1115:          if (icmp != 0)
        !          1116:            {
        !          1117:              ulog (LOG_ERROR, "Called wrong system (%s)", zheresys);
        !          1118:              ubuffree (zstr);
        !          1119:              return FALSE;
        !          1120:            }
        !          1121:        }
        !          1122:     }
        !          1123: #if DEBUG > 1
        !          1124:   else if (zstr[5] != '\0')
        !          1125:     DEBUG_MESSAGE1 (DEBUG_HANDSHAKE,
        !          1126:                    "fdo_call: Strange Shere: %s", zstr);
        !          1127: #endif
        !          1128: 
        !          1129:   ubuffree (zstr);
        !          1130: 
        !          1131:   /* We now send "S" name switches, where name is our UUCP name.  If
        !          1132:      we are using sequence numbers with this system, we send a -Q
        !          1133:      argument with the sequence number.  If the call-timegrade command
        !          1134:      was used, we send a -p argument and a -vgrade= argument with the
        !          1135:      grade to send us (we send both argument to make it more likely
        !          1136:      that one is recognized).  We always send a -N (for new) switch
        !          1137:      indicating what new features we support.  */
        !          1138:   {
        !          1139:     long ival;
        !          1140:     char bgrade;
        !          1141:     char *zsend;
        !          1142:     boolean fret;
        !          1143: 
        !          1144:     /* Determine the grade we should request of the other system.  A
        !          1145:        '\0' means that no restrictions have been made.  */
        !          1146:     if (! ftimespan_match (qsys->uuconf_qcalltimegrade, &ival,
        !          1147:                           (int *) NULL))
        !          1148:       bgrade = '\0';
        !          1149:     else
        !          1150:       bgrade = (char) ival;
        !          1151: 
        !          1152:     /* Determine the name we will call ourselves.  */
        !          1153:     if (qsys->uuconf_zlocalname != NULL)
        !          1154:       qdaemon->zlocalname = qsys->uuconf_zlocalname;
        !          1155:     else
        !          1156:       {
        !          1157:        iuuconf = uuconf_localname (puuconf, &qdaemon->zlocalname);
        !          1158:        if (iuuconf == UUCONF_NOT_FOUND)
        !          1159:          {
        !          1160:            qdaemon->zlocalname = zsysdep_localname ();
        !          1161:            if (qdaemon->zlocalname == NULL)
        !          1162:              return FALSE;
        !          1163:          }
        !          1164:        else if (iuuconf != UUCONF_SUCCESS)
        !          1165:          {
        !          1166:            ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1167:            return FALSE;
        !          1168:          }
        !          1169:       }            
        !          1170: 
        !          1171:     zsend = zbufalc (strlen (qdaemon->zlocalname) + 70);
        !          1172:     if (! qsys->uuconf_fsequence)
        !          1173:       {
        !          1174:        if (bgrade == '\0')
        !          1175:          sprintf (zsend, "S%s -R -N0%o", qdaemon->zlocalname,
        !          1176:                   (unsigned int) (FEATURE_SIZES
        !          1177:                                   | FEATURE_EXEC
        !          1178:                                   | FEATURE_RESTART));
        !          1179:        else
        !          1180:          sprintf (zsend, "S%s -p%c -vgrade=%c -R -N0%o",
        !          1181:                   qdaemon->zlocalname, bgrade, bgrade,
        !          1182:                   (unsigned int) (FEATURE_SIZES
        !          1183:                                   | FEATURE_EXEC
        !          1184:                                   | FEATURE_RESTART));
        !          1185:       }
        !          1186:     else
        !          1187:       {
        !          1188:        long iseq;
        !          1189: 
        !          1190:        iseq = ixsysdep_get_sequence (qsys);
        !          1191:        if (iseq < 0)
        !          1192:          return FALSE;
        !          1193:        if (bgrade == '\0')
        !          1194:          sprintf (zsend, "S%s -Q%ld -R -N0%o", qdaemon->zlocalname, iseq,
        !          1195:                   (unsigned int) (FEATURE_SIZES
        !          1196:                                   | FEATURE_EXEC
        !          1197:                                   | FEATURE_RESTART));
        !          1198:        else
        !          1199:          sprintf (zsend, "S%s -Q%ld -p%c -vgrade=%c -R -N0%o",
        !          1200:                   qdaemon->zlocalname, iseq, bgrade, bgrade,
        !          1201:                   (unsigned int) (FEATURE_SIZES
        !          1202:                                   | FEATURE_EXEC
        !          1203:                                   | FEATURE_RESTART));
        !          1204:       }
        !          1205: 
        !          1206:     fret = fsend_uucp_cmd (qconn, zsend);
        !          1207:     ubuffree (zsend);
        !          1208:     if (! fret)
        !          1209:        return FALSE;
        !          1210:   }
        !          1211: 
        !          1212:   /* Now we should see ROK or Rreason where reason gives a cryptic
        !          1213:      reason for failure.  If we are talking to a counterpart, we will
        !          1214:      get back ROKN, possibly with a feature bitfield attached.  */
        !          1215:   zstr = zget_uucp_cmd (qconn, TRUE);
        !          1216:   if (zstr == NULL)
        !          1217:     return FALSE;
        !          1218: 
        !          1219:   if (zstr[0] != 'R')
        !          1220:     {
        !          1221:       ulog (LOG_ERROR, "Bad reponse to handshake string (%s)",
        !          1222:            zstr);
        !          1223:       ubuffree (zstr);
        !          1224:       return FALSE;
        !          1225:     }
        !          1226: 
        !          1227:   if (strncmp (zstr + 1, "OKN", sizeof "OKN" - 1) == 0)
        !          1228:     {
        !          1229:       if (zstr[sizeof "ROKN" - 1] == '\0')
        !          1230:        qdaemon->ifeatures |= FEATURE_SIZES | FEATURE_V103;
        !          1231:       else
        !          1232:        qdaemon->ifeatures |= (int) strtol (zstr + sizeof "ROKN" - 1,
        !          1233:                                           (char **) NULL, 0);
        !          1234:     }
        !          1235:   else if (strncmp (zstr + 1, "OK", sizeof "OK" - 1) == 0)
        !          1236:     {
        !          1237:       if (zstr[sizeof "ROK" - 1] != '\0')
        !          1238:        {
        !          1239:          char *zopt;
        !          1240: 
        !          1241:          /* SVR4 UUCP returns options following the ROK string.  */
        !          1242:          zopt = zstr + sizeof "ROK" - 1;
        !          1243:          while (*zopt != '\0')
        !          1244:            {
        !          1245:              char b;
        !          1246:              long c;
        !          1247:              char *zend;
        !          1248: 
        !          1249:              b = *zopt++;
        !          1250:              if (isspace (b) || b != '-')
        !          1251:                continue;
        !          1252:              switch (*zopt)
        !          1253:                {
        !          1254:                case 'R':
        !          1255:                  qdaemon->ifeatures |= (FEATURE_RESTART
        !          1256:                                         | FEATURE_SVR4
        !          1257:                                         | FEATURE_SIZES);
        !          1258:                  break;
        !          1259:                case 'U':
        !          1260:                  c = strtol (zopt, &zend, 0);
        !          1261:                  if (c > 0 && c <= LONG_MAX / (long) 512)
        !          1262:                    qdaemon->cmax_receive = c * (long) 512;
        !          1263:                  zopt = zend;
        !          1264:                  break;
        !          1265:                }
        !          1266:              while (*zopt != '\0' && ! isspace (*zopt))
        !          1267:                ++zopt;
        !          1268:            }
        !          1269:        }
        !          1270:     }
        !          1271:   else if (strcmp (zstr + 1, "CB") == 0)
        !          1272:     {
        !          1273:       ulog (LOG_NORMAL, "Remote system will call back");
        !          1274:       qstat->ttype = STATUS_COMPLETE;
        !          1275:       (void) fsysdep_set_status (qsys, qstat);
        !          1276:       ubuffree (zstr);
        !          1277:       return TRUE;
        !          1278:     }
        !          1279:   else
        !          1280:     {
        !          1281:       ulog (LOG_ERROR, "Handshake failed (%s)", zstr + 1);
        !          1282:       ubuffree (zstr);
        !          1283:       return FALSE;
        !          1284:     }
        !          1285: 
        !          1286:   ubuffree (zstr);
        !          1287: 
        !          1288:   /* The slave should now send \020Pprotos\0 where protos is a list of
        !          1289:      supported protocols.  Each protocol is a single character.  */
        !          1290:   zstr = zget_uucp_cmd (qconn, TRUE);
        !          1291:   if (zstr == NULL)
        !          1292:     return FALSE;
        !          1293: 
        !          1294:   if (zstr[0] != 'P')
        !          1295:     {
        !          1296:       ulog (LOG_ERROR, "Bad protocol handshake (%s)", zstr);
        !          1297:       ubuffree (zstr);
        !          1298:       return FALSE;
        !          1299:     }
        !          1300: 
        !          1301:   /* Determine the reliability characteristics of the connection by
        !          1302:      combining information for the port and the dialer.  If we have no
        !          1303:      information, default to a reliable eight-bit full-duplex
        !          1304:      connection.  */
        !          1305:   if (qconn->qport != NULL
        !          1306:       && (qconn->qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
        !          1307:     qdaemon->ireliable = qconn->qport->uuconf_ireliable;
        !          1308:   if (qdialer != NULL
        !          1309:       && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
        !          1310:     {
        !          1311:       if (qdaemon->ireliable != 0)
        !          1312:        qdaemon->ireliable &= qdialer->uuconf_ireliable;
        !          1313:       else
        !          1314:        qdaemon->ireliable = qdialer->uuconf_ireliable;
        !          1315:     }
        !          1316:   if (qdaemon->ireliable == 0)
        !          1317:     qdaemon->ireliable = (UUCONF_RELIABLE_RELIABLE
        !          1318:                          | UUCONF_RELIABLE_EIGHT
        !          1319:                          | UUCONF_RELIABLE_FULLDUPLEX
        !          1320:                          | UUCONF_RELIABLE_SPECIFIED);
        !          1321: 
        !          1322:   /* Now decide which protocol to use.  The system and the port may
        !          1323:      have their own list of protocols.  */
        !          1324:   {
        !          1325:     int i;
        !          1326:     char ab[5];
        !          1327: 
        !          1328:     i = CPROTOCOLS;
        !          1329:     if (qsys->uuconf_zprotocols != NULL
        !          1330:        || (qconn->qport != NULL
        !          1331:            && qconn->qport->uuconf_zprotocols != NULL))
        !          1332:       {
        !          1333:        const char *zproto;
        !          1334: 
        !          1335:        if (qsys->uuconf_zprotocols != NULL)
        !          1336:          zproto = qsys->uuconf_zprotocols;
        !          1337:        else
        !          1338:          zproto = qconn->qport->uuconf_zprotocols;
        !          1339:        for (; *zproto != '\0'; zproto++)
        !          1340:          {
        !          1341:            if (strchr (zstr + 1, *zproto) != NULL)
        !          1342:              {
        !          1343:                for (i = 0; i < CPROTOCOLS; i++)
        !          1344:                  if (asProtocols[i].bname == *zproto)
        !          1345:                    break;
        !          1346:                if (i < CPROTOCOLS)
        !          1347:                  break;
        !          1348:              }
        !          1349:          }
        !          1350:       }
        !          1351:     else
        !          1352:       {
        !          1353:        /* If neither the system nor the port specified a list of
        !          1354:           protocols, we want only protocols that match the known
        !          1355:           reliability of the dialer and the port.  */
        !          1356:        for (i = 0; i < CPROTOCOLS; i++)
        !          1357:          {
        !          1358:            int ipr;
        !          1359: 
        !          1360:            ipr = asProtocols[i].ireliable;
        !          1361:            if ((ipr & qdaemon->ireliable) != ipr)
        !          1362:              continue;
        !          1363:            if (strchr (zstr + 1, asProtocols[i].bname) != NULL)
        !          1364:              break;
        !          1365:          }
        !          1366:       }
        !          1367: 
        !          1368:     ubuffree (zstr);
        !          1369: 
        !          1370:     if (i >= CPROTOCOLS)
        !          1371:       {
        !          1372:        (void) fsend_uucp_cmd (qconn, "UN");
        !          1373:        ulog (LOG_ERROR, "No mutually supported protocols");
        !          1374:        return FALSE;
        !          1375:       }
        !          1376: 
        !          1377:     qdaemon->qproto = &asProtocols[i];
        !          1378: 
        !          1379:     sprintf (ab, "U%c", qdaemon->qproto->bname);
        !          1380:     if (! fsend_uucp_cmd (qconn, ab))
        !          1381:       return FALSE;
        !          1382:   }
        !          1383: 
        !          1384:   /* Run any protocol parameter commands.  */
        !          1385:   if (qdaemon->qproto->qcmds != NULL)
        !          1386:     {
        !          1387:       if (qsys->uuconf_qproto_params != NULL)
        !          1388:        uapply_proto_params (puuconf, qdaemon->qproto->bname,
        !          1389:                             qdaemon->qproto->qcmds,
        !          1390:                             qsys->uuconf_qproto_params);
        !          1391:       if (qconn->qport != NULL
        !          1392:          && qconn->qport->uuconf_qproto_params != NULL)
        !          1393:        uapply_proto_params (puuconf, qdaemon->qproto->bname,
        !          1394:                             qdaemon->qproto->qcmds,
        !          1395:                             qconn->qport->uuconf_qproto_params);
        !          1396:       if (qdialer != NULL
        !          1397:          && qdialer->uuconf_qproto_params != NULL)
        !          1398:        uapply_proto_params (puuconf, qdaemon->qproto->bname,
        !          1399:                             qdaemon->qproto->qcmds,
        !          1400:                             qdialer->uuconf_qproto_params);
        !          1401:     }
        !          1402: 
        !          1403:   /* Turn on the selected protocol.  */
        !          1404:   if (! (*qdaemon->qproto->pfstart) (qdaemon, &zlog))
        !          1405:     return FALSE;
        !          1406:   if (zlog == NULL)
        !          1407:     {
        !          1408:       zlog = zbufalc (sizeof "protocol ''" + 1);
        !          1409:       sprintf (zlog, "protocol '%c'", qdaemon->qproto->bname);
        !          1410:     }
        !          1411:   ulog (LOG_NORMAL, "Handshake successful (%s)", zlog);
        !          1412:   ubuffree (zlog);
        !          1413: 
        !          1414:   *pterr = STATUS_FAILED;
        !          1415: 
        !          1416:   {
        !          1417:     boolean fret;
        !          1418:     long iend_time;
        !          1419: 
        !          1420:     fret = floop (qdaemon);
        !          1421: 
        !          1422:     /* Now send the hangup message.  As the caller, we send six O's
        !          1423:        and expect to receive seven O's.  We send the six O's twice to
        !          1424:        help the other side.  We don't worry about errors here.  */
        !          1425:     if (fsend_uucp_cmd (qconn, "OOOOOO")
        !          1426:        && fsend_uucp_cmd (qconn, "OOOOOO"))
        !          1427:       {
        !          1428:        int i, fdone;
        !          1429: 
        !          1430:        /* We look for the remote hangup string to ensure that the
        !          1431:           modem has sent out our hangup string.  This is only
        !          1432:           necessary because some versions of UUCP complain if they
        !          1433:           don't get the hangup string.  The remote site should send 7
        !          1434:           O's, but some versions of UUCP only send 6.  We look for
        !          1435:           the string several times because supposedly some
        !          1436:           implementations send some garbage after the last packet but
        !          1437:           before the hangup string.  */
        !          1438:        for (i = 0; i < 25; i++)
        !          1439:          {
        !          1440:            zstr = zget_uucp_cmd (qconn, FALSE);
        !          1441:            if (zstr == NULL)
        !          1442:              break;
        !          1443:            fdone = strstr (zstr, "OOOOOO") != NULL;
        !          1444:            ubuffree (zstr);
        !          1445:            if (fdone)
        !          1446:              break;
        !          1447:          }
        !          1448:       }
        !          1449: 
        !          1450:     iend_time = ixsysdep_time ((long *) NULL);
        !          1451: 
        !          1452:     ulog (LOG_NORMAL, "Call complete (%ld seconds)",
        !          1453:          iend_time - istart_time);
        !          1454: 
        !          1455:     if (fret)
        !          1456:       {
        !          1457:        qstat->ttype = STATUS_COMPLETE;
        !          1458:        qstat->ilast = iend_time;
        !          1459:        (void) fsysdep_set_status (qsys, qstat);
        !          1460:       }
        !          1461: 
        !          1462:     return fret;
        !          1463:   }
        !          1464: }
        !          1465: 
        !          1466: /* This routine is called via uuconf_find_port when a matching port is
        !          1467:    found.  It tries to lock the port.  If it fails, it returns
        !          1468:    UUCONF_NOT_FOUND to force uuconf_find_port to continue searching
        !          1469:    for the next matching port.  */
        !          1470: 
        !          1471: static int
        !          1472: iuport_lock (qport, pinfo)
        !          1473:      struct uuconf_port *qport;
        !          1474:      pointer pinfo;
        !          1475: {
        !          1476:   struct spass *q = (struct spass *) pinfo;
        !          1477: 
        !          1478:   q->fmatched = TRUE;
        !          1479: 
        !          1480:   if (! fconn_init (qport, q->qconn))
        !          1481:     return UUCONF_NOT_FOUND;
        !          1482:   else if (! fconn_lock (q->qconn, FALSE))
        !          1483:     {
        !          1484:       uconn_free (q->qconn);
        !          1485:       return UUCONF_NOT_FOUND;
        !          1486:     }
        !          1487:   else
        !          1488:     {
        !          1489:       q->flocked = TRUE;
        !          1490:       return UUCONF_SUCCESS;
        !          1491:     }
        !          1492: }
        !          1493: 
        !          1494: /* Prompt for a login name and a password, and run as the slave.  */
        !          1495: 
        !          1496: static boolean
        !          1497: flogin_prompt (puuconf, qconn)
        !          1498:      pointer puuconf;
        !          1499:      struct sconnection *qconn;
        !          1500: {
        !          1501:   char *zuser, *zpass;
        !          1502:   boolean fret;
        !          1503:   int iuuconf;
        !          1504: 
        !          1505:   DEBUG_MESSAGE0 (DEBUG_HANDSHAKE, "flogin_prompt: Waiting for login");
        !          1506: 
        !          1507:   zuser = NULL;
        !          1508:   do
        !          1509:     {
        !          1510:       ubuffree (zuser);
        !          1511:       if (! fconn_write (qconn, "login: ", sizeof "login: " - 1))
        !          1512:        return FALSE;
        !          1513:       zuser = zget_typed_line (qconn);
        !          1514:     }
        !          1515:   while (zuser != NULL && *zuser == '\0');
        !          1516: 
        !          1517:   if (zuser == NULL)
        !          1518:     return TRUE;
        !          1519: 
        !          1520:   if (! fconn_write (qconn, "Password:", sizeof "Password:" - 1))
        !          1521:     {
        !          1522:       ubuffree (zuser);
        !          1523:       return FALSE;
        !          1524:     }
        !          1525: 
        !          1526:   zpass = zget_typed_line (qconn);
        !          1527:   if (zpass == NULL)
        !          1528:     {
        !          1529:       ubuffree (zuser);
        !          1530:       return TRUE;
        !          1531:     }
        !          1532: 
        !          1533:   fret = TRUE;
        !          1534: 
        !          1535:   iuuconf = uuconf_callin (puuconf, zuser, zpass);
        !          1536:   ubuffree (zpass);
        !          1537:   if (iuuconf == UUCONF_NOT_FOUND)
        !          1538:     ulog (LOG_ERROR, "Bad login");
        !          1539:   else if (iuuconf != UUCONF_SUCCESS)
        !          1540:     {
        !          1541:       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1542:       fret = FALSE;
        !          1543:     }
        !          1544:   else
        !          1545:     {
        !          1546: #if DEBUG > 1
        !          1547:       int iholddebug;
        !          1548: #endif
        !          1549: 
        !          1550:       /* We ignore the return value of faccept_call because we really
        !          1551:         don't care whether the call succeeded or not.  We are going
        !          1552:         to reset the port anyhow.  */
        !          1553: #if DEBUG > 1
        !          1554:       iholddebug = iDebug;
        !          1555: #endif
        !          1556:       (void) faccept_call (puuconf, zuser, qconn, (const char **) NULL);
        !          1557: #if DEBUG > 1
        !          1558:       iDebug = iholddebug;
        !          1559: #endif
        !          1560:     }
        !          1561: 
        !          1562:   ubuffree (zuser);
        !          1563: 
        !          1564:   return fret;
        !          1565: }
        !          1566: 
        !          1567: /* Accept a call from a remote system.  If pqsys is not NULL, *pqsys
        !          1568:    will be set to the system that called in if known.  */
        !          1569: 
        !          1570: static boolean
        !          1571: faccept_call (puuconf, zlogin, qconn, pzsystem)
        !          1572:      pointer puuconf;
        !          1573:      const char *zlogin;
        !          1574:      struct sconnection *qconn;
        !          1575:      const char **pzsystem;
        !          1576: {
        !          1577:   long istart_time;
        !          1578:   const char *zport;
        !          1579:   struct uuconf_port *qport;
        !          1580:   struct uuconf_port sport;
        !          1581:   int iuuconf;
        !          1582:   struct uuconf_dialer *qdialer;
        !          1583:   struct uuconf_dialer sdialer;
        !          1584:   boolean ftcp_port;
        !          1585:   char *zsend, *zspace;
        !          1586:   boolean fret;
        !          1587:   char *zstr;
        !          1588:   struct uuconf_system ssys;
        !          1589:   const struct uuconf_system *qsys;
        !          1590:   const struct uuconf_system *qany;
        !          1591:   char *zloc;
        !          1592:   struct sstatus sstat;
        !          1593:   boolean fgotseq, fgotn;
        !          1594:   int i;
        !          1595:   char *zlog;
        !          1596:   char *zgrade;
        !          1597: 
        !          1598: #ifdef MWCBBS
        !          1599:   char mwcbbs[40];
        !          1600:   char *mwcspace;
        !          1601:   char bbsuser[40];
        !          1602: #endif /* MWCBBS */
        !          1603: 
        !          1604:   if (pzsystem != NULL)
        !          1605:     *pzsystem = NULL;
        !          1606: 
        !          1607:   ulog (LOG_NORMAL, "Incoming call (login %s port %s)", zlogin,
        !          1608:        zLdevice == NULL ? (char *) "unknown" : zLdevice);
        !          1609: 
        !          1610:   istart_time = ixsysdep_time ((long *) NULL);
        !          1611: 
        !          1612:   /* Figure out protocol parameters determined by the port.  If no
        !          1613:      port was specified we're reading standard input, so try to get
        !          1614:      the port name and read information from the port file.  We only
        !          1615:      use the port information to get protocol parameters; we don't
        !          1616:      want to start treating the port as though it were a modem, for
        !          1617:      example.  */
        !          1618:   if (qconn->qport != NULL)
        !          1619:     {
        !          1620:       qport = qconn->qport;
        !          1621:       zport = qport->uuconf_zname;
        !          1622:       ftcp_port = FALSE;
        !          1623:     }
        !          1624:   else
        !          1625:     {
        !          1626:       zport = zsysdep_port_name (&ftcp_port);
        !          1627:       if (zport == NULL)
        !          1628:        {
        !          1629:          qport = NULL;
        !          1630:          zport = "unknown";
        !          1631:        }
        !          1632:       else
        !          1633:        {
        !          1634:          iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0,
        !          1635:                                      (int (*) P((struct uuconf_port *,
        !          1636:                                                  pointer pinfo))) NULL,
        !          1637:                                      (pointer) NULL,
        !          1638:                                      &sport);
        !          1639:          if (iuuconf == UUCONF_NOT_FOUND)
        !          1640:            qport = NULL;
        !          1641:          else if (iuuconf != UUCONF_SUCCESS)
        !          1642:            {
        !          1643:              ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1644:              return FALSE;
        !          1645:            }
        !          1646:          else
        !          1647:            qport = &sport;
        !          1648:        }
        !          1649:     }
        !          1650: 
        !          1651:   /* If we've managed to figure out that this is a modem port, now try
        !          1652:      to get protocol parameters from the dialer.  */
        !          1653:   qdialer = NULL;
        !          1654:   if (qport != NULL)
        !          1655:     {
        !          1656:       if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
        !          1657:        {
        !          1658:          if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
        !          1659:            {
        !          1660:              const char *zdialer;
        !          1661: 
        !          1662:              zdialer = qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0];
        !          1663:              iuuconf = uuconf_dialer_info (puuconf, zdialer, &sdialer);
        !          1664:              if (iuuconf == UUCONF_SUCCESS)
        !          1665:                qdialer = &sdialer;
        !          1666:            }
        !          1667:          else
        !          1668:            qdialer = qport->uuconf_u.uuconf_smodem.uuconf_qdialer;
        !          1669:        }         
        !          1670:       else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TCP
        !          1671:               || (qport->uuconf_ttype == UUCONF_PORTTYPE_TLI
        !          1672:                   && (qport->uuconf_ireliable
        !          1673:                       & UUCONF_RELIABLE_SPECIFIED) == 0))
        !          1674:        ftcp_port = TRUE;
        !          1675:     }
        !          1676: 
        !          1677:   sDaemon.puuconf = puuconf;
        !          1678:   sDaemon.qsys = NULL;
        !          1679:   sDaemon.zlocalname = NULL;
        !          1680:   sDaemon.qconn = qconn;
        !          1681:   sDaemon.qproto = NULL;
        !          1682:   sDaemon.clocal_size = -1;
        !          1683:   sDaemon.cremote_size = -1;
        !          1684:   sDaemon.cmax_ever = -2;
        !          1685:   sDaemon.cmax_receive = -1;
        !          1686:   sDaemon.ifeatures = 0;
        !          1687:   sDaemon.frequest_hangup = FALSE;
        !          1688:   sDaemon.fhangup_requested = FALSE;
        !          1689:   sDaemon.fhangup = FALSE;
        !          1690:   sDaemon.fmaster = FALSE;
        !          1691:   sDaemon.fcaller = FALSE;
        !          1692:   sDaemon.ireliable = 0;
        !          1693:   sDaemon.bgrade = UUCONF_GRADE_LOW;
        !          1694: 
        !          1695:   /* Get the local name to use.  If uuconf_login_localname returns a
        !          1696:      value, it is not always freed up, although it should be.  */
        !          1697:   iuuconf = uuconf_login_localname (puuconf, zlogin, &zloc);
        !          1698:   if (iuuconf == UUCONF_SUCCESS)
        !          1699:     sDaemon.zlocalname = zloc;
        !          1700:   else if (iuuconf == UUCONF_NOT_FOUND)
        !          1701:     {
        !          1702:       sDaemon.zlocalname = zsysdep_localname ();
        !          1703:       if (sDaemon.zlocalname == NULL)
        !          1704:        return FALSE;
        !          1705:     }
        !          1706:   else
        !          1707:     {
        !          1708:       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1709:       return FALSE;
        !          1710:     }
        !          1711: 
        !          1712:   /* Tell the remote system who we are.   */
        !          1713:   zsend = zbufalc (strlen (sDaemon.zlocalname) + sizeof "Shere=");
        !          1714:   sprintf (zsend, "Shere=%s", sDaemon.zlocalname);
        !          1715:   fret = fsend_uucp_cmd (qconn, zsend);
        !          1716:   ubuffree (zsend);
        !          1717:   if (! fret)
        !          1718:     return FALSE;
        !          1719: 
        !          1720:   zstr = zget_uucp_cmd (qconn, TRUE);
        !          1721:   if (zstr == NULL)
        !          1722:     return FALSE;
        !          1723: 
        !          1724:   if (zstr[0] != 'S')
        !          1725:     {
        !          1726:       ulog (LOG_ERROR, "Bad introduction string");
        !          1727:       ubuffree (zstr);
        !          1728:       return FALSE;
        !          1729:     }
        !          1730: 
        !          1731: #ifdef MWCBBS
        !          1732:        strcpy(mwcbbs,zstr);
        !          1733:        mwcspace = strchr(mwcbbs,' ');
        !          1734:        if (mwcspace != NULL){
        !          1735:                *mwcspace = '\0';
        !          1736:        }
        !          1737: #endif /* MWCBBS */
        !          1738: 
        !          1739: 
        !          1740:   zspace = strchr (zstr, ' ');
        !          1741:   if (zspace != NULL)
        !          1742:     *zspace = '\0';
        !          1743: 
        !          1744: #ifdef MWCBBS
        !          1745:        {
        !          1746:                char *tmp;
        !          1747: 
        !          1748:                if((strcmp(mwcbbs+1, "bbsuser") == 0) &&
        !          1749:                   ((tmp = ttyname(fileno(stdin))) != NULL)){
        !          1750:                        sprintf(bbsuser,"SU%s%s",tmp+5,mwcspace+1);
        !          1751:                        zspace = mwcspace;
        !          1752:                        zstr = bbsuser;
        !          1753: /*                     ulog(LOG_NORMAL,"bbsuser is {%s}",bbsuser);
        !          1754:  *                     ulog(LOG_NORMAL,"mwcspace is {%s}",mwcspace+1);
        !          1755:  *                     ulog(LOG_NORMAL,"zstr is {%s}",zstr);
        !          1756:  *                     ulog(LOG_NORMAL,"zspace is {%s}",zspace+1);
        !          1757:  */
        !          1758:                }
        !          1759:        }
        !          1760: #endif /* MWCBBS */
        !          1761: 
        !          1762:   iuuconf = uuconf_system_info (puuconf, zstr + 1, &ssys);
        !          1763:   if (iuuconf == UUCONF_NOT_FOUND)
        !          1764:     {
        !          1765:       char *zscript;
        !          1766: 
        !          1767:       /* Run the remote.unknown script, if appropriate.  */
        !          1768:       iuuconf = uuconf_remote_unknown (puuconf, &zscript);
        !          1769:       if (iuuconf == UUCONF_SUCCESS)
        !          1770:        {
        !          1771:          if (! fsysdep_unknown_caller (zscript, zstr + 1))
        !          1772:            {
        !          1773:              xfree ((pointer) zscript);
        !          1774:              (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
        !          1775:              ubuffree (zstr);
        !          1776:              return FALSE;
        !          1777:            }
        !          1778:          xfree ((pointer) zscript);
        !          1779:        }
        !          1780:       else if (iuuconf != UUCONF_NOT_FOUND)
        !          1781:        {
        !          1782:          ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1783:          ubuffree (zstr);
        !          1784:          return FALSE;
        !          1785:        }
        !          1786: 
        !          1787:       if (! funknown_system (puuconf, zstr + 1, &ssys))
        !          1788:        {
        !          1789:          (void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
        !          1790:          ulog (LOG_ERROR, "Call from unknown system %s", zstr + 1);
        !          1791:          ubuffree (zstr);
        !          1792:          return FALSE;
        !          1793:        }
        !          1794:     }
        !          1795:   else if (iuuconf != UUCONF_SUCCESS)
        !          1796:     {
        !          1797:       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1798:       ubuffree (zstr);
        !          1799:       return FALSE;
        !          1800:     }
        !          1801: 
        !          1802:   qany = NULL;
        !          1803:   for (qsys = &ssys; qsys != NULL; qsys = qsys->uuconf_qalternate)
        !          1804:     {
        !          1805:       if (! qsys->uuconf_fcalled)
        !          1806:        continue;
        !          1807: 
        !          1808:       if (qsys->uuconf_zcalled_login == NULL
        !          1809:          || strcmp (qsys->uuconf_zcalled_login, "ANY") == 0)
        !          1810:        {
        !          1811:          if (qany == NULL)
        !          1812:            qany = qsys;
        !          1813:        }
        !          1814:       else if (strcmp (qsys->uuconf_zcalled_login, zlogin) == 0)
        !          1815:        break;
        !          1816:     }
        !          1817: 
        !          1818:   if (qsys == NULL && qany != NULL)
        !          1819:     {
        !          1820:       iuuconf = uuconf_validate (puuconf, qany, zlogin);
        !          1821:       if (iuuconf == UUCONF_SUCCESS)
        !          1822:        qsys = qany;
        !          1823:       else if (iuuconf != UUCONF_NOT_FOUND)
        !          1824:        {
        !          1825:          ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1826:          ubuffree (zstr);
        !          1827:          return FALSE;
        !          1828:        }
        !          1829:     }
        !          1830: 
        !          1831:   if (qsys == NULL)
        !          1832:     {
        !          1833:       (void) fsend_uucp_cmd (qconn, "RLOGIN");
        !          1834:       ulog (LOG_ERROR, "System %s used wrong login name %s",
        !          1835:            zstr + 1, zlogin);
        !          1836:       ubuffree (zstr);
        !          1837:       return FALSE;
        !          1838:     }
        !          1839: 
        !          1840:   sDaemon.qsys = qsys;
        !          1841: 
        !          1842:   if (pzsystem != NULL)
        !          1843:     *pzsystem = zbufcpy (qsys->uuconf_zname);
        !          1844: 
        !          1845:   ulog_system (qsys->uuconf_zname);
        !          1846: 
        !          1847: #if DEBUG > 1
        !          1848:   if (qsys->uuconf_zdebug != NULL)
        !          1849:     iDebug |= idebug_parse (qsys->uuconf_zdebug);
        !          1850: #endif
        !          1851: 
        !          1852:   /* See if we are supposed to call the system back.  This will queue
        !          1853:      up an empty command.  It would be better to actually call back
        !          1854:      directly at this point as well.  */
        !          1855:   if (qsys->uuconf_fcallback)
        !          1856:     {
        !          1857:       (void) fsend_uucp_cmd (qconn, "RCB");
        !          1858:       ulog (LOG_NORMAL, "Will call back");
        !          1859: 
        !          1860:       /* Clear any existing status.  */
        !          1861:       sstat.ttype = STATUS_COMPLETE;
        !          1862:       sstat.cretries = 0;
        !          1863:       sstat.ilast = ixsysdep_time ((long *) NULL);
        !          1864:       sstat.cwait = 0;
        !          1865:       (void) fsysdep_set_status (qsys, &sstat);
        !          1866: 
        !          1867:       ubuffree (zsysdep_spool_commands (qsys, UUCONF_GRADE_HIGH, 0,
        !          1868:                                        (const struct scmd *) NULL));
        !          1869:       ubuffree (zstr);
        !          1870:       return TRUE;
        !          1871:     }
        !          1872: 
        !          1873:   /* We only permit one call at a time from a remote system.  Lock it.  */
        !          1874:   if (! fsysdep_lock_system (qsys))
        !          1875:     {
        !          1876:       (void) fsend_uucp_cmd (qconn, "RLCK");
        !          1877:       ulog (LOG_ERROR, "System already locked");
        !          1878:       ubuffree (zstr);
        !          1879:       return FALSE;
        !          1880:     }
        !          1881:   sLocked_system = *qsys;
        !          1882:   fLocked_system = TRUE;
        !          1883: 
        !          1884:   /* Set the system status.  We don't care what the status was before.
        !          1885:      We also don't want to kill the conversation just because we can't
        !          1886:      output the .Status file, so we ignore any errors.  */
        !          1887:   sstat.ttype = STATUS_TALKING;
        !          1888:   sstat.cretries = 0;
        !          1889:   sstat.ilast = ixsysdep_time ((long *) NULL);
        !          1890:   sstat.cwait = 0;
        !          1891:   (void) fsysdep_set_status (qsys, &sstat);
        !          1892: 
        !          1893:   /* Check the arguments of the remote system, if any.  */
        !          1894:   fgotseq = FALSE;
        !          1895:   fgotn = FALSE;
        !          1896:   if (zspace != NULL)
        !          1897:     {
        !          1898:       char **paz;
        !          1899:       char **pzset;
        !          1900: 
        !          1901:       ++zspace;
        !          1902: 
        !          1903:       /* Break the introduction line up into arguments.  */
        !          1904:       paz = (char **) xmalloc ((strlen (zspace) / 2 + 2) * sizeof (char *));
        !          1905:       pzset = paz;
        !          1906:       *pzset++ = NULL;
        !          1907:       while (TRUE)
        !          1908:        {
        !          1909:          while (*zspace != '\0' && isspace (BUCHAR (*zspace)))
        !          1910:            ++zspace;
        !          1911:          if (*zspace == '\0')
        !          1912:            break;
        !          1913:          *pzset++ = zspace;
        !          1914:          ++zspace;
        !          1915:          while (*zspace != '\0' && ! isspace (BUCHAR (*zspace)))
        !          1916:            ++zspace;
        !          1917:          if (*zspace == '\0')
        !          1918:            break;
        !          1919:          *zspace++ = '\0';
        !          1920:        }
        !          1921: 
        !          1922:       if (pzset != paz + 1)
        !          1923:        {
        !          1924:          int iopt;
        !          1925: 
        !          1926:          *pzset = NULL;
        !          1927: 
        !          1928:          /* We are going to use getopt to parse the arguments.  We
        !          1929:             must clear optind to force getopt to reinitialize, and
        !          1930:             clear opterr to prevent getopt from printing an error
        !          1931:             message.  This approach assumes we are using the GNU
        !          1932:             getopt, which is distributed with the program anyhow.  */
        !          1933:          optind = 0;
        !          1934:          opterr = 0;
        !          1935:          
        !          1936:          while ((iopt = getopt (pzset - paz, paz,
        !          1937:                                 "N::p:Q:RU:v:x:")) != EOF)
        !          1938:            {
        !          1939:              long iseq;
        !          1940:              long c;
        !          1941:              char b;
        !          1942:              int iwant;
        !          1943: 
        !          1944:              switch (iopt)
        !          1945:                {
        !          1946:                case 'N':
        !          1947:                  /* This is used to indicate support for Taylor UUCP
        !          1948:                     extensions.  An plain -N mean support for size
        !          1949:                     negotiation.  If -N is followed by a number (with
        !          1950:                     no intervening space), the number is a bit field
        !          1951:                     of feature flags as defined in trans.h.  Note
        !          1952:                     that the argument may start with 0x for hex or 0
        !          1953:                     for octal.  */
        !          1954:                  fgotn = TRUE;
        !          1955:                  if (optarg == NULL)
        !          1956:                    sDaemon.ifeatures |= FEATURE_SIZES | FEATURE_V103;
        !          1957:                  else
        !          1958:                    sDaemon.ifeatures |= (int) strtol (optarg,
        !          1959:                                                       (char **) NULL,
        !          1960:                                                       0);
        !          1961:                  break;
        !          1962: 
        !          1963:                case 'p':
        !          1964:                  /* The argument is the lowest grade of work the
        !          1965:                     local system should send.  */
        !          1966:                  if (UUCONF_GRADE_LEGAL (optarg[0]))
        !          1967:                    sDaemon.bgrade = optarg[0];
        !          1968:                  break;
        !          1969: 
        !          1970:                case 'Q':
        !          1971:                  /* The conversation sequence number.  */
        !          1972:                  iseq = strtol (optarg, (char **) NULL, 10);
        !          1973:                  if (qsys->uuconf_fsequence
        !          1974:                      && iseq != ixsysdep_get_sequence (qsys))
        !          1975:                    {
        !          1976:                      (void) fsend_uucp_cmd (qconn, "RBADSEQ");
        !          1977:                      ulog (LOG_ERROR, "Out of sequence call rejected");
        !          1978:                      sstat.ttype = STATUS_FAILED;
        !          1979:                      (void) fsysdep_set_status (qsys, &sstat);
        !          1980:                      xfree ((pointer) paz);
        !          1981:                      ubuffree (zstr);
        !          1982:                      return FALSE;
        !          1983:                    }
        !          1984:                  fgotseq = TRUE;
        !          1985:                  break;
        !          1986: 
        !          1987:                case 'R':
        !          1988:                  /* The remote system supports file restart.  */
        !          1989:                  sDaemon.ifeatures |= FEATURE_RESTART;
        !          1990:                  break;
        !          1991: 
        !          1992:                case 'U':
        !          1993:                  /* The maximum file size the remote system is
        !          1994:                     prepared to received, in blocks where each block
        !          1995:                     is 512 bytes.  */
        !          1996:                  c = strtol (optarg, (char **) NULL, 0);
        !          1997:                  if (c > 0 && c < LONG_MAX / (long) 512)
        !          1998:                    sDaemon.cmax_receive = c * (long) 512;
        !          1999:                  break;
        !          2000: 
        !          2001:                case 'v':
        !          2002:                  /* -vgrade=X can be used to set the lowest grade of
        !          2003:                     work the local system should send.  */
        !          2004:                  if (strncmp (optarg, "grade=", sizeof "grade=" - 1) == 0)
        !          2005:                    {
        !          2006:                      b = optarg[sizeof "grade=" - 1];
        !          2007:                      if (UUCONF_GRADE_LEGAL (b))
        !          2008:                        sDaemon.bgrade = b;
        !          2009:                    }
        !          2010:                  break;
        !          2011: 
        !          2012:                case 'x':
        !          2013:                  iwant = (int) strtol (optarg, (char **) NULL, 10);
        !          2014: #if DEBUG > 1
        !          2015:                  if (iwant <= 9)
        !          2016:                    iwant = (1 << iwant) - 1;
        !          2017:                  if (qsys->uuconf_zmax_remote_debug != NULL)
        !          2018:                    iwant &= idebug_parse (qsys->uuconf_zmax_remote_debug);
        !          2019:                  if ((iDebug | iwant) != iDebug)
        !          2020:                    {
        !          2021:                      iDebug |= iwant;
        !          2022:                      ulog (LOG_NORMAL, "Setting debugging mode to 0%o",
        !          2023:                            iDebug);
        !          2024:                    }
        !          2025: #endif
        !          2026:                  break;
        !          2027: 
        !          2028:                default:
        !          2029:                  break;
        !          2030:                }
        !          2031:            }
        !          2032:        }
        !          2033: 
        !          2034:       xfree ((pointer) paz);
        !          2035:     }
        !          2036: 
        !          2037:   ubuffree (zstr);
        !          2038: 
        !          2039:   if (qsys->uuconf_fsequence && ! fgotseq)
        !          2040:     {
        !          2041:       (void) fsend_uucp_cmd (qconn, "RBADSEQ");
        !          2042:       ulog (LOG_ERROR, "No sequence number (call rejected)");
        !          2043:       sstat.ttype = STATUS_FAILED;
        !          2044:       (void) fsysdep_set_status (qsys, &sstat);
        !          2045:       return FALSE;
        !          2046:     }
        !          2047: 
        !          2048:   /* We recognized the system, and the sequence number (if any) was
        !          2049:      OK.  Send an ROK, and send a list of protocols.  If we got the -N
        !          2050:      switch, send ROKN to confirm it; if the -N switch was followed by
        !          2051:      a feature bitfield, return our own feature bitfield.  */
        !          2052:   {
        !          2053:     char ab[20];
        !          2054:     const char *zreply;
        !          2055: 
        !          2056:     if (! fgotn)
        !          2057:       {
        !          2058:        if ((sDaemon.ifeatures & FEATURE_RESTART) == 0)
        !          2059:          zreply = "ROK";
        !          2060:        else
        !          2061:          {
        !          2062:            /* We got -R without -N, so assume that this is SVR4 UUCP.
        !          2063:               SVR4 UUCP expects ROK -R to signal support for file
        !          2064:               restart.  */
        !          2065:            sDaemon.ifeatures |= FEATURE_SVR4 | FEATURE_SIZES;
        !          2066:            zreply = "ROK -R";
        !          2067:          }
        !          2068:       }
        !          2069:     else if ((sDaemon.ifeatures & FEATURE_V103) != 0)
        !          2070:       zreply = "ROKN";
        !          2071:     else
        !          2072:       {
        !          2073:        sprintf (ab, "ROKN0%o",
        !          2074:                 (unsigned int) (FEATURE_SIZES
        !          2075:                                 | FEATURE_EXEC
        !          2076:                                 | FEATURE_RESTART));
        !          2077:        zreply = ab;
        !          2078:       }
        !          2079:     if (! fsend_uucp_cmd (qconn, zreply))
        !          2080:       {
        !          2081:        sstat.ttype = STATUS_FAILED;
        !          2082:        (void) fsysdep_set_status (qsys, &sstat);
        !          2083:        return FALSE;
        !          2084:       }
        !          2085:   }
        !          2086: 
        !          2087:   /* Determine the reliability of the connection based on the
        !          2088:      reliability of the port and the dialer.  If we have no
        !          2089:      information, default to a reliable eight-bit full-duplex
        !          2090:      connection.  */
        !          2091:   if (ftcp_port)
        !          2092:     sDaemon.ireliable = (UUCONF_RELIABLE_SPECIFIED
        !          2093:                         | UUCONF_RELIABLE_ENDTOEND
        !          2094:                         | UUCONF_RELIABLE_RELIABLE
        !          2095:                         | UUCONF_RELIABLE_EIGHT
        !          2096:                         | UUCONF_RELIABLE_FULLDUPLEX);
        !          2097:   else
        !          2098:     {
        !          2099:       if (qport != NULL
        !          2100:          && (qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
        !          2101:        sDaemon.ireliable = qport->uuconf_ireliable;
        !          2102:       if (qdialer != NULL
        !          2103:          && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
        !          2104:        {
        !          2105:          if (sDaemon.ireliable != 0)
        !          2106:            sDaemon.ireliable &= qdialer->uuconf_ireliable;
        !          2107:          else
        !          2108:            sDaemon.ireliable = qdialer->uuconf_ireliable;
        !          2109:        }
        !          2110:       if (sDaemon.ireliable == 0)
        !          2111:        sDaemon.ireliable = (UUCONF_RELIABLE_RELIABLE
        !          2112:                             | UUCONF_RELIABLE_EIGHT
        !          2113:                             | UUCONF_RELIABLE_FULLDUPLEX
        !          2114:                             | UUCONF_RELIABLE_SPECIFIED);
        !          2115:     }
        !          2116: 
        !          2117:   if (qsys->uuconf_zprotocols != NULL ||
        !          2118:       (qport != NULL && qport->uuconf_zprotocols != NULL))
        !          2119:     {
        !          2120:       const char *zprotos;
        !          2121: 
        !          2122:       if (qsys->uuconf_zprotocols != NULL)
        !          2123:        zprotos = qsys->uuconf_zprotocols;
        !          2124:       else
        !          2125:        zprotos = qport->uuconf_zprotocols;
        !          2126:       zsend = zbufalc (strlen (zprotos) + 2);
        !          2127:       sprintf (zsend, "P%s", zprotos);
        !          2128:     }
        !          2129:   else
        !          2130:     {
        !          2131:       char *zset;
        !          2132: 
        !          2133:       zsend = zbufalc (CPROTOCOLS + 2);
        !          2134:       zset = zsend;
        !          2135:       *zset++ = 'P';
        !          2136: 
        !          2137:       /* If the system did not specify a list of protocols, we want
        !          2138:         only protocols that match the known reliability of the dialer
        !          2139:         and the port.  */
        !          2140:       for (i = 0; i < CPROTOCOLS; i++)
        !          2141:        {
        !          2142:          int ipr;
        !          2143: 
        !          2144:          ipr = asProtocols[i].ireliable;
        !          2145:          if ((ipr & sDaemon.ireliable) != ipr)
        !          2146:            continue;
        !          2147:          *zset++ = asProtocols[i].bname;
        !          2148:        }
        !          2149:       *zset = '\0';
        !          2150:     }
        !          2151: 
        !          2152:   fret = fsend_uucp_cmd (qconn, zsend);
        !          2153:   ubuffree (zsend);
        !          2154:   if (! fret)
        !          2155:     {
        !          2156:       sstat.ttype = STATUS_FAILED;
        !          2157:       (void) fsysdep_set_status (qsys, &sstat);
        !          2158:       return FALSE;
        !          2159:     }
        !          2160:     
        !          2161:   /* The master will now send back the selected protocol.  */
        !          2162:   zstr = zget_uucp_cmd (qconn, TRUE);
        !          2163:   if (zstr == NULL)
        !          2164:     {
        !          2165:       sstat.ttype = STATUS_FAILED;
        !          2166:       (void) fsysdep_set_status (qsys, &sstat);
        !          2167:       return FALSE;
        !          2168:     }
        !          2169: 
        !          2170:   if (zstr[0] != 'U' || zstr[2] != '\0')
        !          2171:     {
        !          2172:       ulog (LOG_ERROR, "Bad protocol response string");
        !          2173:       sstat.ttype = STATUS_FAILED;
        !          2174:       (void) fsysdep_set_status (qsys, &sstat);
        !          2175:       ubuffree (zstr);
        !          2176:       return FALSE;
        !          2177:     }
        !          2178: 
        !          2179:   if (zstr[1] == 'N')
        !          2180:     {
        !          2181:       ulog (LOG_ERROR, "No supported protocol");
        !          2182:       sstat.ttype = STATUS_FAILED;
        !          2183:       (void) fsysdep_set_status (qsys, &sstat);
        !          2184:       ubuffree (zstr);
        !          2185:       return FALSE;
        !          2186:     }
        !          2187: 
        !          2188:   for (i = 0; i < CPROTOCOLS; i++)
        !          2189:     if (asProtocols[i].bname == zstr[1])
        !          2190:       break;
        !          2191: 
        !          2192:   ubuffree (zstr);
        !          2193: 
        !          2194:   if (i >= CPROTOCOLS)
        !          2195:     {
        !          2196:       ulog (LOG_ERROR, "No supported protocol");
        !          2197:       sstat.ttype = STATUS_FAILED;
        !          2198:       (void) fsysdep_set_status (qsys, &sstat);
        !          2199:       return FALSE;
        !          2200:     }
        !          2201: 
        !          2202:   sDaemon.qproto = &asProtocols[i];
        !          2203: 
        !          2204:   /* Run the chat script for when a call is received.  */
        !          2205:   if (! fchat (qconn, puuconf, &qsys->uuconf_scalled_chat, qsys,
        !          2206:               (const struct uuconf_dialer *) NULL, (const char *) NULL,
        !          2207:               FALSE, zport, iconn_baud (qconn)))
        !          2208:     {
        !          2209:       sstat.ttype = STATUS_FAILED;
        !          2210:       sstat.ilast = ixsysdep_time ((long *) NULL);
        !          2211:       (void) fsysdep_set_status (qsys, &sstat);
        !          2212:       return FALSE;
        !          2213:     }
        !          2214: 
        !          2215:   /* Run any protocol parameter commands.  */
        !          2216:   if (sDaemon.qproto->qcmds != NULL)
        !          2217:     {
        !          2218:       if (qsys->uuconf_qproto_params != NULL)
        !          2219:        uapply_proto_params (puuconf, sDaemon.qproto->bname,
        !          2220:                             sDaemon.qproto->qcmds,
        !          2221:                             qsys->uuconf_qproto_params);
        !          2222:       if (qport != NULL
        !          2223:          && qport->uuconf_qproto_params != NULL)
        !          2224:        uapply_proto_params (puuconf, sDaemon.qproto->bname,
        !          2225:                             sDaemon.qproto->qcmds,
        !          2226:                             qport->uuconf_qproto_params);
        !          2227:       if (qdialer != NULL
        !          2228:          && qdialer->uuconf_qproto_params != NULL)
        !          2229:        uapply_proto_params (puuconf, sDaemon.qproto->bname,
        !          2230:                             sDaemon.qproto->qcmds,
        !          2231:                             qdialer->uuconf_qproto_params);
        !          2232:     }
        !          2233: 
        !          2234:   /* We don't need the dialer information any more.  */
        !          2235:   if (qdialer == &sdialer)
        !          2236:     (void) uuconf_dialer_free (puuconf, &sdialer);
        !          2237: 
        !          2238:   /* Get any jobs queued for the system, and turn on the selected
        !          2239:      protocol.  */
        !          2240:   if (! fqueue (&sDaemon, (boolean *) NULL)
        !          2241:       || ! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog))
        !          2242:     {
        !          2243:       uclear_queue (&sDaemon);
        !          2244:       sstat.ttype = STATUS_FAILED;
        !          2245:       sstat.ilast = ixsysdep_time ((long *) NULL);
        !          2246:       (void) fsysdep_set_status (qsys, &sstat);
        !          2247:       return FALSE;
        !          2248:     }
        !          2249: 
        !          2250:   if (zlog == NULL)
        !          2251:     {
        !          2252:       zlog = zbufalc (sizeof "protocol ''" + 1);
        !          2253:       sprintf (zlog, "protocol '%c'", sDaemon.qproto->bname);
        !          2254:     }
        !          2255: 
        !          2256:   zgrade = zbufalc (sizeof "grade  " + 1);
        !          2257:   if (sDaemon.bgrade == UUCONF_GRADE_LOW)
        !          2258:     *zgrade = '\0';
        !          2259:   else
        !          2260:     sprintf (zgrade, "grade %c ", sDaemon.bgrade);
        !          2261: 
        !          2262:   /* If we are using HAVE_HDB_LOGGING, then the previous ``incoming
        !          2263:      call'' message went to the general log, since we didn't know the
        !          2264:      system name at that point.  In that case, we repeat the port and
        !          2265:      login names.  */
        !          2266: #if HAVE_HDB_LOGGING
        !          2267:   ulog (LOG_NORMAL, "Handshake successful (login %s port %s %s%s)",
        !          2268:        zlogin,
        !          2269:        zLdevice == NULL ? "unknown" : zLdevice,
        !          2270:        zgrade, zlog);
        !          2271: #else /* ! HAVE_HDB_LOGGING */
        !          2272:   ulog (LOG_NORMAL, "Handshake successful (%s%s)", zgrade, zlog);
        !          2273: #endif /* ! HAVE_HDB_LOGGING */
        !          2274: 
        !          2275:   ubuffree (zlog);
        !          2276:   ubuffree (zgrade);
        !          2277: 
        !          2278:   {
        !          2279:     long iend_time;
        !          2280: 
        !          2281:     fret = floop (&sDaemon);
        !          2282: 
        !          2283:     /* Hangup.  As the answerer, we send seven O's and expect to
        !          2284:        receive six O's.  We send the seven O's twice to help the other
        !          2285:        side.  We don't worry about errors here.  */
        !          2286:     if (fsend_uucp_cmd (qconn, "OOOOOOO")
        !          2287:        && fsend_uucp_cmd (qconn, "OOOOOOO"))
        !          2288:       {
        !          2289:        int fdone;
        !          2290: 
        !          2291:        /* We look for the remote hangup string to ensure that the
        !          2292:           modem has sent out our hangup string.  This is only
        !          2293:           necessary because some versions of UUCP complain if they
        !          2294:           don't get the hangup string.  We look for the string
        !          2295:           several times because supposedly some implementations send
        !          2296:           some garbage after the last packet but before the hangup
        !          2297:           string.  */
        !          2298:        for (i = 0; i < 25; i++)
        !          2299:          {
        !          2300:            zstr = zget_uucp_cmd (qconn, FALSE);
        !          2301:            if (zstr == NULL)
        !          2302:              break;
        !          2303:            fdone = strstr (zstr, "OOOOOO") != NULL;
        !          2304:            ubuffree (zstr);
        !          2305:            if (fdone)
        !          2306:              break;
        !          2307:          }
        !          2308:       }
        !          2309: 
        !          2310:     iend_time = ixsysdep_time ((long *) NULL);
        !          2311: 
        !          2312:     ulog (LOG_NORMAL, "Call complete (%ld seconds)",
        !          2313:          iend_time - istart_time);
        !          2314: 
        !          2315:     uclear_queue (&sDaemon);
        !          2316: 
        !          2317:     if (fret)
        !          2318:       sstat.ttype = STATUS_COMPLETE;
        !          2319:     else
        !          2320:       sstat.ttype = STATUS_FAILED;
        !          2321:     sstat.ilast = iend_time;
        !          2322:     (void) fsysdep_set_status (qsys, &sstat);
        !          2323: 
        !          2324:     (void) uuconf_system_free (puuconf, &ssys);
        !          2325:     if (qport == &sport)
        !          2326:       (void) uuconf_port_free (puuconf, &sport);
        !          2327:     xfree ((pointer) zloc);
        !          2328: 
        !          2329:     return fret;
        !          2330:   }
        !          2331: }
        !          2332: 
        !          2333: /* Apply protocol parameters, once we know the protocol.  */
        !          2334: 
        !          2335: static void
        !          2336: uapply_proto_params (puuconf, bproto, qcmds, pas)
        !          2337:      pointer puuconf;
        !          2338:      int bproto;
        !          2339:      struct uuconf_cmdtab *qcmds;
        !          2340:      struct uuconf_proto_param *pas;
        !          2341: {
        !          2342:   struct uuconf_proto_param *qp;
        !          2343: 
        !          2344:   for (qp = pas; qp->uuconf_bproto != '\0'; qp++)
        !          2345:     {
        !          2346:       if (qp->uuconf_bproto == bproto)
        !          2347:        {
        !          2348:          struct uuconf_proto_param_entry *qe;
        !          2349: 
        !          2350:          for (qe = qp->uuconf_qentries; qe->uuconf_cargs > 0; qe++)
        !          2351:            {
        !          2352:              int iuuconf;
        !          2353: 
        !          2354:              iuuconf = uuconf_cmd_args (puuconf, qe->uuconf_cargs,
        !          2355:                                         qe->uuconf_pzargs, qcmds,
        !          2356:                                         (pointer) NULL,
        !          2357:                                         (uuconf_cmdtabfn) NULL, 0,
        !          2358:                                         (pointer) NULL);
        !          2359:              if (UUCONF_ERROR_VALUE (iuuconf) != UUCONF_SUCCESS)
        !          2360:                {
        !          2361:                  ulog (LOG_ERROR, "Error in %c protocol parameters",
        !          2362:                        bproto);
        !          2363:                  ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          2364:                }
        !          2365:            }
        !          2366: 
        !          2367:          break;
        !          2368:        }
        !          2369:     }
        !          2370: }
        !          2371: 
        !          2372: /* Send a string to the other system beginning with a DLE
        !          2373:    character and terminated with a null byte.  This is only
        !          2374:    used when no protocol is in force.  */
        !          2375: 
        !          2376: static boolean
        !          2377: fsend_uucp_cmd (qconn, z)
        !          2378:      struct sconnection *qconn;
        !          2379:      const char *z;
        !          2380: {
        !          2381:   size_t cwrite;
        !          2382:   char *zalc;
        !          2383:   boolean fret;
        !          2384: 
        !          2385:   DEBUG_MESSAGE1 (DEBUG_HANDSHAKE, "fsend_uucp_cmd: Sending \"%s\"", z);
        !          2386: 
        !          2387:   cwrite = strlen (z) + 2;
        !          2388: 
        !          2389:   zalc = zbufalc (cwrite);
        !          2390:   zalc[0] = '\020';
        !          2391:   memcpy (zalc + 1, z, cwrite - 1);
        !          2392: 
        !          2393:   fret = fconn_write (qconn, zalc, cwrite);
        !          2394:   ubuffree (zalc);
        !          2395:   return fret;
        !          2396: }
        !          2397: 
        !          2398: /* Get a UUCP command beginning with a DLE character and ending with a
        !          2399:    null byte.  This is only used when no protocol is in force.  This
        !          2400:    implementation has the potential of being seriously slow.  It also
        !          2401:    doesn't have any real error recovery.  The frequired argument is
        !          2402:    passed as TRUE if we need the string; we don't care that much if
        !          2403:    we're closing down the connection anyhow.  */
        !          2404: 
        !          2405: #define CTIMEOUT (120)
        !          2406: #define CSHORTTIMEOUT (10)
        !          2407: #define CINCREMENT (100)
        !          2408: 
        !          2409: static char *
        !          2410: zget_uucp_cmd (qconn, frequired)
        !          2411:      struct sconnection *qconn;
        !          2412:      boolean frequired;
        !          2413: {
        !          2414:   char *zalc;
        !          2415:   size_t calc;
        !          2416:   size_t cgot;
        !          2417:   boolean fintro;
        !          2418:   long iendtime;
        !          2419:   int ctimeout;
        !          2420: #if DEBUG > 1
        !          2421:   int cchars;
        !          2422:   int iolddebug;
        !          2423: #endif
        !          2424: 
        !          2425:   iendtime = ixsysdep_time ((long *) NULL);
        !          2426:   if (frequired)
        !          2427:     iendtime += CTIMEOUT;
        !          2428:   else
        !          2429:     iendtime += CSHORTTIMEOUT;
        !          2430: 
        !          2431: #if DEBUG > 1
        !          2432:   cchars = 0;
        !          2433:   iolddebug = iDebug;
        !          2434:   if (FDEBUGGING (DEBUG_HANDSHAKE))
        !          2435:     {
        !          2436:       ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
        !          2437:       iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
        !          2438:     }
        !          2439: #endif
        !          2440: 
        !          2441:   zalc = NULL;
        !          2442:   calc = 0;
        !          2443:   cgot = 0;
        !          2444:   fintro = FALSE;
        !          2445:   while ((ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL))) > 0)
        !          2446:     {
        !          2447:       int b;
        !          2448:       
        !          2449:       b = breceive_char (qconn, ctimeout, frequired);
        !          2450:       /* Now b == -1 on timeout, -2 on error.  */
        !          2451:       if (b < 0)
        !          2452:        {
        !          2453: #if DEBUG > 1
        !          2454:          if (FDEBUGGING (DEBUG_HANDSHAKE))
        !          2455:            {
        !          2456:              ulog (LOG_DEBUG_END, "\" (%s)",
        !          2457:                    b == -1 ? "timeout" : "error");
        !          2458:              iDebug = iolddebug;
        !          2459:            }
        !          2460: #endif
        !          2461:          if (b == -1 && frequired)
        !          2462:            ulog (LOG_ERROR, "Timeout");
        !          2463:          ubuffree (zalc);
        !          2464:          return NULL;
        !          2465:        }
        !          2466: 
        !          2467:       /* Apparently some systems use parity on these strings, so we
        !          2468:         strip the parity bit.  This may need to be configurable at
        !          2469:         some point, although only if system names can have eight bit
        !          2470:         characters.  */
        !          2471:       if (! isprint (BUCHAR (b)))
        !          2472:        b &= 0x7f;
        !          2473: 
        !          2474: #if DEBUG > 1
        !          2475:       if (FDEBUGGING (DEBUG_HANDSHAKE))
        !          2476:        {
        !          2477:          char ab[5];
        !          2478: 
        !          2479:          ++cchars;
        !          2480:          if (cchars > 60)
        !          2481:            {
        !          2482:              ulog (LOG_DEBUG_END, "\"");
        !          2483:              ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \"");
        !          2484:              cchars = 0;
        !          2485:            }
        !          2486:          (void) cdebug_char (ab, b);
        !          2487:          ulog (LOG_DEBUG_CONTINUE, "%s", ab);
        !          2488:        }
        !          2489: #endif
        !          2490: 
        !          2491:       if (! fintro)
        !          2492:        {
        !          2493:          if (b == '\020')
        !          2494:            fintro = TRUE;
        !          2495:          continue;
        !          2496:        }
        !          2497: 
        !          2498:       /* If we see another DLE, something has gone wrong; continue
        !          2499:         as though this were the first one we saw.  */
        !          2500:       if (b == '\020')
        !          2501:        {
        !          2502:          cgot = 0;
        !          2503:          continue;
        !          2504:        }
        !          2505: 
        !          2506:       /* Some systems send a trailing \n on the Shere line.  As far as
        !          2507:         I can tell this line can never contain a \n, so this
        !          2508:         modification should be safe enough.  */
        !          2509:       if (b == '\r' || b == '\n')
        !          2510:        b = '\0';
        !          2511: 
        !          2512:       if (cgot >= calc)
        !          2513:        {
        !          2514:          char *znew;
        !          2515: 
        !          2516:          calc += CINCREMENT;
        !          2517:          znew = zbufalc (calc);
        !          2518:          memcpy (znew, zalc, cgot);
        !          2519:          ubuffree (zalc);
        !          2520:          zalc = znew;
        !          2521:        }
        !          2522: 
        !          2523:       zalc[cgot] = (char) b;
        !          2524:       ++cgot;
        !          2525: 
        !          2526:       if (b == '\0')
        !          2527:        {
        !          2528: #if DEBUG > 1
        !          2529:          if (FDEBUGGING (DEBUG_HANDSHAKE))
        !          2530:            {
        !          2531:              ulog (LOG_DEBUG_END, "\"");
        !          2532:              iDebug = iolddebug;
        !          2533:            }
        !          2534: #endif
        !          2535:          return zalc;
        !          2536:        }
        !          2537:     }
        !          2538: 
        !          2539: #if DEBUG > 1
        !          2540:   if (FDEBUGGING (DEBUG_HANDSHAKE))
        !          2541:     {
        !          2542:       ulog (LOG_DEBUG_END, "\" (timeout)");
        !          2543:       iDebug = iolddebug;
        !          2544:     }
        !          2545: #endif
        !          2546: 
        !          2547:   ubuffree (zalc);
        !          2548: 
        !          2549:   if (frequired)
        !          2550:     ulog (LOG_ERROR, "Timeout");
        !          2551:   return NULL;
        !          2552: }
        !          2553: 
        !          2554: /* Read a sequence of characters up to a newline or carriage return, and
        !          2555:    return the line without the line terminating character.  */
        !          2556: 
        !          2557: static char *
        !          2558: zget_typed_line (qconn)
        !          2559:      struct sconnection *qconn;
        !          2560: {
        !          2561:   char *zalc;
        !          2562:   size_t calc;
        !          2563:   size_t cgot;
        !          2564: 
        !          2565: #if DEBUG > 1
        !          2566:   int cchars;
        !          2567:   int iolddebug;
        !          2568: 
        !          2569:   cchars = 0;
        !          2570:   iolddebug = iDebug;
        !          2571:   if (FDEBUGGING (DEBUG_CHAT))
        !          2572:     {
        !          2573:       ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
        !          2574:       iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
        !          2575:     }
        !          2576: #endif
        !          2577: 
        !          2578:   zalc = NULL;
        !          2579:   calc = 0;
        !          2580:   cgot = 0;
        !          2581:   while (TRUE)
        !          2582:     {
        !          2583:       int b;
        !          2584:       
        !          2585:       b = breceive_char (qconn, CTIMEOUT, FALSE);
        !          2586: 
        !          2587:       /* Now b == -1 on timeout, -2 on error.  */
        !          2588: 
        !          2589:       if (b == -2 || FGOT_SIGNAL ())
        !          2590:        {
        !          2591: #if DEBUG > 1
        !          2592:          if (FDEBUGGING (DEBUG_CHAT))
        !          2593:            {
        !          2594:              ulog (LOG_DEBUG_END, "\" (error)");
        !          2595:              iDebug = iolddebug;
        !          2596:            }
        !          2597: #endif
        !          2598:          ubuffree (zalc);
        !          2599:          return NULL;
        !          2600:        }
        !          2601: 
        !          2602:       if (b == -1)
        !          2603:        continue;
        !          2604: 
        !          2605: #if DEBUG > 1
        !          2606:       if (FDEBUGGING (DEBUG_CHAT))
        !          2607:        {
        !          2608:          char ab[5];
        !          2609: 
        !          2610:          ++cchars;
        !          2611:          if (cchars > 60)
        !          2612:            {
        !          2613:              ulog (LOG_DEBUG_END, "\"");
        !          2614:              ulog (LOG_DEBUG_START, "zget_typed_line: Got \"");
        !          2615:              cchars = 0;
        !          2616:            }
        !          2617:          (void) cdebug_char (ab, b);
        !          2618:          ulog (LOG_DEBUG_CONTINUE, "%s", ab);
        !          2619:        }
        !          2620: #endif
        !          2621: 
        !          2622:       if (cgot >= calc)
        !          2623:        {
        !          2624:          char *znew;
        !          2625: 
        !          2626:          calc += CINCREMENT;
        !          2627:          znew = zbufalc (calc);
        !          2628:          memcpy (znew, zalc, cgot);
        !          2629:          ubuffree (zalc);
        !          2630:          zalc = znew;
        !          2631:        }
        !          2632: 
        !          2633:       if (b == '\r' || b == '\n')
        !          2634:        b = '\0';
        !          2635: 
        !          2636:       zalc[cgot] = (char) b;
        !          2637:       ++cgot;
        !          2638: 
        !          2639:       if (b == '\0')
        !          2640:        {
        !          2641: #if DEBUG > 1
        !          2642:          if (FDEBUGGING (DEBUG_CHAT))
        !          2643:            {
        !          2644:              ulog (LOG_DEBUG_END, "\"");
        !          2645:              iDebug = iolddebug;
        !          2646:            }
        !          2647: #endif
        !          2648:          return zalc;
        !          2649:        }
        !          2650:     }
        !          2651: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.