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

unix.superglobalmegacorp.com

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