1 #include <u.h> 2 #include <libc.h> 3 4 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 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 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 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 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