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

1.1     ! root        1: /* cu.c
        !             2:    Call up a remote system.
        !             3: 
        !             4:    Copyright (C) 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 cu_rcsid[] = "$Id: cu.c,v 1.1 93/07/30 07:53:00 bin Exp Locker: bin $";
        !            30: #endif
        !            31: 
        !            32: #include "cu.h"
        !            33: #include "uudefs.h"
        !            34: #include "uuconf.h"
        !            35: #include "conn.h"
        !            36: #include "prot.h"
        !            37: #include "system.h"
        !            38: #include "sysdep.h"
        !            39: #include "getopt.h"
        !            40: 
        !            41: #include <stdio.h>
        !            42: #include <ctype.h>
        !            43: #include <errno.h>
        !            44: 
        !            45: /* Here are the user settable variables.  The user is permitted to
        !            46:    change these while running the program, using ~s.  */
        !            47: 
        !            48: /* The escape character used to introduce a special command.  The
        !            49:    escape character is the first character of this string.  */
        !            50: const char *zCuvar_escape = "~";
        !            51: 
        !            52: /* Whether to delay for a second before printing the host name after
        !            53:    seeing an escape character.  */
        !            54: boolean fCuvar_delay = TRUE;
        !            55: 
        !            56: /* The input characters which finish a line.  The escape character is
        !            57:    only recognized following one of these characters.  The default is
        !            58:    carriage return, ^U, ^C, ^O, ^D, ^S, ^Q, ^R, which I got from the
        !            59:    Ultrix /etc/remote file.  */
        !            60: const char *zCuvar_eol = "\r\025\003\017\004\023\021\022";
        !            61: 
        !            62: /* Whether to transfer binary data (nonprintable characters other than
        !            63:    newline and tab) when sending a file.  If this is FALSE, then
        !            64:    newline is changed to carriage return.  */
        !            65: boolean fCuvar_binary = FALSE;
        !            66: 
        !            67: /* A prefix string to use before sending a binary character from a
        !            68:    file; this is only used if fCuvar_binary is TRUE.  The default is
        !            69:    ^Z. */
        !            70: const char *zCuvar_binary_prefix = "\026";
        !            71: 
        !            72: /* Whether to check for echoes of characters sent when sending a file.
        !            73:    This is ignored if fCuvar_binary is TRUE.  */
        !            74: boolean fCuvar_echocheck = FALSE;
        !            75: 
        !            76: /* A character to look for after each newline is sent when sending a
        !            77:    file.  The character is the first character in this string, except
        !            78:    that a '\0' means that no echo check is done.  */
        !            79: const char *zCuvar_echonl = "\r";
        !            80: 
        !            81: /* The timeout to use when looking for an character.  */
        !            82: int cCuvar_timeout = 30;
        !            83: 
        !            84: /* The character to use to kill a line if an echo check fails.  The
        !            85:    first character in this string is sent.  The default is ^U.  */
        !            86: const char *zCuvar_kill = "\025";
        !            87: 
        !            88: /* The number of times to try resending a line if the echo check keeps
        !            89:    failing.  */
        !            90: int cCuvar_resend = 10;
        !            91: 
        !            92: /* The string to send at the end of a file sent with ~>.  The default
        !            93:    is ^D.  */
        !            94: const char *zCuvar_eofwrite = "\004";
        !            95: 
        !            96: /* The string to look for to finish a file received with ~<.  For tip
        !            97:    this is a collection of single characters, but I don't want to do
        !            98:    that because it means that there are characters which cannot be
        !            99:    received.  The default is a guess at a typical shell prompt.  */
        !           100: const char *zCuvar_eofread = "$";
        !           101: 
        !           102: /* Whether to provide verbose information when sending or receiving a
        !           103:    file.  */
        !           104: boolean fCuvar_verbose = TRUE;
        !           105: 
        !           106: /* The table used to give a value to a variable, and to print all the
        !           107:    variable values.  */
        !           108: 
        !           109: static const struct uuconf_cmdtab asCuvars[] =
        !           110: {
        !           111:   { "escape", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_escape, NULL },
        !           112:   { "delay", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_delay, NULL },
        !           113:   { "eol", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eol, NULL },
        !           114:   { "binary", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_binary, NULL },
        !           115:   { "binary-prefix", UUCONF_CMDTABTYPE_STRING,
        !           116:       (pointer) &zCuvar_binary_prefix, NULL },
        !           117:   { "echocheck", UUCONF_CMDTABTYPE_BOOLEAN,
        !           118:       (pointer) &fCuvar_echocheck, NULL },
        !           119:   { "echonl", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_echonl, NULL },
        !           120:   { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cCuvar_timeout, NULL },
        !           121:   { "kill", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_kill, NULL },
        !           122:   { "resend", UUCONF_CMDTABTYPE_INT, (pointer) &cCuvar_resend, NULL },
        !           123:   { "eofwrite", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eofwrite, NULL },
        !           124:   { "eofread", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eofread, NULL },
        !           125:   { "verbose", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_verbose, NULL },
        !           126:   { NULL, 0, NULL, NULL}
        !           127: };
        !           128: 
        !           129: /* The program name.  */
        !           130: char abProgram[] = "cu";
        !           131: 
        !           132: /* The string printed at the initial connect.  */
        !           133: #if ANSI_C
        !           134: #define ZCONNMSG "\aConnected."
        !           135: #else
        !           136: #define ZCONNMSG "Connected."
        !           137: #endif
        !           138: 
        !           139: /* The string printed when disconnecting.  */
        !           140: #if ANSI_C
        !           141: #define ZDISMSG "\aDisconnected."
        !           142: #else
        !           143: #define ZDISMSG "Disconnected."
        !           144: #endif
        !           145: 
        !           146: /* Local variables.  */
        !           147: 
        !           148: /* The string we print when the user is once again connected to the
        !           149:    port after transferring a file or taking some other action.  */
        !           150: static const char abCuconnected[]
        !           151: #if ANSI_C
        !           152:   = "\a[connected]";
        !           153: #else
        !           154:   = "[connected]";
        !           155: #endif
        !           156: 
        !           157: /* Global uuconf pointer.  */
        !           158: static pointer pCuuuconf;
        !           159: 
        !           160: /* Connection.  */
        !           161: static struct sconnection *qCuconn;
        !           162: 
        !           163: /* Whether to close the connection.  */
        !           164: static boolean fCuclose_conn;
        !           165: 
        !           166: /* Dialer used to dial out.  */
        !           167: static struct uuconf_dialer *qCudialer;
        !           168: 
        !           169: /* Whether we need to restore the terminal.  */
        !           170: static boolean fCurestore_terminal;
        !           171: 
        !           172: /* Whether we are doing local echoing.  */
        !           173: static boolean fCulocalecho;
        !           174: 
        !           175: /* Whether we need to call fsysdep_cu_finish.  */
        !           176: static boolean fCustarted;
        !           177: 
        !           178: /* A structure used to pass information to icuport_lock.  */
        !           179: struct sconninfo
        !           180: {
        !           181:   boolean fmatched;
        !           182:   boolean flocked;
        !           183:   struct sconnection *qconn;
        !           184:   const char *zline;
        !           185: };
        !           186: 
        !           187: /* Local functions.  */
        !           188: 
        !           189: static void ucuusage P((void));
        !           190: static void ucuabort P((void));
        !           191: static void uculog_start P((void));
        !           192: static void uculog_end P((void));
        !           193: static int icuport_lock P((struct uuconf_port *qport, pointer pinfo));
        !           194: static boolean fcudo_cmd P((pointer puuconf, struct sconnection *qconn,
        !           195:                            int bcmd));
        !           196: static boolean fcuset_var P((pointer puuconf, char *zline));
        !           197: static int icuunrecogvar P((pointer puuconf, int argc, char **argv,
        !           198:                            pointer pvar, pointer pinfo));
        !           199: static int icuunrecogfn P((pointer puuconf, int argc, char **argv,
        !           200:                           pointer pvar, pointer pinfo));
        !           201: static void uculist_vars P((void));
        !           202: static void uculist_fns P((const char *zescape));
        !           203: static boolean fcudo_subcmd P((pointer puuconf, struct sconnection *qconn,
        !           204:                               char *zline));
        !           205: static boolean fcusend_buf P((struct sconnection *qconn, const char *zbuf,
        !           206:                              size_t cbuf));
        !           207: 
        !           208: #define ucuputs(zline) \
        !           209:        do { if (! fsysdep_terminal_puts (zline)) ucuabort (); } while (0)
        !           210: 
        !           211: /* Long getopt options.  */
        !           212: static const struct option asCulongopts[] = { { NULL, 0, NULL, 0 } };
        !           213: 
        !           214: int
        !           215: main (argc, argv)
        !           216:      int argc;
        !           217:      char **argv;
        !           218: {
        !           219:   /* -c: phone number.  */
        !           220:   char *zphone = NULL;
        !           221:   /* -e: even parity.  */
        !           222:   boolean feven = FALSE;
        !           223:   /* -l: line.  */
        !           224:   char *zline = NULL;
        !           225:   /* -n: prompt for phone number.  */
        !           226:   boolean fprompt = FALSE;
        !           227:   /* -o: odd parity.  */
        !           228:   boolean fodd = FALSE;
        !           229:   /* -p: port name.  */
        !           230:   const char *zport = NULL;
        !           231:   /* -s: speed.  */
        !           232:   long ibaud = 0L;
        !           233:   /* -t: map cr to crlf.  */
        !           234:   boolean fmapcr = FALSE;
        !           235:   /* -z: system.  */
        !           236:   const char *zsystem = NULL;
        !           237:   /* -I: configuration file name.  */
        !           238:   const char *zconfig = NULL;
        !           239:   int iopt;
        !           240:   pointer puuconf;
        !           241:   int iuuconf;
        !           242:   const char *zlocalname;
        !           243:   int i;
        !           244:   struct uuconf_system ssys;
        !           245:   const struct uuconf_system *qsys = NULL;
        !           246:   boolean flooped;
        !           247:   struct uuconf_port sport;
        !           248:   struct sconnection sconn;
        !           249:   struct sconninfo sinfo;
        !           250:   long ihighbaud;
        !           251:   struct uuconf_dialer sdialer;
        !           252:   struct uuconf_dialer *qdialer;
        !           253:   char bcmd;
        !           254: 
        !           255:   /* We want to accept -# as a speed.  It's easiest to look through
        !           256:      the arguments, replace -# with -s#, and let getopt handle it.  */
        !           257:   for (i = 1; i < argc; i++)
        !           258:     {
        !           259:       if (argv[i][0] == '-'
        !           260:          && isdigit (BUCHAR (argv[i][1])))
        !           261:        {
        !           262:          size_t clen;
        !           263:          char *z;
        !           264: 
        !           265:          clen = strlen (argv[i]);
        !           266:          z = zbufalc (clen + 2);
        !           267:          z[0] = '-';
        !           268:          z[1] = 's';
        !           269:          memcpy (z + 2, argv[i] + 1, clen);
        !           270:          argv[i] = z;
        !           271:        }
        !           272:     }
        !           273: 
        !           274:   while ((iopt = getopt_long (argc, argv, "a:c:dehnI:l:op:s:tx:z:",
        !           275:                              asCulongopts, (int *) NULL)) != EOF)
        !           276:     {
        !           277:       switch (iopt)
        !           278:        {
        !           279:        case 'c':
        !           280:          /* Phone number.  */
        !           281:          zphone = optarg;
        !           282:          break;
        !           283: 
        !           284:        case 'd':
        !           285:          /* Set debugging level to maximum.  */
        !           286: #if DEBUG > 1
        !           287:          iDebug = DEBUG_MAX;
        !           288: #endif
        !           289:          break;
        !           290: 
        !           291:        case 'e':
        !           292:          /* Even parity.  */
        !           293:          feven = TRUE;
        !           294:          break;
        !           295: 
        !           296:        case 'h':
        !           297:          /* Local echo.  */
        !           298:          fCulocalecho = TRUE;
        !           299:          break;
        !           300: 
        !           301:        case 'n':
        !           302:          /* Prompt for phone number.  */
        !           303:          fprompt = TRUE;
        !           304:          break;
        !           305: 
        !           306:        case 'l':
        !           307:          /* Line name.  */
        !           308:          zline = optarg;
        !           309:          break;
        !           310: 
        !           311:        case 'o':
        !           312:          /* Odd parity.  */
        !           313:          fodd = TRUE;
        !           314:          break;
        !           315: 
        !           316:        case 'p':
        !           317:        case 'a':
        !           318:          /* Port name (-a is for compatibility).  */
        !           319:          zport = optarg;
        !           320:          break;
        !           321: 
        !           322:        case 's':
        !           323:          /* Speed.  */
        !           324:          ibaud = strtol (optarg, (char **) NULL, 10);
        !           325:          break;
        !           326: 
        !           327:        case 't':
        !           328:          /* Map cr to crlf.  */
        !           329:          fmapcr = TRUE;
        !           330:          break;
        !           331: 
        !           332:        case 'z':
        !           333:          /* System name.  */
        !           334:          zsystem = optarg;
        !           335:          break;
        !           336: 
        !           337:        case 'I':
        !           338:          /* Configuration file name.  */
        !           339:          if (fsysdep_other_config (optarg))
        !           340:            zconfig = optarg;
        !           341:          break;
        !           342: 
        !           343:        case 'x':
        !           344: #if DEBUG > 1
        !           345:          /* Set debugging level.  */
        !           346:          iDebug |= idebug_parse (optarg);
        !           347: #endif
        !           348:          break;
        !           349: 
        !           350:        case 0:
        !           351:          /* Long option found and flag set.  */
        !           352:          break;
        !           353: 
        !           354:        default:
        !           355:          ucuusage ();
        !           356:          break;
        !           357:        }
        !           358:     }
        !           359: 
        !           360:   /* There can be one more argument, which is either a system name, a
        !           361:      phone number, or "dir".  We decide which it is based on the first
        !           362:      character.  To call a UUCP system whose name begins with a digit,
        !           363:      or one which is named "dir", you must use -z.  */
        !           364:   if (optind != argc)
        !           365:     {
        !           366:       if (optind != argc - 1
        !           367:          || zsystem != NULL
        !           368:          || zphone != NULL)
        !           369:        ucuusage ();
        !           370:       if (strcmp (argv[optind], "dir") != 0)
        !           371:        {
        !           372:          if (isdigit (BUCHAR (argv[optind][0])))
        !           373:            zphone = argv[optind];
        !           374:          else
        !           375:            zsystem = argv[optind];
        !           376:        }
        !           377:     }
        !           378: 
        !           379:   /* If the user doesn't give a system, port, line or speed, then
        !           380:      there's no basis on which to select a port.  */
        !           381:   if (zsystem == NULL
        !           382:       && zport == NULL
        !           383:       && zline == NULL
        !           384:       && ibaud == 0L)
        !           385:     ucuusage ();
        !           386: 
        !           387:   if (fprompt)
        !           388:     {
        !           389:       size_t cphone;
        !           390: 
        !           391:       printf ("Phone number: ");
        !           392:       (void) fflush (stdout);
        !           393:       zphone = NULL;
        !           394:       cphone = 0;
        !           395:       if (getline (&zphone, &cphone, stdin) <= 0
        !           396:          || *zphone == '\0')
        !           397:        {
        !           398:          fprintf (stderr, "%s: No phone number entered\n", abProgram);
        !           399:          exit (EXIT_FAILURE);
        !           400:        }
        !           401:     }
        !           402: 
        !           403:   iuuconf = uuconf_init (&puuconf, "cu", zconfig);
        !           404:   if (iuuconf != UUCONF_SUCCESS)
        !           405:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           406:   pCuuuconf = puuconf;
        !           407: 
        !           408: #if DEBUG > 1
        !           409:   {
        !           410:     const char *zdebug;
        !           411: 
        !           412:     iuuconf = uuconf_debuglevel (puuconf, &zdebug);
        !           413:     if (iuuconf != UUCONF_SUCCESS)
        !           414:       ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           415:     if (zdebug != NULL)
        !           416:       iDebug |= idebug_parse (zdebug);
        !           417:   }
        !           418: #endif
        !           419: 
        !           420:   usysdep_initialize (puuconf, INIT_NOCHDIR | INIT_SUID);
        !           421: 
        !           422:   iuuconf = uuconf_localname (puuconf, &zlocalname);
        !           423:   if (iuuconf == UUCONF_NOT_FOUND)
        !           424:     {
        !           425:       zlocalname = zsysdep_localname ();
        !           426:       if (zlocalname == NULL)
        !           427:        exit (EXIT_FAILURE);
        !           428:     }
        !           429:   else if (iuuconf != UUCONF_SUCCESS)
        !           430:     ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           431: 
        !           432:   ulog_fatal_fn (ucuabort);
        !           433:   pfLstart = uculog_start;
        !           434:   pfLend = uculog_end;
        !           435: 
        !           436: #ifdef SIGINT
        !           437:   usysdep_signal (SIGINT);
        !           438: #endif
        !           439: #ifdef SIGHUP
        !           440:   usysdep_signal (SIGHUP);
        !           441: #endif
        !           442: #ifdef SIGQUIT
        !           443:   usysdep_signal (SIGQUIT);
        !           444: #endif
        !           445: #ifdef SIGTERM
        !           446:   usysdep_signal (SIGTERM);
        !           447: #endif
        !           448: #ifdef SIGPIPE
        !           449:   usysdep_signal (SIGPIPE);
        !           450: #endif
        !           451: 
        !           452:   if (zsystem != NULL)
        !           453:     {
        !           454:       iuuconf = uuconf_system_info (puuconf, zsystem, &ssys);
        !           455:       if (iuuconf != UUCONF_SUCCESS)
        !           456:        {
        !           457:          if (iuuconf != UUCONF_NOT_FOUND)
        !           458:            ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           459:          ulog (LOG_FATAL, "%s: System not found", zsystem);
        !           460:        }
        !           461:       qsys = &ssys;
        !           462:     }
        !           463: 
        !           464:   /* This loop is used if a system is specified.  It loops over the
        !           465:      various alternates until it finds one for which the dial
        !           466:      succeeds.  This is an ugly spaghetti construction, and it should
        !           467:      be broken up into different functions someday.  */
        !           468:   flooped = FALSE;
        !           469:   while (TRUE)
        !           470:     {
        !           471:       enum tparitysetting tparity;
        !           472:       enum tstripsetting tstrip;
        !           473: 
        !           474:       /* The uuconf_find_port function only selects directly on a port
        !           475:         name and a speed.  To select based on the line name, we use a
        !           476:         function.  If we can't find any defined port, and the user
        !           477:         specified a line name but did not specify a port name or a
        !           478:         system or a phone number, then we fake a direct port with
        !           479:         that line name (we don't fake a port if a system or phone
        !           480:         number were given because if we fake a port we have no way to
        !           481:         place a call; perhaps we should automatically look up a
        !           482:         particular dialer).  This permits users to say cu -lttyd0
        !           483:         without having to put ttyd0 in the ports file, provided they
        !           484:         have read and write access to the port.  */
        !           485:       sinfo.fmatched = FALSE;
        !           486:       sinfo.flocked = FALSE;
        !           487:       sinfo.qconn = &sconn;
        !           488:       sinfo.zline = zline;
        !           489:       if (zport != NULL || zline != NULL || ibaud != 0L)
        !           490:        {
        !           491:          iuuconf = uuconf_find_port (puuconf, zport, ibaud, 0L,
        !           492:                                      icuport_lock, (pointer) &sinfo,
        !           493:                                      &sport);
        !           494:          if (iuuconf != UUCONF_SUCCESS)
        !           495:            {
        !           496:              if (iuuconf != UUCONF_NOT_FOUND)
        !           497:                {
        !           498:                  if (sinfo.flocked)
        !           499:                    {
        !           500:                      (void) fconn_unlock (&sconn);
        !           501:                      uconn_free (&sconn);
        !           502:                    }
        !           503:                  ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           504:                }
        !           505:              if (zline == NULL
        !           506:                  || zport != NULL
        !           507:                  || zphone != NULL
        !           508:                  || qsys != NULL)
        !           509:                {
        !           510:                  if (sinfo.fmatched)
        !           511:                    ulog (LOG_FATAL, "All matching ports in use");
        !           512:                  else
        !           513:                    ulog (LOG_FATAL, "No matching ports");
        !           514:                }
        !           515: 
        !           516:              sport.uuconf_zname = zline;
        !           517:              sport.uuconf_ttype = UUCONF_PORTTYPE_DIRECT;
        !           518:              sport.uuconf_zprotocols = NULL;
        !           519:              sport.uuconf_qproto_params = NULL;
        !           520:              sport.uuconf_ireliable = 0;
        !           521:              sport.uuconf_zlockname = NULL;
        !           522:              sport.uuconf_palloc = NULL;
        !           523:              sport.uuconf_u.uuconf_sdirect.uuconf_zdevice = NULL;
        !           524:              sport.uuconf_u.uuconf_sdirect.uuconf_ibaud = ibaud;
        !           525: 
        !           526:              if (! fsysdep_port_access (&sport))
        !           527:                ulog (LOG_FATAL, "%s: Permission denied", zline);
        !           528: 
        !           529:              if (! fconn_init (&sport, &sconn))
        !           530:                ucuabort ();
        !           531: 
        !           532:              if (! fconn_lock (&sconn, FALSE))
        !           533:                ulog (LOG_FATAL, "%s: Line in use", zline);
        !           534: 
        !           535:              qCuconn = &sconn;
        !           536:            }
        !           537:          ihighbaud = 0L;
        !           538:        }
        !           539:       else
        !           540:        {
        !           541:          for (; qsys != NULL; qsys = qsys->uuconf_qalternate)
        !           542:            {
        !           543:              if (! qsys->uuconf_fcall)
        !           544:                continue;
        !           545:              if (qsys->uuconf_qport != NULL)
        !           546:                {
        !           547:                  if (fconn_init (qsys->uuconf_qport, &sconn))
        !           548:                    {
        !           549:                      if (fconn_lock (&sconn, FALSE))
        !           550:                        {
        !           551:                          qCuconn = &sconn;
        !           552:                          break;
        !           553:                        }
        !           554:                      uconn_free (&sconn);
        !           555:                    }
        !           556:                }
        !           557:              else
        !           558:                {
        !           559:                  sinfo.fmatched = FALSE;
        !           560:                  sinfo.flocked = FALSE;
        !           561:                  sinfo.qconn = &sconn;
        !           562:                  iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport,
        !           563:                                              qsys->uuconf_ibaud,
        !           564:                                              qsys->uuconf_ihighbaud,
        !           565:                                              icuport_lock,
        !           566:                                              (pointer) &sinfo,
        !           567:                                              &sport);
        !           568:                  if (iuuconf == UUCONF_SUCCESS)
        !           569:                    break;
        !           570:                  if (iuuconf != UUCONF_NOT_FOUND)
        !           571:                    {
        !           572:                      if (sinfo.flocked)
        !           573:                        {
        !           574:                          (void) fconn_unlock (&sconn);
        !           575:                          uconn_free (&sconn);
        !           576:                        }
        !           577:                      ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
        !           578:                    }
        !           579:                }
        !           580:            }
        !           581: 
        !           582:          if (qsys == NULL)
        !           583:            {
        !           584:              const char *zrem;
        !           585: 
        !           586:              if (flooped)
        !           587:                zrem = "remaining ";
        !           588:              else
        !           589:                zrem = "";
        !           590:              if (sinfo.fmatched)
        !           591:                ulog (LOG_FATAL, "%s: All %smatching ports in use",
        !           592:                      zsystem, zrem);
        !           593:              else
        !           594:                ulog (LOG_FATAL, "%s: No %smatching ports", zsystem, zrem);
        !           595:            }
        !           596: 
        !           597:          ibaud = qsys->uuconf_ibaud;
        !           598:          ihighbaud = qsys->uuconf_ihighbaud;
        !           599:        }
        !           600: 
        !           601:       /* Here we have locked a connection to use.  */
        !           602:       if (! fconn_open (&sconn, ibaud, ihighbaud, FALSE))
        !           603:        ucuabort ();
        !           604: 
        !           605:       fCuclose_conn = TRUE;
        !           606: 
        !           607:       if (FGOT_SIGNAL ())
        !           608:        ucuabort ();
        !           609: 
        !           610:       /* Set up the connection.  */
        !           611:       if (fodd && feven)
        !           612:        {
        !           613:          tparity = PARITYSETTING_NONE;
        !           614:          tstrip = STRIPSETTING_SEVENBITS;
        !           615:        }
        !           616:       else if (fodd)
        !           617:        {
        !           618:          tparity = PARITYSETTING_ODD;
        !           619:          tstrip = STRIPSETTING_SEVENBITS;
        !           620:        }
        !           621:       else if (feven)
        !           622:        {
        !           623:          tparity = PARITYSETTING_EVEN;
        !           624:          tstrip = STRIPSETTING_SEVENBITS;
        !           625:        }
        !           626:       else
        !           627:        {
        !           628:          tparity = PARITYSETTING_DEFAULT;
        !           629:          tstrip = STRIPSETTING_DEFAULT;
        !           630:        }
        !           631: 
        !           632:       if (! fconn_set (&sconn, tparity, tstrip, XONXOFF_ON))
        !           633:        ucuabort ();
        !           634: 
        !           635:       if (qsys != NULL)
        !           636:        zphone = qsys->uuconf_zphone;
        !           637: 
        !           638:       if (qsys != NULL || zphone != NULL)
        !           639:        {
        !           640:          enum tdialerfound tdialer;
        !           641: 
        !           642:          if (! fconn_dial (&sconn, puuconf, qsys, zphone, &sdialer,
        !           643:                            &tdialer))
        !           644:            {
        !           645:              if (zport != NULL
        !           646:                  || zline != NULL
        !           647:                  || ibaud != 0L
        !           648:                  || qsys == NULL)
        !           649:                ucuabort ();
        !           650: 
        !           651:              if (qsys->uuconf_qalternate == NULL)
        !           652:                ulog (LOG_FATAL, "%s: No remaining alternates", zsystem);
        !           653: 
        !           654:              fCuclose_conn = FALSE;
        !           655:              (void) fconn_close (&sconn, pCuuuconf, qCudialer, FALSE);
        !           656:              qCuconn = NULL;
        !           657:              (void) fconn_unlock (&sconn);
        !           658:              uconn_free (&sconn);
        !           659: 
        !           660:              /* Loop around and try another alternate.  */
        !           661:              flooped = TRUE;
        !           662:              continue;
        !           663:            }
        !           664:          if (tdialer == DIALERFOUND_FALSE)
        !           665:            qdialer = NULL;
        !           666:          else
        !           667:            qdialer = &sdialer;
        !           668:        }
        !           669:       else
        !           670:        {
        !           671:          /* If no system or phone number was specified, we connect
        !           672:             directly to the modem.  We only permit this if the user
        !           673:             has access to the port, since it permits various
        !           674:             shenanigans such as reprogramming the automatic
        !           675:             callbacks.  */
        !           676:          if (! fsysdep_port_access (sconn.qport))
        !           677:            ulog (LOG_FATAL, "Access to port denied");
        !           678:          qdialer = NULL;
        !           679:          if (! fconn_carrier (&sconn, FALSE))
        !           680:            ulog (LOG_FATAL, "Can't turn off carrier");
        !           681:        }
        !           682: 
        !           683:       break;
        !           684:     }
        !           685: 
        !           686:   qCudialer = qdialer;
        !           687: 
        !           688:   if (FGOT_SIGNAL ())
        !           689:     ucuabort ();
        !           690: 
        !           691:   /* Here we have connected, and can start the main cu protocol.  The
        !           692:      program spends most of its time in system dependent code, and
        !           693:      only comes out when a special command is received from the
        !           694:      terminal.  */
        !           695:   printf ("%s\n", ZCONNMSG);
        !           696: 
        !           697:   if (! fsysdep_terminal_raw (fCulocalecho))
        !           698:     ucuabort ();
        !           699: 
        !           700:   fCurestore_terminal = TRUE;
        !           701: 
        !           702:   if (! fsysdep_cu_init (&sconn))
        !           703:     ucuabort ();
        !           704: 
        !           705:   fCustarted = TRUE;
        !           706: 
        !           707:   while (fsysdep_cu (&sconn, &bcmd, zlocalname))
        !           708:     if (! fcudo_cmd (puuconf, &sconn, bcmd))
        !           709:       break;
        !           710: 
        !           711:   fCustarted = FALSE;
        !           712:   if (! fsysdep_cu_finish ())
        !           713:     ucuabort ();
        !           714: 
        !           715:   fCurestore_terminal = FALSE;
        !           716:   (void) fsysdep_terminal_restore ();
        !           717: 
        !           718:   (void) fconn_close (&sconn, puuconf, qdialer, TRUE);
        !           719:   (void) fconn_unlock (&sconn);
        !           720:   uconn_free (&sconn);
        !           721: 
        !           722:   printf ("\n%s\n", ZDISMSG);
        !           723: 
        !           724:   ulog_close ();
        !           725: 
        !           726:   usysdep_exit (TRUE);
        !           727: 
        !           728:   /* Avoid errors about not returning a value.  */
        !           729:   return 0;
        !           730: }
        !           731: 
        !           732: /* Print a usage message and die.  */
        !           733: 
        !           734: static void
        !           735: ucuusage ()
        !           736: {
        !           737:   fprintf (stderr,
        !           738:           "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
        !           739:           VERSION);
        !           740:   fprintf (stderr,
        !           741:           "Usage: cu [options] [system or phone-number]\n");
        !           742:   fprintf (stderr,
        !           743:           " -a port, -p port: Use named port\n");
        !           744:   fprintf (stderr,
        !           745:           " -l line: Use named device (e.g. tty0)\n");
        !           746:   fprintf (stderr,
        !           747:           " -s speed, -#: Use given speed\n");
        !           748:   fprintf (stderr,
        !           749:           " -c phone: Phone number to call\n");
        !           750:   fprintf (stderr,
        !           751:           " -z system: System to call\n");
        !           752:   fprintf (stderr,
        !           753:           " -e: Set even parity\n");
        !           754:   fprintf (stderr,
        !           755:           " -o: Set odd parity\n");
        !           756:   fprintf (stderr,
        !           757:           " -h: Echo locally\n");
        !           758:   fprintf (stderr,
        !           759:           " -t: Map carriage return to carriage return/linefeed\n");
        !           760:   fprintf (stderr,
        !           761:           " -n: Prompt for phone number\n");
        !           762:   fprintf (stderr,
        !           763:           " -d: Set maximum debugging level\n");
        !           764:   fprintf (stderr,
        !           765:           " -x debug: Set debugging type\n");
        !           766: #if HAVE_TAYLOR_CONFIG
        !           767:   fprintf (stderr,
        !           768:           " -I file: Set configuration file to use\n");
        !           769: #endif /* HAVE_TAYLOR_CONFIG */
        !           770: 
        !           771:   exit (EXIT_FAILURE);
        !           772: }
        !           773: 
        !           774: /* This function is called when a fatal error occurs.  */
        !           775: 
        !           776: static void
        !           777: ucuabort ()
        !           778: {
        !           779:   if (fCustarted)
        !           780:     {
        !           781:       fCustarted = FALSE;
        !           782:       (void) fsysdep_cu_finish ();
        !           783:     }
        !           784: 
        !           785:   if (fCurestore_terminal)
        !           786:     {
        !           787:       fCurestore_terminal = FALSE;
        !           788:       (void) fsysdep_terminal_restore ();
        !           789:     }
        !           790: 
        !           791:   if (qCuconn != NULL)
        !           792:     {
        !           793:       struct sconnection *qconn;
        !           794: 
        !           795:       if (fCuclose_conn)
        !           796:        {
        !           797:          fCuclose_conn = FALSE;
        !           798:          (void) fconn_close (qCuconn, pCuuuconf, qCudialer, FALSE);
        !           799:        }
        !           800:       qconn = qCuconn;
        !           801:       qCuconn = NULL;
        !           802:       (void) fconn_unlock (qconn);
        !           803:       uconn_free (qconn);
        !           804:     }
        !           805: 
        !           806:   ulog_close ();
        !           807: 
        !           808:   printf ("\n%s\n", ZDISMSG);
        !           809: 
        !           810:   usysdep_exit (FALSE);
        !           811: }
        !           812: 
        !           813: /* This variable is just used to communicate between uculog_start and
        !           814:    uculog_end.  */
        !           815: static boolean fCulog_restore;
        !           816: 
        !           817: /* This function is called by ulog before it output anything.  We use
        !           818:    it to restore the terminal, if necessary.  ulog is only called for
        !           819:    errors or debugging in cu, so it's not too costly to do this.  If
        !           820:    we didn't do it, then at least on Unix each line would leave the
        !           821:    cursor in the same column rather than wrapping back to the start,
        !           822:    since CRMOD will not be on.  */
        !           823: 
        !           824: static void
        !           825: uculog_start ()
        !           826: {
        !           827:   if (! fCurestore_terminal)
        !           828:     fCulog_restore = FALSE;
        !           829:   else
        !           830:     {
        !           831:       fCulog_restore = TRUE;
        !           832:       fCurestore_terminal = FALSE;
        !           833:       if (! fsysdep_terminal_restore ())
        !           834:        ucuabort ();
        !           835:     }
        !           836: }
        !           837: 
        !           838: /* This function is called by ulog after everything is output.  It
        !           839:    sets the terminal back, if necessary.  */
        !           840: 
        !           841: static void
        !           842: uculog_end ()
        !           843: {
        !           844:   if (fCulog_restore)
        !           845:     {
        !           846:       if (! fsysdep_terminal_raw (fCulocalecho))
        !           847:        ucuabort ();
        !           848:       fCurestore_terminal = TRUE;
        !           849:     }
        !           850: }
        !           851: 
        !           852: /* Check to see if this port has the desired line, to handle the -l
        !           853:    option.  If it does, or if no line was specified, set up a
        !           854:    connection and lock it.  */
        !           855: 
        !           856: static int
        !           857: icuport_lock (qport, pinfo)
        !           858:      struct uuconf_port *qport;
        !           859:      pointer pinfo;
        !           860: {
        !           861:   struct sconninfo *q = (struct sconninfo *) pinfo;
        !           862: 
        !           863:   if (q->zline != NULL
        !           864:       && ! fsysdep_port_is_line (qport, q->zline))
        !           865:     return UUCONF_NOT_FOUND;
        !           866: 
        !           867:   q->fmatched = TRUE;
        !           868: 
        !           869:   if (! fconn_init (qport, q->qconn))
        !           870:     return UUCONF_NOT_FOUND;
        !           871:   else if (! fconn_lock (q->qconn, FALSE))
        !           872:     {
        !           873:       uconn_free (q->qconn);
        !           874:       return UUCONF_NOT_FOUND;
        !           875:     }
        !           876:   else
        !           877:     {
        !           878:       qCuconn = q->qconn;
        !           879:       q->flocked = TRUE;
        !           880:       return UUCONF_SUCCESS;
        !           881:     }
        !           882: }
        !           883: 
        !           884: /* Execute a cu escape command.  Return TRUE if the connection should
        !           885:    continue, or FALSE if the connection should be terminated.  */
        !           886: 
        !           887: static boolean
        !           888: fcudo_cmd (puuconf, qconn, bcmd)
        !           889:      pointer puuconf;
        !           890:      struct sconnection *qconn;
        !           891:      int bcmd;
        !           892: {
        !           893:   char *zline;
        !           894:   char *z;
        !           895:   char abescape[5];
        !           896:   boolean fret;
        !           897:   size_t clen;
        !           898:   char abbuf[100];
        !           899: 
        !           900:   /* Some commands take a string up to the next newline character.  */
        !           901:   switch (bcmd)
        !           902:     {
        !           903:     default:
        !           904:       zline = NULL;
        !           905:       break;
        !           906:     case '!':
        !           907:     case '$':
        !           908:     case '|':
        !           909:     case '+':
        !           910:     case '%':
        !           911:     case 'c':
        !           912:     case '>':
        !           913:     case '<':
        !           914:     case 'p':
        !           915:     case 't':
        !           916:     case 's':
        !           917:       {
        !           918:        zline = zsysdep_terminal_line ((const char *) NULL);
        !           919:        if (zline == NULL)
        !           920:          ucuabort ();
        !           921:        zline[strcspn (zline, "\n")] = '\0';
        !           922:       }
        !           923:       break;
        !           924:     }
        !           925: 
        !           926:   switch (bcmd)
        !           927:     {
        !           928:     default:
        !           929:       if (! isprint (*zCuvar_escape))
        !           930:        sprintf (abescape, "\\%03o", (unsigned int) *zCuvar_escape);
        !           931:       else
        !           932:        {
        !           933:          abescape[0] = *zCuvar_escape;
        !           934:          abescape[1] = '\0';
        !           935:        }
        !           936:       sprintf (abbuf, "[Unrecognized.  Use %s%s to send %s]",
        !           937:               abescape, abescape, abescape);
        !           938:       ucuputs (abbuf);
        !           939:       return TRUE;
        !           940: 
        !           941:     case '.':
        !           942:       /* Hangup.  */
        !           943:       return FALSE;
        !           944: 
        !           945:     case '!':
        !           946:     case '$':
        !           947:     case '|':
        !           948:     case '+':
        !           949:       /* Shell out.  */
        !           950:       if (! fsysdep_cu_copy (FALSE)
        !           951:          || ! fsysdep_terminal_restore ())
        !           952:        ucuabort ();
        !           953:       fCurestore_terminal = FALSE;
        !           954:       {
        !           955:        enum tshell_cmd t;
        !           956: 
        !           957:        switch (bcmd)
        !           958:          {
        !           959:          default:
        !           960:          case '!': t = SHELL_NORMAL; break;
        !           961:          case '$': t = SHELL_STDOUT_TO_PORT; break;
        !           962:          case '|': t = SHELL_STDIN_FROM_PORT; break;
        !           963:          case '+': t = SHELL_STDIO_ON_PORT; break;
        !           964:          }
        !           965:          
        !           966:        (void) fsysdep_shell (qconn, zline, t);
        !           967:       }
        !           968:       if (! fsysdep_cu_copy (TRUE)
        !           969:          || ! fsysdep_terminal_raw (fCulocalecho))
        !           970:        ucuabort ();
        !           971:       fCurestore_terminal = TRUE;
        !           972:       ubuffree (zline);
        !           973:       return TRUE;
        !           974: 
        !           975:     case '%':
        !           976:       fret = fcudo_subcmd (puuconf, qconn, zline);
        !           977:       ubuffree (zline);
        !           978:       return fret;
        !           979: 
        !           980:     case '#':
        !           981:       if (! fconn_break (qconn))
        !           982:        ucuabort ();
        !           983:       return TRUE;
        !           984: 
        !           985:     case 'c':
        !           986:       (void) fsysdep_chdir (zline);
        !           987:       ubuffree (zline);
        !           988:       return TRUE;
        !           989: 
        !           990:     case '>':
        !           991:     case '<':
        !           992:     case 'p':
        !           993:     case 't':
        !           994:       clen = strlen (zline);
        !           995:       z = zbufalc (clen + 3);
        !           996:       z[0] = bcmd;
        !           997:       z[1] = ' ';
        !           998:       memcpy (z + 2, zline, clen + 1);
        !           999:       ubuffree (zline);
        !          1000:       fret = fcudo_subcmd (puuconf, qconn, z);
        !          1001:       ubuffree (z);
        !          1002:       return fret;
        !          1003: 
        !          1004:     case 'z':
        !          1005:       if (! fsysdep_cu_copy (FALSE)
        !          1006:          || ! fsysdep_terminal_restore ())
        !          1007:        ucuabort ();
        !          1008:       fCurestore_terminal = FALSE;
        !          1009:       if (! fsysdep_suspend ())
        !          1010:        ucuabort ();
        !          1011:       if (! fsysdep_cu_copy (TRUE)
        !          1012:          || ! fsysdep_terminal_raw (fCulocalecho))
        !          1013:        ucuabort ();
        !          1014:       fCurestore_terminal = TRUE;
        !          1015:       return TRUE;
        !          1016:       
        !          1017:     case 's':
        !          1018:       fret = fcuset_var (puuconf, zline);
        !          1019:       ubuffree (zline);
        !          1020:       return fret;
        !          1021: 
        !          1022:     case 'v':
        !          1023:       uculist_vars ();
        !          1024:       return TRUE;
        !          1025: 
        !          1026:     case '?':
        !          1027:       if (! isprint (*zCuvar_escape))
        !          1028:        sprintf (abescape, "\\%03o", (unsigned int) *zCuvar_escape);
        !          1029:       else
        !          1030:        {
        !          1031:          abescape[0] = *zCuvar_escape;
        !          1032:          abescape[1] = '\0';
        !          1033:        }
        !          1034:       ucuputs ("");
        !          1035:       ucuputs ("[Escape sequences]");
        !          1036:       sprintf (abbuf,
        !          1037:               "[%s. hangup]                   [%s!CMD run shell]",
        !          1038:               abescape, abescape);
        !          1039:       ucuputs (abbuf);
        !          1040:       sprintf (abbuf,
        !          1041:               "[%s$CMD stdout to remote]      [%s|CMD stdin from remote]",
        !          1042:               abescape, abescape);
        !          1043:       ucuputs (abbuf);
        !          1044:       sprintf (abbuf,
        !          1045:               "[%s+CMD stdin and stdout to remote]",
        !          1046:               abescape);
        !          1047:       ucuputs (abbuf);
        !          1048:       sprintf (abbuf,
        !          1049:               "[%s# send break]               [%scDIR change directory]",
        !          1050:               abescape, abescape);
        !          1051:       ucuputs (abbuf);
        !          1052:       sprintf (abbuf,
        !          1053:               "[%s> send file]                [%s< receive file]",
        !          1054:               abescape, abescape);
        !          1055:       ucuputs (abbuf);
        !          1056:       sprintf (abbuf,
        !          1057:               "[%spFROM TO send to Unix]      [%stFROM TO receive from Unix]",
        !          1058:               abescape, abescape);
        !          1059:       ucuputs (abbuf);
        !          1060:       sprintf (abbuf,
        !          1061:               "[%ssVAR VAL set variable]      [%ssVAR set boolean]",
        !          1062:               abescape, abescape);
        !          1063:       ucuputs (abbuf);
        !          1064:       sprintf (abbuf,
        !          1065:               "[%ss!VAR unset boolean]        [%sv list variables]",
        !          1066:               abescape, abescape);
        !          1067:       ucuputs (abbuf);
        !          1068: #ifdef SIGTSTP
        !          1069:       sprintf (abbuf,
        !          1070:               "[%sz suspend]",
        !          1071:               abescape);
        !          1072:       ucuputs (abbuf);
        !          1073: #endif
        !          1074:       uculist_fns (abescape);
        !          1075:       return TRUE;
        !          1076:     }
        !          1077: }
        !          1078: 
        !          1079: /* List ~% functions.  */
        !          1080: 
        !          1081: static void
        !          1082: uculist_fns (zescape)
        !          1083:      const char *zescape;
        !          1084: {
        !          1085:   char abbuf[100];
        !          1086: 
        !          1087:   sprintf (abbuf,
        !          1088:           "[%s%%break send break]         [%s%%cd DIR change directory]",
        !          1089:           zescape, zescape);
        !          1090:   ucuputs (abbuf);
        !          1091:   sprintf (abbuf,
        !          1092:           "[%s%%put FROM TO send file]    [%s%%take FROM TO receive file]",
        !          1093:           zescape, zescape);
        !          1094:   ucuputs (abbuf);
        !          1095:   sprintf (abbuf,
        !          1096:           "[%s%%nostop no XON/XOFF]       [%s%%stop use XON/XOFF]",
        !          1097:           zescape, zescape);
        !          1098:   ucuputs (abbuf);
        !          1099: }
        !          1100: 
        !          1101: /* Set a variable.  */
        !          1102: 
        !          1103: static boolean
        !          1104: fcuset_var (puuconf, zline)
        !          1105:      pointer puuconf;
        !          1106:      char *zline;
        !          1107: {
        !          1108:   char *zvar, *zval;
        !          1109:   char *azargs[2];
        !          1110:   char azbool[2];
        !          1111:   int iuuconf;
        !          1112: 
        !          1113:   zvar = strtok (zline, "= \t");
        !          1114:   if (zvar == NULL)
        !          1115:     {
        !          1116:       ucuputs (abCuconnected);
        !          1117:       return TRUE;
        !          1118:     }
        !          1119: 
        !          1120:   zval = strtok ((char *) NULL, " \t");
        !          1121: 
        !          1122:   if (zval == NULL)
        !          1123:     {
        !          1124:       azargs[0] = zvar;
        !          1125:       if (azargs[0][0] != '!')
        !          1126:        azbool[0] = 't';
        !          1127:       else
        !          1128:        {
        !          1129:          ++azargs[0];
        !          1130:          azbool[0] = 'f';
        !          1131:        }
        !          1132:       azbool[1] = '\0';
        !          1133:       azargs[1] = azbool;
        !          1134:     }
        !          1135:   else
        !          1136:     {
        !          1137:       azargs[0] = zvar;
        !          1138:       azargs[1] = zval;
        !          1139:     }
        !          1140: 
        !          1141:   iuuconf = uuconf_cmd_args (puuconf, 2, azargs, asCuvars,
        !          1142:                             (pointer) NULL, icuunrecogvar, 0,
        !          1143:                             (pointer) NULL);
        !          1144:   if (iuuconf != UUCONF_SUCCESS)
        !          1145:     ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1146: 
        !          1147:   return TRUE;
        !          1148: }
        !          1149: 
        !          1150: /* Warn about an unknown variable.  */
        !          1151: 
        !          1152: /*ARGSUSED*/
        !          1153: static int
        !          1154: icuunrecogvar (puuconf, argc, argv, pvar, pinfo)
        !          1155:      pointer puuconf;
        !          1156:      int argc;
        !          1157:      char **argv;
        !          1158:      pointer pvar;
        !          1159:      pointer pinfo;
        !          1160: {
        !          1161:   char abescape[5];
        !          1162: 
        !          1163:   if (! isprint (*zCuvar_escape))
        !          1164:     sprintf (abescape, "\\%03o", (unsigned int) *zCuvar_escape);
        !          1165:   else
        !          1166:     {
        !          1167:       abescape[0] = *zCuvar_escape;
        !          1168:       abescape[1] = '\0';
        !          1169:     }
        !          1170:   ulog (LOG_ERROR, "%s: unknown variable (%sv lists variables)",
        !          1171:        argv[0], abescape);
        !          1172:   return UUCONF_CMDTABRET_CONTINUE;
        !          1173: }
        !          1174: 
        !          1175: /* List all the variables with their values.  */
        !          1176: 
        !          1177: static void
        !          1178: uculist_vars ()
        !          1179: {
        !          1180:   const struct uuconf_cmdtab *q;
        !          1181:   char abbuf[100];
        !          1182: 
        !          1183:   ucuputs ("");
        !          1184:   for (q = asCuvars; q->uuconf_zcmd != NULL; q++)
        !          1185:     {
        !          1186:       switch (UUCONF_TTYPE_CMDTABTYPE (q->uuconf_itype))
        !          1187:        {
        !          1188:        case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_BOOLEAN):
        !          1189:          if (*(boolean *) q->uuconf_pvar)
        !          1190:            sprintf (abbuf, "%s true", q->uuconf_zcmd);
        !          1191:          else
        !          1192:            sprintf (abbuf, "%s false", q->uuconf_zcmd);
        !          1193:          break;
        !          1194: 
        !          1195:        case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_INT):
        !          1196:          sprintf (abbuf, "%s %d", q->uuconf_zcmd, *(int *) q->uuconf_pvar);
        !          1197:          break;
        !          1198: 
        !          1199:        case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_LONG):
        !          1200:          sprintf (abbuf, "%s %ld", q->uuconf_zcmd,
        !          1201:                   *(long *) q->uuconf_pvar);
        !          1202:          break;
        !          1203: 
        !          1204:        case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_STRING):
        !          1205:        case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_FULLSTRING):
        !          1206:          {
        !          1207:            const char *z;
        !          1208:            char abchar[5];
        !          1209:            size_t clen;
        !          1210: 
        !          1211:            sprintf (abbuf, "%s ", q->uuconf_zcmd);
        !          1212:            clen = strlen (abbuf);
        !          1213:            for (z = *(const char **) q->uuconf_pvar; *z != '\0'; z++)
        !          1214:              {
        !          1215:                int cchar;
        !          1216: 
        !          1217:                if (! isprint (*z))
        !          1218:                  {
        !          1219:                    sprintf (abchar, "\\%03o", (unsigned int) *z);
        !          1220:                    cchar = 4;
        !          1221:                  }
        !          1222:                else
        !          1223:                  {
        !          1224:                    abchar[0] = *z;
        !          1225:                    abchar[1] = '\0';
        !          1226:                    cchar = 1;
        !          1227:                  }
        !          1228:                if (clen + cchar < sizeof (abbuf))
        !          1229:                  strcat (abbuf, abchar);
        !          1230:                clen += cchar;
        !          1231:              }
        !          1232:          }
        !          1233:          break;
        !          1234: 
        !          1235:        default:
        !          1236:          sprintf (abbuf, "%s [unprintable type]", q->uuconf_zcmd);
        !          1237:          break;
        !          1238:        }
        !          1239: 
        !          1240:       ucuputs (abbuf);
        !          1241:     }
        !          1242: }
        !          1243: 
        !          1244: /* Subcommands.  These are commands that begin with ~%.  */
        !          1245: 
        !          1246: /* This variable is only used so that we can pass a non-NULL address
        !          1247:    in pvar.  It is never assigned to or examined.  */
        !          1248: 
        !          1249: static char bCutype;
        !          1250: 
        !          1251: /* The command table for the subcommands.  */
        !          1252: 
        !          1253: static int icubreak P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1254:                       pointer pinfo));
        !          1255: static int icudebug P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1256:                       pointer pinfo));
        !          1257: static int icuchdir P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1258:                       pointer pinfo));
        !          1259: static int icuput P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1260:                     pointer pinfo));
        !          1261: static int icutake P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1262:                      pointer pinfo));
        !          1263: static int icunostop P((pointer puuconf, int argc, char **argv, pointer pvar,
        !          1264:                        pointer pinfo));
        !          1265: 
        !          1266: static const struct uuconf_cmdtab asCucmds[] =
        !          1267: {
        !          1268:   { "break", UUCONF_CMDTABTYPE_FN | 1, NULL, icubreak },
        !          1269:   { "b", UUCONF_CMDTABTYPE_FN | 1, NULL, icubreak },
        !          1270:   { "cd", UUCONF_CMDTABTYPE_FN | 0, NULL, icuchdir },
        !          1271:   { "d", UUCONF_CMDTABTYPE_FN | 1, NULL, icudebug },
        !          1272:   { "put", UUCONF_CMDTABTYPE_FN | 0, NULL, icuput },
        !          1273:   { "take", UUCONF_CMDTABTYPE_FN | 0, NULL, icutake },
        !          1274:   { "nostop", UUCONF_CMDTABTYPE_FN | 1, NULL, icunostop },
        !          1275:   { "stop", UUCONF_CMDTABTYPE_FN | 1, &bCutype, icunostop },
        !          1276:   { ">", UUCONF_CMDTABTYPE_FN | 0, &bCutype, icuput },
        !          1277:   { "<", UUCONF_CMDTABTYPE_FN | 0, &bCutype, icutake },
        !          1278:   { "p", UUCONF_CMDTABTYPE_FN | 0, NULL, icuput },
        !          1279:   { "t", UUCONF_CMDTABTYPE_FN | 0, NULL, icutake },
        !          1280:   { NULL, 0, NULL, NULL }
        !          1281: };
        !          1282: 
        !          1283: /* Do a subcommand.  This is called by commands beginning with ~%.  */
        !          1284: 
        !          1285: static boolean
        !          1286: fcudo_subcmd (puuconf, qconn, zline)
        !          1287:      pointer puuconf;
        !          1288:      struct sconnection *qconn;
        !          1289:      char *zline;
        !          1290: {
        !          1291:   char *azargs[3];
        !          1292:   int iarg;
        !          1293:   int iuuconf;
        !          1294: 
        !          1295:   for (iarg = 0; iarg < 3; iarg++)
        !          1296:     {
        !          1297:       azargs[iarg] = strtok (iarg == 0 ? zline : (char *) NULL, " \t\n");
        !          1298:       if (azargs[iarg] == NULL)
        !          1299:        break;
        !          1300:     }
        !          1301: 
        !          1302:   if (iarg == 0)
        !          1303:     {
        !          1304:       ucuputs (abCuconnected);
        !          1305:       return TRUE;
        !          1306:     }
        !          1307: 
        !          1308:   iuuconf = uuconf_cmd_args (puuconf, iarg, azargs, asCucmds,
        !          1309:                             (pointer) qconn, icuunrecogfn,
        !          1310:                             0, (pointer) NULL);
        !          1311:   if (iuuconf != UUCONF_SUCCESS)
        !          1312:     ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
        !          1313: 
        !          1314:   return TRUE;
        !          1315: }
        !          1316: 
        !          1317: /* Warn about an unknown function.  */
        !          1318: 
        !          1319: /*ARGSUSED*/
        !          1320: static int
        !          1321: icuunrecogfn (puuconf, argc, argv, pvar, pinfo)
        !          1322:      pointer puuconf;
        !          1323:      int argc;
        !          1324:      char **argv;
        !          1325:      pointer pvar;
        !          1326:      pointer pinfo;
        !          1327: {
        !          1328:   char abescape[5];
        !          1329: 
        !          1330:   if (! isprint (*zCuvar_escape))
        !          1331:     sprintf (abescape, "\\%03o", (unsigned int) *zCuvar_escape);
        !          1332:   else
        !          1333:     {
        !          1334:       abescape[0] = *zCuvar_escape;
        !          1335:       abescape[1] = '\0';
        !          1336:     }
        !          1337:   if (argv[0][0] == '?')
        !          1338:     uculist_fns (abescape);
        !          1339:   else
        !          1340:     ulog (LOG_ERROR, "%s: unknown (%s%%? lists choices)",
        !          1341:          argv[0], abescape);
        !          1342:   return UUCONF_CMDTABRET_CONTINUE;
        !          1343: }
        !          1344: 
        !          1345: /* Send a break.  */
        !          1346: 
        !          1347: /*ARGSUSED*/
        !          1348: static int
        !          1349: icubreak (puuconf, argc, argv, pvar, pinfo)
        !          1350:      pointer puuconf;
        !          1351:      int argc;
        !          1352:      char **argv;
        !          1353:      pointer pvar;
        !          1354:      pointer pinfo;
        !          1355: {
        !          1356:   struct sconnection *qconn = (struct sconnection *) pinfo;
        !          1357: 
        !          1358:   if (! fconn_break (qconn))
        !          1359:     ucuabort ();
        !          1360:   return UUCONF_CMDTABRET_CONTINUE;
        !          1361: }
        !          1362: 
        !          1363: /* Change directories.  */
        !          1364: 
        !          1365: /*ARGSUSED*/
        !          1366: static int
        !          1367: icuchdir (puuconf, argc, argv, pvar, pinfo)
        !          1368:      pointer puuconf;
        !          1369:      int argc;
        !          1370:      char **argv;
        !          1371:      pointer pvar;
        !          1372:      pointer pinfo;
        !          1373: {
        !          1374:   const char *zarg;
        !          1375: 
        !          1376:   if (argc <= 1)
        !          1377:     zarg = NULL;
        !          1378:   else
        !          1379:     zarg = argv[1];
        !          1380:   (void) fsysdep_chdir (zarg);
        !          1381:   return UUCONF_CMDTABRET_CONTINUE;
        !          1382: }
        !          1383: 
        !          1384: /* Toggle debugging.  */
        !          1385: 
        !          1386: /*ARGSUSED*/
        !          1387: static int
        !          1388: icudebug (puuconf, argc, argv, pvar, pinfo)
        !          1389:      pointer puuconf;
        !          1390:      int argc;
        !          1391:      char **argv;
        !          1392:      pointer pvar;
        !          1393:      pointer pinfo;
        !          1394: {
        !          1395: #if DEBUG > 1
        !          1396:   if (iDebug != 0)
        !          1397:     iDebug = 0;
        !          1398:   else
        !          1399:     iDebug = DEBUG_MAX;
        !          1400: #else
        !          1401:   ucuputs ("[compiled without debugging]");
        !          1402: #endif
        !          1403:   return UUCONF_CMDTABRET_CONTINUE;
        !          1404: }
        !          1405: 
        !          1406: /* Control whether the port does xon/xoff handshaking.  If pvar is not
        !          1407:    NULL, this is "stop"; otherwise it is "nostop".  */
        !          1408: 
        !          1409: /*ARGSUSED*/
        !          1410: static int
        !          1411: icunostop (puuconf, argc, argv, pvar, pinfo)
        !          1412:      pointer puuconf;
        !          1413:      int argc;
        !          1414:      char **argv;
        !          1415:      pointer pvar;
        !          1416:      pointer pinfo;
        !          1417: {
        !          1418:   struct sconnection *qconn = (struct sconnection *) pinfo;
        !          1419: 
        !          1420:   if (! fconn_set (qconn, PARITYSETTING_DEFAULT, STRIPSETTING_DEFAULT,
        !          1421:                   pvar == NULL ? XONXOFF_OFF : XONXOFF_ON))
        !          1422:     ucuabort ();
        !          1423:   return UUCONF_CMDTABRET_CONTINUE;
        !          1424: }
        !          1425: 
        !          1426: /* Send a file to the remote system.  The first argument is the file
        !          1427:    to send.  If that argument is not present, it is prompted for.  The
        !          1428:    second argument is to file name to use on the remote system.  If
        !          1429:    that argument is not present, the basename of the local filename is
        !          1430:    used.  If pvar is not NULL, then this is ~>, which is used to send
        !          1431:    a command to a non-Unix system.  We treat is the same as ~%put,
        !          1432:    except that we assume the user has already entered the appropriate
        !          1433:    command (for ~%put, we force ``cat >to'' to the other side).  */
        !          1434: 
        !          1435: /*ARGSUSED*/
        !          1436: static int
        !          1437: icuput (puuconf, argc, argv, pvar, pinfo)
        !          1438:      pointer puuconf;
        !          1439:      int argc;
        !          1440:      char **argv;
        !          1441:      pointer pvar;
        !          1442:      pointer pinfo;
        !          1443: {
        !          1444:   struct sconnection *qconn = (struct sconnection *) pinfo;
        !          1445:   char *zfrom;
        !          1446:   char *zto = NULL;
        !          1447:   char *zalc;
        !          1448:   openfile_t e;
        !          1449:   int cline;
        !          1450:   char *zbuf;
        !          1451:   size_t cbuf;
        !          1452: 
        !          1453:   if (argc > 1)
        !          1454:     zfrom = zbufcpy (argv[1]);
        !          1455:   else
        !          1456:     {
        !          1457:       zfrom = zsysdep_terminal_line ("File to send: ");
        !          1458:       if (zfrom == NULL)
        !          1459:        ucuabort ();
        !          1460:       zfrom[strcspn (zfrom, " \t\n")] = '\0';
        !          1461: 
        !          1462:       if (*zfrom == '\0')
        !          1463:        {
        !          1464:          ubuffree (zfrom);
        !          1465:          ucuputs (abCuconnected);
        !          1466:          return UUCONF_CMDTABRET_CONTINUE;
        !          1467:        }
        !          1468:     }
        !          1469: 
        !          1470:   if (pvar == NULL)
        !          1471:     {
        !          1472:       if (argc > 2)
        !          1473:        zto = zbufcpy (argv[2]);
        !          1474:       else
        !          1475:        {
        !          1476:          char *zbase;
        !          1477:          char *zprompt;
        !          1478: 
        !          1479:          zbase = zsysdep_base_name (zfrom);
        !          1480:          if (zbase == NULL)
        !          1481:            ucuabort ();
        !          1482: 
        !          1483:          zprompt = zbufalc (sizeof "Remote file name []: " +
        !          1484:                             strlen (zbase));
        !          1485:          sprintf (zprompt, "Remote file name [%s]: ", zbase);
        !          1486:          zto = zsysdep_terminal_line (zprompt);
        !          1487:          ubuffree (zprompt);
        !          1488:          if (zto == NULL)
        !          1489:            ucuabort ();
        !          1490: 
        !          1491:          zto[strcspn (zto, " \t\n")] = '\0';
        !          1492:          if (*zto != '\0')
        !          1493:            ubuffree (zbase);
        !          1494:          else
        !          1495:            {
        !          1496:              ubuffree (zto);
        !          1497:              zto = zbase;
        !          1498:            }
        !          1499:        }
        !          1500:     }
        !          1501: 
        !          1502:   e = esysdep_user_fopen (zfrom, TRUE, fCuvar_binary);
        !          1503:   if (! ffileisopen (e))
        !          1504:     {
        !          1505:       const char *zerrstr;
        !          1506: 
        !          1507:       if (pvar == NULL)
        !          1508:        ubuffree (zto);
        !          1509:       zerrstr = strerror (errno);
        !          1510:       zalc = zbufalc (strlen (zfrom) + sizeof ": " + strlen (zerrstr));
        !          1511:       sprintf (zalc, "%s: %s", zfrom, zerrstr);
        !          1512:       ubuffree (zfrom);
        !          1513:       ucuputs (zalc);
        !          1514:       ubuffree (zalc);
        !          1515:       ucuputs (abCuconnected);
        !          1516:       return UUCONF_CMDTABRET_CONTINUE;
        !          1517:     }
        !          1518: 
        !          1519:   ubuffree (zfrom);
        !          1520: 
        !          1521:   /* Tell the system dependent layer to stop copying data from the
        !          1522:      port to the terminal.  We want to read the echoes ourself.  Also
        !          1523:      permit the local user to generate signals.  */
        !          1524:   if (! fsysdep_cu_copy (FALSE)
        !          1525:       || ! fsysdep_terminal_signals (TRUE))
        !          1526:     ucuabort ();
        !          1527: 
        !          1528:   /* If pvar is NULL, then we are sending a file to a Unix system.  We
        !          1529:      send over the command "cat > TO" to prepare it to receive.  If
        !          1530:      pvar is not NULL, the user is assumed to have set up whatever
        !          1531:      action was needed to receive the file.  */
        !          1532:   if (pvar == NULL)
        !          1533:     {
        !          1534:       boolean fret;
        !          1535: 
        !          1536:       zalc = zbufalc (sizeof "cat > \n" + strlen (zto));
        !          1537:       sprintf (zalc, "cat > %s\n", zto);
        !          1538:       ubuffree (zto);
        !          1539:       fret = fcusend_buf (qconn, zalc, strlen (zalc));
        !          1540:       ubuffree (zalc);
        !          1541:       if (! fret)
        !          1542:        {
        !          1543:          (void) ffileclose (e);
        !          1544:          if (! fsysdep_cu_copy (TRUE)
        !          1545:              || ! fsysdep_terminal_signals (FALSE))
        !          1546:            ucuabort ();
        !          1547:          ucuputs (abCuconnected);
        !          1548:          return UUCONF_CMDTABRET_CONTINUE;
        !          1549:        }
        !          1550:     }
        !          1551: 
        !          1552:   cline = 0;
        !          1553: 
        !          1554:   zbuf = NULL;
        !          1555:   cbuf = 0;
        !          1556: 
        !          1557:   while (TRUE)
        !          1558:     {
        !          1559:       char abbuf[512];
        !          1560:       size_t c;
        !          1561: 
        !          1562: #if USE_STDIO
        !          1563:       if (fCuvar_binary)
        !          1564: #endif
        !          1565:        {
        !          1566:          if (ffileeof (e))
        !          1567:            break;
        !          1568:          c = cfileread (e, abbuf, sizeof abbuf);
        !          1569:          if (ffilereaderror (e, c))
        !          1570:            {
        !          1571:              ucuputs ("[file read error]");
        !          1572:              break;
        !          1573:            }
        !          1574:          if (c == 0)
        !          1575:            break;
        !          1576:          zbuf = abbuf;
        !          1577:        }
        !          1578: #if USE_STDIO
        !          1579:       else
        !          1580:        {
        !          1581:          if (getline (&zbuf, &cbuf, e) <= 0)
        !          1582:            {
        !          1583:              xfree ((pointer) zbuf);
        !          1584:              break;
        !          1585:            }
        !          1586:          c = strlen (zbuf);
        !          1587:        }
        !          1588: #endif
        !          1589: 
        !          1590:       if (fCuvar_verbose)
        !          1591:        {
        !          1592:          ++cline;
        !          1593:          printf ("%d ", cline);
        !          1594:          (void) fflush (stdout);
        !          1595:        }
        !          1596: 
        !          1597:       if (! fcusend_buf (qconn, zbuf, c))
        !          1598:        {
        !          1599:          if (! fCuvar_binary)
        !          1600:            xfree ((pointer) zbuf);
        !          1601:          (void) fclose (e);
        !          1602:          if (! fsysdep_cu_copy (TRUE)
        !          1603:              || ! fsysdep_terminal_signals (FALSE))
        !          1604:            ucuabort ();
        !          1605:          ucuputs (abCuconnected);
        !          1606:          return UUCONF_CMDTABRET_CONTINUE;
        !          1607:        }
        !          1608:     }
        !          1609: 
        !          1610:   (void) ffileclose (e);
        !          1611: 
        !          1612:   if (pvar == NULL)
        !          1613:     {
        !          1614:       char beof;
        !          1615: 
        !          1616:       beof = '\004';
        !          1617:       if (! fconn_write (qconn, &beof, 1))
        !          1618:        ucuabort ();
        !          1619:     }
        !          1620:   else
        !          1621:     {
        !          1622:       if (*zCuvar_eofwrite != '\0')
        !          1623:        {
        !          1624:          if (! fconn_write (qconn, zCuvar_eofwrite,
        !          1625:                             strlen (zCuvar_eofwrite)))
        !          1626:            ucuabort ();
        !          1627:        }
        !          1628:     }
        !          1629: 
        !          1630:   if (fCuvar_verbose)
        !          1631:     ucuputs ("");
        !          1632: 
        !          1633:   ucuputs ("[file transfer complete]");
        !          1634: 
        !          1635:   if (! fsysdep_cu_copy (TRUE)
        !          1636:       || ! fsysdep_terminal_signals (FALSE))
        !          1637:     ucuabort ();
        !          1638: 
        !          1639:   ucuputs (abCuconnected);
        !          1640:   return UUCONF_CMDTABRET_CONTINUE;
        !          1641: }
        !          1642: 
        !          1643: /* Get a file from the remote side.  This is ~%take, or ~t, or ~<.
        !          1644:    The first two are assumed to be taking the file from a Unix system,
        !          1645:    so we force the command "cat FROM; echo  */
        !          1646: 
        !          1647: /*ARGSUSED*/
        !          1648: static int
        !          1649: icutake (puuconf, argc, argv, pvar, pinfo)
        !          1650:      pointer puuconf;
        !          1651:      int argc;
        !          1652:      char **argv;
        !          1653:      pointer pvar;
        !          1654:      pointer pinfo;
        !          1655: {
        !          1656:   struct sconnection *qconn = (struct sconnection *) pinfo;
        !          1657:   const char *zeof;
        !          1658:   char *zfrom, *zto, *zcmd;
        !          1659:   char *zalc;
        !          1660:   openfile_t e;
        !          1661:   char bcr;
        !          1662:   size_t ceoflen;
        !          1663:   char *zlook = NULL;
        !          1664:   size_t ceofhave;
        !          1665:   boolean ferr;
        !          1666: 
        !          1667:   if (argc > 1)
        !          1668:     zfrom = zbufcpy (argv[1]);
        !          1669:   else
        !          1670:     {
        !          1671:       zfrom = zsysdep_terminal_line ("Remote file to retreive: ");
        !          1672:       if (zfrom == NULL)
        !          1673:        ucuabort ();
        !          1674:       zfrom[strcspn (zfrom, " \t\n")] = '\0';
        !          1675:       if (*zfrom == '\0')
        !          1676:        {
        !          1677:          ubuffree (zfrom);
        !          1678:          ucuputs (abCuconnected);
        !          1679:          return UUCONF_CMDTABRET_CONTINUE;
        !          1680:        }
        !          1681:     }
        !          1682: 
        !          1683:   if (argc > 2)
        !          1684:     zto = zbufcpy (argv[2]);
        !          1685:   else
        !          1686:     {
        !          1687:       char *zbase;
        !          1688:       char *zprompt;
        !          1689: 
        !          1690:       zbase = zsysdep_base_name (zfrom);
        !          1691:       if (zbase == NULL)
        !          1692:        ucuabort ();
        !          1693: 
        !          1694:       zprompt = zbufalc (sizeof "Local file name []: " + strlen (zbase));
        !          1695:       sprintf (zprompt, "Local file name [%s]: ", zbase);
        !          1696:       zto = zsysdep_terminal_line (zprompt);
        !          1697:       ubuffree (zprompt);
        !          1698:       if (zto == NULL)
        !          1699:        ucuabort ();
        !          1700: 
        !          1701:       zto[strcspn (zto, " \t\n")] = '\0';
        !          1702:       if (*zto != '\0')
        !          1703:        ubuffree (zbase);
        !          1704:       else
        !          1705:        {
        !          1706:          ubuffree (zto);
        !          1707:          zto = zbase;
        !          1708:        }
        !          1709:     }
        !          1710: 
        !          1711:   if (pvar != NULL)
        !          1712:     {
        !          1713:       zcmd = zsysdep_terminal_line ("Remote command to execute: ");
        !          1714:       if (zcmd == NULL)
        !          1715:        ucuabort ();
        !          1716:       zcmd[strcspn (zcmd, "\n")] = '\0';
        !          1717:       zeof = zCuvar_eofread;
        !          1718:     }
        !          1719:   else
        !          1720:     {
        !          1721:       zcmd = zbufalc (sizeof "cat ; echo; echo ////cuend////"
        !          1722:                      + strlen (zfrom));
        !          1723:       sprintf (zcmd, "cat %s; echo; echo ////cuend////", zfrom);
        !          1724:       zeof = "\n////cuend////\n";
        !          1725:     }
        !          1726: 
        !          1727:   ubuffree (zfrom);
        !          1728: 
        !          1729:   e = esysdep_user_fopen (zto, FALSE, fCuvar_binary);
        !          1730:   if (! ffileisopen (e))
        !          1731:     {
        !          1732:       const char *zerrstr;
        !          1733: 
        !          1734:       ubuffree (zcmd);
        !          1735:       zerrstr = strerror (errno);
        !          1736:       zalc = zbufalc (strlen (zto) + sizeof ": " + strlen (zerrstr));
        !          1737:       sprintf (zalc, "%s: %s\n", zto, zerrstr);
        !          1738:       ucuputs (zalc);
        !          1739:       ubuffree (zalc);
        !          1740:       ucuputs (abCuconnected);
        !          1741:       ubuffree (zto);
        !          1742:       return UUCONF_CMDTABRET_CONTINUE;
        !          1743:     }
        !          1744: 
        !          1745:   ubuffree (zto);
        !          1746: 
        !          1747:   if (! fsysdep_cu_copy (FALSE)
        !          1748:       || ! fsysdep_terminal_signals (TRUE))
        !          1749:     ucuabort ();
        !          1750: 
        !          1751:   if (! fconn_write (qconn, zcmd, strlen (zcmd)))
        !          1752:     ucuabort ();
        !          1753:   bcr = '\r';
        !          1754:   if (! fconn_write (qconn, &bcr, 1))
        !          1755:     ucuabort ();
        !          1756: 
        !          1757:   ubuffree (zcmd);
        !          1758: 
        !          1759:   /* Eliminated any previously echoed data to avoid confusion.  */
        !          1760:   iPrecstart = 0;
        !          1761:   iPrecend = 0;
        !          1762: 
        !          1763:   /* If we're dealing with a Unix system, we can reliably discard the
        !          1764:      command.  Otherwise, the command will probably wind up in the
        !          1765:      file; too bad.  */
        !          1766:   if (pvar == NULL)
        !          1767:     {
        !          1768:       int b;
        !          1769: 
        !          1770:       while ((b = breceive_char (qconn, cCuvar_timeout, TRUE)) != '\n')
        !          1771:        {
        !          1772:          if (b == -2)
        !          1773:            ucuabort ();
        !          1774:          if (b < 0)
        !          1775:            {
        !          1776:              ucuputs ("[timed out waiting for newline]");
        !          1777:              ucuputs (abCuconnected);
        !          1778:              return UUCONF_CMDTABRET_CONTINUE;
        !          1779:            }
        !          1780:        }
        !          1781:     }
        !          1782: 
        !          1783:   ceoflen = strlen (zeof);
        !          1784:   zlook = zbufalc (ceoflen);
        !          1785:   ceofhave = 0;
        !          1786:   ferr = FALSE;
        !          1787: 
        !          1788:   while (TRUE)
        !          1789:     {
        !          1790:       int b;
        !          1791: 
        !          1792:       if (FGOT_SIGNAL ())
        !          1793:        {
        !          1794:          /* Make sure the signal is logged.  */
        !          1795:          ulog (LOG_ERROR, (const char *) NULL);
        !          1796:          ucuputs ("[file receive aborted]");
        !          1797:          /* Reset the SIGINT flag so that it does not confuse us in
        !          1798:             the future.  */
        !          1799:          afSignal[INDEXSIG_SIGINT] = FALSE;
        !          1800:          break;
        !          1801:        }       
        !          1802: 
        !          1803:       b = breceive_char (qconn, cCuvar_timeout, TRUE);
        !          1804:       if (b == -2)
        !          1805:        ucuabort ();
        !          1806:       if (b < 0)
        !          1807:        {
        !          1808:          if (ceofhave > 0)
        !          1809:            (void) fwrite (zlook, sizeof (char), ceofhave, e);
        !          1810:          ucuputs ("[timed out]");
        !          1811:          break;
        !          1812:        }
        !          1813: 
        !          1814:       if (ceoflen == 0)
        !          1815:        {
        !          1816:          if (cfilewrite (e, &b, 1) != 1)
        !          1817:            {
        !          1818:              ferr = TRUE;
        !          1819:              break;
        !          1820:            }
        !          1821:        }
        !          1822:       else
        !          1823:        {
        !          1824:          zlook[ceofhave] = b;
        !          1825:          ++ceofhave;
        !          1826:          if (ceofhave == ceoflen)
        !          1827:            {
        !          1828:              size_t cmove;
        !          1829:              char *zmove;
        !          1830: 
        !          1831:              if (memcmp (zeof, zlook, ceoflen) == 0)
        !          1832:                {
        !          1833:                  ucuputs ("[file transfer complete]");
        !          1834:                  break;
        !          1835:                }
        !          1836: 
        !          1837:              if (cfilewrite (e, zlook, 1) != 1)
        !          1838:                {
        !          1839:                  ferr = TRUE;
        !          1840:                  break;
        !          1841:                }
        !          1842: 
        !          1843:              zmove = zlook;
        !          1844:              for (cmove = ceoflen - 1, zmove = zlook;
        !          1845:                   cmove > 0;
        !          1846:                   cmove--, zmove++)
        !          1847:                zmove[0] = zmove[1];
        !          1848: 
        !          1849:              --ceofhave;
        !          1850:            }
        !          1851:        }
        !          1852:     }
        !          1853: 
        !          1854:   ubuffree (zlook);
        !          1855: 
        !          1856:   if (! ffileclose (e))
        !          1857:     ferr = TRUE;
        !          1858:   if (ferr)
        !          1859:     ucuputs ("[file write error]");
        !          1860: 
        !          1861:   if (! fsysdep_cu_copy (TRUE)
        !          1862:       || ! fsysdep_terminal_signals (FALSE))
        !          1863:     ucuabort ();
        !          1864: 
        !          1865:   ucuputs (abCuconnected);
        !          1866: 
        !          1867:   return UUCONF_CMDTABRET_CONTINUE;
        !          1868: }
        !          1869: 
        !          1870: /* Send a buffer to the remote system.  If fCuvar_binary is FALSE,
        !          1871:    each buffer passed in will be a single line; in this case we can
        !          1872:    check the echoed characters and kill the line if they do not match.
        !          1873:    This returns FALSE if an echo check fails.  If a port error
        !          1874:    occurrs, it calls ucuabort.  */
        !          1875: 
        !          1876: static boolean
        !          1877: fcusend_buf (qconn, zbufarg, cbufarg)
        !          1878:      struct sconnection *qconn;
        !          1879:      const char *zbufarg;
        !          1880:      size_t cbufarg;
        !          1881: {
        !          1882:   const char *zbuf;
        !          1883:   size_t cbuf;
        !          1884:   int ctries;
        !          1885:   size_t cbplen;
        !          1886:   char *zsendbuf;
        !          1887: 
        !          1888:   zbuf = zbufarg;
        !          1889:   cbuf = cbufarg;
        !          1890:   ctries = 0;
        !          1891: 
        !          1892:   if (fCuvar_binary)
        !          1893:     cbplen = strlen (zCuvar_binary_prefix);
        !          1894:   else
        !          1895:     cbplen = 1;
        !          1896:   zsendbuf = zbufalc (64 * (cbplen + 1));
        !          1897: 
        !          1898:   /* Loop while we still have characters to send.  The value of cbuf
        !          1899:      will be reset to cbufarg if an echo failure occurs while sending
        !          1900:      a line in non-binary mode.  */
        !          1901:   while (cbuf > 0)
        !          1902:     {
        !          1903:       int csend;
        !          1904:       char *zput;
        !          1905:       const char *zget;
        !          1906:       boolean fnl;
        !          1907:       int i;
        !          1908: 
        !          1909:       if (FGOT_SIGNAL ())
        !          1910:        {
        !          1911:          /* Make sure the signal is logged.  */
        !          1912:          ubuffree (zsendbuf);
        !          1913:          ulog (LOG_ERROR, (const char *) NULL);
        !          1914:          ucuputs ("[file send aborted]");
        !          1915:          /* Reset the SIGINT flag so that it does not confuse us in
        !          1916:             the future.  */
        !          1917:          afSignal[INDEXSIG_SIGINT] = FALSE;
        !          1918:          return FALSE;
        !          1919:        }
        !          1920: 
        !          1921:       /* Discard anything we've read from the port up to now, to avoid
        !          1922:         confusing the echo checking.  */
        !          1923:       iPrecstart = 0;
        !          1924:       iPrecend = 0;
        !          1925: 
        !          1926:       /* Send all characters up to a newline before actually sending
        !          1927:         the newline.  This makes it easier to handle the special
        !          1928:         newline echo checking.  Send up to 64 characters at a time
        !          1929:         before doing echo checking.  */
        !          1930:       if (*zbuf == '\n')
        !          1931:        csend = 1;
        !          1932:       else
        !          1933:        {
        !          1934:          const char *znl;
        !          1935: 
        !          1936:          znl = memchr (zbuf, '\n', cbuf);
        !          1937:          if (znl == NULL)
        !          1938:            csend = cbuf;
        !          1939:          else
        !          1940:            csend = znl - zbuf;
        !          1941:          if (csend > 64)
        !          1942:            csend = 64;
        !          1943:        }
        !          1944: 
        !          1945:       /* Translate this part of the buffer.  If we are not in binary
        !          1946:         mode, we translate \n to \r, and ignore any nonprintable
        !          1947:         characters.  */
        !          1948:       zput = zsendbuf;
        !          1949:       fnl = FALSE;
        !          1950:       for (i = 0, zget = zbuf; i < csend; i++, zget++)
        !          1951:        {
        !          1952:          if (isprint (*zget)
        !          1953:              || *zget == '\t')
        !          1954:            *zput++ = *zget;
        !          1955:          else if (*zget == '\n')
        !          1956:            {
        !          1957:              if (fCuvar_binary)
        !          1958:                *zput++ = '\n';
        !          1959:              else
        !          1960:                *zput++ = '\r';
        !          1961:              fnl = TRUE;
        !          1962:            }
        !          1963:          else if (fCuvar_binary)
        !          1964:            {
        !          1965:              strcpy (zput, zCuvar_binary_prefix);
        !          1966:              zput += cbplen;
        !          1967:              *zput++ = *zget;
        !          1968:            }
        !          1969:        }
        !          1970:                
        !          1971:       zbuf += csend;
        !          1972:       cbuf -= csend;
        !          1973: 
        !          1974:       if (zput == zsendbuf)
        !          1975:        continue;
        !          1976: 
        !          1977:       /* Send the data over the port.  */
        !          1978:       if (! fsend_data (qconn, zsendbuf, (size_t) (zput - zsendbuf), TRUE))
        !          1979:        ucuabort ();
        !          1980: 
        !          1981:       /* We do echo checking if requested, unless we are in binary
        !          1982:         mode.  Echo checking of a newline is different from checking
        !          1983:         of normal characters; when we send a newline we look for
        !          1984:         *zCuvar_echonl.  */
        !          1985:       if ((fCuvar_echocheck && ! fCuvar_binary)
        !          1986:          || (fnl && *zCuvar_echonl != '\0'))
        !          1987:        {
        !          1988:          long iend;
        !          1989: 
        !          1990:          iend = ixsysdep_time ((long *) NULL) + (long) cCuvar_timeout;
        !          1991:          for (zget = zsendbuf; zget < zput; zget++)
        !          1992:            {
        !          1993:              int bread;
        !          1994:              int bwant;
        !          1995: 
        !          1996:              if (fCuvar_binary ? *zget == '\n' : *zget == '\r')
        !          1997:                {
        !          1998:                  bwant = *zCuvar_echonl;
        !          1999:                  if (bwant == '\0')
        !          2000:                    continue;
        !          2001:                }
        !          2002:              else
        !          2003:                {
        !          2004:                  if (! fCuvar_echocheck || ! isprint (*zget))
        !          2005:                    continue;
        !          2006:                  bwant = *zget;
        !          2007:                }
        !          2008: 
        !          2009:              do
        !          2010:                {
        !          2011:                  if (FGOT_SIGNAL ())
        !          2012:                    {
        !          2013:                      /* Make sure the signal is logged.  */
        !          2014:                      ubuffree (zsendbuf);
        !          2015:                      ulog (LOG_ERROR, (const char *) NULL);
        !          2016:                      ucuputs ("[file send aborted]");
        !          2017:                      /* Reset the SIGINT flag so that it does not
        !          2018:                         confuse us in the future.  */
        !          2019:                      afSignal[INDEXSIG_SIGINT] = FALSE;
        !          2020:                      return FALSE;
        !          2021:                    }
        !          2022: 
        !          2023:                  bread = breceive_char (qconn,
        !          2024:                                         iend - ixsysdep_time ((long *) NULL),
        !          2025:                                         TRUE);
        !          2026:                  if (bread < 0)
        !          2027:                    {
        !          2028:                      if (bread == -2)
        !          2029:                        ucuabort ();
        !          2030: 
        !          2031:                      /* If we timed out, and we're not in binary
        !          2032:                         mode, we kill the line and try sending it
        !          2033:                         again from the beginning.  */
        !          2034:                      if (! fCuvar_binary && *zCuvar_kill != '\0')
        !          2035:                        {
        !          2036:                          ++ctries;
        !          2037:                          if (ctries < cCuvar_resend)
        !          2038:                            {
        !          2039:                              if (fCuvar_verbose)
        !          2040:                                {
        !          2041:                                  printf ("R ");
        !          2042:                                  (void) fflush (stdout);
        !          2043:                                }
        !          2044:                              if (! fsend_data (qconn, zCuvar_kill, 1,
        !          2045:                                                TRUE))
        !          2046:                                ucuabort ();
        !          2047:                              zbuf = zbufarg;
        !          2048:                              cbuf = cbufarg;
        !          2049:                              break;
        !          2050:                            }
        !          2051:                        }
        !          2052:                      ubuffree (zsendbuf);
        !          2053:                      ucuputs ("[timed out looking for echo]");
        !          2054:                      return FALSE;
        !          2055:                    }
        !          2056:                }
        !          2057:              while (bread != *zget);
        !          2058: 
        !          2059:              if (bread < 0)
        !          2060:                break;
        !          2061:            }
        !          2062:        }
        !          2063:     }
        !          2064: 
        !          2065:   ubuffree (zsendbuf);
        !          2066: 
        !          2067:   return TRUE;
        !          2068: }

unix.superglobalmegacorp.com

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