|
|
1.1 ! root 1: /* conn.c ! 2: Connection routines for the Taylor UUCP package. ! 3: ! 4: Copyright (C) 1991, 1992 Ian Lance Taylor ! 5: ! 6: This file is part of the Taylor UUCP package. ! 7: ! 8: This program is free software; you can redistribute it and/or ! 9: modify it under the terms of the GNU General Public License as ! 10: published by the Free Software Foundation; either version 2 of the ! 11: License, or (at your option) any later version. ! 12: ! 13: This program is distributed in the hope that it will be useful, but ! 14: WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 16: General Public License for more details. ! 17: ! 18: You should have received a copy of the GNU General Public License ! 19: along with this program; if not, write to the Free Software ! 20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 21: ! 22: The author of the program may be contacted at [email protected] or ! 23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. ! 24: */ ! 25: ! 26: #include "uucp.h" ! 27: ! 28: #if USE_RCS_ID ! 29: const char conn_rcsid[] = "$Id: conn.c,v 1.1 93/07/30 07:52:56 bin Exp Locker: bin $"; ! 30: #endif ! 31: ! 32: #include <ctype.h> ! 33: ! 34: #include "uudefs.h" ! 35: #include "uuconf.h" ! 36: #include "conn.h" ! 37: ! 38: static boolean fcdo_dial P((struct sconnection *qconn, pointer puuconf, ! 39: struct uuconf_dialer *qdialer, ! 40: const char *zphone, boolean ftranslate)); ! 41: ! 42: /* Create a new connection. This relies on system dependent functions ! 43: to set the qcmds and psysdep fields. If qport is NULL, it opens a ! 44: standard input port. */ ! 45: ! 46: boolean ! 47: fconn_init (qport, qconn) ! 48: struct uuconf_port *qport; ! 49: struct sconnection *qconn; ! 50: { ! 51: qconn->qport = qport; ! 52: switch (qport == NULL ? UUCONF_PORTTYPE_STDIN : qport->uuconf_ttype) ! 53: { ! 54: case UUCONF_PORTTYPE_STDIN: ! 55: return fsysdep_stdin_init (qconn); ! 56: case UUCONF_PORTTYPE_MODEM: ! 57: return fsysdep_modem_init (qconn); ! 58: case UUCONF_PORTTYPE_DIRECT: ! 59: return fsysdep_direct_init (qconn); ! 60: #if HAVE_TCP ! 61: case UUCONF_PORTTYPE_TCP: ! 62: return fsysdep_tcp_init (qconn); ! 63: #endif ! 64: #if HAVE_TLI ! 65: case UUCONF_PORTTYPE_TLI: ! 66: return fsysdep_tli_init (qconn); ! 67: #endif ! 68: default: ! 69: ulog (LOG_ERROR, "Unknown port type"); ! 70: return FALSE; ! 71: } ! 72: } ! 73: ! 74: /* Connection dispatch routines. */ ! 75: ! 76: /* Free a connection. */ ! 77: ! 78: void ! 79: uconn_free (qconn) ! 80: struct sconnection *qconn; ! 81: { ! 82: (*qconn->qcmds->pufree) (qconn); ! 83: } ! 84: ! 85: /* Lock a connection. */ ! 86: ! 87: boolean ! 88: fconn_lock (qconn, fin) ! 89: struct sconnection *qconn; ! 90: boolean fin; ! 91: { ! 92: boolean (*pflock) P((struct sconnection *, boolean)); ! 93: ! 94: pflock = qconn->qcmds->pflock; ! 95: if (pflock == NULL) ! 96: return TRUE; ! 97: return (*pflock) (qconn, fin); ! 98: } ! 99: ! 100: /* Unlock a connection. */ ! 101: ! 102: boolean ! 103: fconn_unlock (qconn) ! 104: struct sconnection *qconn; ! 105: { ! 106: boolean (*pfunlock) P((struct sconnection *)); ! 107: ! 108: pfunlock = qconn->qcmds->pfunlock; ! 109: if (pfunlock == NULL) ! 110: return TRUE; ! 111: return (*pfunlock) (qconn); ! 112: } ! 113: ! 114: /* Open a connection. */ ! 115: ! 116: boolean ! 117: fconn_open (qconn, ibaud, ihighbaud, fwait) ! 118: struct sconnection *qconn; ! 119: long ibaud; ! 120: long ihighbaud; ! 121: boolean fwait; ! 122: { ! 123: boolean fret; ! 124: ! 125: #if DEBUG > 1 ! 126: if (FDEBUGGING (DEBUG_PORT)) ! 127: { ! 128: char abspeed[20]; ! 129: ! 130: if (ibaud == (long) 0) ! 131: strcpy (abspeed, "default speed"); ! 132: else ! 133: sprintf (abspeed, "speed %ld", ibaud); ! 134: ! 135: if (qconn->qport == NULL) ! 136: ulog (LOG_DEBUG, "fconn_open: Opening stdin port (%s)", ! 137: abspeed); ! 138: else if (qconn->qport->uuconf_zname == NULL) ! 139: ulog (LOG_DEBUG, "fconn_open: Opening unnamed port (%s)", ! 140: abspeed); ! 141: else ! 142: ulog (LOG_DEBUG, "fconn_open: Opening port %s (%s)", ! 143: qconn->qport->uuconf_zname, abspeed); ! 144: } ! 145: #endif ! 146: ! 147: /* If the system provides a range of baud rates, we select the ! 148: highest baud rate supported by the port. */ ! 149: if (ihighbaud != 0 && qconn->qport != NULL) ! 150: { ! 151: struct uuconf_port *qport; ! 152: ! 153: qport = qconn->qport; ! 154: ibaud = ihighbaud; ! 155: if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM) ! 156: { ! 157: if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0) ! 158: { ! 159: if (qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud < ibaud) ! 160: ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud; ! 161: } ! 162: else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0) ! 163: ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ibaud; ! 164: } ! 165: else if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT) ! 166: { ! 167: if (qport->uuconf_u.uuconf_sdirect.uuconf_ibaud != 0) ! 168: ibaud = qport->uuconf_u.uuconf_sdirect.uuconf_ibaud; ! 169: } ! 170: } ! 171: ! 172: /* This will normally be overridden by the port specific open ! 173: routine. */ ! 174: if (qconn->qport == NULL) ! 175: ulog_device ("stdin"); ! 176: else ! 177: ulog_device (qconn->qport->uuconf_zname); ! 178: ! 179: fret = (*qconn->qcmds->pfopen) (qconn, ibaud, fwait); ! 180: ! 181: if (! fret) ! 182: ulog_device ((const char *) NULL); ! 183: ! 184: return fret; ! 185: } ! 186: ! 187: /* Close a connection. */ ! 188: ! 189: boolean ! 190: fconn_close (qconn, puuconf, qdialer, fsuccess) ! 191: struct sconnection *qconn; ! 192: pointer puuconf; ! 193: struct uuconf_dialer *qdialer; ! 194: boolean fsuccess; ! 195: { ! 196: boolean fret; ! 197: ! 198: DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_close: Closing connection"); ! 199: ! 200: /* Don't report hangup signals while we're closing. */ ! 201: fLog_sighup = FALSE; ! 202: ! 203: fret = (*qconn->qcmds->pfclose) (qconn, puuconf, qdialer, fsuccess); ! 204: ! 205: /* Make sure any signal reporting has been done before we set ! 206: fLog_sighup back to TRUE. */ ! 207: ulog (LOG_ERROR, (const char *) NULL); ! 208: fLog_sighup = TRUE; ! 209: ! 210: ulog_device ((const char *) NULL); ! 211: ! 212: return fret; ! 213: } ! 214: ! 215: /* Reset the connection. */ ! 216: ! 217: boolean ! 218: fconn_reset (qconn) ! 219: struct sconnection *qconn; ! 220: { ! 221: DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_reset: Resetting connection"); ! 222: ! 223: return (*qconn->qcmds->pfreset) (qconn); ! 224: } ! 225: ! 226: /* Dial out on the connection. */ ! 227: ! 228: boolean ! 229: fconn_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) ! 230: struct sconnection *qconn; ! 231: pointer puuconf; ! 232: const struct uuconf_system *qsys; ! 233: const char *zphone; ! 234: struct uuconf_dialer *qdialer; ! 235: enum tdialerfound *ptdialerfound; ! 236: { ! 237: struct uuconf_dialer sdialer; ! 238: enum tdialerfound tfound; ! 239: boolean (*pfdial) P((struct sconnection *, pointer, ! 240: const struct uuconf_system *, const char *, ! 241: struct uuconf_dialer *, enum tdialerfound *)); ! 242: ! 243: if (qdialer == NULL) ! 244: qdialer = &sdialer; ! 245: if (ptdialerfound == NULL) ! 246: ptdialerfound = &tfound; ! 247: ! 248: qdialer->uuconf_zname = NULL; ! 249: *ptdialerfound = DIALERFOUND_FALSE; ! 250: ! 251: pfdial = qconn->qcmds->pfdial; ! 252: if (pfdial == NULL) ! 253: return TRUE; ! 254: return (*pfdial) (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound); ! 255: } ! 256: ! 257: /* Read data from the connection. */ ! 258: ! 259: boolean ! 260: fconn_read (qconn, zbuf, pclen, cmin, ctimeout, freport) ! 261: struct sconnection *qconn; ! 262: char *zbuf; ! 263: size_t *pclen; ! 264: size_t cmin; ! 265: int ctimeout; ! 266: boolean freport; ! 267: { ! 268: boolean fret; ! 269: ! 270: fret = (*qconn->qcmds->pfread) (qconn, zbuf, pclen, cmin, ctimeout, ! 271: freport); ! 272: ! 273: #if DEBUG > 1 ! 274: if (FDEBUGGING (DEBUG_INCOMING)) ! 275: udebug_buffer ("fconn_read: Read", zbuf, *pclen); ! 276: else if (FDEBUGGING (DEBUG_PORT)) ! 277: ulog (LOG_DEBUG, "fconn_read: Read %lu", (unsigned long) *pclen); ! 278: #endif ! 279: ! 280: return fret; ! 281: } ! 282: ! 283: /* Write data to the connection. */ ! 284: ! 285: boolean ! 286: fconn_write (qconn, zbuf, clen) ! 287: struct sconnection *qconn; ! 288: const char *zbuf; ! 289: size_t clen; ! 290: { ! 291: #if DEBUG > 1 ! 292: if (FDEBUGGING (DEBUG_OUTGOING)) ! 293: udebug_buffer ("fconn_write: Writing", zbuf, clen); ! 294: else if (FDEBUGGING (DEBUG_PORT)) ! 295: ulog (LOG_DEBUG, "fconn_write: Writing %lu", (unsigned long) clen); ! 296: #endif ! 297: ! 298: return (*qconn->qcmds->pfwrite) (qconn, zbuf, clen); ! 299: } ! 300: ! 301: /* Read and write data. */ ! 302: ! 303: boolean ! 304: fconn_io (qconn, zwrite, pcwrite, zread, pcread) ! 305: struct sconnection *qconn; ! 306: const char *zwrite; ! 307: size_t *pcwrite; ! 308: char *zread; ! 309: size_t *pcread; ! 310: { ! 311: boolean fret; ! 312: #if DEBUG > 1 ! 313: size_t cwrite = *pcwrite; ! 314: size_t cread = *pcread; ! 315: ! 316: if (cread == 0 || cwrite == 0) ! 317: ulog (LOG_FATAL, "fconn_io: cread %lu; cwrite %lu", ! 318: (unsigned long) cread, (unsigned long) cwrite); ! 319: #endif ! 320: ! 321: #if DEBUG > 1 ! 322: if (FDEBUGGING (DEBUG_OUTGOING)) ! 323: udebug_buffer ("fconn_io: Writing", zwrite, cwrite); ! 324: #endif ! 325: ! 326: fret = (*qconn->qcmds->pfio) (qconn, zwrite, pcwrite, zread, pcread); ! 327: ! 328: DEBUG_MESSAGE4 (DEBUG_PORT, ! 329: "fconn_io: Wrote %lu of %lu, read %lu of %lu", ! 330: (unsigned long) *pcwrite, (unsigned long) cwrite, ! 331: (unsigned long) *pcread, (unsigned long) cread); ! 332: ! 333: #if DEBUG > 1 ! 334: if (*pcread > 0 && FDEBUGGING (DEBUG_INCOMING)) ! 335: udebug_buffer ("fconn_io: Read", zread, *pcread); ! 336: #endif ! 337: ! 338: return fret; ! 339: } ! 340: ! 341: /* Send a break character to a connection. Some port types may not ! 342: support break characters, in which case we just return TRUE. */ ! 343: ! 344: boolean ! 345: fconn_break (qconn) ! 346: struct sconnection *qconn; ! 347: { ! 348: boolean (*pfbreak) P((struct sconnection *)); ! 349: ! 350: pfbreak = *qconn->qcmds->pfbreak; ! 351: if (pfbreak == NULL) ! 352: return TRUE; ! 353: ! 354: DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_break: Sending break character"); ! 355: ! 356: return (*pfbreak) (qconn); ! 357: } ! 358: ! 359: /* Change the setting of a connection. Some port types may not ! 360: support this, in which case we just return TRUE. */ ! 361: ! 362: boolean ! 363: fconn_set (qconn, tparity, tstrip, txonxoff) ! 364: struct sconnection *qconn; ! 365: enum tparitysetting tparity; ! 366: enum tstripsetting tstrip; ! 367: enum txonxoffsetting txonxoff; ! 368: { ! 369: boolean (*pfset) P((struct sconnection *, enum tparitysetting, ! 370: enum tstripsetting, enum txonxoffsetting)); ! 371: ! 372: pfset = qconn->qcmds->pfset; ! 373: if (pfset == NULL) ! 374: return TRUE; ! 375: ! 376: DEBUG_MESSAGE3 (DEBUG_PORT, ! 377: "fconn_set: Changing setting to %d, %d, %d", ! 378: (int) tparity, (int) tstrip, (int) txonxoff); ! 379: ! 380: return (*pfset) (qconn, tparity, tstrip, txonxoff); ! 381: } ! 382: ! 383: /* Require or ignore carrier on a connection. */ ! 384: ! 385: boolean ! 386: fconn_carrier (qconn, fcarrier) ! 387: struct sconnection *qconn; ! 388: boolean fcarrier; ! 389: { ! 390: boolean (*pfcarrier) P((struct sconnection *, boolean)); ! 391: ! 392: pfcarrier = qconn->qcmds->pfcarrier; ! 393: if (pfcarrier == NULL) ! 394: return TRUE; ! 395: return (*pfcarrier) (qconn, fcarrier); ! 396: } ! 397: ! 398: /* Run a chat program on a connection. */ ! 399: ! 400: boolean ! 401: fconn_run_chat (qconn, pzprog) ! 402: struct sconnection *qconn; ! 403: char **pzprog; ! 404: { ! 405: return (*qconn->qcmds->pfchat) (qconn, pzprog); ! 406: } ! 407: ! 408: /* Get the baud rate of a connection. */ ! 409: ! 410: long ! 411: iconn_baud (qconn) ! 412: struct sconnection *qconn; ! 413: { ! 414: long (*pibaud) P((struct sconnection *)); ! 415: ! 416: pibaud = qconn->qcmds->pibaud; ! 417: if (pibaud == NULL) ! 418: return 0; ! 419: return (*pibaud) (qconn); ! 420: } ! 421: ! 422: /* Modem dialing routines. */ ! 423: ! 424: /*ARGSUSED*/ ! 425: boolean ! 426: fmodem_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) ! 427: struct sconnection *qconn; ! 428: pointer puuconf; ! 429: const struct uuconf_system *qsys; ! 430: const char *zphone; ! 431: struct uuconf_dialer *qdialer; ! 432: enum tdialerfound *ptdialerfound; ! 433: { ! 434: *ptdialerfound = DIALERFOUND_FALSE; ! 435: ! 436: if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL) ! 437: { ! 438: char **pz; ! 439: boolean ffirst; ! 440: ! 441: /* The pzdialer field is a sequence of dialer/token pairs. The ! 442: dialer portion names a dialer to use. The token portion is ! 443: what \D and \T in the chat script expand to. If there is no ! 444: token for the last dialer, the phone number for the system is ! 445: used. */ ! 446: ffirst = TRUE; ! 447: pz = qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer; ! 448: while (*pz != NULL) ! 449: { ! 450: int iuuconf; ! 451: struct uuconf_dialer *q; ! 452: struct uuconf_dialer s; ! 453: const char *ztoken; ! 454: boolean ftranslate; ! 455: ! 456: if (! ffirst) ! 457: q = &s; ! 458: else ! 459: q = qdialer; ! 460: ! 461: iuuconf = uuconf_dialer_info (puuconf, *pz, q); ! 462: if (iuuconf == UUCONF_NOT_FOUND) ! 463: { ! 464: ulog (LOG_ERROR, "%s: Dialer not found", *pz); ! 465: return FALSE; ! 466: } ! 467: else if (iuuconf != UUCONF_SUCCESS) ! 468: { ! 469: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 470: return FALSE; ! 471: } ! 472: ! 473: ++pz; ! 474: ztoken = *pz; ! 475: ! 476: ftranslate = FALSE; ! 477: if (ztoken == NULL ! 478: || strcmp (ztoken, "\\D") == 0) ! 479: ztoken = zphone; ! 480: else if (strcmp (ztoken, "\\T") == 0) ! 481: { ! 482: ztoken = zphone; ! 483: ftranslate = TRUE; ! 484: } ! 485: ! 486: if (! fcdo_dial (qconn, puuconf, q, ztoken, ftranslate)) ! 487: { ! 488: (void) uuconf_dialer_free (puuconf, q); ! 489: if (! ffirst) ! 490: (void) uuconf_dialer_free (puuconf, qdialer); ! 491: return FALSE; ! 492: } ! 493: ! 494: if (ffirst) ! 495: { ! 496: *ptdialerfound = DIALERFOUND_FREE; ! 497: ffirst = FALSE; ! 498: } ! 499: else ! 500: (void) uuconf_dialer_free (puuconf, q); ! 501: ! 502: if (*pz != NULL) ! 503: ++pz; ! 504: } ! 505: ! 506: return TRUE; ! 507: } ! 508: else if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer != NULL) ! 509: { ! 510: struct uuconf_dialer *q; ! 511: ! 512: q = qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer; ! 513: *qdialer = *q; ! 514: *ptdialerfound = DIALERFOUND_TRUE; ! 515: return fcdo_dial (qconn, puuconf, q, zphone, FALSE); ! 516: } ! 517: else ! 518: { ! 519: ulog (LOG_ERROR, "No dialer information"); ! 520: return FALSE; ! 521: } ! 522: } ! 523: ! 524: /* Actually use a dialer. We set up the modem (which may include ! 525: opening the dialer device), run the chat script, and finish dealing ! 526: with the modem. */ ! 527: ! 528: static boolean ! 529: fcdo_dial (qconn, puuconf, qdial, zphone, ftranslate) ! 530: struct sconnection *qconn; ! 531: pointer puuconf; ! 532: struct uuconf_dialer *qdial; ! 533: const char *zphone; ! 534: boolean ftranslate; ! 535: { ! 536: const char *zname; ! 537: ! 538: if (! fsysdep_modem_begin_dial (qconn, qdial)) ! 539: return FALSE; ! 540: ! 541: if (qconn->qport == NULL) ! 542: zname = NULL; ! 543: else ! 544: zname = qconn->qport->uuconf_zname; ! 545: ! 546: if (! fchat (qconn, puuconf, &qdial->uuconf_schat, ! 547: (const struct uuconf_system *) NULL, qdial, ! 548: zphone, ftranslate, zname, iconn_baud (qconn))) ! 549: return FALSE; ! 550: ! 551: return fsysdep_modem_end_dial (qconn, qdial); ! 552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.