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