This is dial.c in view mode; [Download] [Up]
/* * The routines that dial the modem and listen for the return codes. */ #define HZ 60 #undef USLEEP #include <stdio.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 */ /* * 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. */ void dial_it(num) int num; { extern int fd; int i, skip; char s[100], number[40], *strcpy(), *strcat(), *n, *strchr(); void send_str(); #ifdef UNIXPC 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(1); /* 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. */ void send_str(s, slow) char *s; int slow; { extern int fd; int skip, has_pause; char *strchr(); unsigned int sleep(); static void do_pause(); /* 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 6 * "connect" strings and the 4 "no connect" strings. Return the connected * baud rate (as a string) or the error message. */ int rc_index; char * read_codes() { extern int fd; int i; static int match(); char c; static char rc_buf[512]; #ifdef UNIXPC 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 */ /* 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"); /* 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]); } /* 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 int match(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 void do_pause() { #ifdef USLEEP usleep(100000); #else /* 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 /* USLEEP */ return; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.