diff options
Diffstat (limited to 'gnu/libexec/uucp/cu/cu.c')
-rw-r--r-- | gnu/libexec/uucp/cu/cu.c | 2186 |
1 files changed, 0 insertions, 2186 deletions
diff --git a/gnu/libexec/uucp/cu/cu.c b/gnu/libexec/uucp/cu/cu.c deleted file mode 100644 index 3b41df3a28ac..000000000000 --- a/gnu/libexec/uucp/cu/cu.c +++ /dev/null @@ -1,2186 +0,0 @@ -/* cu.c - Call up a remote system. - - Copyright (C) 1992, 1993, 1994, 1995 Ian Lance Taylor - - This file is part of the Taylor UUCP package. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The author of the program may be contacted at ian@airs.com or - c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144. - */ - -#include "uucp.h" - -#if USE_RCS_ID -const char cu_rcsid[] = "$FreeBSD$"; -#endif - -#include "cu.h" -#include "uudefs.h" -#include "uuconf.h" -#include "conn.h" -#include "prot.h" -#include "system.h" -#include "sysdep.h" -#include "getopt.h" - -#include <stdio.h> -#include <ctype.h> -#include <errno.h> - -/* Here are the user settable variables. The user is permitted to - change these while running the program, using ~s. */ - -/* The escape character used to introduce a special command. The - escape character is the first character of this string. */ -const char *zCuvar_escape = "~"; - -/* Whether to delay for a second before printing the host name after - seeing an escape character. */ -boolean fCuvar_delay = TRUE; - -/* The input characters which finish a line. The escape character is - only recognized following one of these characters. The default is - carriage return, ^U, ^C, ^O, ^D, ^S, ^Q, ^R, which I got from the - Ultrix /etc/remote file. */ -const char *zCuvar_eol = "\r\025\003\017\004\023\021\022"; - -/* Whether to transfer binary data (nonprintable characters other than - newline and tab) when sending a file. If this is FALSE, then - newline is changed to carriage return. */ -boolean fCuvar_binary = FALSE; - -/* A prefix string to use before sending a binary character from a - file; this is only used if fCuvar_binary is TRUE. The default is - ^V. */ -const char *zCuvar_binary_prefix = "\026"; - -/* Whether to check for echoes of characters sent when sending a file. - This is ignored if fCuvar_binary is TRUE. */ -boolean fCuvar_echocheck = FALSE; - -/* A character to look for after each newline is sent when sending a - file. The character is the first character in this string, except - that a '\0' means that no echo check is done. */ -const char *zCuvar_echonl = "\r"; - -/* The timeout to use when looking for an character. */ -int cCuvar_timeout = 30; - -/* The character to use to kill a line if an echo check fails. The - first character in this string is sent. The default is ^U. */ -const char *zCuvar_kill = "\025"; - -/* The number of times to try resending a line if the echo check keeps - failing. */ -int cCuvar_resend = 10; - -/* The string to send at the end of a file sent with ~>. The default - is ^D. */ -const char *zCuvar_eofwrite = "\004"; - -/* The string to look for to finish a file received with ~<. For tip - this is a collection of single characters, but I don't want to do - that because it means that there are characters which cannot be - received. The default is a guess at a typical shell prompt. */ -const char *zCuvar_eofread = "$"; - -/* Whether to provide verbose information when sending or receiving a - file. */ -boolean fCuvar_verbose = TRUE; - -/* The table used to give a value to a variable, and to print all the - variable values. */ - -static const struct uuconf_cmdtab asCuvars[] = -{ - { "escape", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_escape, NULL }, - { "delay", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_delay, NULL }, - { "eol", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eol, NULL }, - { "binary", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_binary, NULL }, - { "binary-prefix", UUCONF_CMDTABTYPE_STRING, - (pointer) &zCuvar_binary_prefix, NULL }, - { "echocheck", UUCONF_CMDTABTYPE_BOOLEAN, - (pointer) &fCuvar_echocheck, NULL }, - { "echonl", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_echonl, NULL }, - { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cCuvar_timeout, NULL }, - { "kill", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_kill, NULL }, - { "resend", UUCONF_CMDTABTYPE_INT, (pointer) &cCuvar_resend, NULL }, - { "eofwrite", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eofwrite, NULL }, - { "eofread", UUCONF_CMDTABTYPE_STRING, (pointer) &zCuvar_eofread, NULL }, - { "verbose", UUCONF_CMDTABTYPE_BOOLEAN, (pointer) &fCuvar_verbose, NULL }, - { NULL, 0, NULL, NULL} -}; - -/* The string printed at the initial connect. */ -#if ANSI_C -#define ZCONNMSG "\aConnected." -#else -#define ZCONNMSG "Connected." -#endif - -/* The string printed when disconnecting. */ -#if ANSI_C -#define ZDISMSG "\aDisconnected." -#else -#define ZDISMSG "Disconnected." -#endif - -/* Local variables. */ - -/* The string we print when the user is once again connected to the - port after transferring a file or taking some other action. */ -static const char abCuconnected[] -#if ANSI_C - = "\a[connected]"; -#else - = "[connected]"; -#endif - -/* Global uuconf pointer. */ -static pointer pCuuuconf; - -/* Connection. */ -static struct sconnection *qCuconn; - -/* Whether to close the connection. */ -static boolean fCuclose_conn; - -/* Dialer used to dial out. */ -static struct uuconf_dialer *qCudialer; - -/* Whether we need to restore the terminal. */ -static boolean fCurestore_terminal; - -/* Whether we are doing local echoing. */ -static boolean fCulocalecho; - -/* Whether we need to call fsysdep_cu_finish. */ -static boolean fCustarted; - -/* Whether ZCONNMSG has been printed yet. */ -static boolean fCuconnprinted = FALSE; - -/* A structure used to pass information to icuport_lock. */ -struct sconninfo -{ - boolean fmatched; - boolean flocked; - struct sconnection *qconn; - const char *zline; -}; - -/* Local functions. */ - -static void ucuusage P((void)); -static void ucuhelp P((void)); -static void ucuabort P((void)); -static void uculog_start P((void)); -static void uculog_end P((void)); -static int icuport_lock P((struct uuconf_port *qport, pointer pinfo)); -static boolean fcudo_cmd P((pointer puuconf, struct sconnection *qconn, - int bcmd)); -static boolean fcuset_var P((pointer puuconf, char *zline)); -static int icuunrecogvar P((pointer puuconf, int argc, char **argv, - pointer pvar, pointer pinfo)); -static int icuunrecogfn P((pointer puuconf, int argc, char **argv, - pointer pvar, pointer pinfo)); -static void uculist_vars P((void)); -static void uculist_fns P((const char *zescape)); -static boolean fcudo_subcmd P((pointer puuconf, struct sconnection *qconn, - char *zline)); -static boolean fcusend_buf P((struct sconnection *qconn, const char *zbuf, - size_t cbuf)); - -#define ucuputs(zline) \ - do { if (! fsysdep_terminal_puts (zline)) ucuabort (); } while (0) - -/* Long getopt options. */ -static const struct option asCulongopts[] = -{ - { "phone", required_argument, NULL, 'c' }, - { "escape", required_argument, NULL, 'E' }, - { "parity", required_argument, NULL, 2 }, - { "halfduplex", no_argument, NULL, 'h' }, - { "prompt", no_argument, NULL, 'n' }, - { "line", required_argument, NULL, 'l' }, - { "port", required_argument, NULL, 'p' }, - { "speed", required_argument, NULL, 's' }, - { "baud", required_argument, NULL, 's' }, - { "mapcr", no_argument, NULL, 't' }, - { "nostop", no_argument, NULL, 3 }, - { "system", required_argument, NULL, 'z' }, - { "config", required_argument, NULL, 'I' }, - { "debug", required_argument, NULL, 'x' }, - { "version", no_argument, NULL, 'v' }, - { "help", no_argument, NULL, 1 }, - { NULL, 0, NULL, 0 } -}; - -int -main (argc, argv) - int argc; - char **argv; -{ - /* -c: phone number. */ - char *zphone = NULL; - /* -e: even parity. */ - boolean feven = FALSE; - /* -l: line. */ - char *zline = NULL; - /* -n: prompt for phone number. */ - boolean fprompt = FALSE; - /* -o: odd parity. */ - boolean fodd = FALSE; - /* -p: port name. */ - const char *zport = NULL; - /* -s: speed. */ - long ibaud = 0L; - /* -t: map cr to crlf. */ - boolean fmapcr = FALSE; - /* -z: system. */ - const char *zsystem = NULL; - /* --nostop: turn off XON/XOFF. */ - enum txonxoffsetting txonxoff = XONXOFF_ON; - /* -I: configuration file name. */ - const char *zconfig = NULL; - int iopt; - pointer puuconf; - int iuuconf; - const char *zlocalname; - int i; - struct uuconf_system ssys; - const struct uuconf_system *qsys = NULL; - boolean flooped; - struct uuconf_port sport; - struct sconnection sconn; - struct sconninfo sinfo; - long ihighbaud; - struct uuconf_dialer sdialer; - struct uuconf_dialer *qdialer; - char bcmd; - - zProgram = argv[0]; - - /* We want to accept -# as a speed. It's easiest to look through - the arguments, replace -# with -s#, and let getopt handle it. */ - for (i = 1; i < argc; i++) - { - if (argv[i][0] == '-' - && isdigit (BUCHAR (argv[i][1]))) - { - size_t clen; - char *z; - - clen = strlen (argv[i]); - z = zbufalc (clen + 2); - z[0] = '-'; - z[1] = 's'; - memcpy (z + 2, argv[i] + 1, clen); - argv[i] = z; - } - } - - while ((iopt = getopt_long (argc, argv, "a:c:deE:hnI:l:op:s:tvx:z:", - asCulongopts, (int *) NULL)) != EOF) - { - switch (iopt) - { - case 'c': - /* Phone number. */ - zphone = optarg; - break; - - case 'd': - /* Set debugging level to maximum. */ -#if DEBUG > 1 - iDebug = DEBUG_MAX; -#endif - break; - - case 'e': - /* Even parity. */ - feven = TRUE; - break; - - case 'E': - /* Escape character. */ - zCuvar_escape = optarg; - break; - - case 'h': - /* Local echo. */ - fCulocalecho = TRUE; - break; - - case 'n': - /* Prompt for phone number. */ - fprompt = TRUE; - break; - - case 'l': - /* Line name. */ - zline = optarg; - break; - - case 'o': - /* Odd parity. */ - fodd = TRUE; - break; - - case 'p': - case 'a': - /* Port name (-a is for compatibility). */ - zport = optarg; - break; - - case 's': - /* Speed. */ - ibaud = strtol (optarg, (char **) NULL, 10); - break; - - case 't': - /* Map cr to crlf. */ - fmapcr = TRUE; - break; - - case 'z': - /* System name. */ - zsystem = optarg; - break; - - case 'I': - /* Configuration file name. */ - if (fsysdep_other_config (optarg)) - zconfig = optarg; - break; - - case 'x': -#if DEBUG > 1 - /* Set debugging level. */ - iDebug |= idebug_parse (optarg); -#endif - break; - - case 'v': - /* Print version and exit. */ - fprintf - (stderr, - "%s: Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n", - zProgram, VERSION); - exit (EXIT_SUCCESS); - /*NOTREACHED*/ - - case 2: - /* --parity. */ - if (strncmp (optarg, "even", strlen (optarg)) == 0) - feven = TRUE; - else if (strncmp (optarg, "odd", strlen (optarg)) == 0) - fodd = TRUE; - else if (strncmp (optarg, "none", strlen (optarg)) == 0) - { - feven = TRUE; - fodd = TRUE; - } - else - { - fprintf (stderr, "%s: --parity requires even, odd or none\n", - zProgram); - ucuusage (); - } - break; - - case 3: - /* --nostop. */ - txonxoff = XONXOFF_OFF; - break; - - case 1: - /* --help. */ - ucuhelp (); - exit (EXIT_SUCCESS); - /*NOTREACHED*/ - - case 0: - /* Long option found and flag set. */ - break; - - default: - ucuusage (); - /*NOTREACHED*/ - } - } - - /* There can be one more argument, which is either a system name, a - phone number, or "dir". We decide which it is based on the first - character. To call a UUCP system whose name begins with a digit, - or one which is named "dir", you must use -z. */ - if (optind != argc) - { - if (optind != argc - 1 - || zsystem != NULL - || zphone != NULL) - { - fprintf (stderr, "%s: too many arguments\n", zProgram); - ucuusage (); - } - if (strcmp (argv[optind], "dir") != 0) - { - if (isdigit (BUCHAR (argv[optind][0]))) - zphone = argv[optind]; - else - zsystem = argv[optind]; - } - } - - /* If the user doesn't give a system, port, line or speed, then - there's no basis on which to select a port. */ - if (zsystem == NULL - && zport == NULL - && zline == NULL - && ibaud == 0L) - { - fprintf (stderr, "%s: must specify system, line, port or speed\n", - zProgram); - ucuusage (); - } - - if (fprompt) - { - size_t cphone; - - printf ("Phone number: "); - (void) fflush (stdout); - zphone = NULL; - cphone = 0; - if (getline (&zphone, &cphone, stdin) <= 0 - || *zphone == '\0') - { - fprintf (stderr, "%s: no phone number entered\n", zProgram); - exit (EXIT_FAILURE); - } - } - - iuuconf = uuconf_init (&puuconf, "cu", zconfig); - if (iuuconf != UUCONF_SUCCESS) - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - pCuuuconf = puuconf; - -#if DEBUG > 1 - { - const char *zdebug; - - iuuconf = uuconf_debuglevel (puuconf, &zdebug); - if (iuuconf != UUCONF_SUCCESS) - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - if (zdebug != NULL) - iDebug |= idebug_parse (zdebug); - } -#endif - - usysdep_initialize (puuconf, INIT_NOCHDIR | INIT_SUID); - - iuuconf = uuconf_localname (puuconf, &zlocalname); - if (iuuconf == UUCONF_NOT_FOUND) - { - zlocalname = zsysdep_localname (); - if (zlocalname == NULL) - exit (EXIT_FAILURE); - } - else if (iuuconf != UUCONF_SUCCESS) - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - - ulog_fatal_fn (ucuabort); - pfLstart = uculog_start; - pfLend = uculog_end; - -#ifdef SIGINT - usysdep_signal (SIGINT); -#endif -#ifdef SIGHUP - usysdep_signal (SIGHUP); -#endif -#ifdef SIGQUIT - usysdep_signal (SIGQUIT); -#endif -#ifdef SIGTERM - usysdep_signal (SIGTERM); -#endif -#ifdef SIGPIPE - usysdep_signal (SIGPIPE); -#endif - - if (zsystem != NULL) - { - iuuconf = uuconf_system_info (puuconf, zsystem, &ssys); - if (iuuconf != UUCONF_SUCCESS) - { - if (iuuconf != UUCONF_NOT_FOUND) - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - ulog (LOG_FATAL, "%s: System not found", zsystem); - } - qsys = &ssys; - } - - /* This loop is used if a system is specified. It loops over the - various alternates until it finds one for which the dial - succeeds. This is an ugly spaghetti construction, and it should - be broken up into different functions someday. */ - flooped = FALSE; - while (TRUE) - { - enum tparitysetting tparity; - enum tstripsetting tstrip; - long iusebaud; - - /* The uuconf_find_port function only selects directly on a port - name and a speed. To select based on the line name, we use a - function. If we can't find any defined port, and the user - specified a line name but did not specify a port name or a - system or a phone number, then we fake a direct port with - that line name (we don't fake a port if a system or phone - number were given because if we fake a port we have no way to - place a call; perhaps we should automatically look up a - particular dialer). This permits users to say cu -lttyd0 - without having to put ttyd0 in the ports file, provided they - have read and write access to the port. */ - sinfo.fmatched = FALSE; - sinfo.flocked = FALSE; - sinfo.qconn = &sconn; - sinfo.zline = zline; - if (zport != NULL || zline != NULL || ibaud != 0L) - { - iuuconf = uuconf_find_port (puuconf, zport, ibaud, 0L, - icuport_lock, (pointer) &sinfo, - &sport); - if (iuuconf != UUCONF_SUCCESS) - { - if (iuuconf != UUCONF_NOT_FOUND) - { - if (sinfo.flocked) - { - (void) fconn_unlock (&sconn); - uconn_free (&sconn); - } - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - } - if (zline == NULL - || zport != NULL - || zphone != NULL - || qsys != NULL) - { - if (sinfo.fmatched) - ulog (LOG_FATAL, "All matching ports in use"); - else - ulog (LOG_FATAL, "No matching ports"); - } - - sport.uuconf_zname = zline; - sport.uuconf_ttype = UUCONF_PORTTYPE_DIRECT; - sport.uuconf_zprotocols = NULL; - sport.uuconf_qproto_params = NULL; - sport.uuconf_ireliable = 0; - sport.uuconf_zlockname = NULL; - sport.uuconf_palloc = NULL; - sport.uuconf_u.uuconf_sdirect.uuconf_zdevice = NULL; - sport.uuconf_u.uuconf_sdirect.uuconf_ibaud = ibaud; - - if (! fconn_init (&sport, &sconn, UUCONF_PORTTYPE_UNKNOWN)) - ucuabort (); - - if (! fconn_lock (&sconn, FALSE)) - ulog (LOG_FATAL, "%s: Line in use", zline); - - qCuconn = &sconn; - - /* Check user access after locking the port, because on - some systems shared lines affect the ownership and - permissions. In such a case ``Line in use'' is more - clear than ``Permission denied.'' */ - if (! fsysdep_port_access (&sport)) - ulog (LOG_FATAL, "%s: Permission denied", zline); - } - iusebaud = ibaud; - ihighbaud = 0L; - } - else - { - for (; qsys != NULL; qsys = qsys->uuconf_qalternate) - { - if (! qsys->uuconf_fcall) - continue; - if (qsys->uuconf_qport != NULL) - { - if (fconn_init (qsys->uuconf_qport, &sconn, - UUCONF_PORTTYPE_UNKNOWN)) - { - if (fconn_lock (&sconn, FALSE)) - { - qCuconn = &sconn; - break; - } - uconn_free (&sconn); - } - } - else - { - sinfo.fmatched = FALSE; - sinfo.flocked = FALSE; - sinfo.qconn = &sconn; - iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport, - qsys->uuconf_ibaud, - qsys->uuconf_ihighbaud, - icuport_lock, - (pointer) &sinfo, - &sport); - if (iuuconf == UUCONF_SUCCESS) - break; - if (iuuconf != UUCONF_NOT_FOUND) - { - if (sinfo.flocked) - { - (void) fconn_unlock (&sconn); - uconn_free (&sconn); - } - ulog_uuconf (LOG_FATAL, puuconf, iuuconf); - } - } - } - - if (qsys == NULL) - { - const char *zrem; - - if (flooped) - zrem = "remaining "; - else - zrem = ""; - if (sinfo.fmatched) - ulog (LOG_FATAL, "%s: All %smatching ports in use", - zsystem, zrem); - else - ulog (LOG_FATAL, "%s: No %smatching ports", zsystem, zrem); - } - - iusebaud = qsys->uuconf_ibaud; - ihighbaud = qsys->uuconf_ihighbaud; - } - - /* Here we have locked a connection to use. */ - if (! fconn_open (&sconn, iusebaud, ihighbaud, FALSE)) - ucuabort (); - - fCuclose_conn = TRUE; - - if (FGOT_SIGNAL ()) - ucuabort (); - - /* Set up the connection. */ - if (fodd && feven) - { - tparity = PARITYSETTING_NONE; - tstrip = STRIPSETTING_SEVENBITS; - } - else if (fodd) - { - tparity = PARITYSETTING_ODD; - tstrip = STRIPSETTING_SEVENBITS; - } - else if (feven) - { - tparity = PARITYSETTING_EVEN; - tstrip = STRIPSETTING_SEVENBITS; - } - else - { - tparity = PARITYSETTING_DEFAULT; - tstrip = STRIPSETTING_DEFAULT; - } - - if (! fconn_set (&sconn, tparity, tstrip, txonxoff)) - ucuabort (); - - if (qsys != NULL) - zphone = qsys->uuconf_zphone; - - if (qsys != NULL || zphone != NULL) - { - enum tdialerfound tdialer; - - if (! fconn_dial (&sconn, puuconf, qsys, zphone, &sdialer, - &tdialer)) - { - if (zport != NULL - || zline != NULL - || ibaud != 0L - || qsys == NULL) - ucuabort (); - - qsys = qsys->uuconf_qalternate; - if (qsys == NULL) - ulog (LOG_FATAL, "%s: No remaining alternates", zsystem); - - fCuclose_conn = FALSE; - (void) fconn_close (&sconn, pCuuuconf, qCudialer, FALSE); - qCuconn = NULL; - (void) fconn_unlock (&sconn); - uconn_free (&sconn); - - /* Loop around and try another alternate. */ - flooped = TRUE; - continue; - } - if (tdialer == DIALERFOUND_FALSE) - qdialer = NULL; - else - qdialer = &sdialer; - } - else - { - /* If no system or phone number was specified, we connect - directly to the modem. We only permit this if the user - has access to the port, since it permits various - shenanigans such as reprogramming the automatic - callbacks. */ - if (! fsysdep_port_access (sconn.qport)) - ulog (LOG_FATAL, "Access to port denied"); - qdialer = NULL; - if (! fconn_carrier (&sconn, FALSE)) - ulog (LOG_FATAL, "Can't turn off carrier"); - } - - break; - } - - qCudialer = qdialer; - - if (FGOT_SIGNAL ()) - ucuabort (); - - /* Here we have connected, and can start the main cu protocol. The - program spends most of its time in system dependent code, and - only comes out when a special command is received from the - terminal. */ - printf ("%s\n", ZCONNMSG); - fCuconnprinted = TRUE; - - if (! fsysdep_terminal_raw (fCulocalecho)) - ucuabort (); - - fCurestore_terminal = TRUE; - - if (! fsysdep_cu_init (&sconn)) - ucuabort (); - - fCustarted = TRUE; - - while (fsysdep_cu (&sconn, &bcmd, zlocalname)) - if (! fcudo_cmd (puuconf, &sconn, bcmd)) - break; - - fCustarted = FALSE; - if (! fsysdep_cu_finish ()) - ucuabort (); - - fCurestore_terminal = FALSE; - (void) fsysdep_terminal_restore (); - - (void) fconn_close (&sconn, puuconf, qdialer, TRUE); - (void) fconn_unlock (&sconn); - uconn_free (&sconn); - - if (fCuconnprinted) - printf ("\n%s\n", ZDISMSG); - - ulog_close (); - - usysdep_exit (TRUE); - - /* Avoid errors about not returning a value. */ - return 0; -} - -/* Print a usage message and die. */ - -static void -ucuusage () -{ - fprintf (stderr, "Usage: %s [options] [system or phone-number]\n", - zProgram); - fprintf (stderr, "Use %s --help for help\n", zProgram); - exit (EXIT_FAILURE); -} - -/* Print a help message. */ - -static void -ucuhelp () -{ - fprintf (stderr, - "Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995 Ian Lance Taylor\n", - VERSION); - fprintf (stderr, - "Usage: %s [options] [system or phone-number]\n", zProgram); - fprintf (stderr, - " -a,-p,--port port: Use named port\n"); - fprintf (stderr, - " -l,--line line: Use named device (e.g. tty0)\n"); - fprintf (stderr, - " -s,--speed,--baud speed, -#: Use given speed\n"); - fprintf (stderr, - " -c,--phone phone: Phone number to call\n"); - fprintf (stderr, - " -z,--system system: System to call\n"); - fprintf (stderr, - " -e: Set even parity\n"); - fprintf (stderr, - " -o: Set odd parity\n"); - fprintf (stderr, - " --parity={odd,even}: Set parity\n"); - fprintf (stderr, - " -E,--escape char: Set escape character\n"); - fprintf (stderr, - " -h,--halfduplex: Echo locally\n"); - fprintf (stderr, - " --nostop: Turn off XON/XOFF handling\n"); - fprintf (stderr, - " -t,--mapcr: Map carriage return to carriage return/linefeed\n"); - fprintf (stderr, - " -n,--prompt: Prompt for phone number\n"); - fprintf (stderr, - " -d: Set maximum debugging level\n"); - fprintf (stderr, - " -x,--debug debug: Set debugging type\n"); -#if HAVE_TAYLOR_CONFIG - fprintf (stderr, - " -I,--config file: Set configuration file to use\n"); -#endif /* HAVE_TAYLOR_CONFIG */ - fprintf (stderr, - " -v,--version: Print version and exit\n"); - fprintf (stderr, - " --help: Print help and exit\n"); -} - -/* This function is called when a fatal error occurs. */ - -static void -ucuabort () -{ - if (fCustarted) - { - fCustarted = FALSE; - (void) fsysdep_cu_finish (); - } - - if (fCurestore_terminal) - { - fCurestore_terminal = FALSE; - (void) fsysdep_terminal_restore (); - } - - if (qCuconn != NULL) - { - struct sconnection *qconn; - - if (fCuclose_conn) - { - fCuclose_conn = FALSE; - (void) fconn_close (qCuconn, pCuuuconf, qCudialer, FALSE); - } - qconn = qCuconn; - qCuconn = NULL; - (void) fconn_unlock (qconn); - uconn_free (qconn); - } - - ulog_close (); - - if (fCuconnprinted) - printf ("\n%s\n", ZDISMSG); - - usysdep_exit (FALSE); -} - -/* This variable is just used to communicate between uculog_start and - uculog_end. */ -static boolean fCulog_restore; - -/* This function is called by ulog before it output anything. We use - it to restore the terminal, if necessary. ulog is only called for - errors or debugging in cu, so it's not too costly to do this. If - we didn't do it, then at least on Unix each line would leave the - cursor in the same column rather than wrapping back to the start, - since CRMOD will not be on. */ - -static void -uculog_start () -{ - if (! fCurestore_terminal) - fCulog_restore = FALSE; - else - { - fCulog_restore = TRUE; - fCurestore_terminal = FALSE; - if (! fsysdep_terminal_restore ()) - ucuabort (); - } -} - -/* This function is called by ulog after everything is output. It - sets the terminal back, if necessary. */ - -static void -uculog_end () -{ - if (fCulog_restore) - { - if (! fsysdep_terminal_raw (fCulocalecho)) - ucuabort (); - fCurestore_terminal = TRUE; - } -} - -/* Check to see if this port has the desired line, to handle the -l - option. If it does, or if no line was specified, set up a - connection and lock it. */ - -static int -icuport_lock (qport, pinfo) - struct uuconf_port *qport; - pointer pinfo; -{ - struct sconninfo *q = (struct sconninfo *) pinfo; - - if (q->zline != NULL - && ! fsysdep_port_is_line (qport, q->zline)) - return UUCONF_NOT_FOUND; - - q->fmatched = TRUE; - - if (! fconn_init (qport, q->qconn, UUCONF_PORTTYPE_UNKNOWN)) - return UUCONF_NOT_FOUND; - else if (! fconn_lock (q->qconn, FALSE)) - { - uconn_free (q->qconn); - return UUCONF_NOT_FOUND; - } - else - { - qCuconn = q->qconn; - q->flocked = TRUE; - return UUCONF_SUCCESS; - } -} - -/* Execute a cu escape command. Return TRUE if the connection should - continue, or FALSE if the connection should be terminated. */ - -static boolean -fcudo_cmd (puuconf, qconn, bcmd) - pointer puuconf; - struct sconnection *qconn; - int bcmd; -{ - char *zline; - char *z; - char abescape[5]; - boolean fret; - size_t clen; - char abbuf[100]; - - /* Some commands take a string up to the next newline character. */ - switch (bcmd) - { - default: - zline = NULL; - break; - case '!': - case '$': - case '|': - case '+': - case '%': - case 'c': - case '>': - case '<': - case 'p': - case 't': - case 's': - { - zline = zsysdep_terminal_line ((const char *) NULL); - if (zline == NULL) - ucuabort (); - zline[strcspn (zline, "\n")] = '\0'; - } - break; - } - - switch (bcmd) - { - default: - if (! isprint (*zCuvar_escape)) - sprintf (abescape, "\\%03o", BUCHAR (*zCuvar_escape)); - else - { - abescape[0] = *zCuvar_escape; - abescape[1] = '\0'; - } - sprintf (abbuf, "[Unrecognized. Use %s%s to send %s]", - abescape, abescape, abescape); - ucuputs (abbuf); - return TRUE; - - case '.': - /* Hangup. */ - return FALSE; - - case '!': - case '$': - case '|': - case '+': - /* Shell out. */ - if (! fsysdep_cu_copy (FALSE) - || ! fsysdep_terminal_restore ()) - ucuabort (); - fCurestore_terminal = FALSE; - { - enum tshell_cmd t; - - switch (bcmd) - { - default: - case '!': t = SHELL_NORMAL; break; - case '$': t = SHELL_STDOUT_TO_PORT; break; - case '|': t = SHELL_STDIN_FROM_PORT; break; - case '+': t = SHELL_STDIO_ON_PORT; break; - } - - (void) fsysdep_shell (qconn, zline, t); - } - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_raw (fCulocalecho)) - ucuabort (); - fCurestore_terminal = TRUE; - ubuffree (zline); - return TRUE; - - case '%': - fret = fcudo_subcmd (puuconf, qconn, zline); - ubuffree (zline); - return fret; - - case '#': - if (! fconn_break (qconn)) - ucuabort (); - return TRUE; - - case 'c': - (void) fsysdep_chdir (zline); - ubuffree (zline); - return TRUE; - - case '>': - case '<': - case 'p': - case 't': - clen = strlen (zline); - z = zbufalc (clen + 3); - z[0] = bcmd; - z[1] = ' '; - memcpy (z + 2, zline, clen + 1); - ubuffree (zline); - fret = fcudo_subcmd (puuconf, qconn, z); - ubuffree (z); - return fret; - - case 'z': - if (! fsysdep_cu_copy (FALSE) - || ! fsysdep_terminal_restore ()) - ucuabort (); - fCurestore_terminal = FALSE; - if (! fsysdep_suspend ()) - ucuabort (); - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_raw (fCulocalecho)) - ucuabort (); - fCurestore_terminal = TRUE; - return TRUE; - - case 's': - fret = fcuset_var (puuconf, zline); - ubuffree (zline); - return fret; - - case 'v': - uculist_vars (); - return TRUE; - - case '?': - if (! isprint (*zCuvar_escape)) - sprintf (abescape, "\\%03o", BUCHAR (*zCuvar_escape)); - else - { - abescape[0] = *zCuvar_escape; - abescape[1] = '\0'; - } - ucuputs (""); - ucuputs ("[Escape sequences]"); - sprintf (abbuf, - "[%s. hangup] [%s!CMD run shell]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s$CMD stdout to remote] [%s|CMD stdin from remote]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s+CMD stdin and stdout to remote]", - abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s# send break] [%scDIR change directory]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s> send file] [%s< receive file]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%spFROM TO send to Unix] [%stFROM TO receive from Unix]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%ssVAR VAL set variable] [%ssVAR set boolean]", - abescape, abescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%ss!VAR unset boolean] [%sv list variables]", - abescape, abescape); - ucuputs (abbuf); -#ifdef SIGTSTP - sprintf (abbuf, - "[%sz suspend]", - abescape); - ucuputs (abbuf); -#endif - uculist_fns (abescape); - return TRUE; - } -} - -/* List ~% functions. */ - -static void -uculist_fns (zescape) - const char *zescape; -{ - char abbuf[100]; - - sprintf (abbuf, - "[%s%%break send break] [%s%%cd DIR change directory]", - zescape, zescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s%%put FROM TO send file] [%s%%take FROM TO receive file]", - zescape, zescape); - ucuputs (abbuf); - sprintf (abbuf, - "[%s%%nostop no XON/XOFF] [%s%%stop use XON/XOFF]", - zescape, zescape); - ucuputs (abbuf); -} - -/* Set a variable. */ - -static boolean -fcuset_var (puuconf, zline) - pointer puuconf; - char *zline; -{ - char *zvar, *zval; - char *azargs[2]; - int iuuconf; - - zvar = strtok (zline, "= \t"); - if (zvar == NULL) - { - ucuputs (abCuconnected); - return TRUE; - } - - zval = strtok ((char *) NULL, " \t"); - - if (zval == NULL) - { - azargs[0] = zvar; - if (azargs[0][0] != '!') - azargs[1] = zbufcpy ("t"); - else - { - ++azargs[0]; - azargs[1] = zbufcpy ("f"); - } - } - else - { - azargs[0] = zvar; - azargs[1] = zbufcpy (zval); - } - - iuuconf = uuconf_cmd_args (puuconf, 2, azargs, asCuvars, - (pointer) NULL, icuunrecogvar, 0, - (pointer) NULL); - - if ((iuuconf & UUCONF_CMDTABRET_KEEP) == 0) - ubuffree (azargs[1]); - - if ((iuuconf &~ UUCONF_CMDTABRET_KEEP) != UUCONF_SUCCESS) - ulog_uuconf (LOG_ERROR, puuconf, iuuconf); - - return TRUE; -} - -/* Warn about an unknown variable. */ - -/*ARGSUSED*/ -static int -icuunrecogvar (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - char abescape[5]; - - if (! isprint (*zCuvar_escape)) - sprintf (abescape, "\\%03o", BUCHAR (*zCuvar_escape)); - else - { - abescape[0] = *zCuvar_escape; - abescape[1] = '\0'; - } - ulog (LOG_ERROR, "%s: unknown variable (%sv lists variables)", - argv[0], abescape); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* List all the variables with their values. */ - -static void -uculist_vars () -{ - const struct uuconf_cmdtab *q; - char abbuf[100]; - - ucuputs (""); - for (q = asCuvars; q->uuconf_zcmd != NULL; q++) - { - switch (UUCONF_TTYPE_CMDTABTYPE (q->uuconf_itype)) - { - case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_BOOLEAN): - if (*(boolean *) q->uuconf_pvar) - sprintf (abbuf, "%s true", q->uuconf_zcmd); - else - sprintf (abbuf, "%s false", q->uuconf_zcmd); - break; - - case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_INT): - sprintf (abbuf, "%s %d", q->uuconf_zcmd, *(int *) q->uuconf_pvar); - break; - - case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_LONG): - sprintf (abbuf, "%s %ld", q->uuconf_zcmd, - *(long *) q->uuconf_pvar); - break; - - case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_STRING): - case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_FULLSTRING): - { - const char *z; - char abchar[5]; - size_t clen; - - sprintf (abbuf, "%s ", q->uuconf_zcmd); - clen = strlen (abbuf); - for (z = *(const char **) q->uuconf_pvar; *z != '\0'; z++) - { - int cchar; - - if (! isprint (*z)) - { - sprintf (abchar, "\\%03o", BUCHAR (*z)); - cchar = 4; - } - else - { - abchar[0] = *z; - abchar[1] = '\0'; - cchar = 1; - } - if (clen + cchar < sizeof (abbuf)) - strcat (abbuf, abchar); - clen += cchar; - } - } - break; - - default: - sprintf (abbuf, "%s [unprintable type]", q->uuconf_zcmd); - break; - } - - ucuputs (abbuf); - } -} - -/* Subcommands. These are commands that begin with ~%. */ - -/* This variable is only used so that we can pass a non-NULL address - in pvar. It is never assigned to or examined. */ - -static char bCutype; - -/* The command table for the subcommands. */ - -static int icubreak P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); -static int icudebug P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); -static int icuchdir P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); -static int icuput P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); -static int icutake P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); -static int icunostop P((pointer puuconf, int argc, char **argv, pointer pvar, - pointer pinfo)); - -static const struct uuconf_cmdtab asCucmds[] = -{ - { "break", UUCONF_CMDTABTYPE_FN | 1, NULL, icubreak }, - { "b", UUCONF_CMDTABTYPE_FN | 1, NULL, icubreak }, - { "cd", UUCONF_CMDTABTYPE_FN | 0, NULL, icuchdir }, - { "d", UUCONF_CMDTABTYPE_FN | 1, NULL, icudebug }, - { "put", UUCONF_CMDTABTYPE_FN | 0, NULL, icuput }, - { "take", UUCONF_CMDTABTYPE_FN | 0, NULL, icutake }, - { "nostop", UUCONF_CMDTABTYPE_FN | 1, NULL, icunostop }, - { "stop", UUCONF_CMDTABTYPE_FN | 1, &bCutype, icunostop }, - { ">", UUCONF_CMDTABTYPE_FN | 0, &bCutype, icuput }, - { "<", UUCONF_CMDTABTYPE_FN | 0, &bCutype, icutake }, - { "p", UUCONF_CMDTABTYPE_FN | 0, NULL, icuput }, - { "t", UUCONF_CMDTABTYPE_FN | 0, NULL, icutake }, - { NULL, 0, NULL, NULL } -}; - -/* Do a subcommand. This is called by commands beginning with ~%. */ - -static boolean -fcudo_subcmd (puuconf, qconn, zline) - pointer puuconf; - struct sconnection *qconn; - char *zline; -{ - char *azargs[3]; - int iarg; - int iuuconf; - - for (iarg = 0; iarg < 3; iarg++) - { - azargs[iarg] = strtok (iarg == 0 ? zline : (char *) NULL, " \t\n"); - if (azargs[iarg] == NULL) - break; - } - - if (iarg == 0) - { - ucuputs (abCuconnected); - return TRUE; - } - - iuuconf = uuconf_cmd_args (puuconf, iarg, azargs, asCucmds, - (pointer) qconn, icuunrecogfn, - 0, (pointer) NULL); - if (iuuconf != UUCONF_SUCCESS) - ulog_uuconf (LOG_ERROR, puuconf, iuuconf); - - return TRUE; -} - -/* Warn about an unknown function. */ - -/*ARGSUSED*/ -static int -icuunrecogfn (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - char abescape[5]; - - if (! isprint (*zCuvar_escape)) - sprintf (abescape, "\\%03o", BUCHAR (*zCuvar_escape)); - else - { - abescape[0] = *zCuvar_escape; - abescape[1] = '\0'; - } - if (argv[0][0] == '?') - uculist_fns (abescape); - else - ulog (LOG_ERROR, "%s: unknown (%s%%? lists choices)", - argv[0], abescape); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Send a break. */ - -/*ARGSUSED*/ -static int -icubreak (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - struct sconnection *qconn = (struct sconnection *) pinfo; - - if (! fconn_break (qconn)) - ucuabort (); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Change directories. */ - -/*ARGSUSED*/ -static int -icuchdir (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - const char *zarg; - - if (argc <= 1) - zarg = NULL; - else - zarg = argv[1]; - (void) fsysdep_chdir (zarg); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Toggle debugging. */ - -/*ARGSUSED*/ -static int -icudebug (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ -#if DEBUG > 1 - if (iDebug != 0) - iDebug = 0; - else - iDebug = DEBUG_MAX; -#else - ucuputs ("[compiled without debugging]"); -#endif - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Control whether the port does xon/xoff handshaking. If pvar is not - NULL, this is "stop"; otherwise it is "nostop". */ - -/*ARGSUSED*/ -static int -icunostop (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - struct sconnection *qconn = (struct sconnection *) pinfo; - - if (! fconn_set (qconn, PARITYSETTING_DEFAULT, STRIPSETTING_DEFAULT, - pvar == NULL ? XONXOFF_OFF : XONXOFF_ON)) - ucuabort (); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Send a file to the remote system. The first argument is the file - to send. If that argument is not present, it is prompted for. The - second argument is to file name to use on the remote system. If - that argument is not present, the basename of the local filename is - used. If pvar is not NULL, then this is ~>, which is used to send - a command to a non-Unix system. We treat is the same as ~%put, - except that we assume the user has already entered the appropriate - command (for ~%put, we force ``cat >to'' to the other side). */ - -/*ARGSUSED*/ -static int -icuput (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - struct sconnection *qconn = (struct sconnection *) pinfo; - char *zfrom; - char *zto = NULL; - char *zalc; - openfile_t e; - int cline; - char *zbuf; - size_t cbuf; - - if (argc > 1) - zfrom = zbufcpy (argv[1]); - else - { - zfrom = zsysdep_terminal_line ("File to send: "); - if (zfrom == NULL) - ucuabort (); - zfrom[strcspn (zfrom, " \t\n")] = '\0'; - - if (*zfrom == '\0') - { - ubuffree (zfrom); - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; - } - } - - if (pvar == NULL) - { - if (argc > 2) - zto = zbufcpy (argv[2]); - else - { - char *zbase; - char *zprompt; - - zbase = zsysdep_base_name (zfrom); - if (zbase == NULL) - ucuabort (); - - zprompt = zbufalc (sizeof "Remote file name []: " + - strlen (zbase)); - sprintf (zprompt, "Remote file name [%s]: ", zbase); - zto = zsysdep_terminal_line (zprompt); - ubuffree (zprompt); - if (zto == NULL) - ucuabort (); - - zto[strcspn (zto, " \t\n")] = '\0'; - if (*zto != '\0') - ubuffree (zbase); - else - { - ubuffree (zto); - zto = zbase; - } - } - } - - e = esysdep_user_fopen (zfrom, TRUE, fCuvar_binary); - if (! ffileisopen (e)) - { - const char *zerrstr; - - if (pvar == NULL) - ubuffree (zto); - zerrstr = strerror (errno); - zalc = zbufalc (strlen (zfrom) + sizeof ": " + strlen (zerrstr)); - sprintf (zalc, "%s: %s", zfrom, zerrstr); - ubuffree (zfrom); - ucuputs (zalc); - ubuffree (zalc); - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; - } - - ubuffree (zfrom); - - /* Tell the system dependent layer to stop copying data from the - port to the terminal. We want to read the echoes ourself. Also - permit the local user to generate signals. */ - if (! fsysdep_cu_copy (FALSE) - || ! fsysdep_terminal_signals (TRUE)) - ucuabort (); - - /* If pvar is NULL, then we are sending a file to a Unix system. We - send over the command "cat > TO" to prepare it to receive. If - pvar is not NULL, the user is assumed to have set up whatever - action was needed to receive the file. */ - if (pvar == NULL) - { - boolean fret; - - zalc = zbufalc (sizeof "cat > \n" + strlen (zto)); - sprintf (zalc, "cat > %s\n", zto); - ubuffree (zto); - fret = fcusend_buf (qconn, zalc, strlen (zalc)); - ubuffree (zalc); - if (! fret) - { - (void) ffileclose (e); - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_signals (FALSE)) - ucuabort (); - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; - } - } - - cline = 0; - - zbuf = NULL; - cbuf = 0; - - while (TRUE) - { - char abbuf[512]; - size_t c; - -#if USE_STDIO - if (fCuvar_binary) -#endif - { - if (ffileeof (e)) - break; - c = cfileread (e, abbuf, sizeof abbuf); - if (ffileioerror (e, c)) - { - ucuputs ("[file read error]"); - break; - } - if (c == 0) - break; - zbuf = abbuf; - } -#if USE_STDIO - else - { - if (getline (&zbuf, &cbuf, e) <= 0) - { - xfree ((pointer) zbuf); - break; - } - c = strlen (zbuf); - } -#endif - - if (fCuvar_verbose) - { - ++cline; - printf ("%d ", cline); - (void) fflush (stdout); - } - - if (! fcusend_buf (qconn, zbuf, c)) - { - if (! fCuvar_binary) - xfree ((pointer) zbuf); - (void) fclose (e); - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_signals (FALSE)) - ucuabort (); - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; - } - } - - (void) ffileclose (e); - - if (pvar == NULL) - { - char beof; - - beof = '\004'; - if (! fconn_write (qconn, &beof, 1)) - ucuabort (); - } - else - { - if (*zCuvar_eofwrite != '\0') - { - if (! fconn_write (qconn, zCuvar_eofwrite, - strlen (zCuvar_eofwrite))) - ucuabort (); - } - } - - if (fCuvar_verbose) - ucuputs (""); - - ucuputs ("[file transfer complete]"); - - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_signals (FALSE)) - ucuabort (); - - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Get a file from the remote side. This is ~%take, or ~t, or ~<. - The first two are assumed to be taking the file from a Unix system, - so we force the command "cat FROM; echo */ - -/*ARGSUSED*/ -static int -icutake (puuconf, argc, argv, pvar, pinfo) - pointer puuconf; - int argc; - char **argv; - pointer pvar; - pointer pinfo; -{ - struct sconnection *qconn = (struct sconnection *) pinfo; - const char *zeof; - char *zfrom, *zto, *zcmd; - char *zalc; - openfile_t e; - char bcr; - size_t ceoflen; - char *zlook = NULL; - size_t ceofhave; - boolean ferr; - - if (argc > 1) - zfrom = zbufcpy (argv[1]); - else - { - zfrom = zsysdep_terminal_line ("Remote file to retreive: "); - if (zfrom == NULL) - ucuabort (); - zfrom[strcspn (zfrom, " \t\n")] = '\0'; - if (*zfrom == '\0') - { - ubuffree (zfrom); - ucuputs (abCuconnected); - return UUCONF_CMDTABRET_CONTINUE; - } - } - - if (argc > 2) - zto = zbufcpy (argv[2]); - else - { - char *zbase; - char *zprompt; - - zbase = zsysdep_base_name (zfrom); - if (zbase == NULL) - ucuabort (); - - zprompt = zbufalc (sizeof "Local file name []: " + strlen (zbase)); - sprintf (zprompt, "Local file name [%s]: ", zbase); - zto = zsysdep_terminal_line (zprompt); - ubuffree (zprompt); - if (zto == NULL) - ucuabort (); - - zto[strcspn (zto, " \t\n")] = '\0'; - if (*zto != '\0') - ubuffree (zbase); - else - { - ubuffree (zto); - zto = zbase; - } - } - - if (pvar != NULL) - { - zcmd = zsysdep_terminal_line ("Remote command to execute: "); - if (zcmd == NULL) - ucuabort (); - zcmd[strcspn (zcmd, "\n")] = '\0'; - zeof = zCuvar_eofread; - } - else - { - zcmd = zbufalc (sizeof "cat ; echo; echo ////cuend////" - + strlen (zfrom)); - sprintf (zcmd, "cat %s; echo; echo ////cuend////", zfrom); - zeof = "\n////cuend////\n"; - } - - ubuffree (zfrom); - - e = esysdep_user_fopen (zto, FALSE, fCuvar_binary); - if (! ffileisopen (e)) - { - const char *zerrstr; - - ubuffree (zcmd); - zerrstr = strerror (errno); - zalc = zbufalc (strlen (zto) + sizeof ": " + strlen (zerrstr)); - sprintf (zalc, "%s: %s\n", zto, zerrstr); - ucuputs (zalc); - ubuffree (zalc); - ucuputs (abCuconnected); - ubuffree (zto); - return UUCONF_CMDTABRET_CONTINUE; - } - - if (! fsysdep_cu_copy (FALSE) - || ! fsysdep_terminal_signals (TRUE)) - ucuabort (); - - if (! fconn_write (qconn, zcmd, strlen (zcmd))) - ucuabort (); - bcr = '\r'; - if (! fconn_write (qconn, &bcr, 1)) - ucuabort (); - - ubuffree (zcmd); - - /* Eliminated any previously echoed data to avoid confusion. */ - iPrecstart = 0; - iPrecend = 0; - - /* If we're dealing with a Unix system, we can reliably discard the - command. Otherwise, the command will probably wind up in the - file; too bad. */ - if (pvar == NULL) - { - int b; - - while ((b = breceive_char (qconn, cCuvar_timeout, TRUE)) != '\n') - { - if (b == -2) - ucuabort (); - if (b < 0) - { - ucuputs ("[timed out waiting for newline]"); - ucuputs (abCuconnected); - ubuffree (zto); - return UUCONF_CMDTABRET_CONTINUE; - } - } - } - - ceoflen = strlen (zeof); - zlook = zbufalc (ceoflen); - ceofhave = 0; - ferr = FALSE; - - while (TRUE) - { - int b; - - if (FGOT_SIGNAL ()) - { - /* Make sure the signal is logged. */ - ulog (LOG_ERROR, (const char *) NULL); - ucuputs ("[file receive aborted]"); - /* Reset the SIGINT flag so that it does not confuse us in - the future. */ - afSignal[INDEXSIG_SIGINT] = FALSE; - break; - } - - b = breceive_char (qconn, cCuvar_timeout, TRUE); - if (b == -2) - ucuabort (); - if (b < 0) - { - if (ceofhave > 0) - (void) fwrite (zlook, sizeof (char), ceofhave, e); - ucuputs ("[timed out]"); - break; - } - - if (b == '\r' && ! fCuvar_binary) - continue; - - if (ceoflen == 0) - { - if (cfilewrite (e, &b, 1) != 1) - { - ferr = TRUE; - break; - } - } - else - { - zlook[ceofhave] = b; - ++ceofhave; - if (ceofhave == ceoflen) - { - size_t cmove; - char *zmove; - - if (memcmp (zeof, zlook, ceoflen) == 0) - { - ucuputs ("[file transfer complete]"); - break; - } - - if (cfilewrite (e, zlook, 1) != 1) - { - ferr = TRUE; - break; - } - - zmove = zlook; - for (cmove = ceoflen - 1, zmove = zlook; - cmove > 0; - cmove--, zmove++) - zmove[0] = zmove[1]; - - --ceofhave; - } - } - } - - ubuffree (zlook); - - if (! fsysdep_sync (e, zto)) - { - (void) ffileclose (e); - ferr = TRUE; - } - else - { - if (! ffileclose (e)) - ferr = TRUE; - } - if (ferr) - ucuputs ("[file write error]"); - - if (! fsysdep_cu_copy (TRUE) - || ! fsysdep_terminal_signals (FALSE)) - ucuabort (); - - ucuputs (abCuconnected); - - ubuffree (zto); - - return UUCONF_CMDTABRET_CONTINUE; -} - -/* Send a buffer to the remote system. If fCuvar_binary is FALSE, - each buffer passed in will be a single line; in this case we can - check the echoed characters and kill the line if they do not match. - This returns FALSE if an echo check fails. If a port error - occurrs, it calls ucuabort. */ - -static boolean -fcusend_buf (qconn, zbufarg, cbufarg) - struct sconnection *qconn; - const char *zbufarg; - size_t cbufarg; -{ - const char *zbuf; - size_t cbuf; - int ctries; - size_t cbplen; - char *zsendbuf; - - zbuf = zbufarg; - cbuf = cbufarg; - ctries = 0; - - if (fCuvar_binary) - cbplen = strlen (zCuvar_binary_prefix); - else - cbplen = 1; - zsendbuf = zbufalc (64 * (cbplen + 1)); - - /* Loop while we still have characters to send. The value of cbuf - will be reset to cbufarg if an echo failure occurs while sending - a line in non-binary mode. */ - while (cbuf > 0) - { - int csend; - char *zput; - const char *zget; - boolean fnl; - int i; - - if (FGOT_SIGNAL ()) - { - /* Make sure the signal is logged. */ - ubuffree (zsendbuf); - ulog (LOG_ERROR, (const char *) NULL); - ucuputs ("[file send aborted]"); - /* Reset the SIGINT flag so that it does not confuse us in - the future. */ - afSignal[INDEXSIG_SIGINT] = FALSE; - return FALSE; - } - - /* Discard anything we've read from the port up to now, to avoid - confusing the echo checking. */ - iPrecstart = 0; - iPrecend = 0; - - /* Send all characters up to a newline before actually sending - the newline. This makes it easier to handle the special - newline echo checking. Send up to 64 characters at a time - before doing echo checking. */ - if (*zbuf == '\n') - csend = 1; - else - { - const char *znl; - - znl = memchr (zbuf, '\n', cbuf); - if (znl == NULL) - csend = cbuf; - else - csend = znl - zbuf; - if (csend > 64) - csend = 64; - } - - /* Translate this part of the buffer. If we are not in binary - mode, we translate \n to \r, and ignore any nonprintable - characters. */ - zput = zsendbuf; - fnl = FALSE; - for (i = 0, zget = zbuf; i < csend; i++, zget++) - { - if (isprint (*zget) - || *zget == '\t') - *zput++ = *zget; - else if (*zget == '\n') - { - if (fCuvar_binary) - *zput++ = '\n'; - else - *zput++ = '\r'; - fnl = TRUE; - } - else if (fCuvar_binary) - { - strcpy (zput, zCuvar_binary_prefix); - zput += cbplen; - *zput++ = *zget; - } - } - - zbuf += csend; - cbuf -= csend; - - if (zput == zsendbuf) - continue; - - /* Send the data over the port. */ - if (! fsend_data (qconn, zsendbuf, (size_t) (zput - zsendbuf), TRUE)) - ucuabort (); - - /* We do echo checking if requested, unless we are in binary - mode. Echo checking of a newline is different from checking - of normal characters; when we send a newline we look for - *zCuvar_echonl. */ - if ((fCuvar_echocheck && ! fCuvar_binary) - || (fnl && *zCuvar_echonl != '\0')) - { - long iend; - - iend = ixsysdep_time ((long *) NULL) + (long) cCuvar_timeout; - for (zget = zsendbuf; zget < zput; zget++) - { - int bread; - int bwant; - - if (fCuvar_binary ? *zget == '\n' : *zget == '\r') - { - bwant = *zCuvar_echonl; - if (bwant == '\0') - continue; - } - else - { - if (! fCuvar_echocheck || ! isprint (*zget)) - continue; - bwant = *zget; - } - - do - { - if (FGOT_SIGNAL ()) - { - /* Make sure the signal is logged. */ - ubuffree (zsendbuf); - ulog (LOG_ERROR, (const char *) NULL); - ucuputs ("[file send aborted]"); - /* Reset the SIGINT flag so that it does not - confuse us in the future. */ - afSignal[INDEXSIG_SIGINT] = FALSE; - return FALSE; - } - - bread = breceive_char (qconn, - iend - ixsysdep_time ((long *) NULL), - TRUE); - if (bread < 0) - { - if (bread == -2) - ucuabort (); - - /* If we timed out, and we're not in binary - mode, we kill the line and try sending it - again from the beginning. */ - if (! fCuvar_binary && *zCuvar_kill != '\0') - { - ++ctries; - if (ctries < cCuvar_resend) - { - if (fCuvar_verbose) - { - printf ("R "); - (void) fflush (stdout); - } - if (! fsend_data (qconn, zCuvar_kill, 1, - TRUE)) - ucuabort (); - zbuf = zbufarg; - cbuf = cbufarg; - break; - } - } - ubuffree (zsendbuf); - ucuputs ("[timed out looking for echo]"); - return FALSE; - } - } - while (bread != *zget); - - if (bread < 0) - break; - } - } - } - - ubuffree (zsendbuf); - - return TRUE; -} |