/[LeafOK_CVS]/pvpgn-1.7.4/src/bntrackd/bntrackd.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bntrackd/bntrackd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 /*
2 * Copyright (C) 1999 Mark Baysinger (mbaysing@ucsd.edu)
3 * Copyright (C) 2000 Ross Combs (rocombs@cs.nmsu.edu)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #define TRACKER_INTERNAL_ACCESS
20 #include "common/setup_before.h"
21 #include <stdio.h>
22 #ifdef HAVE_STDDEF_H
23 # include <stddef.h>
24 #else
25 # ifndef NULL
26 # define NULL ((void *)0)
27 # endif
28 #endif
29 #ifdef STDC_HEADERS
30 # include <stdlib.h>
31 #else
32 # ifdef HAVE_MALLOC_H
33 # include <malloc.h>
34 # endif
35 #endif
36 #include "compat/exitstatus.h"
37 #ifdef HAVE_STRING_H
38 # include <string.h>
39 #else
40 # ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 # endif
43 #endif
44 #ifdef HAVE_MEMORY_H
45 # include <memory.h>
46 #endif
47 #include "compat/memset.h"
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif
51 #include "compat/stdfileno.h"
52 #include <errno.h>
53 #include "compat/strerror.h"
54 #ifdef TIME_WITH_SYS_TIME
55 # include <sys/time.h>
56 # include <time.h>
57 #else
58 # ifdef HAVE_SYS_TIME_H
59 # include <sys/time.h>
60 # else
61 # include <time.h>
62 # endif
63 #endif
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
66 #endif
67 #ifdef HAVE_SYS_SOCKET_H
68 # include <sys/socket.h>
69 #endif
70 #include "compat/socket.h"
71 #include "compat/send.h"
72 #ifdef HAVE_SYS_PARAM_H
73 # include <sys/param.h>
74 #endif
75 #ifdef HAVE_NETINET_IN_H
76 # include <netinet/in.h>
77 #endif
78 #include "compat/netinet_in.h"
79 #ifdef HAVE_ARPA_INET_H
80 # include <arpa/inet.h>
81 #endif
82 #include "compat/inet_ntoa.h"
83 #include "compat/psock.h"
84 #include "common/list.h"
85 #include "common/version.h"
86 #include "common/eventlog.h"
87 #include "common/util.h"
88 #include "common/tracker.h"
89 #include "common/xalloc.h"
90 #include "common/setup_after.h"
91
92
93 /******************************************************************************
94 * TYPES
95 *****************************************************************************/
96 typedef struct
97 {
98 struct in_addr address;
99 time_t updated;
100 t_trackpacket info;
101 } t_server;
102
103 typedef struct
104 {
105 int foreground;
106 int debug;
107 int XML_mode;
108 unsigned int expire;
109 unsigned int update;
110 unsigned short port;
111 char const * outfile;
112 char const * pidfile;
113 char const * logfile;
114 char const * process;
115 } t_prefs;
116
117
118 /******************************************************************************
119 * STATIC FUNCTION PROTOTYPES
120 *****************************************************************************/
121 static int server_process(int sockfd);
122 static void usage(char const * progname);
123 static void getprefs(int argc, char * argv[]);
124 static void fixup_str(char * str);
125
126
127 /******************************************************************************
128 * GLOBAL VARIABLES
129 *****************************************************************************/
130 static t_prefs prefs;
131
132
133 extern int main(int argc, char * argv[])
134 {
135 int sockfd;
136
137 if (argc<1 || !argv || !argv[0])
138 {
139 fprintf(stderr,"bad arguments\n");
140 return STATUS_FAILURE;
141 }
142
143 getprefs(argc,argv);
144
145 if (!prefs.debug)
146 eventlog_del_level("debug");
147 if (prefs.logfile)
148 {
149 eventlog_set(stderr);
150 if (eventlog_open(prefs.logfile)<0)
151 {
152 eventlog(eventlog_level_fatal,__FUNCTION__,"could not use file \"%s\" for the eventlog (exiting)",prefs.logfile);
153 return STATUS_FAILURE;
154 }
155 }
156
157 #ifdef DO_DAEMONIZE
158 if (!prefs.foreground)
159 {
160 switch (fork())
161 {
162 case -1:
163 eventlog(eventlog_level_error,__FUNCTION__,"could not fork (fork: %s)\n",pstrerror(errno));
164 return STATUS_FAILURE;
165 case 0: /* child */
166 break;
167 default: /* parent */
168 return STATUS_SUCCESS;
169 }
170
171 close(STDINFD);
172 close(STDOUTFD);
173 close(STDERRFD);
174
175 # ifdef HAVE_SETPGID
176 if (setpgid(0,0)<0)
177 {
178 eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgid: %s)\n",pstrerror(errno));
179 return STATUS_FAILURE;
180 }
181 # else
182 # ifdef HAVE_SETPGRP
183 # ifdef SETPGRP_VOID
184 if (setpgrp()<0)
185 {
186 eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)\n",pstrerror(errno));
187 return STATUS_FAILURE;
188 }
189 # else
190 if (setpgrp(0,0)<0)
191 {
192 eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)\n",pstrerror(errno));
193 return STATUS_FAILURE;
194 }
195 # endif
196 # else
197 # ifdef HAVE_SETSID
198 if (setsid()<0)
199 {
200 eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setsid: %s)\n",pstrerror(errno));
201 return STATUS_FAILURE;
202 }
203 # else
204 # error "One of setpgid(), setpgrp(), or setsid() is required"
205 # endif
206 # endif
207 # endif
208 }
209 #endif
210
211 if (prefs.pidfile)
212 {
213 #ifdef HAVE_GETPID
214 FILE * fp;
215
216 if (!(fp = fopen(prefs.pidfile,"w")))
217 {
218 eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",prefs.pidfile,pstrerror(errno));
219 prefs.pidfile = NULL;
220 }
221 else
222 {
223 fprintf(fp,"%u",(unsigned int)getpid());
224 if (fclose(fp)<0)
225 eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",prefs.pidfile,pstrerror(errno));
226 }
227 #else
228 eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, do not use the -P or the --pidfile option");
229 prefs.pidfile = NULL;
230 #endif
231 }
232
233 #ifdef HAVE_GETPID
234 eventlog(eventlog_level_info,__FUNCTION__,"bntrackd version "PVPGN_VERSION" process %u",(unsigned int)getpid());
235 #else
236 eventlog(eventlog_level_info,__FUNCTION__,"bntrackd version "PVPGN_VERSION);
237 #endif
238
239 if (psock_init()<0)
240 {
241 eventlog(eventlog_level_error,__FUNCTION__,"could not initialize socket functions");
242 return STATUS_FAILURE;
243 }
244
245 /* create the socket */
246 if ((sockfd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_DGRAM,PSOCK_IPPROTO_UDP))<0)
247 {
248 eventlog(eventlog_level_error,__FUNCTION__,"could not create UDP listen socket (psock_socket: %s)\n",pstrerror(psock_errno()));
249 return STATUS_FAILURE;
250 }
251
252 {
253 struct sockaddr_in servaddr;
254
255 /* bind the socket to correct port and interface */
256 memset(&servaddr,0,sizeof(servaddr));
257 servaddr.sin_family = PSOCK_AF_INET;
258 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
259 servaddr.sin_port = htons(prefs.port);
260 if (psock_bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0)
261 {
262 eventlog(eventlog_level_error,__FUNCTION__,"could not bind to UDP port %hu (psock_bind: %s)\n",prefs.port,pstrerror(psock_errno()));
263 return STATUS_FAILURE;
264 }
265 }
266
267 if (server_process(sockfd)<0)
268 return STATUS_FAILURE;
269 return STATUS_SUCCESS;
270 }
271
272
273 static int server_process(int sockfd)
274 {
275 t_list * serverlist_head;
276 t_elem * curr;
277 t_server * server;
278 struct sockaddr_in cliaddr;
279 t_psock_fd_set rfds;
280 struct timeval tv;
281 time_t last;
282 FILE * outfile;
283 psock_t_socklen len;
284 t_trackpacket packet;
285
286 if (!(serverlist_head = list_create()))
287 {
288 eventlog(eventlog_level_error,__FUNCTION__,"could not create server list");
289 return -1;
290 }
291
292 /* the main loop */
293 last = time(NULL) - prefs.update;
294 for (;;)
295 {
296 /* time to dump our list to disk and call the process command */
297 /* (I'm making the assumption that this won't take very long.) */
298 if (last+(signed)prefs.update<time(NULL))
299 {
300 last = time(NULL);
301
302 if (!(outfile = fopen(prefs.outfile,"w")))
303 {
304 eventlog(eventlog_level_error,__FUNCTION__,"unable to open file \"%s\" for writing (fopen: %s)",prefs.outfile,pstrerror(errno));
305 continue;
306 }
307
308 LIST_TRAVERSE(serverlist_head,curr)
309 {
310 server = elem_get_data(curr);
311
312 if (server->updated+(signed)prefs.expire<last)
313 {
314 list_remove_elem(serverlist_head,&curr);
315 xfree(server);
316 }
317 else
318 {
319 if (prefs.XML_mode == 1)
320 {
321 fprintf(outfile,"<server>\n\t<address>%s</address>\n",inet_ntoa(server->address));
322 fprintf(outfile,"\t<port>%hu</port>\n",(unsigned short)ntohs(server->info.port));
323 fprintf(outfile,"\t<location>%s</location>\n",server->info.server_location);
324 fprintf(outfile,"\t<software>%s</software>\n",server->info.software);
325 fprintf(outfile,"\t<version>%s</version>\n",server->info.version);
326 fprintf(outfile,"\t<users>%lu</users>\n",(unsigned long)ntohl(server->info.users));
327 fprintf(outfile,"\t<channels>%lu</channels>\n",(unsigned long)ntohl(server->info.channels));
328 fprintf(outfile,"\t<games>%lu</games>\n",(unsigned long)ntohl(server->info.games));
329 fprintf(outfile,"\t<description>%s</description>\n",server->info.server_desc);
330 fprintf(outfile,"\t<platform>%s</platform>\n",server->info.platform);
331 fprintf(outfile,"\t<url>%s</url>\n",server->info.server_url);
332 fprintf(outfile,"\t<contact_name>%s</contact_name>\n",server->info.contact_name);
333 fprintf(outfile,"\t<contact_email>%s</contact_email>\n",server->info.contact_email);
334 fprintf(outfile,"\t<uptime>%lu</uptime>\n",(unsigned long)ntohl(server->info.uptime));
335 fprintf(outfile,"\t<total_games>%lu</total_games>\n",(unsigned long)ntohl(server->info.total_games));
336 fprintf(outfile,"\t<logins>%lu</logins>\n",(unsigned long)ntohl(server->info.total_logins));
337 fprintf(outfile,"</server>\n");
338 }
339 else
340 {
341 fprintf(outfile,"%s\n##\n",inet_ntoa(server->address));
342 fprintf(outfile,"%hu\n##\n",(unsigned short)ntohs(server->info.port));
343 fprintf(outfile,"%s\n##\n",server->info.server_location);
344 fprintf(outfile,"%s\n##\n",server->info.software);
345 fprintf(outfile,"%s\n##\n",server->info.version);
346 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.users));
347 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.channels));
348 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.games));
349 fprintf(outfile,"%s\n##\n",server->info.server_desc);
350 fprintf(outfile,"%s\n##\n",server->info.platform);
351 fprintf(outfile,"%s\n##\n",server->info.server_url);
352 fprintf(outfile,"%s\n##\n",server->info.contact_name);
353 fprintf(outfile,"%s\n##\n",server->info.contact_email);
354 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.uptime));
355 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.total_games));
356 fprintf(outfile,"%lu\n##\n",(unsigned long)ntohl(server->info.total_logins));
357 fprintf(outfile,"###\n");
358 }
359 }
360 }
361 if (fclose(outfile)<0)
362 eventlog(eventlog_level_error,__FUNCTION__,"could not close output file \"%s\" after writing (fclose: %s)",prefs.outfile,pstrerror(errno));
363
364 if (prefs.process[0]!='\0')
365 system(prefs.process);
366 }
367
368 /* select socket to operate on */
369 PSOCK_FD_ZERO(&rfds);
370 PSOCK_FD_SET(sockfd,&rfds);
371 tv.tv_sec = BNTRACKD_GRANULARITY;
372 tv.tv_usec = 0;
373 switch (psock_select(sockfd+1,&rfds,NULL,NULL,&tv))
374 {
375 case -1: /* error */
376 if (
377 #ifdef PSOCK_EINTR
378 errno!=PSOCK_EINTR &&
379 #endif
380 1)
381 eventlog(eventlog_level_error,__FUNCTION__,"select failed (select: %s)",pstrerror(errno));
382 case 0: /* timeout and no sockets ready */
383 continue;
384 }
385
386 /* New tracking packet */
387 if (PSOCK_FD_ISSET(sockfd,&rfds))
388 {
389
390 len = sizeof(cliaddr);
391 if (psock_recvfrom(sockfd,&packet,sizeof(packet),0,(struct sockaddr *)&cliaddr,&len)>=0)
392 {
393
394 if (ntohs(packet.packet_version)>=TRACK_VERSION)
395 {
396 packet.software[sizeof(packet.software)-1] = '\0';
397 if (strstr(packet.software,"##"))
398 fixup_str(packet.software);
399 packet.version[sizeof(packet.version)-1] = '\0';
400 if (strstr(packet.version,"##"))
401 fixup_str(packet.version);
402 packet.platform[sizeof(packet.platform)-1] = '\0';
403 if (strstr(packet.platform,"##"))
404 fixup_str(packet.platform);
405 packet.server_desc[sizeof(packet.server_desc)-1] = '\0';
406 if (strstr(packet.server_desc,"##"))
407 fixup_str(packet.server_desc);
408 packet.server_location[sizeof(packet.server_location)-1] = '\0';
409 if (strstr(packet.server_location,"##"))
410 fixup_str(packet.server_location);
411 packet.server_url[sizeof(packet.server_url)-1] = '\0';
412 if (strstr(packet.server_url,"##"))
413 fixup_str(packet.server_url);
414 packet.contact_name[sizeof(packet.contact_name)-1] = '\0';
415 if (strstr(packet.contact_name,"##"))
416 fixup_str(packet.contact_name);
417 packet.contact_email[sizeof(packet.contact_email)-1] = '\0';
418 if (strstr(packet.contact_email,"##"))
419 fixup_str(packet.contact_email);
420
421 /* Find this server's slot */
422 LIST_TRAVERSE(serverlist_head,curr)
423 {
424 server = elem_get_data(curr);
425
426 if (!memcmp(&server->address,&cliaddr.sin_addr,sizeof(struct in_addr)))
427 {
428 if (ntohl(packet.flags)&TF_SHUTDOWN)
429 {
430 list_remove_elem(serverlist_head,&curr);
431 xfree(server);
432 }
433 else
434 {
435 /* update in place */
436 server->info = packet;
437 server->updated = time(NULL);
438 }
439 break;
440 }
441 }
442
443 /* Not found? Make a new slot */
444 if (!(ntohl(packet.flags)&TF_SHUTDOWN) && !curr)
445 {
446 server = xmalloc(sizeof(t_server));
447 server->address = cliaddr.sin_addr;
448 server->info = packet;
449 server->updated = time(NULL);
450
451 list_append_data(serverlist_head,server);
452 }
453
454 eventlog(eventlog_level_debug,__FUNCTION__,
455 "Packet received from %s:"
456 " packet_version=%u"
457 " flags=0x%08lx"
458 " port=%hu"
459 " software=\"%s\""
460 " version=\"%s\""
461 " platform=\"%s\""
462 " server_desc=\"%s\""
463 " server_location=\"%s\""
464 " server_url=\"%s\""
465 " contact_name=\"%s\""
466 " contact_email=\"%s\""
467 " uptime=%lu"
468 " total_games=%lu"
469 " total_logins=%lu",
470 inet_ntoa(cliaddr.sin_addr),
471 ntohs(packet.packet_version),
472 (unsigned long)ntohl(packet.flags),
473 ntohs(packet.port),
474 packet.software,
475 packet.version,
476 packet.platform,
477 packet.server_desc,
478 packet.server_location,
479 packet.server_url,
480 packet.contact_name,
481 packet.contact_email,
482 (unsigned long)ntohl(packet.uptime),
483 (unsigned long)ntohl(packet.total_games),
484 (unsigned long)ntohl(packet.total_logins));
485 }
486
487 }
488 }
489
490 }
491 }
492
493
494 static void usage(char const * progname)
495 {
496 fprintf(stderr,"usage: %s [<options>]\n",progname);
497 fprintf(stderr,
498 " -c COMMAND, --command=COMMAND execute COMMAND update\n"
499 " -d, --debug turn on debug mode\n"
500 " -e SECS, --expire SECS forget a list entry after SEC seconds\n"
501 #ifdef DO_DAEMONIZE
502 " -f, --foreground don't daemonize\n"
503 #else
504 " -f, --foreground don't daemonize (default)\n"
505 #endif
506 " -l FILE, --logfile=FILE write event messages to FILE\n"
507 " -o FILE, --outfile=FILE write server list to FILE\n");
508 fprintf(stderr,
509 " -p PORT, --port=PORT listen for announcments on UDP port PORT\n"
510 " -P FILE, --pidfile=FILE write pid to FILE\n"
511 " -u SECS, --update SECS write output file every SEC seconds\n"
512 " -x, --XML write output file in XML format\n"
513 " -h, --help, --usage show this information and exit\n"
514 " -v, --version print version number and exit\n");
515 exit(STATUS_FAILURE);
516 }
517
518
519 static void getprefs(int argc, char * argv[])
520 {
521 int a;
522
523 prefs.foreground = 0;
524 prefs.debug = 0;
525 prefs.expire = 0;
526 prefs.update = 0;
527 prefs.port = 0;
528 prefs.XML_mode = 0;
529 prefs.outfile = NULL;
530 prefs.pidfile = NULL;
531 prefs.process = NULL;
532 prefs.logfile = NULL;
533
534 for (a=1; a<argc; a++)
535 if (strncmp(argv[a],"--command=",10)==0)
536 {
537 if (prefs.process)
538 {
539 fprintf(stderr,"%s: processing command was already specified as \"%s\"\n",argv[0],prefs.process);
540 usage(argv[0]);
541 }
542 prefs.process = &argv[a][10];
543 }
544 else if (strcmp(argv[a],"-c")==0)
545 {
546 if (a+1>=argc)
547 {
548 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
549 usage(argv[0]);
550 }
551 if (prefs.process)
552 {
553 fprintf(stderr,"%s: processing command was already specified as \"%s\"\n",argv[0],prefs.process);
554 usage(argv[0]);
555 }
556 a++;
557 prefs.process = argv[a];
558 }
559 else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--debug")==0)
560 prefs.debug = 1;
561 else if (strncmp(argv[a],"--expire=",9)==0)
562 {
563 if (prefs.expire)
564 {
565 fprintf(stderr,"%s: expiration period was already specified as \"%u\"\n",argv[0],prefs.expire);
566 usage(argv[0]);
567 }
568 if (str_to_uint(&argv[a][9],&prefs.expire)<0)
569 {
570 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][9]);
571 usage(argv[0]);
572 }
573 }
574 else if (strcmp(argv[a],"-e")==0)
575 {
576 if (a+1>=argc)
577 {
578 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
579 usage(argv[0]);
580 }
581 if (prefs.expire)
582 {
583 fprintf(stderr,"%s: expiration period was already specified as \"%u\"\n",argv[0],prefs.expire);
584 usage(argv[0]);
585 }
586 a++;
587 if (str_to_uint(argv[a],&prefs.expire)<0)
588 {
589 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]);
590 usage(argv[0]);
591 }
592 }
593 else if (strcmp(argv[a],"-f")==0 || strcmp(argv[a],"--foreground")==0)
594 prefs.foreground = 1;
595 else if (strcmp(argv[a],"-x")==0 || strcmp(argv[a],"--XML")==0)
596 prefs.XML_mode = 1;
597 else if (strncmp(argv[a],"--logfile=",10)==0)
598 {
599 if (prefs.logfile)
600 {
601 fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],prefs.logfile);
602 usage(argv[0]);
603 }
604 prefs.logfile = &argv[a][10];
605 }
606 else if (strcmp(argv[a],"-l")==0)
607 {
608 if (a+1>=argc)
609 {
610 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
611 usage(argv[0]);
612 }
613 if (prefs.logfile)
614 {
615 fprintf(stderr,"%s: eventlog file was already specified as \"%s\"\n",argv[0],prefs.logfile);
616 usage(argv[0]);
617 }
618 a++;
619 prefs.logfile = argv[a];
620 }
621 else if (strncmp(argv[a],"--outfile=",10)==0)
622 {
623 if (prefs.outfile)
624 {
625 fprintf(stderr,"%s: output file was already specified as \"%s\"\n",argv[0],prefs.outfile);
626 usage(argv[0]);
627 }
628 prefs.outfile = &argv[a][10];
629 }
630 else if (strcmp(argv[a],"-o")==0)
631 {
632 if (a+1>=argc)
633 {
634 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
635 usage(argv[0]);
636 }
637 if (prefs.outfile)
638 {
639 fprintf(stderr,"%s: output file was already specified as \"%s\"\n",argv[0],prefs.outfile);
640 usage(argv[0]);
641 }
642 a++;
643 prefs.outfile = argv[a];
644 }
645 else if (strncmp(argv[a],"--pidfile=",10)==0)
646 {
647 if (prefs.pidfile)
648 {
649 fprintf(stderr,"%s: pid file was already specified as \"%s\"\n",argv[0],prefs.pidfile);
650 usage(argv[0]);
651 }
652 prefs.pidfile = &argv[a][10];
653 }
654 else if (strncmp(argv[a],"--port=",7)==0)
655 {
656 if (prefs.port)
657 {
658 fprintf(stderr,"%s: port number was already specified as \"%hu\"\n",argv[0],prefs.port);
659 usage(argv[0]);
660 }
661 if (str_to_ushort(&argv[a][7],&prefs.port)<0)
662 {
663 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][7]);
664 usage(argv[0]);
665 }
666 }
667 else if (strcmp(argv[a],"-p")==0)
668 {
669 if (a+1>=argc)
670 {
671 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
672 usage(argv[0]);
673 }
674 if (prefs.port)
675 {
676 fprintf(stderr,"%s: port number was already specified as \"%hu\"\n",argv[0],prefs.port);
677 usage(argv[0]);
678 }
679 a++;
680 if (str_to_ushort(argv[a],&prefs.port)<0)
681 {
682 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]);
683 usage(argv[0]);
684 }
685 }
686 else if (strcmp(argv[a],"-P")==0)
687 {
688 if (a+1>=argc)
689 {
690 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
691 usage(argv[0]);
692 }
693 if (prefs.pidfile)
694 {
695 fprintf(stderr,"%s: pid file was already specified as \"%s\"\n",argv[0],prefs.pidfile);
696 usage(argv[0]);
697 }
698 a++;
699 prefs.pidfile = argv[a];
700 }
701 else if (strncmp(argv[a],"--update=",9)==0)
702 {
703 if (prefs.update)
704 {
705 fprintf(stderr,"%s: update period was already specified as \"%u\"\n",argv[0],prefs.expire);
706 usage(argv[0]);
707 }
708 if (str_to_uint(&argv[a][9],&prefs.update)<0)
709 {
710 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],&argv[a][9]);
711 usage(argv[0]);
712 }
713 }
714 else if (strcmp(argv[a],"-u")==0)
715 {
716 if (a+1>=argc)
717 {
718 fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
719 usage(argv[0]);
720 }
721 if (prefs.update)
722 {
723 fprintf(stderr,"%s: update period was already specified as \"%u\"\n",argv[0],prefs.expire);
724 usage(argv[0]);
725 }
726 a++;
727 if (str_to_uint(argv[a],&prefs.update)<0)
728 {
729 fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]);
730 usage(argv[0]);
731 }
732 }
733 else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")
734 ==0)
735 usage(argv[0]);
736 else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0)
737 {
738 printf("version "PVPGN_VERSION"\n");
739 exit(0);
740 }
741 else if (strcmp(argv[a],"--command")==0 || strcmp(argv[a],"--expire")==0 ||
742 strcmp(argv[a],"--logfile")==0 || strcmp(argv[a],"--outfile")==0 ||
743 strcmp(argv[a],"--port")==0 || strcmp(argv[a],"--pidfile")==0 ||
744 strcmp(argv[a],"--update")==0)
745 {
746 fprintf(stderr,"%s: option \"%s\" requires and argument.\n",argv[0],argv[a]);
747 usage(argv[0]);
748 }
749 else
750 {
751 fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]);
752 usage(argv[0]);
753 }
754
755 if (!prefs.process)
756 prefs.process = BNTRACKD_PROCESS;
757 if (prefs.expire==0)
758 prefs.expire = BNTRACKD_EXPIRE;
759 if (!prefs.logfile)
760 prefs.logfile = BNTRACKD_LOGFILE;
761 if (!prefs.outfile)
762 prefs.outfile = BNTRACKD_OUTFILE;
763 if (prefs.port==0)
764 prefs.port = BNTRACKD_SERVER_PORT;
765 if (!prefs.pidfile)
766 prefs.pidfile = BNTRACKD_PIDFILE;
767 if (prefs.expire==0)
768 prefs.update = BNTRACKD_UPDATE;
769
770 if (prefs.logfile[0]=='\0')
771 prefs.logfile = NULL;
772 if (prefs.pidfile[0]=='\0')
773 prefs.pidfile = NULL;
774 }
775
776
777 static void fixup_str(char * str)
778 {
779 char prev;
780 unsigned int i;
781
782 for (prev='\0',i=0; i<strlen(str); prev=str[i],i++)
783 if (prev=='#' && str[i]=='#')
784 str[i] = '%';
785 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1