1/* conn.c 2 Connection routines for the Taylor UUCP package. 3 4 Copyright (C) 1991, 1992, 1993, 1994, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char conn_rcsid[] = "$Id: conn.c,v 1.18 2002/03/05 19:10:41 ian Rel $"; 29#endif 30 31#include <ctype.h> 32 33#include "uudefs.h" 34#include "uuconf.h" 35#include "conn.h" 36 37/* Create a new connection. This relies on system dependent functions 38 to set the qcmds and psysdep fields. If qport is NULL, it opens a 39 standard input port, in which case ttype is the type of port to 40 use. */ 41 42boolean 43fconn_init (qport, qconn, ttype) 44 struct uuconf_port *qport; 45 struct sconnection *qconn; 46 enum uuconf_porttype ttype; 47{ 48 qconn->qport = qport; 49 switch (qport == NULL ? ttype : qport->uuconf_ttype) 50 { 51 case UUCONF_PORTTYPE_STDIN: 52 return fsysdep_stdin_init (qconn); 53 case UUCONF_PORTTYPE_MODEM: 54 return fsysdep_modem_init (qconn); 55 case UUCONF_PORTTYPE_DIRECT: 56 return fsysdep_direct_init (qconn); 57#if HAVE_TCP 58 case UUCONF_PORTTYPE_TCP: 59 return fsysdep_tcp_init (qconn); 60#endif 61#if HAVE_TLI 62 case UUCONF_PORTTYPE_TLI: 63 return fsysdep_tli_init (qconn); 64#endif 65 case UUCONF_PORTTYPE_PIPE: 66 return fsysdep_pipe_init (qconn); 67 default: 68 ulog (LOG_ERROR, "Unknown or unsupported port type"); 69 return FALSE; 70 } 71} 72 73/* Connection dispatch routines. */ 74 75/* Free a connection. */ 76 77void 78uconn_free (qconn) 79 struct sconnection *qconn; 80{ 81 (*qconn->qcmds->pufree) (qconn); 82} 83 84/* Lock a connection. */ 85 86boolean 87fconn_lock (qconn, fin, fuser) 88 struct sconnection *qconn; 89 boolean fin; 90 boolean fuser; 91{ 92 boolean (*pflock) P((struct sconnection *, boolean, boolean)); 93 94 pflock = qconn->qcmds->pflock; 95 if (pflock == NULL) 96 return TRUE; 97 return (*pflock) (qconn, fin, fuser); 98} 99 100/* Unlock a connection. */ 101 102boolean 103fconn_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 116boolean 117fconn_open (qconn, ibaud, ihighbaud, fwait, fuser) 118 struct sconnection *qconn; 119 long ibaud; 120 long ihighbaud; 121 boolean fwait; 122 boolean fuser; 123{ 124 boolean fret; 125 126#if DEBUG > 1 127 if (FDEBUGGING (DEBUG_PORT)) 128 { 129 char abspeed[20]; 130 131 if (ibaud == (long) 0) 132 strcpy (abspeed, "default speed"); 133 else 134 sprintf (abspeed, "speed %ld", ibaud); 135 136 if (qconn->qport == NULL) 137 ulog (LOG_DEBUG, "fconn_open: Opening stdin port (%s)", 138 abspeed); 139 else if (qconn->qport->uuconf_zname == NULL) 140 ulog (LOG_DEBUG, "fconn_open: Opening unnamed port (%s)", 141 abspeed); 142 else 143 ulog (LOG_DEBUG, "fconn_open: Opening port %s (%s)", 144 qconn->qport->uuconf_zname, abspeed); 145 } 146#endif 147 148 /* If the system provides a range of baud rates, we select the 149 highest baud rate supported by the port. */ 150 if (ihighbaud != 0 && qconn->qport != NULL) 151 { 152 struct uuconf_port *qport; 153 154 qport = qconn->qport; 155 ibaud = ihighbaud; 156 if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM) 157 { 158 if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0) 159 { 160 if (qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud < ibaud) 161 ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud; 162 } 163 else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0) 164 ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ibaud; 165 } 166 else if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT) 167 { 168 if (qport->uuconf_u.uuconf_sdirect.uuconf_ibaud != 0) 169 ibaud = qport->uuconf_u.uuconf_sdirect.uuconf_ibaud; 170 } 171 } 172 173 /* This will normally be overridden by the port specific open 174 routine. */ 175 if (qconn->qport == NULL) 176 ulog_device ("stdin"); 177 else 178 ulog_device (qconn->qport->uuconf_zname); 179 180 fret = (*qconn->qcmds->pfopen) (qconn, ibaud, fwait, fuser); 181 182 if (! fret) 183 ulog_device ((const char *) NULL); 184 185 return fret; 186} 187 188/* Close a connection. */ 189 190boolean 191fconn_close (qconn, puuconf, qdialer, fsuccess) 192 struct sconnection *qconn; 193 pointer puuconf; 194 struct uuconf_dialer *qdialer; 195 boolean fsuccess; 196{ 197 boolean fret; 198 199 DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_close: Closing connection"); 200 201 /* Don't report hangup signals while we're closing. */ 202 fLog_sighup = FALSE; 203 204 fret = (*qconn->qcmds->pfclose) (qconn, puuconf, qdialer, fsuccess); 205 206 /* Ignore any SIGHUP we may have gotten, and make sure any signal 207 reporting has been done before we reset fLog_sighup. */ 208 afSignal[INDEXSIG_SIGHUP] = FALSE; 209 ulog (LOG_ERROR, (const char *) NULL); 210 fLog_sighup = TRUE; 211 212 ulog_device ((const char *) NULL); 213 214 return fret; 215} 216 217/* Dial out on the connection. */ 218 219boolean 220fconn_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) 221 struct sconnection *qconn; 222 pointer puuconf; 223 const struct uuconf_system *qsys; 224 const char *zphone; 225 struct uuconf_dialer *qdialer; 226 enum tdialerfound *ptdialerfound; 227{ 228 struct uuconf_dialer sdialer; 229 enum tdialerfound tfound; 230 boolean (*pfdial) P((struct sconnection *, pointer, 231 const struct uuconf_system *, const char *, 232 struct uuconf_dialer *, enum tdialerfound *)); 233 234 if (qdialer == NULL) 235 qdialer = &sdialer; 236 if (ptdialerfound == NULL) 237 ptdialerfound = &tfound; 238 239 qdialer->uuconf_zname = NULL; 240 *ptdialerfound = DIALERFOUND_FALSE; 241 242 pfdial = qconn->qcmds->pfdial; 243 if (pfdial == NULL) 244 return TRUE; 245 return (*pfdial) (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound); 246} 247 248/* Read data from the connection. */ 249 250boolean 251fconn_read (qconn, zbuf, pclen, cmin, ctimeout, freport) 252 struct sconnection *qconn; 253 char *zbuf; 254 size_t *pclen; 255 size_t cmin; 256 int ctimeout; 257 boolean freport; 258{ 259 boolean fret; 260 261 fret = (*qconn->qcmds->pfread) (qconn, zbuf, pclen, cmin, ctimeout, 262 freport); 263 264#if DEBUG > 1 265 if (FDEBUGGING (DEBUG_INCOMING)) 266 udebug_buffer ("fconn_read: Read", zbuf, *pclen); 267 else if (FDEBUGGING (DEBUG_PORT)) 268 ulog (LOG_DEBUG, "fconn_read: Read %lu", (unsigned long) *pclen); 269#endif 270 271 return fret; 272} 273 274/* Write data to the connection. */ 275 276boolean 277fconn_write (qconn, zbuf, clen) 278 struct sconnection *qconn; 279 const char *zbuf; 280 size_t clen; 281{ 282#if DEBUG > 1 283 if (FDEBUGGING (DEBUG_OUTGOING)) 284 udebug_buffer ("fconn_write: Writing", zbuf, clen); 285 else if (FDEBUGGING (DEBUG_PORT)) 286 ulog (LOG_DEBUG, "fconn_write: Writing %lu", (unsigned long) clen); 287#endif 288 289 return (*qconn->qcmds->pfwrite) (qconn, zbuf, clen); 290} 291 292/* Read and write data. */ 293 294boolean 295fconn_io (qconn, zwrite, pcwrite, zread, pcread) 296 struct sconnection *qconn; 297 const char *zwrite; 298 size_t *pcwrite; 299 char *zread; 300 size_t *pcread; 301{ 302 boolean fret; 303#if DEBUG > 1 304 size_t cwrite = *pcwrite; 305 size_t cread = *pcread; 306 307 if (cread == 0 || cwrite == 0) 308 ulog (LOG_FATAL, "fconn_io: cread %lu; cwrite %lu", 309 (unsigned long) cread, (unsigned long) cwrite); 310#endif 311 312#if DEBUG > 1 313 if (FDEBUGGING (DEBUG_OUTGOING)) 314 udebug_buffer ("fconn_io: Writing", zwrite, cwrite); 315#endif 316 317 fret = (*qconn->qcmds->pfio) (qconn, zwrite, pcwrite, zread, pcread); 318 319 DEBUG_MESSAGE4 (DEBUG_PORT, 320 "fconn_io: Wrote %lu of %lu, read %lu of %lu", 321 (unsigned long) *pcwrite, (unsigned long) cwrite, 322 (unsigned long) *pcread, (unsigned long) cread); 323 324#if DEBUG > 1 325 if (*pcread > 0 && FDEBUGGING (DEBUG_INCOMING)) 326 udebug_buffer ("fconn_io: Read", zread, *pcread); 327#endif 328 329 return fret; 330} 331 332/* Send a break character to a connection. Some port types may not 333 support break characters, in which case we just return TRUE. */ 334 335boolean 336fconn_break (qconn) 337 struct sconnection *qconn; 338{ 339 boolean (*pfbreak) P((struct sconnection *)); 340 341 pfbreak = qconn->qcmds->pfbreak; 342 if (pfbreak == NULL) 343 return TRUE; 344 345 DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_break: Sending break character"); 346 347 return (*pfbreak) (qconn); 348} 349 350/* Change the setting of a connection. Some port types may not 351 support this, in which case we just return TRUE. */ 352 353boolean 354fconn_set (qconn, tparity, tstrip, txonxoff) 355 struct sconnection *qconn; 356 enum tparitysetting tparity; 357 enum tstripsetting tstrip; 358 enum txonxoffsetting txonxoff; 359{ 360 boolean (*pfset) P((struct sconnection *, enum tparitysetting, 361 enum tstripsetting, enum txonxoffsetting)); 362 363 pfset = qconn->qcmds->pfset; 364 if (pfset == NULL) 365 return TRUE; 366 367 DEBUG_MESSAGE3 (DEBUG_PORT, 368 "fconn_set: Changing setting to %d, %d, %d", 369 (int) tparity, (int) tstrip, (int) txonxoff); 370 371 return (*pfset) (qconn, tparity, tstrip, txonxoff); 372} 373 374/* Require or ignore carrier on a connection. */ 375 376boolean 377fconn_carrier (qconn, fcarrier) 378 struct sconnection *qconn; 379 boolean fcarrier; 380{ 381 boolean (*pfcarrier) P((struct sconnection *, boolean)); 382 383 pfcarrier = qconn->qcmds->pfcarrier; 384 if (pfcarrier == NULL) 385 return TRUE; 386 return (*pfcarrier) (qconn, fcarrier); 387} 388 389/* Run a chat program on a connection. */ 390 391boolean 392fconn_run_chat (qconn, pzprog) 393 struct sconnection *qconn; 394 char **pzprog; 395{ 396 return (*qconn->qcmds->pfchat) (qconn, pzprog); 397} 398 399/* Get the baud rate of a connection. */ 400 401long 402iconn_baud (qconn) 403 struct sconnection *qconn; 404{ 405 long (*pibaud) P((struct sconnection *)); 406 407 pibaud = qconn->qcmds->pibaud; 408 if (pibaud == NULL) 409 return 0; 410 return (*pibaud) (qconn); 411} 412 413/* Run through a dialer sequence. The pzdialer argument is a list of 414 strings, which are considered in dialer/token pairs. The dialer 415 string names a dialer to use. The token string is what \D and \T 416 in the chat script expand to. If there is no token for the last 417 dialer, the zphone argument is used. The qdialer argument is 418 filled in with information for the first dialer, and *ptdialerfound 419 is set to whether the information should be freed or not. However, 420 if *ptdialerfound is not DIALERFOUND_FALSE when this function is 421 called, then the information for the first dialer is already in 422 qdialer. */ 423 424boolean 425fconn_dial_sequence (qconn, puuconf, pzdialer, qsys, zphone, qdialer, 426 ptdialerfound) 427 struct sconnection *qconn; 428 pointer puuconf; 429 char **pzdialer; 430 const struct uuconf_system *qsys; 431 const char *zphone; 432 struct uuconf_dialer *qdialer; 433 enum tdialerfound *ptdialerfound; 434{ 435 const char *zname; 436 boolean ffirst, ffreefirst; 437 438 if (qconn->qport == NULL) 439 zname = NULL; 440 else 441 zname = qconn->qport->uuconf_zname; 442 ffirst = TRUE; 443 ffreefirst = FALSE; 444 while (*pzdialer != NULL) 445 { 446 struct uuconf_dialer *q; 447 struct uuconf_dialer s; 448 const char *ztoken; 449 boolean ftranslate; 450 451 if (! ffirst) 452 q = &s; 453 else 454 q = qdialer; 455 456 if (! ffirst || *ptdialerfound == DIALERFOUND_FALSE) 457 { 458 int iuuconf; 459 460 iuuconf = uuconf_dialer_info (puuconf, *pzdialer, q); 461 if (iuuconf == UUCONF_NOT_FOUND) 462 { 463 ulog (LOG_ERROR, "%s: Dialer not found", *pzdialer); 464 if (ffreefirst) 465 (void) uuconf_dialer_free (puuconf, qdialer); 466 return FALSE; 467 } 468 else if (iuuconf != UUCONF_SUCCESS) 469 { 470 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 471 if (ffreefirst) 472 (void) uuconf_dialer_free (puuconf, qdialer); 473 return FALSE; 474 } 475 476 if (ffirst) 477 { 478 *ptdialerfound = DIALERFOUND_FREE; 479 ffreefirst = TRUE; 480 } 481 } 482 483 ++pzdialer; 484 ztoken = *pzdialer; 485 486 ftranslate = FALSE; 487 if (ztoken == NULL 488 || strcmp (ztoken, "\\D") == 0) 489 ztoken = zphone; 490 else if (strcmp (ztoken, "\\T") == 0) 491 { 492 ztoken = zphone; 493 ftranslate = TRUE; 494 } 495 496 if (! fchat (qconn, puuconf, &q->uuconf_schat, qsys, q, ztoken, 497 ftranslate, zname, iconn_baud (qconn))) 498 { 499 if (q == &s) 500 (void) uuconf_dialer_free (puuconf, q); 501 if (ffreefirst) 502 (void) uuconf_dialer_free (puuconf, qdialer); 503 return FALSE; 504 } 505 506 if (ffirst) 507 ffirst = FALSE; 508 else 509 (void) uuconf_dialer_free (puuconf, q); 510 511 if (*pzdialer != NULL) 512 ++pzdialer; 513 } 514 515 return TRUE; 516} 517 518/* Modem dialing routine. */ 519 520/*ARGSUSED*/ 521boolean 522fmodem_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) 523 struct sconnection *qconn; 524 pointer puuconf; 525 const struct uuconf_system *qsys; 526 const char *zphone; 527 struct uuconf_dialer *qdialer; 528 enum tdialerfound *ptdialerfound; 529{ 530 char **pzdialer; 531 532 *ptdialerfound = DIALERFOUND_FALSE; 533 534 pzdialer = qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer; 535 if (pzdialer != NULL && *pzdialer != NULL) 536 { 537 int iuuconf; 538 boolean fret; 539 540 iuuconf = uuconf_dialer_info (puuconf, *pzdialer, qdialer); 541 if (iuuconf == UUCONF_NOT_FOUND) 542 { 543 ulog (LOG_ERROR, "%s: Dialer not found", *pzdialer); 544 return FALSE; 545 } 546 else if (iuuconf != UUCONF_SUCCESS) 547 { 548 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 549 return FALSE; 550 } 551 552 *ptdialerfound = DIALERFOUND_FREE; 553 554 fret = (fsysdep_modem_begin_dial (qconn, qdialer) 555 && fconn_dial_sequence (qconn, puuconf, pzdialer, qsys, zphone, 556 qdialer, ptdialerfound) 557 && fsysdep_modem_end_dial (qconn, qdialer)); 558 559 if (! fret) 560 (void) uuconf_dialer_free (puuconf, qdialer); 561 562 return fret; 563 } 564 else if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer != NULL) 565 { 566 struct uuconf_dialer *q; 567 const char *zname; 568 569 q = qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer; 570 *qdialer = *q; 571 *ptdialerfound = DIALERFOUND_TRUE; 572 573 if (qconn->qport == NULL) 574 zname = NULL; 575 else 576 zname = qconn->qport->uuconf_zname; 577 578 return (fsysdep_modem_begin_dial (qconn, q) 579 && fchat (qconn, puuconf, &q->uuconf_schat, qsys, q, 580 zphone, FALSE, zname, iconn_baud (qconn)) 581 && fsysdep_modem_end_dial (qconn, q)); 582 } 583 else 584 { 585 ulog (LOG_ERROR, "No dialer information"); 586 return FALSE; 587 } 588} 589