|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.