Commit | Line | Data |
---|---|---|
1c2fdcc2 FT |
1 | #include <stdio.h> |
2 | #include <stdarg.h> | |
3 | #include <string.h> | |
4 | #include <stdlib.h> | |
5 | #include <unistd.h> | |
6 | #include <termios.h> | |
7 | #include <fcntl.h> | |
8 | #include <sys/socket.h> | |
9 | #include <netinet/in.h> | |
10 | #include <errno.h> | |
11 | #include <sys/poll.h> | |
12 | #include <sys/select.h> | |
13 | #include <signal.h> | |
14 | #include <syslog.h> | |
15 | ||
16 | #define MODEM_DEV "/dev/modem" | |
17 | #define PIDFILE "/var/run/cidd.pid" | |
18 | #define PORT 5001 | |
19 | ||
20 | int mdm, sock; | |
21 | int ibuflen = 0; | |
22 | unsigned char ibuf[1024]; | |
23 | unsigned char tmpbuf[1024]; | |
24 | fd_set cfds; | |
25 | int isdaemon; | |
26 | ||
27 | void write2(int fd, unsigned char *buf, int len) | |
28 | { | |
29 | int ret; | |
30 | ||
31 | while(len) | |
32 | { | |
33 | ret = write(fd, buf, len); | |
34 | if(ret < 0) | |
35 | { | |
36 | perror("write"); | |
37 | exit(1); | |
38 | } | |
39 | buf += ret; | |
40 | len -= ret; | |
41 | } | |
42 | } | |
43 | ||
44 | void sendcmd(unsigned char *cmd) | |
45 | { | |
46 | unsigned char *lbuf; | |
47 | ||
48 | lbuf = strcpy(malloc(strlen(cmd) + 3), cmd); | |
49 | strcat(lbuf, "\r\n"); | |
50 | write2(mdm, lbuf, strlen(cmd) + 2); | |
51 | free(lbuf); | |
52 | } | |
53 | ||
54 | unsigned char *getline(int block) | |
55 | { | |
56 | int i; | |
57 | unsigned char *p; | |
58 | int ret, len; | |
59 | static unsigned char retbuf[1024]; | |
60 | struct pollfd pf; | |
61 | ||
62 | while(1) | |
63 | { | |
64 | while((p = memchr(ibuf, '\r', ibuflen)) != NULL) | |
65 | { | |
66 | memcpy(retbuf, ibuf, len = (p - ibuf)); | |
67 | retbuf[len] = 0; | |
68 | memmove(ibuf, p + 1, ibuflen -= (len + 1)); | |
69 | for(p = retbuf; *p; p++) | |
70 | { | |
71 | while(*p == '\n') | |
72 | memmove(p, p + 1, len--); | |
73 | } | |
74 | if(len && (memcmp(retbuf, "AT", 2))) | |
75 | return(retbuf); | |
76 | } | |
77 | if(!block) | |
78 | { | |
79 | pf.fd = mdm; | |
80 | pf.events = POLLIN; | |
81 | pf.revents = 0; | |
82 | if(poll(&pf, 1, 0) == 0) | |
83 | return(NULL); | |
84 | } | |
85 | ret = read(mdm, ibuf + ibuflen, 1024 - ibuflen); | |
86 | if(ret < 0) | |
87 | { | |
88 | perror("read"); | |
89 | exit(1); | |
90 | } | |
91 | ibuflen += ret; | |
92 | } | |
93 | } | |
94 | ||
95 | void broadcast(unsigned char *buf, ...) | |
96 | { | |
97 | int i; | |
98 | va_list args; | |
99 | ||
100 | va_start(args, buf); | |
101 | vsprintf(tmpbuf, buf, args); | |
102 | va_end(args); | |
103 | strcat(tmpbuf, "\n"); | |
104 | for(i = 0; i < FD_SETSIZE; i++) | |
105 | { | |
106 | if(FD_ISSET(i, &cfds) && (i != mdm) && (i != sock)) | |
107 | write2(i, tmpbuf, strlen(tmpbuf)); | |
108 | } | |
109 | } | |
110 | ||
111 | void initmodem(void) | |
112 | { | |
113 | sendcmd("ATZ"); | |
114 | if(strcmp(getline(1), "OK")) | |
115 | { | |
116 | if(isdaemon) | |
117 | syslog(LOG_CRIT, "Could not reset modem"); | |
118 | else | |
119 | fprintf(stderr, "Could not reset modem\n"); | |
120 | exit(1); | |
121 | } | |
122 | sendcmd("AT#CID=1"); | |
123 | if(strcmp(getline(1), "OK")) | |
124 | { | |
125 | if(isdaemon) | |
126 | syslog(LOG_CRIT, "Could not activate called ID\n"); | |
127 | else | |
128 | fprintf(stderr, "Could not activate caller ID\n"); | |
129 | exit(1); | |
130 | } | |
131 | } | |
132 | ||
133 | void sighandler(int sig) | |
134 | { | |
135 | if(sig == SIGHUP) | |
136 | { | |
137 | initmodem(); | |
138 | } | |
139 | } | |
140 | ||
141 | int main(int argc, unsigned char **argv) | |
142 | { | |
143 | int i; | |
144 | unsigned char *p; | |
145 | int nsock; | |
146 | int ret; | |
147 | struct sockaddr_in name; | |
148 | struct termios tio; | |
149 | fd_set rfds; | |
150 | FILE *pidst; | |
151 | ||
152 | isdaemon = 0; | |
153 | if((mdm = open(MODEM_DEV, O_RDWR)) < 0) | |
154 | { | |
155 | perror(MODEM_DEV); | |
156 | return(1); | |
157 | } | |
158 | if(tcgetattr(mdm, &tio) < 0) | |
159 | { | |
160 | perror("tcgetattr"); | |
161 | return(1); | |
162 | } | |
163 | cfmakeraw(&tio); | |
164 | cfsetispeed(&tio, B0); | |
165 | cfsetospeed(&tio, B38400); | |
166 | if(tcsetattr(mdm, TCSANOW, &tio) < 0) | |
167 | { | |
168 | perror("tcsetattr"); | |
169 | return(1); | |
170 | } | |
171 | if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) | |
172 | { | |
173 | perror("socket"); | |
174 | return(1); | |
175 | } | |
176 | name.sin_family = AF_INET; | |
177 | name.sin_port = htons(PORT); | |
178 | name.sin_addr.s_addr = 0; | |
179 | if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) | |
180 | { | |
181 | perror("bind"); | |
182 | return(1); | |
183 | } | |
184 | if(listen(sock, 16) < 0) | |
185 | { | |
186 | perror("listen"); | |
187 | return(1); | |
188 | } | |
189 | initmodem(); | |
190 | signal(SIGHUP, sighandler); | |
191 | if((pidst = fopen(PIDFILE, "w")) == NULL) | |
192 | { | |
193 | perror("open " PIDFILE); | |
194 | exit(1); | |
195 | } | |
196 | daemon(0, 0); | |
197 | fprintf(pidst, "%i\n", getpid()); | |
198 | fclose(pidst); | |
199 | openlog("cidd", LOG_PID, LOG_DAEMON); | |
200 | isdaemon = 1; | |
201 | FD_ZERO(&cfds); | |
202 | FD_SET(mdm, &cfds); | |
203 | FD_SET(sock, &cfds); | |
204 | while(1) | |
205 | { | |
206 | rfds = cfds; | |
207 | ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL); | |
208 | if((ret < 0) && (errno != EINTR)) | |
209 | { | |
210 | syslog(LOG_CRIT, "select return %m"); | |
211 | return(1); | |
212 | } | |
213 | if(ret > 0) | |
214 | { | |
215 | for(i = 0; i < FD_SETSIZE; i++) | |
216 | { | |
217 | if(FD_ISSET(i, &rfds)) | |
218 | { | |
219 | if(i == mdm) | |
220 | { | |
221 | while((p = getline(0)) != NULL) | |
222 | { | |
223 | if(!strcmp(p, "RING")) | |
224 | broadcast("R"); | |
225 | if(!memcmp(p, "NMBR = ", 7)) | |
226 | { | |
227 | p += 7; | |
228 | broadcast("N%s", p); | |
229 | } | |
230 | } | |
231 | } else if(i == sock) { | |
232 | if((nsock = accept(sock, NULL, 0)) >= 0) | |
233 | FD_SET(nsock, &cfds); | |
234 | } else { | |
235 | if(read(i, tmpbuf, 1024) == 0) | |
236 | { | |
237 | FD_CLR(i, &cfds); | |
238 | close(i); | |
239 | } | |
240 | } | |
241 | } | |
242 | } | |
243 | } | |
244 | } | |
245 | } |