home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / sysvdial / part3 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  38.2 KB

  1. Subject: v06i088:  System V generic dial routines (sysVdial), Part3/3
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: ihnp4!quest!gene
  6. Mod.sources: Volume 6, Issue 88
  7. Archive-name: sysVdial/Part3
  8.  
  9. [  I did not try to compile this, as we run BSD exlusively.  It appears
  10.    that the hardest part of doing the port will be emulating the timed-
  11.    out reads (c_cc[VTIME]) in dial.c  --r$  ]
  12.  
  13. #    Generic Modem Dialer subroutine and support programs for system V.
  14. #    
  15. #    Modem configuration is done in the user configured file
  16. #    dialinfo.  Should be able to dial any modem (eg Vadic, Hayes)
  17. #    with a built-in auto dialer.   Replaces ATT dial(3C).
  18. #    Works with CU, uucico, lp, etc.
  19. #    
  20. #    This is part 3 of 3.
  21. #    
  22. #    The parts are:
  23. #    
  24. #    1)    README file and all documentation.
  25. #    2)    Makefile, dialinfo, *.h, some *.c files
  26. #    3)    dial.c
  27. #    
  28. #--------CUT---------CUT---------CUT---------CUT--------#
  29. #########################################################
  30. #                                                       #
  31. # This is a shell archive file.  To extract files:      #
  32. #                                                       #
  33. #    1)    Create an empty directory for the files.        #
  34. #    2) Write a file, such as "file.shar", containing   #
  35. #       this archive file into the directory.           #
  36. #    3) Type "sh file.shar".  Do not use csh.           #
  37. #                                                       #
  38. #########################################################
  39. echo Creating: dial.c
  40. sed -e 's/^#//' >dial.c <<'end_dial.c'
  41. #/****************************************************************
  42. # *    Copyright 1986, Gene H. Olson, Quest Research, Burnsville   *
  43. # *    Minnesota.   Permission to copy and distribute this         *
  44. # *    program, all associated code in source and binary form,     *
  45. # *    for any purpose, so long as this notice is preserved.       *
  46. # ****************************************************************/
  47. #
  48. #
  49. #/********************************************************************
  50. # *          System V dial(3) generic modem dialer.                  *
  51. # ********************************************************************/
  52. #
  53. ##include <stdio.h>
  54. ##include <time.h>
  55. ##include <setjmp.h>
  56. ##include <signal.h>
  57. ##include <fcntl.h>
  58. ##include <ctype.h>
  59. ##include <errno.h>
  60. ##include <termio.h>
  61. #
  62. ##include "dial.h"
  63. ##include "dialinfo.h"
  64. #
  65. ##define loop for(;;)
  66. #
  67. ##define YIPE(x) { if ((x) < 0) yipe(__LINE__); }
  68. ##define NS(x) ( (x) ? (x) : nullstring )
  69. #
  70. #extern int errno ;
  71. #extern int sys_nerr ;
  72. #extern char *sys_errlist[] ;
  73. #
  74. #extern void perror() ;
  75. #extern int (*signal())() ;
  76. #extern struct tm *localtime() ;
  77. #extern char *getenv() ;
  78. #extern unsigned alarm() ;
  79. #extern long time() ;
  80. #extern char *ttyname() ;
  81. #extern char *strcat() ;
  82. #extern char *strcpy() ;
  83. #extern char *strncpy() ;
  84. #extern char *strncat() ;
  85. #extern void exit() ;
  86. #extern unsigned sleep() ;
  87. #
  88. #extern char *parseshort() ;
  89. #extern void dialfree() ;
  90. #
  91. #
  92. #/*
  93. # *    Externally visible stuff.
  94. # */
  95. #
  96. #int nolock ;                        /* Disable lockfile usage */
  97. #
  98. #char *ldevice[9] ;                    /* L-devices pointer array */
  99. #
  100. #char dialdev[50];                    /* Device pathname */
  101. #char diallock[50];                    /* Lockfile pathname */
  102. #char dialnum[50] ;                    /* Telephone number */
  103. #
  104. #int dialfd ;                        /* Dialer file descriptor */
  105. #
  106. #/*
  107. # *    Local storage.
  108. # */
  109. #
  110. #static jmp_buf jmpstate ;            /* Interrupt recovery */
  111. #
  112. #static char ldbuf[100] ;            /* L-devices buffer */
  113. #
  114. #static int iflags[4] ;                /* Initial termio c_cflag */
  115. #static int cflags[4] ;                /* Current termio c_cflag */
  116. #
  117. #static int carrier ;                /* Carrier detect option */
  118. #static int debug ;                    /* Selected debug options */
  119. #static int gotalarm ;                /* Dialer alarms */
  120. #static int inline ;                    /* In middle of output line */
  121. #
  122. #static char nullstring[] = "(null)" ;
  123. #
  124. #/*
  125. # *    Match list definition.
  126. # */
  127. #
  128. ##define NMATCH 20                    /* Max # of match strings */
  129. #
  130. #typedef struct {
  131. #    short    m_index ;                /* Number of chars */
  132. #    short    m_state ;                /* Associated state value */
  133. #    char*    m_string ;                /* Match string */
  134. #    } MATCH ;
  135. #
  136. #/*
  137. # *    Dialer state stuff.
  138. # */
  139. #
  140. ##define NBUF 1000                    /* Size of temporary buffer */
  141. #
  142. ##define DS_NONE        1001            /* No state defined */
  143. ##define DS_FAIL        1003            /* Fail state */
  144. ##define DS_SUCCEED    1004            /* Succeed state */
  145. ##define DS_TIMEOUT    1005            /* Timeout state */
  146. ##define DS_HANGUP    1006            /* Hangup state */
  147. #
  148. #typedef struct {
  149. #    short    ds_retry ;                /* Retry counter */
  150. #    short    ds_sec ;                /* Timeout in seconds */
  151. #    short    ds_hangup ;                /* Hangup state */
  152. #    short    ds_timeout ;            /* Timeout state */
  153. #    short    ds_nmatch ;                /* Number of match items */
  154. #    MATCH    ds_match[NMATCH] ;        /* Match item array */
  155. #    char     *ds_buf ;                /* Current buffer pointer */
  156. #    char    ds_failmsg[80] ;        /* Failure message */
  157. #    char    ds_buffer[NBUF] ;        /* Scratch buffer */
  158. #    } DSTATE ;
  159. #
  160. #/*
  161. # *    Dialer debug options.
  162. # *
  163. # *    The user may specify a DIALDEBUG variable in
  164. # *    the environment, using one or more of the characters
  165. # *    listed in the table below.   When this is done,
  166. # *    debugging output is produced.
  167. # */
  168. #
  169. ##define D_ALL        0xff            /* Show everything */
  170. ##define D_DEVICE    0x01            /* Show L-device decisions */
  171. ##define D_STATE        0x02            /* Show state transitions */
  172. ##define D_LINE        0x04            /* Show line control actions */
  173. ##define D_MATCH        0x08            /* Show matched strings */
  174. ##define D_COMM        0x10            /* Show transmitted/received comm */
  175. #
  176. #static char dtable[] = {
  177. #    'd',    D_DEVICE,
  178. #    's',    D_STATE,
  179. #    'l',    D_LINE,
  180. #    'm',    D_MATCH,
  181. #    'c',    (D_COMM|D_LINE|D_MATCH),
  182. #    'a',    (D_DEVICE|D_STATE|D_LINE|D_MATCH|D_COMM),
  183. #    0 } ;
  184. #
  185. #
  186. #/*
  187. # *    Dialer baud rate table.
  188. # */
  189. #
  190. #static short btable[] = {
  191. #    50,        CSTOPB|B50,
  192. #    75,        CSTOPB|B75,
  193. #    110,    CSTOPB|B110,
  194. #    134,    CSTOPB|B134,
  195. #    150,    B150,
  196. #    200,    B200,
  197. #    300,    B300,
  198. #    600,    B600,
  199. #    1200,    B1200,
  200. #    1800,    B1800,
  201. #    2400,    B2400,
  202. #    4800,    B4800,
  203. #    9600,    B9600,
  204. #    0 } ;
  205. #
  206. #
  207. #
  208. #/******
  209. # *    getbaud - Get baud rate entry.
  210. # */
  211. #
  212. #static int
  213. #getbaud(rate)
  214. #int rate ;
  215. #{
  216. #    register short *sp ;
  217. #
  218. #    for (sp = btable ;; sp += 2) {
  219. #        if (sp[0] == 0) return(-1) ;
  220. #        if (sp[0] == rate) return(sp[1]) ;
  221. #        }
  222. #    }
  223. #
  224. #
  225. #
  226. #/*****
  227. # *    errstring - Get system error string.
  228. # */
  229. #
  230. #static
  231. #char *
  232. #errstring()
  233. #{
  234. #    static char buf[20] ;
  235. #
  236. #    if ((unsigned) errno <= sys_nerr) return(sys_errlist[errno]) ;
  237. #
  238. #    (void) sprintf(buf, "errno=%d", errno) ;
  239. #    return(buf) ;
  240. #    }
  241. #
  242. #
  243. #
  244. #/*****
  245. # *    dialmsg - Dialer debug output routine.
  246. # */
  247. #
  248. #/*VARARGS1*/
  249. #void
  250. #dialmsg(s, args)
  251. #char *s ;                            /* Printf-style string */
  252. #struct { char _arg[16] ; } args ;    /* Printf-style arguments */
  253. #{
  254. #    struct tm tm ;
  255. #    long clock ;
  256. #
  257. #    /*
  258. #     *    Finish up any line in progress.
  259. #     */
  260. #
  261. #    if (inline) {
  262. #        (void) putc('\n', stderr) ;
  263. #        inline = 0 ;
  264. #        }
  265. #
  266. #    /*
  267. #     *    Note the time.
  268. #     */
  269. #
  270. #    if (debug) {
  271. #        (void) time(&clock) ;
  272. #        tm = *localtime(&clock) ;
  273. #
  274. #        (void) fprintf(stderr,"%02d:%02d:%02d  ",
  275. #            tm.tm_hour, tm.tm_min, tm.tm_sec
  276. #            ) ;
  277. #        }
  278. #
  279. #    /*
  280. #     *    Output the user's message.
  281. #     */
  282. #
  283. #    (void) fprintf(stderr, s, args) ;
  284. #    (void) fflush(stderr) ;
  285. #    }
  286. #
  287. #
  288. #
  289. #/*****
  290. # *    yipe - Print error messages for unexpected errors.
  291. # */
  292. #
  293. #static void
  294. #yipe(lineno)
  295. #int lineno ;
  296. #{
  297. #    dialmsg("dial.c line %d: %s\n", lineno, errstring()) ;
  298. #    }
  299. #
  300. #
  301. #
  302. #/*****
  303. # *    wakeup - Wakeup on alarm interrupts.
  304. # */
  305. #
  306. #static int
  307. #wakeup()
  308. #{
  309. #    /*
  310. #     *    Note that we got the interrupt, re-arm for
  311. #     *    the next interrupt, and schedule another one
  312. #     *    so we can't get caught in a window where the
  313. #     *    interrupt is lost.
  314. #     */
  315. #
  316. #    gotalarm = 1 ;
  317. #    (void) signal(SIGALRM, wakeup) ;
  318. #    return alarm(1) ;
  319. #    }
  320. #
  321. #
  322. #
  323. #/*****
  324. # *    catch - Catch SIGHUP, SIGINT, SIGQUIT, SIGTERM.
  325. # */
  326. #
  327. #static int
  328. #catch(num)
  329. #{
  330. #    /*
  331. #     *    Do a longjump back to "dial" which will then
  332. #     *    return failure.
  333. #     */
  334. #
  335. #    if (debug) dialmsg("Got signal: %d\n", num) ;
  336. #    longjmp(jmpstate,num) ;
  337. #    }
  338. #
  339. #
  340. #
  341. #/*****
  342. # *    showchar - Display a character in unambiguous format.
  343. # */
  344. #
  345. #static void
  346. #showchar(ch)
  347. #register int ch ;
  348. #{
  349. #    if (ch < 0x20) {
  350. #        (void) putc('^', stderr) ;
  351. #        ch |= 0x40 ;
  352. #        }
  353. #
  354. #    (void) putc(ch, stderr) ;
  355. #    }
  356. #
  357. #
  358. #
  359. #/*****
  360. # *    showstring - Show a string in an unambigous format.
  361. # */
  362. #
  363. #static void
  364. #showstring(str)
  365. #register char *str ;
  366. #{
  367. #    while (*str) showchar(*str++) ;
  368. #    }
  369. #
  370. #
  371. #
  372. #/*****
  373. # *    dialerror - Handle communication error.
  374. # */
  375. #
  376. #static void
  377. #dialerror()
  378. #{
  379. #    /*
  380. #     *    Flush the tty and make sure we aren't blocked
  381. #     *    by XOFF.
  382. #     */
  383. #
  384. #    YIPE(ioctl(dialfd,TCFLSH,2)) ;
  385. #    YIPE(ioctl(dialfd,TCXONC,1)) ;
  386. #
  387. #    if (debug & D_LINE) {
  388. #        dialmsg("Flushed device.\n") ;
  389. #        }
  390. #    }
  391. #
  392. #
  393. #
  394. #/******
  395. # *    setflags - Set termio flags on communication line.
  396. # */
  397. #
  398. #static void
  399. #setflags()
  400. #{
  401. #    static struct termio tio ;
  402. #
  403. #    tio.c_iflag = IGNPAR|IGNBRK|ISTRIP ;
  404. #    tio.c_oflag = 0 ;
  405. #    tio.c_cflag = cflags[carrier] ;
  406. #    tio.c_lflag = NOFLSH ;
  407. #
  408. #    tio.c_cc[VMIN] = 10 ;
  409. #    tio.c_cc[VTIME] = 1 ;
  410. #
  411. #    YIPE(ioctl(dialfd,TCSETA,&tio)) ;
  412. #
  413. #    if (debug & D_LINE) dialmsg("Control flags now: %06o\n", tio.c_cflag) ;
  414. #    }
  415. #
  416. #
  417. #
  418. #/*****
  419. # *    dropdtr - Drop DTR for a "n" seconds.
  420. # */
  421. #
  422. #void
  423. #dropdtr(n)
  424. #short n ;                    /* Number of seconds to hang up */
  425. #{
  426. #    /*
  427. #     *    Hang up the line.
  428. #     */
  429. #
  430. #    carrier = 0 ;
  431. #    cflags[0] = 0 ;
  432. #    setflags() ;
  433. #
  434. #    /*
  435. #     *    Sleep for the specified interval.
  436. #     */
  437. #
  438. #    if (debug & D_LINE) dialmsg("Dropping DTR for %d seconds\n", n) ;
  439. #
  440. #    (void) sleep((unsigned) n) ;
  441. #
  442. #    /*
  443. #     *    Raise DTR, and restore the baud rate.
  444. #     */
  445. #
  446. #    cflags[0] = iflags[0] ;
  447. #    cflags[1] = iflags[1] ;
  448. #    cflags[2] = iflags[2] ;
  449. #    cflags[3] = iflags[3] ;
  450. #
  451. #    setflags() ;
  452. #
  453. #    /*
  454. #     *    For some reason, this open appears to be necessary,
  455. #     *    at least on Plexus.
  456. #     */
  457. #
  458. #    YIPE(close(open(dialdev, O_RDWR))) ;
  459. #    }
  460. #
  461. #
  462. #
  463. #/****
  464. # *    setcarrier - Set carrier detect option.
  465. # *
  466. # *    state     0 = set default c_cflags and CLOCAL.
  467. # *            1 = set user c_cflags and CLOCAL.
  468. # *            2 = set user c_cflags and call.modem CLOCAL option.
  469. # *            3 = use user c_cflags and ~CLOCAL.
  470. # */
  471. #
  472. #static void
  473. #setcarrier(state)
  474. #int state ;                /* Set carrier detect */
  475. #{
  476. #    /*
  477. #     *    Enable or disable carrier sense.
  478. #     */
  479. #
  480. #    if (state != carrier) {
  481. #        carrier = state ;
  482. #
  483. #        setflags() ;
  484. #
  485. #        if (debug & D_LINE) dialmsg("Set connect option %d\n", state) ;
  486. #        }
  487. #    }
  488. #
  489. #
  490. #
  491. #/*****
  492. # *    newbaud - Change baud rate.
  493. # */
  494. #
  495. #static int
  496. #newbaud(baud)
  497. #int baud ;                        /* New baud rate */
  498. #{
  499. #    register int i ;
  500. #
  501. #    i = getbaud(baud) ;
  502. #    if (i == -1) return(A_PROB) ;
  503. #
  504. #    cflags[0] = (cflags[0] & ~(CSTOPB|CBAUD)) | i ;
  505. #    cflags[1] = (cflags[1] & ~(CSTOPB|CBAUD)) | i ;
  506. #    cflags[2] = (cflags[2] & ~(CSTOPB|CBAUD)) | i ;
  507. #    cflags[3] = (cflags[3] & ~(CSTOPB|CBAUD)) | i ;
  508. #
  509. #    setflags() ;
  510. #
  511. #    if (debug & D_LINE) dialmsg("New baud rate: %d\n", baud) ;
  512. #    return(0) ;
  513. #    }
  514. #
  515. #
  516. #
  517. #/*****
  518. # *    waitcarrier - Wait for carrier.
  519. # */
  520. #
  521. #static int
  522. #waitcarrier(timeout)
  523. #short timeout ;                /* Max time to wait */
  524. #{
  525. #    register int fd ;
  526. #
  527. #    if (debug & D_LINE) dialmsg("Waiting for carrier detect.\n") ;
  528. #
  529. #    (void) alarm((unsigned)timeout) ;
  530. #
  531. #    fd = open(dialdev, O_RDWR) ;
  532. #    if (fd < 0) {
  533. #        if (debug & D_LINE) dialmsg("%s: %s\n", errstring(), dialdev) ;
  534. #        }
  535. #    else {
  536. #        (void) close(fd) ;
  537. #        if (debug & D_LINE) dialmsg("Carrier detected.\n") ;
  538. #        }
  539. #
  540. #    (void) alarm(0) ;
  541. #
  542. #    return(fd) ;
  543. #    }
  544. #
  545. #
  546. #
  547. #/*****
  548. # *    dialopen - Open communication line device.
  549. # */
  550. #
  551. #static int
  552. #dialopen()
  553. #{
  554. #    /*
  555. #     *    Open the tty communication line device with O_NDELAY.
  556. #     *    Once the device is open, turn off O_NDELAY.
  557. #     */
  558. #
  559. #    dialfd = open(dialdev, O_RDWR|O_NDELAY) ;
  560. #    if (dialfd < 0) {
  561. #        if (debug) dialmsg("%s: %s\n", errstring(), dialdev) ;
  562. #        return(-1) ;
  563. #        }
  564. #
  565. #    if (debug & D_LINE) dialmsg("Opened comm line.\n") ;
  566. #
  567. #    /*
  568. #     *    Turn off carrier sense.
  569. #     */
  570. #
  571. #    carrier = -1 ;
  572. #    setcarrier(0) ;
  573. #
  574. #    /*
  575. #     *    For some reason, this open appears to be necessary,
  576. #     *    at least on Plexus.
  577. #     */
  578. #
  579. #    YIPE(close(open(dialdev, O_RDWR))) ;
  580. #
  581. #    /*
  582. #     *    Turn off NDELAY, flush I/O and unblock output.
  583. #     */
  584. #
  585. #    YIPE(fcntl(dialfd, F_SETFL, O_RDWR)) ;
  586. #    YIPE(ioctl(dialfd, TCFLSH, 2)) ;
  587. #    YIPE(ioctl(dialfd, TCXONC, 1)) ;
  588. #
  589. #    return(0) ;
  590. #    }
  591. #
  592. #
  593. #
  594. #/*****
  595. # *    dialbreak - Send break.
  596. # */
  597. #
  598. #static void
  599. #dialbreak()
  600. #{
  601. #    YIPE(ioctl(dialfd,TCSBRK,0)) ;
  602. #
  603. #    if (debug & (D_LINE|D_COMM)) dialmsg("Sent break signal.\n") ;
  604. #    }
  605. #
  606. #
  607. #
  608. #/****
  609. # *    dialclose - Close communication line.
  610. # */
  611. #
  612. #static void
  613. #dialclose()
  614. #{
  615. #    YIPE(ioctl(dialfd,TCFLSH,2)) ;
  616. #    YIPE(close(dialfd)) ;
  617. #    dialfd = -1 ;
  618. #
  619. #    if (debug & D_LINE) {
  620. #        dialmsg("Closed comm device.\n") ;
  621. #        }
  622. #    }
  623. #
  624. #
  625. #
  626. #/*****
  627. # *    send - Send characters to the comm line.
  628. # */
  629. #
  630. #static int
  631. #send(buf)
  632. #char *buf ;                        /* Buffer to send */
  633. #{
  634. #    register short nsend ;
  635. #    register short nbyte ;
  636. #
  637. #    /*
  638. #     *    Flush I/O queues and make sure we are not blocked
  639. #     *    by an XOFF.
  640. #     */
  641. #
  642. #    YIPE(ioctl(dialfd,TCFLSH,2)) ;
  643. #    YIPE(ioctl(dialfd,TCXONC,1)) ;
  644. #
  645. #    /*
  646. #     *    Setup an alarm to detect transmit failure and
  647. #     *    write the data.
  648. #     */
  649. #
  650. #    gotalarm = 0 ;
  651. #    (void) alarm(10) ;
  652. #
  653. #    nsend = strlen(buf) ;
  654. #    nbyte = write(dialfd, buf, (unsigned) nsend) ;
  655. #
  656. #    (void) alarm(0) ;
  657. #
  658. #    /*
  659. #     *    Debug print.
  660. #     */
  661. #
  662. #    if (debug & D_COMM) {
  663. #        dialmsg("Sent: ") ;
  664. #        showstring(buf) ;
  665. #        (void) putc('\n', stderr) ;
  666. #        }
  667. #
  668. #    /*
  669. #     *    Return status.
  670. #     */
  671. #
  672. #    return (nbyte != nsend || gotalarm) ? -1 : 0 ;
  673. #    }
  674. #
  675. #
  676. #
  677. #/****
  678. # *    receive - Receive data from the comm line until a
  679. # *              recognized state, a hangup, or a timeout
  680. # *              is detected.
  681. # */
  682. #
  683. #static int
  684. #receive(nmatch, match, sec)
  685. #short nmatch ;                        /* Number of match items */
  686. #MATCH *match ;                        /* Match string array */
  687. #short sec ;                            /* Timeout */
  688. #{
  689. #    register MATCH *mp ;
  690. #    register char *s ;
  691. #    register short ch ;
  692. #    register short index ;
  693. #    register short i ;
  694. #    register short last ;
  695. #    register short l ;
  696. #    register short n ;
  697. #    short state ;
  698. #    char buf[4] ;
  699. #
  700. #    state = DS_NONE ;
  701. #    match += nmatch ;
  702. #
  703. #    gotalarm = 0 ;
  704. #    (void) alarm((unsigned)sec) ;
  705. #
  706. #    /*
  707. #     *    Major loop - read data and scan for a state.
  708. #     */
  709. #
  710. #    loop {
  711. #        /*
  712. #         *    Read the next input character.  This is done
  713. #         *    unbuffered deliberately,  so we don't read
  714. #         *    ahead any data we want to leave in the buffer
  715. #         *    for the caller.
  716. #         */
  717. #
  718. #        if (gotalarm == 0) {
  719. #            n = read(dialfd, buf, 1) ;
  720. #            if (n < 0 && (debug & D_LINE)) {
  721. #                dialmsg("Read: %d, %s\n", n, errstring()) ;
  722. #                }
  723. #            }
  724. #
  725. #        /*
  726. #         *    Handle timeout condition.
  727. #         */
  728. #
  729. #        if (gotalarm) {
  730. #            if (debug & (D_LINE|D_MATCH)) dialmsg("Receive timeout.\n") ;
  731. #            dialerror() ;
  732. #            state = DS_TIMEOUT ;
  733. #            break ;
  734. #            }
  735. #
  736. #        /*
  737. #         *    Handle hangup condition.
  738. #         */
  739. #
  740. #        if (n == 0) {
  741. #            if (debug & (D_LINE|D_MATCH)) dialmsg("Lost carrier.\n") ;
  742. #            dialerror() ;
  743. #            state = DS_HANGUP ;
  744. #            break ;
  745. #            }
  746. #
  747. #        /*
  748. #         *    Handle unexpected error and fail.
  749. #         */
  750. #
  751. #        if (n != 1) {
  752. #            dialmsg("Read returned %d, %s\n", n, errstring) ;
  753. #            dialerror() ;
  754. #            state = DS_FAIL ;
  755. #            break ;
  756. #            }
  757. #
  758. #        /*
  759. #         *    Utterly ignore nulls and rubouts.
  760. #         */
  761. #
  762. #        ch = buf[0] ;
  763. #        if (ch == 0 || ch == 0x7f) continue ;
  764. #
  765. #        /*
  766. #         *    Debug print.
  767. #         */
  768. #
  769. #        if (debug & D_COMM) {
  770. #            if (inline == 0) {
  771. #                dialmsg("Got: ") ;
  772. #                inline = 1 ;
  773. #                }
  774. #            showchar(ch) ;
  775. #            if (ch == '\n') {
  776. #                (void) putc('\n', stderr) ;
  777. #                (void) fflush(stderr) ;
  778. #                inline = 0 ;
  779. #                }
  780. #            }
  781. #
  782. #        /*
  783. #         *    Match the received character against all
  784. #         *    the expected receive match strings.
  785. #         *
  786. #         *    Each match item contains an "index" which
  787. #         *    keeps track of the number of characters matched
  788. #         *    so far.
  789. #         *
  790. #         *    When all characters in a string are matched,
  791. #         *    we return the associated "state".
  792. #         *
  793. #         *    When a character match fails, "index" is
  794. #         *    backed down accordingly.
  795. #         */
  796. #
  797. #        n = nmatch ;
  798. #        mp = match ;
  799. #
  800. #        while (--n >= 0) {
  801. #            --mp ;
  802. #            index = mp->m_index ;
  803. #            s = mp->m_string ;
  804. #
  805. #            if (ch == s[index]) {
  806. #                index++ ;
  807. #                if (s[index] == 0) {
  808. #                    state = mp->m_state ;
  809. #                    break ;
  810. #                    }
  811. #                }
  812. #
  813. #            else if (index != 0) {
  814. #                last = index ;
  815. #                index-- ;
  816. #                loop {
  817. #                    if (ch == s[index]) {
  818. #                        i = index ;
  819. #                        l = last ;
  820. #                        while (--i >= 0 && s[i] == s[--l]) ;
  821. #                        if (i < 0) break ;
  822. #                        }
  823. #                    if (--index < 0) break ;
  824. #                    }
  825. #                index++ ;
  826. #                }
  827. #
  828. #            mp->m_index = index ;
  829. #            }
  830. #
  831. #        if (state != DS_NONE) {
  832. #            if (debug & D_MATCH) {
  833. #                dialmsg("Matched: ") ;
  834. #                showstring(s) ;
  835. #                (void) putc('\n', stderr) ;
  836. #                (void) fflush(stderr) ;
  837. #                }
  838. #            break ;
  839. #            }
  840. #        }
  841. #
  842. #    (void) alarm(0) ;
  843. #
  844. #    if (inline) {
  845. #        (void) putc('\n', stderr) ;
  846. #        (void) fflush(stderr) ;
  847. #        }
  848. #
  849. #    return(state) ;
  850. #    }
  851. #
  852. #
  853. #
  854. #/******
  855. # *    statestr - Generate state string representation.
  856. # */
  857. #
  858. #static void
  859. #statestr(str, state)
  860. #char *str ;                        /* Destination string */
  861. #int state ;                        /* State to display */
  862. #{
  863. #    if (state == DS_FAIL) (void) strcpy(str, "-") ;
  864. #    else if (state == DS_SUCCEED) (void) strcpy(str, "+") ;
  865. #    else (void) sprintf(str, "%d", state) ;
  866. #    }
  867. #
  868. #
  869. #
  870. #/******
  871. # *    expand - Expand string.
  872. # */
  873. #
  874. #static void
  875. #expand(dest, source, di)
  876. #register char *dest ;                /* Destination string */
  877. #register char *source ;                /* Source string */
  878. #DINFO *di ;                            /* Dial info structure */
  879. #{
  880. #    register char *cp ;
  881. #    register char *rp ;
  882. #    register short ch ;
  883. #    register short c ;
  884. #    register int i ;
  885. #
  886. #    rp = 0 ;
  887. #
  888. #    while (ch = *source++) {
  889. #
  890. #        /*
  891. #         *    Get control character escapes.
  892. #         */
  893. #
  894. #        if (ch == '^') ch = *source++ & 0x1f ;
  895. #
  896. #        /*
  897. #         *    Handle escape characters.
  898. #         */
  899. #
  900. #        else if (ch == '\\') {
  901. #
  902. #            switch (ch = *source++) {
  903. #
  904. #                /*
  905. #                 *    Standard "C" escapes.
  906. #                 */
  907. #
  908. #                case 'f':
  909. #                    ch = '\f' ;
  910. #                    break ;
  911. #
  912. #                case 'b':
  913. #                    ch = '\b' ;
  914. #                    break ;
  915. #
  916. #                case 'n':
  917. #                    ch = '\n' ;
  918. #                    break ;
  919. #
  920. #                case 'r':
  921. #                    ch = '\r' ;
  922. #                    break ;
  923. #
  924. #                case 't':
  925. #                    ch = '\t' ;
  926. #                    break ;
  927. #
  928. ##ifndef lint
  929. #                /*
  930. #                 *    Hex character constant.
  931. #                 */
  932. #
  933. #                case '$':
  934. #                    ch = 0 ;
  935. #                    i = 2 ;
  936. #                    loop {
  937. #                        c = *source ;
  938. #                        if ('0' <= c && c <= '9') c -= '0' ;
  939. #                        else if ('A' <= c && c <= 'F') c -= 'A' - 10 ;
  940. #                        else if ('a' <= c && c <= 'f') c -= 'a' - 10 ;
  941. #                        else break ;
  942. #                        ch = 16 * ch + c ;
  943. #                        source++ ;
  944. #                        if (--i == 0) break ;
  945. #                        }
  946. #                    break ;
  947. ##endif
  948. #
  949. #                /*
  950. #                 *    Octal character constant.
  951. #                 */
  952. #
  953. #                case '0':
  954. #                case '1':
  955. #                case '2':
  956. #                case '3':
  957. #                case '4':
  958. #                case '5':
  959. #                case '6':
  960. #                case '7':
  961. #                    ch = 0 ;
  962. #                    i = 3 ;
  963. #                    loop {
  964. #                        c = *source ;
  965. #                        if ('0' <= c && c <= '7') c -= '0' ;
  966. #                        else break ;
  967. #                        ch = 8 * ch + c ;
  968. #                        source++ ;
  969. #                        if (--i == 0) break ;
  970. #                        }
  971. #                    break ;
  972. #
  973. #                default:
  974. #                    ch = *source++ ;
  975. #                }
  976. #            }
  977. #
  978. #        /*
  979. #         *    Handle %x escapes.
  980. #         */
  981. #
  982. #        else if (ch == '%') {
  983. #
  984. #            switch(ch = *source++) {
  985. #
  986. #                /*
  987. #                 *    Columns 1-9 of L-devices.
  988. #                 */
  989. #
  990. #                case '1':
  991. #                case '2':
  992. #                case '3':
  993. #                case '4':
  994. #                case '5':
  995. #                case '6':
  996. #                case '7':
  997. #                case '8':
  998. #                case '9':
  999. #                    rp = ldevice[ch - '0'] ;
  1000. #                    break ;
  1001. #
  1002. #                /*
  1003. #                 *    Environment variable.
  1004. #                 */
  1005. #
  1006. #                case '{':
  1007. #                    ch = 0 ;
  1008. #                    cp = source ;
  1009. #                    rp = dest ;
  1010. #                    loop {
  1011. #                        if (*cp == 0) {
  1012. #                            rp = "%{";
  1013. #                            break;
  1014. #                            }
  1015. #                        if (*cp == '}') {
  1016. #                            *rp = 0;
  1017. #                            rp = getenv(dest);
  1018. #                            source = cp + 1;
  1019. #                            break;
  1020. #                            }
  1021. #                        *rp++ = *cp++;
  1022. #                        }
  1023. #                    break;
  1024. #
  1025. #                /*
  1026. #                 *    Untranslated phone number.
  1027. #                 */
  1028. #
  1029. #                case 'n':
  1030. #                    rp = dialnum ;
  1031. #                    break;
  1032. #
  1033. #                /*
  1034. #                 *    Translated telephone number.
  1035. #                 */
  1036. #
  1037. #                case 'N':
  1038. #                    cp = dialnum;
  1039. #                    while (ch = *cp++) {
  1040. #                        switch (ch) {
  1041. #                            case '*':
  1042. #                            case ':':
  1043. #                            case 's':
  1044. #                                rp = di->di_star ;
  1045. #                                break ;
  1046. #
  1047. #                            case '#':
  1048. #                            case ';':
  1049. #                            case 'p':
  1050. #                                rp = di->di_pound ;
  1051. #                                break ;
  1052. #
  1053. #                            case '-':
  1054. #                            case 'd':
  1055. #                                rp = di->di_delay ;
  1056. #                                break ;
  1057. #
  1058. #                            case '=':
  1059. #                            case 'w':
  1060. #                                rp = di->di_wait ;
  1061. #                                break ;
  1062. #
  1063. #                            case 'f':
  1064. #                                rp = di->di_flash ;
  1065. #                                break ;
  1066. #                            }
  1067. #
  1068. #                        if (rp != 0) {
  1069. #                            while (*rp) *dest++ = *rp++ ;
  1070. #                            rp = 0 ;
  1071. #                            }
  1072. #                        else *dest++ = ch ;
  1073. #                        }
  1074. #                    break;
  1075. #
  1076. #                /*
  1077. #                 *    %% becomes %.
  1078. #                 */
  1079. #
  1080. #                case '%':
  1081. #                    break;
  1082. #
  1083. #                /*
  1084. #                 *    Other %x escapes pass through untouched.
  1085. #                 */
  1086. #
  1087. #                default:
  1088. #                    *dest++ = '%';
  1089. #                    break;
  1090. #                }
  1091. #            }
  1092. #
  1093. #        /*
  1094. #         *    Output translate string, translated character,
  1095. #         *    or original character untouched.
  1096. #         */
  1097. #
  1098. #        if (rp != 0) {
  1099. #            while (*rp) *dest++ = *rp++ ;
  1100. #            rp = 0;
  1101. #            }
  1102. #
  1103. #        else if (ch != 0) *dest++ = ch ;
  1104. #        }
  1105. #
  1106. #    *dest = 0 ;
  1107. #    }
  1108. #
  1109. #
  1110. #
  1111. ##if 0
  1112. #/******
  1113. # *    sysname - Read L.sys file and look up phone number as
  1114. # *              system name.
  1115. # */
  1116. #
  1117. #static void
  1118. #sysname(telno)
  1119. #register char *telno ;
  1120. #{
  1121. #    register FILE *file ;
  1122. #    register short ch ;
  1123. #    register short i ;
  1124. #    char *word[5] ;
  1125. #    register char *bp ;
  1126. #    char buf[80] ;
  1127. #    static char fname[] = "/usr/lib/uucp/L.sys" ;
  1128. #
  1129. #    file = fopen(fname, "r") ;
  1130. #    if (file == 0) {
  1131. #        if (errno != EACCES) dialmsg("%s: %s\n", errstring(), fname) ;
  1132. #        return ;
  1133. #        }
  1134. #
  1135. #    /*
  1136. #     *    Read all lines from the file.
  1137. #     */
  1138. #
  1139. #    for (;;) {
  1140. #
  1141. #        /*
  1142. #         *    Read a line from the file and break it out
  1143. #         *    into 5 fields separated by white space.
  1144. #         */
  1145. #
  1146. #        ch = getc(file) ;
  1147. #        bp = buf ;
  1148. #
  1149. #        for (i = 0 ; i < 5 ; i++) {
  1150. #            word[i] = bp ;
  1151. #            while (ch != ' ' && ch != '\t' && ch != '\n') {
  1152. #                if (ch == EOF) goto done ;
  1153. #                if (bp < buf+75) *bp++ = ch ;
  1154. #                ch = getc(file) ;
  1155. #                }
  1156. #            *bp++ = 0 ;
  1157. #            while (ch == ' ' || ch == '\t') ch = getc(file) ;
  1158. #            }
  1159. #
  1160. #        while (ch != '\n') {
  1161. #            ch = getc(file) ;
  1162. #            if (ch == EOF) goto done ;
  1163. #            }
  1164. #
  1165. ##if 0
  1166. #        (void) printf("L.sys: %s %s %s %s %s\n",
  1167. #            word[0], word[1], word[2], word[3], word[4]
  1168. #            ) ;
  1169. ##endif
  1170. #
  1171. #        /*
  1172. #         *    If the system name matches, and not a direct
  1173. #         *    entry, replace the phone number with the phone
  1174. #         *    number for the system.
  1175. #         */
  1176. #
  1177. #        if    (    strcmp(word[0], telno) == 0
  1178. #            &&    strcmp(word[2], "DIR") != 0
  1179. #            )
  1180. #        {
  1181. #            (void) strcpy(telno, word[4]) ;
  1182. #            break ;
  1183. #            }
  1184. #        }
  1185. #
  1186. #done:
  1187. #    (void) fclose(file) ;
  1188. #    }
  1189. ##endif
  1190. #
  1191. #
  1192. #
  1193. #/******
  1194. # *    dialcodes - Read dialcodes file and fool with phone number.
  1195. # */
  1196. #
  1197. #static void
  1198. #dialcodes(telno)
  1199. #register char *telno ;
  1200. #{
  1201. #    register FILE *file ;
  1202. #    register char *cp ;
  1203. #    register int ch ;
  1204. #    register int n ;
  1205. #    char buf[100] ;
  1206. #    static char fname[] = "/usr/lib/uucp/L-dialcodes" ;
  1207. #
  1208. #    /*
  1209. #     *    Open the dialcodes file.
  1210. #     */
  1211. #
  1212. #    file = fopen(fname, "r") ;
  1213. #    if (file == 0) {
  1214. #        dialmsg("%s: %s\n", errstring(), fname) ;
  1215. #        return ;
  1216. #        }
  1217. #
  1218. #    /*
  1219. #     *    Read all lines of the file until a match
  1220. #     *    or end-of-file is reached.
  1221. #     */
  1222. #
  1223. #    loop {
  1224. #
  1225. #        /*
  1226. #         *    Search for a space-terminated code in the file
  1227. #         *    which matches the phone number prefix.
  1228. #         *
  1229. #         *    When a match is found, replace the match prefix
  1230. #         *    with the remainder of the line.
  1231. #         */
  1232. #
  1233. #        cp = telno ;
  1234. #        loop {
  1235. #            ch = getc(file) ;
  1236. #            if (ch == ' ') {
  1237. #                (void) strncpy(buf, cp, sizeof(buf)) ;
  1238. #                n = sizeof(buf) - 1 ;
  1239. #                loop {
  1240. #                    ch = getc(file) ;
  1241. #                    if (ch == EOF || ch == '\n' || --n < 0) break ;
  1242. #                    *telno++ = ch ;
  1243. #                    }
  1244. #                cp = buf ;
  1245. #                while (*cp && --n >= 0) *telno++ = *cp++ ;
  1246. #                *telno = 0 ;
  1247. #                goto done ;
  1248. #                }
  1249. #            if (ch != *cp++) break ;
  1250. #            }
  1251. #
  1252. #        /*
  1253. #         *    Skip to end-of-line.
  1254. #         */
  1255. #
  1256. #        while (ch != '\n') {
  1257. #            if (ch == EOF) goto done ;
  1258. #            ch = getc(file) ;
  1259. #            }
  1260. #        }
  1261. #
  1262. #done:
  1263. #    (void) fclose(file) ;
  1264. #    }
  1265. #
  1266. #
  1267. #
  1268. #static int
  1269. #dostate(state, di, ds, depth)
  1270. #int state ;                        /* State number */
  1271. #register DINFO *di ;            /* Dialer information */
  1272. #register DSTATE *ds ;            /* State variables */
  1273. #int depth ;                        /* Use state depth */
  1274. #{
  1275. #    register char *cp ;
  1276. #    register char *bp ;
  1277. #    register MATCH *mp ;
  1278. #    char *errp ;
  1279. #    register short ch ;
  1280. #    short i ;
  1281. #
  1282. #    cp = di->di_state[state] ;
  1283. #
  1284. #    if (cp == 0) {
  1285. #        dialmsg("Transferred to undefined state: %d\n", state) ;
  1286. #        return (A_PROB) ;
  1287. #        }
  1288. #
  1289. #    if (depth > 10) {
  1290. #        dialmsg("Use command depth overflow, state: %d\n", state) ;
  1291. #        return(A_PROB) ;
  1292. #        }
  1293. #
  1294. #    if (debug & D_STATE) {
  1295. #        dialmsg("using: s%d=%s\n", state, cp) ;
  1296. #        }
  1297. #
  1298. #    /*
  1299. #     *    Loop over all commands in string.
  1300. #     */
  1301. #
  1302. #    loop {
  1303. #
  1304. #        /*
  1305. #         *    Skip over white space.
  1306. #         */
  1307. #
  1308. #        ch = *cp++ ;
  1309. #        while (isspace(ch)) ch = *cp++ ;
  1310. #
  1311. #        if (ch == 0) return(DS_NONE) ;
  1312. #
  1313. #        errp = cp - 1 ;
  1314. #
  1315. #        /*
  1316. #         *    Parse next command in state string.
  1317. #         */
  1318. #
  1319. #        if (islower(ch)) ch = toupper(ch) ;
  1320. #
  1321. #        switch (ch) {
  1322. #
  1323. #            /*
  1324. #             *    Parse Break.
  1325. #             */
  1326. #
  1327. #            case 'B':
  1328. #                break ;
  1329. #
  1330. #            /*
  1331. #             *    Error messages and modem string.
  1332. #             */
  1333. #
  1334. #            case 'E':
  1335. #            case 'M':
  1336. #            case 'F':
  1337. #                if (*cp++ != '"') goto error ;
  1338. #                bp = ds->ds_buf ;
  1339. #                loop {
  1340. #                    if (*cp == '"') break ;
  1341. #                    if (*cp == 0) goto error ;
  1342. #                    if (cp[0] == '\\' && cp[1] == ']') cp++ ;
  1343. #                    *bp++ = *cp++ ;
  1344. #                    }
  1345. #                *bp++ = 0 ;
  1346. #                cp++ ;
  1347. #                break ;
  1348. #
  1349. #            /*
  1350. #             *    Carrier sense.
  1351. #             */
  1352. #
  1353. #            case 'C':
  1354. #                cp = parseshort(cp, &i, 0, 4) ;
  1355. #                break ;
  1356. #
  1357. #            /*
  1358. #             *    Retry decrement.
  1359. #             */
  1360. #
  1361. #            case 'R':
  1362. #                cp = parseshort(cp, &i, 1, 1000) ;
  1363. #                break ;
  1364. #
  1365. #            /*
  1366. #             *    Baud rate.
  1367. #             */
  1368. #
  1369. #            case 'N':
  1370. #                cp = parseshort(cp, &i, 50, 30000) ;
  1371. #                break ;
  1372. #
  1373. #            /*
  1374. #             *    Delay time, Pause time, and Seconds of timeout.
  1375. #             */
  1376. #
  1377. #            case 'D':
  1378. #            case 'P':
  1379. #            case 'S':
  1380. #                cp = parseshort(cp, &i, 1, 120) ;
  1381. #                break ;
  1382. #
  1383. #            /*
  1384. #             *    Pattern match.
  1385. #             */
  1386. #
  1387. #            case '[':
  1388. #                bp = ds->ds_buf + 50 ;
  1389. #                loop {
  1390. #                    if (*cp == ']') break ;
  1391. #                    if (*cp == 0) goto error ;
  1392. #                    if (cp[0] == '\\' && cp[1] == ']') cp++ ;
  1393. #                    *bp++ = *cp++ ;
  1394. #                    }
  1395. #                *bp = 0 ;
  1396. #                cp++ ;
  1397. #
  1398. #            /*
  1399. #             *    Goto, Hangup, and Timeout states.
  1400. #             */
  1401. #
  1402. #            case 'G':
  1403. #            case 'H':
  1404. #            case 'T':
  1405. #                if (*cp == '+') {
  1406. #                    cp++ ;
  1407. #                    i = DS_SUCCEED ;
  1408. #                    break ;
  1409. #                    }
  1410. #                if (*cp == '-') {
  1411. #                    cp++ ;
  1412. #                    i = DS_FAIL ;
  1413. #                    break ;
  1414. #                    }
  1415. #
  1416. #            /*
  1417. #             *    Use other state.
  1418. #             */
  1419. #
  1420. #            case 'U':
  1421. #                cp = parseshort(cp, &i, 0, NSTATE-1) ;
  1422. #                break ;
  1423. #
  1424. #            default:
  1425. #                cp = 0 ;
  1426. #            }
  1427. #
  1428. #        /*
  1429. #         *    Handle parsing error.
  1430. #         */
  1431. #
  1432. #        if (cp == 0) goto error ;
  1433. #
  1434. #        /*
  1435. #         *    Action parsed okay, now execute it.
  1436. #         */
  1437. #
  1438. #        switch (ch) {
  1439. #
  1440. #            /*
  1441. #             *    Send a break signal to the remote.
  1442. #             */
  1443. #
  1444. #            case 'B':
  1445. #                dialbreak() ;
  1446. #                break ;
  1447. #
  1448. #            /*
  1449. #             *    Change carrier sense.
  1450. #             */
  1451. #
  1452. #            case 'C':
  1453. #                if (i <= 3) setcarrier(i) ;
  1454. #                else {
  1455. #                    setcarrier(3) ;
  1456. #                    i = waitcarrier(ds->ds_sec) ;
  1457. #                    if (i < 0) return(DS_TIMEOUT) ;
  1458. #                    }
  1459. #                break ;
  1460. #
  1461. #            /*
  1462. #             *    Drop DTR time.
  1463. #             */
  1464. #
  1465. #            case 'D':
  1466. #                dropdtr(i) ;
  1467. #                break ;
  1468. #
  1469. #            /*
  1470. #             *    String to standard error.
  1471. #             */
  1472. #
  1473. #            case 'E':
  1474. #                expand(bp, ds->ds_buf, di) ;
  1475. #                dialmsg("%s\n", bp) ;
  1476. #                break ;
  1477. #
  1478. #            /*
  1479. #             *    Fail message string.
  1480. #             */
  1481. #
  1482. #            case 'F':
  1483. #                expand(ds->ds_failmsg, ds->ds_buf, di) ;
  1484. #                break ;
  1485. #
  1486. #            /*
  1487. #             *    Unconditional goto.
  1488. #             */
  1489. #
  1490. #            case 'G':
  1491. #                return(i) ;
  1492. #
  1493. #            /*
  1494. #             *    Hangup state.
  1495. #             */
  1496. #
  1497. #            case 'H':
  1498. #                ds->ds_hangup = i ;
  1499. #                break ;
  1500. #
  1501. #            /*
  1502. #             *    Send control string to modem.
  1503. #             */
  1504. #
  1505. #            case 'M':
  1506. #                expand(bp, ds->ds_buf, di) ;
  1507. #                if (send(bp) < 0) return(DS_TIMEOUT) ;
  1508. #                break ;
  1509. #
  1510. #            /*
  1511. #             *    Adopt new baud rate.
  1512. #             */
  1513. #
  1514. #            case 'N':
  1515. #                if (newbaud(i) < 0) goto error ;
  1516. #                break ;
  1517. #
  1518. #            /*
  1519. #             *    Pause for specified interval.
  1520. #             */
  1521. #
  1522. #            case 'P':
  1523. #                if (debug & D_LINE)
  1524. #                    dialmsg("Pause for %d seconds\n", i) ;
  1525. #                (void) sleep((unsigned) i) ;
  1526. #                break ;
  1527. #
  1528. #            /*
  1529. #             *    Decrement retry count.  If it goes negative,
  1530. #             *    return failure.
  1531. #             */
  1532. #
  1533. #            case 'R':
  1534. #                ds->ds_retry -= i ;
  1535. #                if (debug & D_STATE)
  1536. #                    dialmsg("Decrement retry by %d to %d\n", i, ds->ds_retry) ;
  1537. #                if (ds->ds_retry < 0) return(DS_FAIL) ;
  1538. #                break ;
  1539. #
  1540. #            /*
  1541. #             *    Seconds of timeout.
  1542. #             */
  1543. #
  1544. #            case 'S':
  1545. #                ds->ds_sec = i ;
  1546. #                break ;
  1547. #
  1548. #            /*
  1549. #             *    Timeout state.
  1550. #             */
  1551. #
  1552. #            case 'T':
  1553. #                ds->ds_timeout = i ;
  1554. #                break ;
  1555. #
  1556. #            /*
  1557. #             *    Use another state definition string.
  1558. #             */
  1559. #
  1560. #            case 'U':
  1561. #                i = dostate(i, di, ds, depth+1) ;
  1562. #                if (i != DS_NONE) return(i) ;
  1563. #                break ;
  1564. #
  1565. #            /*
  1566. #             *    Setup match strings.
  1567. #             */
  1568. #
  1569. #            case '[':
  1570. #                expand(ds->ds_buf, ds->ds_buf+50, di) ;
  1571. #                if (ds->ds_nmatch >= NMATCH) goto error ;
  1572. #                mp = &ds->ds_match[ds->ds_nmatch++] ;
  1573. #                mp->m_string = ds->ds_buf ;
  1574. #                mp->m_index = 0 ;
  1575. #                mp->m_state = i ;
  1576. #                ds->ds_buf += strlen(ds->ds_buf) + 1 ;
  1577. #                if (ds->ds_buf >= &ds->ds_buffer[NBUF-100]) goto error ;
  1578. #                break ;
  1579. #
  1580. #            default:
  1581. #                goto error ;
  1582. #            }
  1583. #        }
  1584. #
  1585. #    /*
  1586. #     *    Print diagnostic error.
  1587. #     */
  1588. #
  1589. #error:
  1590. #    dialmsg("Problem in dialer %s, state %d, field %s\n",
  1591. #        ldevice[2], state, errp) ;
  1592. #    return(A_PROB) ;
  1593. #    }
  1594. #
  1595. #
  1596. #
  1597. #/******
  1598. # *    dialstate - Dialer state machine.
  1599. # *
  1600. # *    Returns:    open file descriptor >= 0 for success.
  1601. # *                error code < 0 for failure.
  1602. # */
  1603. #
  1604. #static int
  1605. #dialstate(di)
  1606. #DINFO *di ;                        /* Dialer info structure */
  1607. #{
  1608. #    register short state ;
  1609. #    DSTATE ds ;
  1610. #    register int i ;
  1611. #    register MATCH *mp ;
  1612. #    char str1[10], str2[10] ;
  1613. #
  1614. #    /*
  1615. #     *    Initialize state machine.
  1616. #     */
  1617. #
  1618. #    ds.ds_retry = (di->di_retry > 0) ? di->di_retry : 1 ;
  1619. #    ds.ds_sec = 30 ;
  1620. #    ds.ds_timeout = DS_FAIL ;
  1621. #    ds.ds_hangup = DS_FAIL ;
  1622. #    ds.ds_failmsg[0] = 0 ;
  1623. #
  1624. #    cflags[0] = iflags[0] ;
  1625. #    cflags[1] = iflags[1] ;
  1626. #    cflags[2] = iflags[2] ;
  1627. #    cflags[3] = iflags[3] ;
  1628. #
  1629. #    /*
  1630. #     *    Begin in state 0 with the communication line open.
  1631. #     */
  1632. #
  1633. #    state = 0 ;
  1634. #    if (dialopen() < 0) return(L_PROB) ;
  1635. #
  1636. #    /*
  1637. #     *    Process dial states until success or failure.
  1638. #     */
  1639. #
  1640. #    loop {
  1641. #
  1642. #        if (debug & D_STATE) {
  1643. #            dialmsg("Entering state: %d\n", state) ;
  1644. #            }
  1645. #
  1646. #        /*
  1647. #         *    Initialize the match list.
  1648. #         */
  1649. #
  1650. #        ds.ds_nmatch = 0 ;
  1651. #        ds.ds_buf = &ds.ds_buffer[0] ;
  1652. #
  1653. #        /*
  1654. #         *    Execute the specified state.
  1655. #         */
  1656. #
  1657. #        state = dostate(state, di, &ds, 1) ;
  1658. #
  1659. #        /*
  1660. #         *    Do the receive with the user-specified
  1661. #         *    timeout value.
  1662. #         */
  1663. #
  1664. #        if (state == DS_NONE) {
  1665. #            if (debug & D_MATCH) {
  1666. #                statestr(str1, ds.ds_hangup) ;
  1667. #                statestr(str2, ds.ds_timeout) ;
  1668. #                dialmsg("Receive parameters: C%d H%s S%d T%s\n",
  1669. #                    carrier, str1, ds.ds_sec, str2
  1670. #                    ) ;
  1671. #                dialmsg("Patterns:") ;
  1672. #                i = ds.ds_nmatch ;
  1673. #                mp = ds.ds_match ;
  1674. #                while (--i >= 0) {
  1675. #                    statestr(str1, mp->m_state) ;
  1676. #                    (void) fprintf(stderr, " [%s]%s", mp->m_string, str1) ;
  1677. #                    mp++ ;
  1678. #                    }
  1679. #                (void) fprintf(stderr, "\n") ;
  1680. #                }
  1681. #            state = receive(ds.ds_nmatch, ds.ds_match, ds.ds_sec) ;
  1682. #            }
  1683. #
  1684. #        /*
  1685. #         *    Determine next state.
  1686. #         */
  1687. #
  1688. #        if (state == DS_TIMEOUT) {
  1689. #            state = ds.ds_timeout ;
  1690. #            }
  1691. #        else if (state == DS_HANGUP) {
  1692. #            state = ds.ds_hangup ;
  1693. #            }
  1694. #
  1695. #        if (state == DS_NONE) state = 0 ;
  1696. #
  1697. #        if (state == DS_SUCCEED) return(dialfd) ;
  1698. #
  1699. #        if ((unsigned) state >= NSTATE) {
  1700. #            if (*ds.ds_failmsg) dialmsg("%s\n", ds.ds_failmsg) ;
  1701. #            dialclose() ;
  1702. #            return(state >= 0 ? NO_ANS : state) ;
  1703. #            }
  1704. #        }
  1705. #    }
  1706. #
  1707. #
  1708. #
  1709. #/******
  1710. # *    dial - System V dial(3).
  1711. # */
  1712. #
  1713. #int
  1714. #dial(call)
  1715. #CALL call ;                        /* See dial(3) */
  1716. #{
  1717. #    register char *cp ;
  1718. #    register char *dp ;
  1719. #    register int i ;
  1720. #    register int n ;
  1721. #    register int ch ;
  1722. #    register FILE *file ;
  1723. #    int lockfd ;
  1724. #    int gotint ;
  1725. #    int gotdinfo ;
  1726. #    int rtn ;
  1727. #    int num ;
  1728. #    int speed ;
  1729. #    unsigned alarmval ;
  1730. #    int (*alarmproc)() ;
  1731. #    int found ;
  1732. #    int (*save)() ;
  1733. #    int (*sigsave[4])() ;
  1734. #    struct termio attr ;
  1735. #    DINFO dinfo ;
  1736. #
  1737. #    static short signum[4] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM } ;
  1738. #
  1739. #    /*
  1740. #     *    Setup debug print options.
  1741. #     */
  1742. #
  1743. #    cp = getenv("DIALDEBUG") ;
  1744. #    if (cp) {
  1745. #        while (ch = *cp++) {
  1746. #            for (dp = dtable ; *dp ; dp += 2) {
  1747. #                if (dp[0] == ch) debug |= dp[1] ;
  1748. #                }
  1749. #            }
  1750. #        }
  1751. #
  1752. #    /*
  1753. #     *    Debug print call parameters.
  1754. #     */
  1755. #
  1756. #    if (debug) {
  1757. #        dialmsg("Dial called with:\n") ;
  1758. #        dialmsg("\tbaud=%d, speed=%d, line=%s, telno=%s\n",
  1759. #            call.baud, call.speed, NS(call.line), NS(call.telno)) ;
  1760. #        dialmsg("\tmodem=%d, device=%s, devlen=%d\n",
  1761. #            call.modem, NS(call.device), call.dev_len) ;
  1762. #        }
  1763. #
  1764. #    /*
  1765. #     *    Remove any pathname stuff from the beginning of
  1766. #     *    the line device name.
  1767. #     */
  1768. #
  1769. #    if (call.line != 0) {
  1770. #        cp = call.line ;
  1771. #        while (*cp) if (*cp++ == '/') call.line = cp ;
  1772. #        }
  1773. #
  1774. #    /*
  1775. #     *    Setup to catch interrupts.
  1776. #     */
  1777. #
  1778. #    lockfd = -1 ;
  1779. #    dialfd = -1 ;
  1780. #    file = 0 ;
  1781. #    gotdinfo = 0 ;
  1782. #
  1783. #    alarmval = alarm(0) ;
  1784. #    if ((alarmproc = signal(SIGALRM, SIG_IGN)) != SIG_IGN)
  1785. #        (void) signal(SIGALRM, wakeup) ;
  1786. #
  1787. #    if (gotint = setjmp(jmpstate)) {
  1788. #        rtn = INTRPT ;
  1789. #        goto done ;
  1790. #        }
  1791. #
  1792. #    for (i = 0 ; i < 4 ; i++)
  1793. #        if ((sigsave[i] = signal(signum[i], SIG_IGN)) != SIG_IGN)
  1794. #            (void) signal(signum[i], catch) ;
  1795. #
  1796. #    /*
  1797. #     *    Validate baud rates.
  1798. #     */
  1799. #
  1800. #    if (call.speed <= 0) call.speed = call.baud ;
  1801. #    if (call.baud <= 0) call.baud = call.speed ;
  1802. #
  1803. #    if    (    (call.speed > 0 && getbaud(call.speed) == -1)
  1804. #        ||    (call.baud > 0 && getbaud(call.baud) == -1)
  1805. #        )
  1806. #    {
  1807. #        rtn = ILL_BD ;
  1808. #        goto done ;
  1809. #        }
  1810. #
  1811. #    /*
  1812. #     *    Open and read L-devices file.
  1813. #     */
  1814. #
  1815. #    file = fopen("/usr/lib/uucp/L-devices", "r") ;
  1816. #    if (file == 0) {
  1817. #        rtn = NO_Ldv ;
  1818. #        goto done ;
  1819. #        }
  1820. #
  1821. #    /*
  1822. #     *    Traverse the L-devices file.
  1823. #     */
  1824. #
  1825. #    found = 0 ;
  1826. #
  1827. #    loop {
  1828. #
  1829. #        /*
  1830. #         *    Get the first 9 fields in each line.
  1831. #         */
  1832. #
  1833. #        ch = getc(file) ;
  1834. #        n = sizeof(ldbuf) - 9 ;
  1835. #        cp = ldbuf ;
  1836. #
  1837. #        for (i = 0 ; i < 9 ; i++) {
  1838. #            ldevice[i] = cp ;
  1839. #
  1840. #            while (ch == ' ' || ch == '\t') ch = getc(file) ;
  1841. #
  1842. #            while (ch != EOF && ch != ' ' && ch != '\t' && ch != '\n') {
  1843. #                if (--n > 0) *cp++ = ch ;
  1844. #                ch = getc(file) ;
  1845. #                }
  1846. #
  1847. #            *cp++ = 0 ;
  1848. #            n++ ;
  1849. #            }
  1850. #
  1851. #        while (ch != EOF && ch != '\n') ch = getc(file) ;
  1852. #
  1853. #        /*
  1854. #         *    If we have read to EOF, and still haven't found
  1855. #         *    a compatible device,  exit with an error.
  1856. #         */
  1857. #
  1858. #        if (ch == EOF) {
  1859. #            if (debug) dialmsg("No entry found in L-devices.\n") ;
  1860. #            rtn =
  1861. #                (    (call.line == 0 || *call.line == 0)
  1862. #                ?    (found ? NO_BD_A : NO_BD_K)
  1863. #                :    (found ? DV_NT_A : DV_NT_K)
  1864. #                ) ;
  1865. #            goto done ;
  1866. #            }
  1867. #
  1868. #        /*
  1869. #         *    Check for compatibility between the user's
  1870. #         *    request, and the current entry.
  1871. #         */
  1872. #
  1873. #        speed = atoi(ldevice[3]) ;
  1874. #
  1875. #        if    (    (    (call.telno == 0 || *call.telno == 0)
  1876. #                ?    strcmp(ldevice[0], "DIR") == 0
  1877. #                :    strcmp(ldevice[0], "ACU") == 0
  1878. #                )
  1879. #            &&    (    call.line == 0
  1880. #                ||    *call.line == 0
  1881. #                ||    strcmp(ldevice[1], call.line) == 0
  1882. #                )
  1883. #            &&    (call.speed <= 0 || speed == call.speed)
  1884. #            )
  1885. #        {
  1886. #            /*
  1887. #             *    This looks like a compatible entry.
  1888. #             */
  1889. #
  1890. #            found++ ;
  1891. #
  1892. #            if (debug & D_DEVICE) {
  1893. #                dialmsg("Using L-device: %s %s %s %s\n",
  1894. #                    ldevice[0], ldevice[1], ldevice[2], ldevice[3]) ;
  1895. #                }
  1896. #
  1897. #            /*
  1898. #             *    Attempt to create the lock file.  If we
  1899. #             *    can't,  advance to the next entry.
  1900. #             */
  1901. #
  1902. #            (void) strcpy(diallock, "/usr/spool/uucp/LCK..") ;
  1903. #            (void) strncat(diallock, ldevice[1], 20) ;
  1904. #
  1905. #            if (nolock == 0) {
  1906. #                lockfd = open(diallock, O_WRONLY|O_CREAT|O_EXCL, 0444) ;
  1907. #                if (lockfd < 0) {
  1908. #                    if (debug & D_DEVICE) {
  1909. #                        dialmsg("%s: %s\n", errstring(), diallock) ;
  1910. #                        }
  1911. #                    continue ;
  1912. #                    }
  1913. #
  1914. #                (void) close(lockfd) ;
  1915. #
  1916. #                if (debug & (D_LINE|D_DEVICE))
  1917. #                    dialmsg("Created lock file: %s\n", diallock) ;
  1918. #                }
  1919. #
  1920. #            /*
  1921. #             *    Get dialer characteristics from dialinfo file.
  1922. #             */
  1923. #
  1924. #            gotdinfo = 1 ;
  1925. #            if (dialinfo(&dinfo, ldevice[2]) < 0) {
  1926. #                rtn = A_PROB ;
  1927. #                goto done ;
  1928. #                }
  1929. #
  1930. #            /*
  1931. #             *    Figure out what the termio(7) c_cflags
  1932. #             *    byte should contain based on the user's
  1933. #             *    requests.
  1934. #             */
  1935. #
  1936. #            iflags[0] = getbaud(speed) ;
  1937. #            if (iflags[0] == -1) {
  1938. #                rtn = ILL_BD ;
  1939. #                goto done ;
  1940. #                }
  1941. #
  1942. #            iflags[0] |= CS8 | CREAD | CLOCAL | HUPCL ;
  1943. #
  1944. #            if (call.attr != 0) {
  1945. #                iflags[1] = call.attr->c_cflag | CREAD | CLOCAL | HUPCL ;
  1946. #                if ((iflags[1] & CBAUD) == 0) {
  1947. #                    iflags[1] |= iflags[0] & (CBAUD|CSTOPB) ;
  1948. #                    }
  1949. #                if (call.baud > 0) {
  1950. #                    iflags[1] &= ~CBAUD ;
  1951. #                    iflags[1] |= getbaud(call.baud) ;
  1952. #                    }
  1953. #                if ((iflags[1] & CSIZE) == 0) {
  1954. #                    iflags[1] |= iflags[0] & CSIZE ;
  1955. #                    }
  1956. #                }
  1957. #            else {
  1958. #                iflags[1] = iflags[0] ;
  1959. #                }
  1960. #
  1961. #            iflags[3] = iflags[1] & ~CLOCAL ;
  1962. #
  1963. #            iflags[2] = ((call.telno && *call.telno) || call.modem)
  1964. #                ? iflags[3] : iflags[1] ;
  1965. #
  1966. #            /*
  1967. #             *    Attempt dial out on all specified phone
  1968. #             *    numbers.
  1969. #             *
  1970. #             *    The "telno" string is a list of phone numbers
  1971. #             *    separated by commas.  Run through the list
  1972. #             *    until we get a connect or we get an error
  1973. #             *    more serious than "no answer".
  1974. #             */
  1975. #
  1976. #            (void) strcpy(dialdev, "/dev/") ;
  1977. #            (void) strcat(dialdev, ldevice[1]) ;
  1978. #
  1979. #            if (call.telno == 0) {
  1980. #                dialnum[0] = 0 ;
  1981. #                rtn = dialstate(&dinfo) ;
  1982. #                }
  1983. #            else {
  1984. #                cp = call.telno ;
  1985. #                loop {
  1986. #                    dp = dialnum ;
  1987. #                    i = sizeof(dialnum) ;
  1988. #                    while (*cp != 0 && *cp != ',' && --i > 0)
  1989. #                        *dp++ = *cp++ ;
  1990. #                    *dp = 0 ;
  1991. ##if 0
  1992. #                    sysname(dialnum) ;
  1993. ##endif
  1994. #                    dialcodes(dialnum) ;
  1995. #
  1996. #                    if (debug & D_DEVICE) dialmsg("Telno: %s\n", dialnum) ;
  1997. #
  1998. #                    rtn = dialstate(&dinfo) ;
  1999. #                    if (rtn != NO_ANS || *cp == 0) break ;
  2000. #                    cp++ ;
  2001. #                    }
  2002. #                }
  2003. #
  2004. #            if (rtn < 0) goto done ;
  2005. #
  2006. #            /*
  2007. #             *    Set the user's termio options.
  2008. #             */
  2009. #
  2010. #            if (call.attr != 0) {
  2011. #                attr = *call.attr ;
  2012. #                attr.c_cflag = cflags[carrier] ;
  2013. #                YIPE(ioctl(dialfd, TCSETA, &attr)) ;
  2014. #                }
  2015. #            goto done ;
  2016. #            }
  2017. #        }
  2018. #
  2019. #    /*
  2020. #     *    Universal return point.  Remove the lock file,
  2021. #     *    and restore all the caller's signals.  If we
  2022. #     *    got an interrupt apparently for the user, either
  2023. #     *    ignore it, call his processing routine, or exit
  2024. #     *    depending on his original options.
  2025. #     */
  2026. #
  2027. #done:
  2028. #    if (gotdinfo) dialfree(&dinfo) ;
  2029. #
  2030. #    if (file != 0) (void) fclose(file) ;
  2031. #
  2032. #    if (rtn < 0) {
  2033. #        if (lockfd >= 0 && nolock == 0) {
  2034. #            if (unlink(diallock) < 0)
  2035. #                dialmsg("Could not unlink %s: %s\n", diallock, errstring()) ;
  2036. #            else if (debug & (D_LINE|D_DEVICE))
  2037. #                dialmsg("Removed lock file: %s\n", diallock) ;
  2038. #            }
  2039. #        if (dialfd >= 0) dialclose() ;
  2040. #        }
  2041. #    else if (call.device != 0 && call.dev_len > 0)
  2042. #        (void) strncpy(call.device, dialdev, call.dev_len) ;
  2043. #
  2044. #    for (i = 0 ; i < 4 ; i++) {
  2045. #        num = signum[i] ;
  2046. #        save = sigsave[i] ;
  2047. #        if (save != SIG_IGN) {
  2048. #            (void) signal(num, save) ;
  2049. #            if (num == gotint) {
  2050. #                if (save == SIG_DFL) exit(1) ;
  2051. #                else (*save)(gotint) ;
  2052. #                }
  2053. #            }
  2054. #        }
  2055. #
  2056. #    (void) signal(SIGALRM, alarmproc) ;
  2057. #    (void) alarm((unsigned)alarmval) ;
  2058. #
  2059. #    if (debug) dialmsg("Dial returned: %d\n", rtn) ;
  2060. #
  2061. #    return(rtn) ;
  2062. #    }
  2063. #
  2064. #
  2065. #
  2066. #/*****
  2067. # *    undial - Clean up after successful dial.
  2068. # */
  2069. #
  2070. #void
  2071. #undial(fd)
  2072. #register int fd ;                /* File descriptor to close */
  2073. #{
  2074. #    register char *tty ;
  2075. #    register char *cp ;
  2076. #    char buf[50] ;
  2077. #
  2078. #    /*
  2079. #     *    Get the file descriptor tty name and
  2080. #     *    convert it to its uucp lockfile name.
  2081. #     */
  2082. #
  2083. #    tty = ttyname(fd) ;
  2084. #
  2085. #    if (tty == 0) {
  2086. #        dialmsg("Undial fd=%d: not a tty\n", fd) ;
  2087. #        return ;
  2088. #        }
  2089. #
  2090. #    cp = tty ;
  2091. #    while (*cp) {
  2092. #        if (*cp++ == '/') tty = cp ;
  2093. #        }
  2094. #
  2095. #    (void) strcpy(buf, "/usr/spool/uucp/LCK..") ;
  2096. #    (void) strcat(buf, tty) ;
  2097. #
  2098. #    if (!nolock && unlink(buf) < 0)
  2099. #        dialmsg("%s: %s", buf, errstring()) ;
  2100. #
  2101. #    /*
  2102. #     *    Close the file.
  2103. #     */
  2104. #
  2105. #    if (close(fd) < 0)
  2106. #        dialmsg("Undial fd=%d: %s\n", fd, errstring()) ;
  2107. #
  2108. #    if (debug & D_LINE)
  2109. #        dialmsg("Undial complete: fd=%d, %s\n", fd, tty) ;
  2110. #    }
  2111. end_dial.c
  2112.  
  2113.  
  2114.  
  2115.