home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / pcomm2 / part04 / dial.c < prev    next >
C/C++ Source or Header  |  1988-09-14  |  7KB  |  357 lines

  1. /*
  2.  * The routines that dial the modem and listen for the return codes.
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <termio.h>
  7. #include "config.h"
  8. #ifdef UNIXPC
  9. #include <sys/phone.h>
  10. #endif /* UNIXPC */
  11. #include "dial_dir.h"
  12. #include "misc.h"
  13. #include "modem.h"
  14. #include "param.h"
  15.  
  16. /*
  17.  * Get the dial string ready, send it to the modem.  The parameter is not
  18.  * the actual entry number, it is an index into the queue.
  19.  */
  20.  
  21. void
  22. dial_it(num)
  23. int num;
  24. {
  25.     extern int fd;
  26.     int i, skip;
  27.     char s[100], number[40], *strcpy(), *strcat(), *n, *strchr();
  28.     void send_str();
  29. #ifdef UNIXPC
  30.     struct updata pbuf;
  31.     unsigned int sleep();
  32. #endif /* UNIXPC */
  33.  
  34.     /*
  35.      * Create the string to be sent to the modem.  The long distance
  36.      * codes are added if they are requested.
  37.      */
  38.     s[0] = NULL;
  39.     strcpy(s, modem->dial[modem->m_cur]);
  40.  
  41.     switch (dir->q_ld[num]) {
  42.         case 0:            /* no ld code requested */
  43.             break;
  44.         case '+':
  45.             strcat(s, param->ld_plus);
  46.             break;
  47.         case '-':
  48.             strcat(s, param->ld_minus);
  49.             break;
  50.         case '@':
  51.             strcat(s, param->ld_at);
  52.             break;
  53.         case '#':
  54.             strcat(s, param->ld_pound);
  55.             break;
  56.     }
  57.     /*
  58.      * Purify the phone number by removing all the pretty characters
  59.      * that don't need to be sent to the modem.  Typically the "-",
  60.      * "(", ")", and space characters are just for looks.  To prevent
  61.      * this action, prepend a "\" to the character.
  62.      */
  63.     i = 0;
  64.     skip = 0;
  65.     n = dir->number[dir->q_num[num]];
  66.     while (*n) {
  67.         if (*n == '\\' && !skip) {
  68.             skip++;
  69.             n++;
  70.             continue;
  71.         }
  72.         if (!strchr("-() ", *n) || skip)
  73.             number[i++] = *n;
  74.         n++;
  75.         skip = 0;
  76.     }
  77.     number[i] = NULL;
  78.                     /* add it to the string */
  79.     strcat(s, number);
  80.     strcat(s, modem->suffix[modem->m_cur]);
  81. #ifdef DEBUG
  82.     fprintf(stderr, "raw dial string: '%s'\n", s);
  83. #endif /* DEBUG */
  84.  
  85. #ifdef UNIXPC
  86.                     /* special case for OBM */
  87.     if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  88.                     /* prepare the modem */
  89.         pbuf.c_lineparam = DATA|DTMF;
  90.         pbuf.c_waitdialtone = 5;
  91.         pbuf.c_linestatus = 0;
  92.         pbuf.c_feedback = SPEAKERON|NORMSPK;
  93.         pbuf.c_waitflash = 500;
  94.         ioctl(fd, PIOCSETP, &pbuf);
  95.         sleep(1);
  96.                     /* connect the dialer */
  97.         ioctl(fd, PIOCRECONN);
  98.         sleep(1);
  99.                     /* dial each digit */
  100.         n = s;
  101.         while (*n) {
  102.                     /* switch tone/pulse dialing? */
  103.             switch (*n) {
  104.                 case '^':
  105.                     pbuf.c_lineparam = DATA|PULSE;
  106.                     ioctl(fd, PIOCSETP, &pbuf);
  107.                     break;
  108.                 case '%':
  109.                     pbuf.c_lineparam = DATA|DTMF;
  110.                     ioctl(fd, PIOCSETP, &pbuf);
  111.                     break;
  112.                 default:
  113.                     ioctl(fd, PIOCDIAL, n);
  114.                     break;
  115.             }
  116.             n++;
  117.         }
  118.         return;
  119.     }
  120. #endif /* UNIXPC */
  121.  
  122.     send_str(s);
  123.     return;
  124. }
  125.  
  126. /*
  127.  * Send a string to the modem.  Performs all the character synonym
  128.  * translations.  No sanity checking on the "m_cur" value.
  129.  */
  130.  
  131. void
  132. send_str(s)
  133. char *s;
  134. {
  135.     extern int fd;
  136.     int skip;
  137.     unsigned int sleep();
  138.                     /* empty string? */
  139.     if (s == NULL || *s == NULL)
  140.         return;
  141.  
  142.     ioctl(fd, TCFLSH, 1);
  143.     /*
  144.      * Change the character synonyms to their real values.  Writes
  145.      * the characters to the modem.  To remove the special meaning
  146.      * of one of the characters, prepend a "\" to it.
  147.      */
  148.     skip = 0;
  149.     while (*s) {
  150.                     /* send the literal character */
  151.         if (skip) {
  152.             skip = 0;
  153.             write(fd, s, 1);
  154.             ioctl(fd, TCSBRK, 1);
  155. #ifdef DEBUG
  156.             fprintf(stderr, "send_str: '%c', %02x, %03o, %d\n", *s, *s, *s, *s);
  157. #endif /* DEBUG */
  158.             s++;
  159.             continue;
  160.         }
  161.                     /* turn off the special meaning */
  162.         if (*s == '\\') {
  163.             skip++;
  164.             s++;
  165.             continue;
  166.         }
  167.                     /* pause synonym */
  168.         if (*s == param->pause_char) {
  169.             sleep(1);
  170.             s++;
  171.             continue;
  172.         }
  173.                     /* carriage return synonym */
  174.         if (*s == param->cr_char)
  175.             *s = '\r';
  176.                     /* 2 character control sequence */
  177.         if (*s == param->ctrl_char) {
  178.             s++;
  179.                     /* premature EOF? */
  180.             if (*s == NULL)
  181.                 break;
  182.                     /* upper and lower case */
  183.             if (*s > '_')
  184.                 *s -= 96;
  185.             else
  186.                 *s -= 64;
  187.         }
  188.                     /* escape synonym */
  189.         if (*s == param->esc_char)
  190.             *s = ESC;
  191.                     /* modem break synonym */
  192.         if (*s == param->brk_char) {
  193.             ioctl(fd, TCSBRK, 0);
  194.             sleep(1);
  195.             s++;
  196.             continue;
  197.         }
  198.  
  199.         write(fd, s, 1);
  200. #ifdef DEBUG
  201.         fprintf(stderr, "send_str: '%c', %02x, %03o, %d\n", *s, *s, *s, *s);
  202. #endif /* DEBUG */
  203.         /*
  204.          * Because the pause char makes the timing critical, we
  205.          * wait until the buffer is clear before we continue.
  206.          */
  207.         ioctl(fd, TCSBRK, 1);
  208.         s++;
  209.     }
  210.     return;
  211. }
  212.  
  213. /*
  214.  * Read the result codes coming back from the modem.  Test for the 6
  215.  * "connect" strings and the 4 "no connect" strings.  Return the connected
  216.  * baud rate (as a string) or the error message.
  217.  */
  218.  
  219. char rc_buf[512];
  220. int rc_index;
  221.  
  222. char *
  223. read_codes()
  224. {
  225.     extern int fd;
  226.     char c;
  227. #ifdef UNIXPC
  228.     unsigned int sleep();
  229.     struct updata pbuf;
  230.                     /* special case for OBM */
  231.     if (!strcmp(modem->mname[modem->m_cur], "OBM")) {
  232.         ioctl(fd, PIOCGETP, &pbuf);
  233.  
  234.         /*
  235.          * The OBM doesn't use a return message to announce the
  236.          * connection to a remote, so we fake one.  The 1200
  237.          * is quite arbitrary... it is not an indicator of the
  238.          * connected baud rate.
  239.          */
  240.         if (pbuf.c_linestatus & MODEMCONNECTED)
  241.             return("1200");
  242.  
  243.         sleep(1);
  244.         return(NULL);
  245.     }
  246. #endif /* UNIXPC */
  247.                     /* search for key words */
  248.     for (; rc_index<511; rc_index++) {
  249.         if ((int) (c = getc_line(1)) <= 0)
  250.             return(NULL);
  251. #ifdef DEBUG
  252.         fprintf(stderr, "read_codes: '%c', %02x, %03o, %d\n", c, c, c, c);
  253. #endif /* DEBUG */
  254.  
  255.         rc_buf[rc_index] = c;
  256.         rc_buf[rc_index+1] = NULL;
  257.                     /* the connect strings */
  258.         if (match(rc_buf, modem->con_3[modem->m_cur]))
  259.             return("300");
  260.  
  261.         if (match(rc_buf, modem->con_12[modem->m_cur]))
  262.             return("1200");
  263.  
  264.         if (match(rc_buf, modem->con_24[modem->m_cur]))
  265.             return("2400");
  266.  
  267.         if (match(rc_buf, modem->con_48[modem->m_cur]))
  268.             return("4800");
  269.  
  270.         if (match(rc_buf, modem->con_96[modem->m_cur]))
  271.             return("9600");
  272.  
  273.         if (match(rc_buf, modem->con_192[modem->m_cur]))
  274.             return("19200");
  275.  
  276.                     /* the no connect strings */
  277.         if (match(rc_buf, modem->no_con1[modem->m_cur]))
  278.             return(modem->no_con1[modem->m_cur]);
  279.  
  280.         if (match(rc_buf, modem->no_con2[modem->m_cur]))
  281.             return(modem->no_con2[modem->m_cur]);
  282.  
  283.         if (match(rc_buf, modem->no_con3[modem->m_cur]))
  284.             return(modem->no_con3[modem->m_cur]);
  285.  
  286.         if (match(rc_buf, modem->no_con4[modem->m_cur]))
  287.             return(modem->no_con4[modem->m_cur]);
  288.     }
  289.                     /* ran out of buffer? */
  290.     return("ERROR");
  291. }
  292.  
  293. /*
  294.  * Test for a match between two character strings.  A return code of 1
  295.  * means that s2 was found at the end of s1.
  296.  */
  297.  
  298. static int
  299. match(s1, s2)
  300. char *s1, *s2;
  301. {
  302.     register int i;
  303.     int skip, diff;
  304.     char new[40];
  305.                     /* if no string to match */
  306.     if (*s2 == NULL)
  307.         return(0);
  308.                     /* translate synonyms */
  309.     i = 0;
  310.     skip = 0;
  311.     while (*s2) {
  312.                     /* literal character */
  313.         if (skip) {
  314.             skip = 0;
  315.             new[i++] = *s2;
  316.             s2++;
  317.             continue;
  318.         }
  319.                     /* turn off the special meaning */
  320.         if (*s2 == '\\') {
  321.             skip++;
  322.             s2++;
  323.             continue;
  324.         }
  325.                     /* carriage return synonym */
  326.         if (*s2 == param->cr_char)
  327.             *s2 = '\r';
  328.  
  329.                     /* 2 character control sequence */
  330.         if (*s2 == param->ctrl_char) {
  331.             s2++;
  332.             if (*s2 == NULL)
  333.                 break;
  334.             if (*s2 > '_')
  335.                 *s2 -= 96;
  336.             else
  337.                 *s2 -= 64;
  338.         }
  339.                     /* escape synonym */
  340.         if (*s2 == param->esc_char)
  341.             *s2 = ESC;
  342.  
  343.         new[i++] = *s2;
  344.         s2++;
  345.     }
  346.     new[i] = NULL;
  347.  
  348.     diff = strlen(s1) - strlen(new);
  349.                     /* is it possible? */
  350.     if (diff < 0)
  351.         return(0);
  352.                     /* test it out */
  353.     if (!strcmp(&s1[diff], new))
  354.         return(1);
  355.     return(0);
  356. }
  357.