xref: /plan9/sys/src/cmd/dial/at.c (revision 853458f38e7eb3a48cfa3a36aefdb799375e398a)
1 #include <u.h>
2 #include <libc.h>
3 
4 void
usage(void)5 usage(void)
6 {
7 	fprint(2, "usage: %s [-q] [-t seconds] command\n", argv0);
8 	exits("usage");
9 }
10 
11 struct {
12 	char	*resp;
13 	int	ok;
14 } tab[] =
15 {
16 	{ "ok\n",		1 },
17 	{ "connect\n",		1 },
18 	{ "no carrier\n",	0 },
19 	{ "no dialtone\n",	0 },
20 	{ "error\n",		0 },
21 	{ "busy\n",		0 },
22 	{ "no answer\n",	0 },
23 	{ "delayed\n",		0 },
24 	{ "blacklisted\n",	0 },
25 };
26 
27 int
writewithoutcr(int fd,char * p,int i)28 writewithoutcr(int fd, char *p, int i)
29 {
30 	char *q, *e;
31 
32 	/* dump cr's */
33 	for(e = p+i; p < e; ){
34 		q = memchr(p, '\r', e-p);
35 		if(q == nil)
36 			break;
37 		if(q > p)
38 			if(write(fd, p, q-p) < 0)
39 				return -1;
40 		p = q+1;
41 	}
42 	if(p < e)
43 		if(write(fd, p, e-p) < 0)
44 			return -1;
45 	return i;
46 }
47 
48 int
readln(int fd,char * buf,int n)49 readln(int fd, char *buf, int n)
50 {
51 	int c, i, sofar;
52 
53 	sofar = 0;
54 	buf[sofar] = 0;
55 	while(sofar < n-1){
56 		i = read(fd, buf+sofar, 1);
57 		if(i <= 0)
58 			return i;
59 		c = buf[sofar];
60 		if(c == '\r')
61 			continue;
62 		sofar++;
63 		if(c == '\n')
64 			break;
65 	}
66 	buf[sofar] = 0;
67 	return sofar;
68 }
69 
70 void
docmd(char * cmd,int timeout,int quiet,int consfd)71 docmd(char *cmd, int timeout, int quiet, int consfd)
72 {
73 	char buf[4096];
74 	int i;
75 	char *p, *cp;
76 
77 	if(timeout == 0){
78 		if(*cmd == 'd' || *cmd == 'D')
79 			timeout = 2*60;
80 		else
81 			timeout = 5;
82 	}
83 
84 	p = smprint("at%s\r", cmd);
85 	for(cp = p; *cp; cp++){
86 		write(1, cp, 1);
87 		sleep(100);
88 	}
89 	free(p);
90 
91 	alarm(timeout*1000);
92 	for(;;){
93 		i = readln(0, buf, sizeof(buf));
94 		if(i <= 0){
95 			rerrstr(buf, sizeof buf);
96 			exits(buf);
97 		}
98 		if(!quiet)
99 			writewithoutcr(consfd, buf, i);
100 		for(i = 0; i < nelem(tab); i++)
101 			if(cistrcmp(buf, tab[i].resp) == 0){
102 				if(tab[i].ok)
103 					goto out;
104 				else
105 					exits(buf);
106 			}
107 	}
108 out:
109 	alarm(0);
110 }
111 
112 void
main(int argc,char ** argv)113 main(int argc, char **argv)
114 {
115 	int timeout;
116 	int quiet;
117 	int i;
118 	int consfd;
119 
120 	timeout = 0;
121 	quiet = 0;
122 	ARGBEGIN {
123 	case 't':
124 		timeout = atoi(EARGF(usage()));
125 		break;
126 	case 'q':
127 		quiet = 1;
128 		break;
129 	default:
130 		usage();
131 	} ARGEND;
132 
133 	if(argc < 1)
134 		usage();
135 
136 	consfd = open("/dev/cons", ORDWR);
137 	if(consfd < 0)
138 		sysfatal("opening /dev/cons: %r");
139 
140 	for(i = 0; i < argc; i++)
141 		docmd(argv[i], timeout, quiet, consfd);
142 
143 	exits(0);
144 }
145