⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dial.c

📁 通讯程序源码
💻 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 + -