📄 dial.c
字号:
/* * The routines that dial the modem and listen for the return codes. */#define HZ 60#include <stdio.h>#include <ctype.h>#include "config.h"#include "dial_dir.h"#include "misc.h"#include "modem.h"#include "param.h"#ifdef BSD#include <sys/time.h>#else /* BSD */#include <sys/types.h>#include <sys/times.h>#endif /* BSD */#ifdef UNIXPC#include <sys/phone.h>#endif /* UNIXPC */static void do_pause();static int match();/* * Get the dial string ready, send it to the modem. The parameter is not * the actual entry number, it is an index into the queue. */voiddial_it(num)int num;{ int i, skip; char s[100], number[40], *strcpy(), *strcat(), *n, *strchr(); void send_str();#ifdef UNIXPC extern int fd; struct updata pbuf; unsigned int sleep();#endif /* UNIXPC */ /* * Create the string to be sent to the modem. The long distance * codes are added if they are requested. */ s[0] = '\0'; strcpy(s, modem->dial[modem->m_cur]); switch (dir->q_ld[num]) { case 0: /* no ld code requested */ break; case '+': strcat(s, param->ld_plus); break; case '-': strcat(s, param->ld_minus); break; case '@': strcat(s, param->ld_at); break; case '#': strcat(s, param->ld_pound); break; } /* * Purify the phone number by removing all the pretty characters * that don't need to be sent to the modem. Typically the "-", * "(", ")", and space characters are just for looks. To prevent * this action, prepend a "\" to the character. */ i = 0; skip = 0; n = dir->number[dir->q_num[num]]; while (*n) { if (*n == '\\' && !skip) { skip++; n++; continue; } if (!strchr("-() ", *n) || skip) number[i++] = *n; n++; skip = 0; } number[i] = '\0'; /* add it to the string */ strcat(s, number); strcat(s, modem->suffix[modem->m_cur]);#ifdef DEBUG fprintf(stderr, "raw dial string: \"%s\"\n", s);#endif /* DEBUG */#ifdef UNIXPC /* special case for OBM */ if (!strcmp(modem->mname[modem->m_cur], "OBM")) { /* prepare the modem */ pbuf.c_lineparam = DATA|DTMF; pbuf.c_waitdialtone = 5; pbuf.c_linestatus = 0; pbuf.c_feedback = SPEAKERON|NORMSPK; pbuf.c_waitflash = 500; ioctl(fd, PIOCSETP, &pbuf); sleep(1); /* connect the dialer */ ioctl(fd, PIOCRECONN); sleep(2); /* dial each digit */ n = s; while (*n) { /* switch tone/pulse dialing? */ switch (*n) { case '^': pbuf.c_lineparam = DATA|PULSE; ioctl(fd, PIOCSETP, &pbuf); break; case '%': pbuf.c_lineparam = DATA|DTMF; ioctl(fd, PIOCSETP, &pbuf); break; default: ioctl(fd, PIOCDIAL, n); break; } n++; } /* * It seems that the OBM doesn't always talk reliably to * other types of modems (most notibly Telebits). Here * is some witchcraft to fix the problem. */ ioctl(fd, PIOCOVSPD); return; }#endif /* UNIXPC */ send_str(s, SLOW); return;}/* * Send a string to the modem. Performs all the character synonym * translations. */voidsend_str(s, slow)char *s;int slow;{ extern int fd; int skip, has_pause; char *strchr(); unsigned int sleep(); /* empty string? */ if (s == NULL || *s == '\0') return; /* contains a pause? */ has_pause = 0; if (strchr(s, '~')) has_pause++; tty_flush(fd, 1); /* * Change the character synonyms to their real values. Writes * the characters to the modem. To remove the special meaning * of one of the characters, prepend a "\" to it. */ skip = 0; while (*s) { /* send the literal character */ if (skip) { skip = 0; write(fd, s, 1); if (has_pause || slow) tty_drain(fd); if (slow) do_pause();#ifdef DEBUG fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s);#endif /* DEBUG */ s++; continue; } /* turn off the special meaning */ if (*s == '\\') { skip++; s++; continue; } /* pause synonym */ if (*s == param->pause_char) { sleep(1); s++; continue; } /* carriage return synonym */ if (*s == param->cr_char) *s = '\r'; /* 2 character control sequence */ if (*s == param->ctrl_char) { s++; /* premature EOF? */ if (*s == '\0') break; /* upper and lower case */ if (*s > '_') *s -= 96; else *s -= 64; } /* escape synonym */ if (*s == param->esc_char) *s = ESC; /* modem break synonym */ if (*s == param->brk_char) { tty_break(fd); sleep(1); s++; continue; } write(fd, s, 1);#ifdef DEBUG fprintf(stderr, "send_str: \"%c\", %02x, %03o, %d\n", *s, *s, *s, *s);#endif /* DEBUG */ /* * Because the pause char makes the timing critical, we * wait until the buffer is clear before we continue. */ if (has_pause || slow) tty_drain(fd); if (slow) do_pause(); s++; } return;}/* * Read the result codes coming back from the modem. Test for the 7 * "connect" strings and the 4 "no connect" strings. Return the connected * baud rate (as a string) or the error message. */char *read_codes(tic)int tic;{ int i, j, k; char c; static char rc_buf[512]; static int rc_index;#ifdef UNIXPC extern int fd; unsigned int sleep(); struct updata pbuf; /* special case for OBM */ if (!strcmp(modem->mname[modem->m_cur], "OBM")) { ioctl(fd, PIOCGETP, &pbuf); /* * The OBM doesn't use a return message to announce the * connection to a remote, so we fake one. The 1200 * is quite arbitrary... it is not an indicator of the * connected baud rate. */ if (pbuf.c_linestatus & MODEMCONNECTED) return("1200"); sleep(1); return(NULL); }#endif /* UNIXPC */ if (tic == 0) rc_index = 0; /* search for key words */ for (; rc_index<511; rc_index++) { if ((i = getc_line(1)) <= 0) return(NULL); c = i & 0x7f;#ifdef DEBUG fprintf(stderr, "read_codes: \"%c\", %02x, %03o, %d\n", c, c, c, c);#endif /* DEBUG */ /* no NULLs please */ if (c == '\0') { if (rc_index) rc_index--; continue; } rc_buf[rc_index] = c; rc_buf[rc_index+1] = '\0'; /* the connect strings */ if (match(rc_buf, modem->con_3[modem->m_cur])) return("300"); if (match(rc_buf, modem->con_12[modem->m_cur])) return("1200"); if (match(rc_buf, modem->con_24[modem->m_cur])) return("2400"); if (match(rc_buf, modem->con_48[modem->m_cur])) return("4800"); if (match(rc_buf, modem->con_96[modem->m_cur])) return("9600"); if (match(rc_buf, modem->con_192[modem->m_cur])) return("19200"); if (match(rc_buf, modem->con_384[modem->m_cur])) return("38400"); /* the no connect strings */ if (match(rc_buf, modem->no_con1[modem->m_cur])) return(modem->no_con1[modem->m_cur]); if (match(rc_buf, modem->no_con2[modem->m_cur])) return(modem->no_con2[modem->m_cur]); if (match(rc_buf, modem->no_con3[modem->m_cur])) return(modem->no_con3[modem->m_cur]); if (match(rc_buf, modem->no_con4[modem->m_cur])) return(modem->no_con4[modem->m_cur]); /* * OK.. this is the tricky part. What if the modem returns * the connected rate (in lieu of the DTE rate)? For * example, the message is "CONNECT 14400", but the DTE * is locked at 38400. */ if (modem->lock_sp[modem->t_cur]) { for (j=0; j<512; j++) { if (rc_buf[j] == '\0') break; if (isdigit(rc_buf[j])) { k = atoi(&rc_buf[j]); switch(k) { case 7200: return("7200"); case 12000: return("12000"); case 14400: return("14400"); } break; } } } } /* ran out of buffer? */ return("ERROR");}/* * Test for a match between two character strings. A non-zero return code * means that s2 was found at the end of s1. */static intmatch(s1, s2)char *s1, *s2;{ register int i; int skip, diff; char new[40]; /* if no string to match */ if (*s2 == '\0') return(0); /* translate synonyms */ i = 0; skip = 0; while (*s2) { /* literal character */ if (skip) { skip = 0; new[i++] = *s2; s2++; continue; } /* turn off the special meaning */ if (*s2 == '\\') { skip++; s2++; continue; } /* carriage return synonym */ if (*s2 == param->cr_char) *s2 = '\r'; /* 2 character control sequence */ if (*s2 == param->ctrl_char) { s2++; if (*s2 == '\0') break; if (*s2 > '_') *s2 -= 96; else *s2 -= 64; } /* escape synonym */ if (*s2 == param->esc_char) *s2 = ESC; new[i++] = *s2; s2++; } new[i] = '\0'; diff = strlen(s1) - strlen(new); /* is it possible? */ if (diff < 0) return(0); /* test it out */ if (!strcmp(&s1[diff], new)) return(1); return(0);}/* * Apparently some modems can't take input at the rated speed while * in the command mode. Therefore, a 0.10 sec pause a required between * characters. */static voiddo_pause(){#ifdef HAVE_USLEEP usleep(100000);#else /* HAVE_USLEEP */ /* Hey! I know these routines are a hack */#ifdef BSD struct timeval tv; struct timezone tz; double t1; gettimeofday(&tv, &tz); t1 = tv.tv_sec + (tv.tv_usec / 1000000.0); do gettimeofday(&tv, &tz); while ((tv.tv_sec + (tv.tv_usec / 1000000.0) - t1) < 0.1);#else /* BSD */ struct tms t; long t1; t1 = times(&t); while ((times(&t) - t1) < HZ/10) ;#endif /* BSD */#endif /* HAVE_USLEEP */ return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -