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

unix.superglobalmegacorp.com

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