249 lines · 4.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h> void setspeed(int, int);int getspeed(char*, int);void godial(int, int, char*);int readmsg(int, int);void punt(char*, ...); int pulsed;int verbose;char msgbuf[128];		/* last message read */ enum{	Ok,	Success,	Failure,	Noise,}; typedef struct Msg	Msg;struct Msg{	char	*text;	int	type;};  Msg msgs[] ={	{ "OK",			Ok, },	{ "NO CARRIER", 	Failure, },	{ "ERROR",		Failure, },	{ "NO DIALTONE",	Failure, },	{ "BUSY",		Failure, },	{ "NO ANSWER",		Failure, },	{ "CONNECT",		Success, },	{ 0,			0 },}; voidusage(void){	punt("usage: hayes [-p] telno [device]");} voidmain(int argc, char **argv){	int data = -1;	int ctl = -1;	char *cname; 	ARGBEGIN{	case 'p':		pulsed = 1;		break;	case 'v':		verbose = 1;		break;	default:		usage();	}ARGEND 	switch(argc){	case 1:		data = 1;		break;	case 2:		data = open(argv[1], ORDWR);		if(data < 0){			fprint(2, "hayes: %r opening %s\n", argv[1]);			exits("hayes");		}		cname = malloc(strlen(argv[1])+4);		sprint(cname, "%sctl", argv[1]);		ctl = open(cname, ORDWR);		free(cname);		break;	default:		usage();	}	godial(data, ctl, argv[0]);	exits(0);} intsend(int fd, char *x){	return write(fd, x, strlen(x));} voidgodial(int data, int ctl, char *number){	char *dialstr;	int m;	int baud; 	/* get the modem's attention */	if(send(data, "\r+++\r") < 0)		punt("failed write");	readmsg(data, 2);	sleep(1000); 	/* initialize */	if(send(data, "ATZ\r") < 0)		punt("failed write");	m = readmsg(data, 2);	if(m < 0)		punt("can't get modem's attention"); 	/*	 *	Q0 = report result codes	 * 	V1 = full word result codes	 *	W1 = negotiation progress codes enabled	 *	E1 = echo commands	 *	M1 = speaker on until on-line	 */	if(send(data, "ATQ0V1E1M1\r") < 0)		punt("failed write");	m = readmsg(data, 2);	if(m != Ok)		punt("can't get modem's attention");	if(send(data, "ATW1\r") < 0)		punt("failed write");	readmsg(data, 2);	sleep(1000); 	/* godial */	dialstr = malloc(6+strlen(number));	sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);	if(send(data, dialstr) < 0) {		free(dialstr);		punt("failed write");	}	free(dialstr);	m = readmsg(data, 60);	if(m != Success)		punt("dial failed: %s", msgbuf);	baud = getspeed(msgbuf, 9600);	setspeed(ctl, baud);	fprint(2, "hayes: connected at %d baud\n", baud);} /* *  read until we see a message or we time out */intreadmsg(int f, int secs){	ulong start;	char *p;	int len;	Dir *d;	Msg *pp; 	p = msgbuf;	len = sizeof(msgbuf) - 1;	for(start = time(0); time(0) <= start+secs;){		if((d = dirfstat(f)) == nil)			punt("failed read");		if(d->length == 0){			free(d);			sleep(100);			continue;		}		free(d);		if(read(f, p, 1) <= 0)			punt("failed read");		if(*p == '\n' || *p == '\r' || len == 0){			*p = 0;			if(verbose && p != msgbuf)				fprint(2, "%s\n", msgbuf);			for(pp = msgs; pp->text; pp++)				if(strncmp(pp->text, msgbuf, strlen(pp->text))==0)					return pp->type;			start = time(0);			p = msgbuf;			len = sizeof(msgbuf) - 1;			continue;		}		len--;		p++;	}	strcpy(msgbuf, "No response from modem");	return Noise;} /* *  get baud rate from a connect message */intgetspeed(char *msg, int speed){	char *p;	int s; 	p = msg + sizeof("CONNECT") - 1;	while(*p == ' ' || *p == '\t')		p++;	s = atoi(p);	if(s <= 0)		return speed;	else		return s;} /* *  set speed and RTS/CTS modem flow control */voidsetspeed(int ctl, int baud){	char buf[32]; 	if(ctl < 0)		return;	sprint(buf, "b%d", baud);	write(ctl, buf, strlen(buf));	write(ctl, "m1", 2);}  voidpunt(char *fmt, ...){	char buf[256];	va_list arg;	int n; 	strcpy(buf, "hayes: ");	va_start(arg, fmt);	n = vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;	va_end(arg);	buf[n] = '\n';	write(2, buf, n+1);	exits("hayes");}