56 return (char *)"ERROR"; |
66 return (char *)"ERROR"; |
57 } |
67 } |
58 |
68 |
59 |
69 |
60 |
70 |
61 void do_cmd(char *cmd) |
71 int server_init(void) |
62 { |
72 { |
63 char buf[1024]; |
73 int optval = 1; |
64 int slen, tries = 0; |
74 |
65 |
75 memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in)); |
|
76 memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in)); |
|
77 myaddr_in.sin_family = AF_INET; |
|
78 myaddr_in.sin_addr.s_addr = INADDR_ANY; |
|
79 myaddr_in.sin_port = htons(Config.my_port); |
|
80 |
|
81 ls = socket(AF_INET, SOCK_STREAM, 0); |
|
82 if (ls == -1) { |
|
83 syslog(LOG_NOTICE, "Can't create listen socket: %s", strerror(errno)); |
|
84 fprintf(stderr, "Can't create listen socket: %s\n", strerror(errno)); |
|
85 return 1; |
|
86 } |
|
87 |
|
88 if (setsockopt(ls, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) { |
|
89 syslog(LOG_NOTICE, "Can't setsockopt SO_KEEPALIVE socket: %s", strerror(errno)); |
|
90 close(ls); |
|
91 return 1; |
|
92 } |
|
93 |
|
94 if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { |
|
95 syslog(LOG_NOTICE, "Can't setsockopt SO_REUSEADDR socket: %s", strerror(errno)); |
|
96 close(ls); |
|
97 return 1; |
|
98 } |
|
99 |
|
100 if (bind(ls, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) { |
|
101 syslog(LOG_NOTICE, "Can't bind to listen socket: %s", strerror(errno)); |
|
102 close(ls); |
|
103 return 1; |
|
104 } |
|
105 |
|
106 syslog(LOG_NOTICE, "listen socket created %d", ls); |
66 if (debug) |
107 if (debug) |
67 fprintf(stdout, "do_cmd(%s)\n", cmd); |
108 fprintf(stdout, "listen socket created %d\n", ls); |
68 |
109 |
69 snprintf(buf, 1024, "%s", exe_cmd(cmd)); |
110 |
70 |
111 return 0; |
|
112 } |
|
113 |
|
114 |
|
115 |
|
116 /* |
|
117 * Send message to client |
|
118 */ |
|
119 int srv_send(const char *format, ...) |
|
120 { |
|
121 char out[SS_BUFSIZE]; |
|
122 va_list va_ptr; |
|
123 |
|
124 if (s == -1) |
|
125 return -1; |
|
126 |
|
127 va_start(va_ptr, format); |
|
128 vsnprintf(out, SS_BUFSIZE-1, format, va_ptr); |
|
129 va_end(va_ptr); |
|
130 |
|
131 if (send(s, out, strlen(out), 0) != strlen(out)) { |
|
132 syslog(LOG_NOTICE, "srv_send failed"); |
|
133 return -1; |
|
134 } |
|
135 |
|
136 if (send(s, (char *)"\r\n", 2, 0) != 2) { |
|
137 syslog(LOG_NOTICE, "srv_send failed"); |
|
138 return -1; |
|
139 } |
|
140 |
|
141 syslog(LOG_NOTICE, "send: \"%s\"", out); |
|
142 return 0; |
|
143 } |
|
144 |
|
145 |
|
146 |
|
147 void cmd_die(int onsig) |
|
148 { |
|
149 syslog(LOG_NOTICE, "Server process die on signal %d", onsig); |
|
150 close(s); |
|
151 exit(0); |
|
152 } |
|
153 |
|
154 |
|
155 |
|
156 void cmd_server(void) |
|
157 { |
|
158 char *hostname, buf[SS_BUFSIZE]; |
|
159 int i, rc, rlen, timer; |
|
160 socklen_t fromlen; |
|
161 struct pollfd pfd[1]; |
|
162 |
|
163 /* |
|
164 * Close listen socket |
|
165 */ |
|
166 close(ls); |
|
167 /* |
|
168 * Install private signal handler. |
|
169 */ |
|
170 for (i = 0; i < NSIG; i++) { |
|
171 if ((i == SIGHUP) || (i == SIGPIPE) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV)) |
|
172 signal(i, (void (*))cmd_die); |
|
173 else |
|
174 signal(i, SIG_IGN); |
|
175 } |
|
176 |
|
177 hp = gethostbyaddr ((char *) &peeraddr_in.sin_addr, sizeof(struct in_addr), peeraddr_in.sin_family); |
|
178 if (hp == NULL) { |
|
179 hostname = inet_ntoa(peeraddr_in.sin_addr); |
|
180 } else { |
|
181 hostname = hp->h_name; |
|
182 } |
|
183 |
|
184 clients++; |
|
185 syslog(LOG_NOTICE, "Start new client connection (%d) from %s port %u", clients, hostname, ntohs(peeraddr_in.sin_port)); |
|
186 timer = SS_TIMEOUT * 4; |
|
187 |
|
188 /* |
|
189 * Receive loop |
|
190 */ |
|
191 for (;;) { |
|
192 /* |
|
193 * Poll socket until a define timeout of 0,25 second. |
|
194 */ |
|
195 pfd[0].fd = s; |
|
196 pfd[0].events = POLLIN; |
|
197 pfd[0].revents = 0; |
|
198 rc = poll(pfd, 1, 250); |
|
199 |
|
200 if (rc == -1) { |
|
201 /* |
|
202 * Poll can be interrupted by a finished child so that's not a real error. |
|
203 */ |
|
204 if (errno != EINTR) { |
|
205 syslog(LOG_NOTICE, "poll() rc=%d sock=%d events=%04x", rc, s, pfd[0].revents); |
|
206 } |
|
207 } else if (rc) { |
|
208 if (pfd[0].revents & POLLIN) { |
|
209 memset((char *)&buf, 0, SS_BUFSIZE); |
|
210 fromlen = sizeof(peeraddr_in); |
|
211 rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); |
|
212 if (rlen == -1) { |
|
213 syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); |
|
214 } else { |
|
215 for (i = 0; i < strlen(buf); i++) { |
|
216 if (buf[i] == '\n') |
|
217 buf[i] = '\0'; |
|
218 if (buf[i] == '\r') |
|
219 buf[i] = '\0'; |
|
220 } |
|
221 timer = SS_TIMEOUT * 4; |
|
222 if (strlen(buf)) { |
|
223 syslog(LOG_NOTICE, "recv: \"%s\"", buf); |
|
224 |
|
225 /* |
|
226 * Process command from the client |
|
227 */ |
|
228 srv_send(exe_cmd(buf)); |
|
229 } |
|
230 } |
|
231 } else { |
|
232 syslog(LOG_NOTICE, "poll other event"); |
|
233 } |
|
234 |
|
235 } else { |
|
236 /* |
|
237 * Poll timeout, do some housekeeping |
|
238 */ |
|
239 if (timer) { |
|
240 timer--; |
|
241 } else { |
|
242 /* Inactivity timeout */ |
|
243 break; |
|
244 } |
|
245 if (my_shutdown) { |
|
246 break; |
|
247 } |
|
248 } |
|
249 } |
|
250 } |
|
251 |
|
252 |
|
253 |
|
254 PI_THREAD (my_server_loop) |
|
255 { |
|
256 socklen_t addrlen; |
|
257 |
|
258 syslog(LOG_NOTICE, "Thread my_server_loop started"); |
71 if (debug) |
259 if (debug) |
72 fprintf(stdout, "do_cmd() reply=\"%s\" len=%d\n", buf, strlen(buf)); |
260 fprintf(stdout, "Thread my_server_loop started\n"); |
73 |
261 |
|
262 /* |
|
263 * Loop forever until the external shutdown variable is set. |
|
264 */ |
74 for (;;) { |
265 for (;;) { |
75 // slen = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&from, fromlen); |
266 |
76 |
267 addrlen = sizeof(struct sockaddr_in); |
77 if (debug) |
268 /* |
78 fprintf(stdout, "do_cmd() slen=%d tries=%d %s\n", slen, tries, strerror(errno)); |
269 * This call will block until a new connection |
79 // if (slen == -1) |
270 * arrives. Then it will return the address of |
80 // syslog(LOG_NOTICE, "do_cmd(): sendto error %d %s", tries, from.sun_path); |
271 * the connecting peer, and a new socket |
81 else if (slen != strlen(buf)) |
272 * descriptor, s, for that connection. |
82 syslog(LOG_NOTICE, "do_cmd(): send %d of %d bytes, try=%d", slen, strlen(buf), tries); |
273 */ |
83 else |
274 s = accept(ls, (struct sockaddr *)&peeraddr_in, &addrlen); |
84 return; |
275 if (s == -1) { |
85 tries++; |
276 syslog(LOG_NOTICE, "my_server_loop accept failed %s", strerror(errno)); |
86 if (tries == 3) |
277 if (debug) |
87 return; |
278 fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno)); |
88 else |
279 return 1; |
89 sleep(1); |
280 } |
90 } |
281 |
91 } |
282 switch (fork()) { |
92 |
283 case -1: /* |
93 |
284 * Can't fork, just continue. |
|
285 */ |
|
286 return 1; |
|
287 case 0: /* |
|
288 * Child process, the commandline server. |
|
289 */ |
|
290 cmd_server(); |
|
291 return 0; |
|
292 default: /* |
|
293 * Daemon process comes here. The daemon |
|
294 * needs to remember to close the new |
|
295 * accept socket after forking the child. |
|
296 */ |
|
297 close(s); |
|
298 } |
|
299 |
|
300 if (my_shutdown) { |
|
301 syslog(LOG_NOTICE, "Thread my_server_loop stopped"); |
|
302 if (debug) |
|
303 fprintf(stdout, "Thread my_server_loop stopped\n"); |
|
304 return 0; |
|
305 } |
|
306 |
|
307 } |
|
308 } |
|
309 |
|
310 |
|
311 |