1 /*
2 * Copyright (c) 1997, 98, 99, 2000, 01, 02
3 * Motoyuki Kasahara
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * 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
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <errno.h>
23 #include <syslog.h>
24 #include <signal.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28
29 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
30 #include <string.h>
31 #if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
32 #include <memory.h>
33 #endif /* not STDC_HEADERS and HAVE_MEMORY_H */
34 #else /* not STDC_HEADERS and not HAVE_STRING_H */
35 #include <strings.h>
36 #endif /* not STDC_HEADERS and not HAVE_STRING_H */
37
38 #ifdef HAVE_STDLIB_H
39 #include <stdlib.h>
40 #endif
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 #if defined(HAVE_SYS_WAIT_H) || defined(HAVE_UNION_WAIT)
47 #include <sys/wait.h>
48 #endif
49
50 #ifdef HAVE_LIMITS_H
51 #include <limits.h>
52 #endif
53
54 #ifdef HAVE_LOCALE_H
55 #include <locale.h>
56 #endif
57
58 #ifndef HAVE_STRCHR
59 #define strchr index
60 #define strrchr rindex
61 #endif /* HAVE_STRCHR */
62
63 #ifndef HAVE_GETCWD
64 #define getcwd(d,n) getwd(d)
65 #endif
66
67 #ifndef PATH_MAX
68 #ifdef MAXPATHLEN
69 #define PATH_MAX MAXPATHLEN
70 #else /* not MAXPATHLEN */
71 #define PATH_MAX 1024
72 #endif /* not MAXPATHLEN */
73 #endif /* not PATH_MAX */
74
75 #ifdef HAVE_UNION_WAIT
76 #ifndef WTERMSIG
77 #define WTERMSIG(x) ((x).w_termsig)
78 #endif
79 #ifndef WCOREDUMP
80 #define WCOREDUMP(x) ((x).w_coredump)
81 #endif
82 #ifndef WEXITSTATUS
83 #define WEXITSTATUS(x) ((x).w_retcode)
84 #endif
85 #ifndef WIFSIGNALED
86 #define WIFSIGNALED(x) (WTERMSIG(x) != 0)
87 #endif
88 #ifndef WIFEXITED
89 #define WIFEXITED(x) (WTERMSIG(x) == 0)
90 #endif
91 #else /* not HAVE_UNION_WAIT */
92 #ifndef WTERMSIG
93 #define WTERMSIG(x) ((x) & 0x7f)
94 #endif
95 #ifndef WCOREDUMP
96 #define WCOREDUMP(x) ((x) & 0x80)
97 #endif
98 #ifndef WEXITSTATUS
99 #define WEXITSTATUS(x) (((x) >> 8) & 0xff)
100 #endif
101 #ifndef WIFSIGNALED
102 #define WIFSIGNALED(x) (WTERMSIG (x) != 0)
103 #endif
104 #ifndef WIFEXITED
105 #define WIFEXITED(x) (WTERMSIG (x) == 0)
106 #endif
107 #endif /* not HAVE_UNION_WAIT */
108
109 #ifndef SHUT_RD
110 #define SHUT_RD 0
111 #endif
112 #ifndef SHUT_WR
113 #define SHUT_WR 1
114 #endif
115 #ifndef SHUT_RDWR
116 #define SHUT_RDWR 2
117 #endif
118
119 #include "confutil.h"
120 #include "daemon.h"
121 #include "fakelog.h"
122 #include "fdset.h"
123 #include "filename.h"
124 #include "getopt.h"
125 #include "hostname.h"
126 #include "linebuf.h"
127 #include "logpid.h"
128 #include "openmax.h"
129 #include "permission.h"
130 #include "privilege.h"
131 #include "serverport.h"
132 #include "signame.h"
133 #include "ticket.h"
134 #include "wildcard.h"
135
136 #include "defs.h"
137
138 /*
139 * Unexported functions.
140 */
141 static void standalone_main EBNETD_P((void));
142 static void inetd_main EBNETD_P((void));
143 static void test_main EBNETD_P((void));
144 static void output_help EBNETD_P((void));
145 static void set_signal_handler EBNETD_P((int, RETSIGTYPE (*)(int)));
146 static void block_signal EBNETD_P((int));
147 static void unblock_signal EBNETD_P((int));
148 static RETSIGTYPE abort_parent EBNETD_P((int));
149 static RETSIGTYPE abort_child EBNETD_P((int));
150 static RETSIGTYPE terminate_parent EBNETD_P((int));
151 static RETSIGTYPE terminate_child EBNETD_P((int));
152 static RETSIGTYPE restart_parent EBNETD_P((int));
153 static RETSIGTYPE wait_child EBNETD_P((int));
154
155 /*
156 * Command line options.
157 */
158 static const char *short_options = "c:hitv";
159 static struct option long_options[] = {
160 {"configuration-file", required_argument, NULL, 'c'},
161 {"help", no_argument, NULL, 'h'},
162 {"inetd", no_argument, NULL, 'i'},
163 {"test", no_argument, NULL, 't'},
164 {"version", no_argument, NULL, 'v'},
165 {NULL, 0, NULL, 0}
166 };
167
168 /*
169 * The flag is set when the server is started.
170 */
171 static int once_started;
172
173 /*
174 * The flag is set if SIGHUP is received.
175 */
176 static int restart_trigger;
177
178 /*
179 * Process group ID of the server.
180 */
181 pid_t process_group_id;
182
183 /*
184 * Signal mask.
185 */
186 #if !defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSETMASK)
187 static int signal_mask = 0;
188 #endif
189
190
191 int
main(argc,argv)192 main(argc, argv)
193 int argc;
194 char *argv[];
195 {
196 EB_Error_Code error_code;
197 int ch;
198
199 /*
200 * We must output US-ASCII syslog messages.
201 */
202 #ifdef HAVE_SETENV
203 setenv("LC_ALL", "C", 1);
204 setenv("LANGUAGE", "C", 1);
205 #else
206 putenv("LC_ALL=C");
207 putenv("LANGUAGE=C");
208 #endif
209
210 #ifdef HAVE_SETLOCALE
211 setlocale(LC_ALL, "C");
212 #endif
213
214 /*
215 * Set program name and version.
216 */
217 invoked_name = argv[0];
218 program_name = SERVER_PROGRAM_NAME;
219 program_version = VERSION;
220
221 /*
222 * Set umask.
223 */
224 umask(SERVER_UMASK);
225
226 /*
227 * Set fakelog behavior.
228 */
229 set_fakelog_name(invoked_name);
230 set_fakelog_mode(FAKELOG_TO_SYSLOG);
231 set_fakelog_level(LOG_DEBUG);
232
233 /*
234 * Open syslog.
235 * If LOG_DAEMON is not defined, it assumes old style syslog
236 * It doesn't have facility.
237 */
238 syslog_facility = DEFAULT_SYSLOG_FACILITY;
239 #ifdef LOG_DAEMON
240 openlog(program_name, LOG_NDELAY | LOG_PID, syslog_facility);
241 #else
242 openlog(program_name, LOG_NDELAY | LOG_PID);
243 #endif
244 syslog(LOG_DEBUG, "debug: open syslog");
245
246 /*
247 * Initialize EB Library.
248 */
249 error_code = eb_initialize_library();
250 if (error_code != EB_SUCCESS) {
251 syslog(LOG_ERR, "%s\n", eb_error_message(error_code));
252 exit(1);
253 }
254
255 /*
256 * Initialize variables.
257 */
258 once_started = 0;
259 initialize_fdset(&listening_files, &max_listening_file);
260 server_mode = SERVER_MODE_STANDALONE;
261
262 if (PATH_MAX < strlen(DEFAULT_CONFIGURATION_FILE_NAME)) {
263 syslog(LOG_ERR,
264 "internal error, too long DEFAULT_CONFIGURATION_FILE_NAME");
265 goto die;
266 }
267 strcpy(configuration_file_name, DEFAULT_CONFIGURATION_FILE_NAME);
268 initialize_global_variables();
269
270 /*
271 * Parse command line options.
272 */
273 for (;;) {
274 ch = getopt_long(argc, argv, short_options, long_options, NULL);
275 if (ch == -1)
276 break;
277 switch (ch) {
278 case 'c':
279 /*
280 * Option `-c file'. Specify the configuration file name.
281 */
282 if (PATH_MAX < strlen(optarg)) {
283 fprintf(stderr, "%s: too long configuration file name\n",
284 invoked_name);
285 goto die;
286 }
287 strcpy(configuration_file_name, optarg);
288 if (canonicalize_file_name(configuration_file_name) < 0)
289 goto die;
290 break;
291
292 case 'h':
293 /*
294 * Option `-h'. Help.
295 */
296 output_help();
297 exit(0);
298
299 case 'i':
300 /*
301 * Option `-i'. Inetd mode.
302 */
303 server_mode = SERVER_MODE_INETD;
304 break;
305
306 case 't':
307 /*
308 * Option `-t'. Test mode.
309 */
310 server_mode = SERVER_MODE_TEST;
311 break;
312
313 case 'v':
314 /*
315 * Option `-v'. Show version and exit immediately.
316 */
317 output_version();
318 exit(0);
319
320 default:
321 output_try_help();
322 exit(1);
323 }
324 }
325
326 /*
327 * Check for the number of rest arguments.
328 */
329 if (0 < argc - optind) {
330 fprintf(stderr, "%s: too many arguments\n", invoked_name);
331 output_try_help();
332 exit(1);
333 }
334
335 /*
336 * Main routine for each server mode.
337 */
338 switch (server_mode) {
339 case SERVER_MODE_STANDALONE:
340 for (;;)
341 standalone_main();
342 break;
343 case SERVER_MODE_INETD:
344 inetd_main();
345 break;
346 case SERVER_MODE_TEST:
347 test_main();
348 break;
349 }
350
351 return 0;
352
353 /*
354 * A fatal error occurrs...
355 */
356 die:
357 if (server_mode == SERVER_MODE_STANDALONE)
358 syslog(LOG_CRIT, "the server exits");
359 else if (server_mode == SERVER_MODE_INETD)
360 syslog(LOG_INFO, "the server exits");
361
362 exit(1);
363 }
364
365
366 /*
367 * Main routine for standalone mode.
368 */
369 static void
standalone_main()370 standalone_main()
371 {
372 #if defined(ENABLE_IPV6)
373 struct sockaddr_storage address;
374 #else
375 struct sockaddr_in address;
376 #endif
377 socklen_t address_length;
378 int fd;
379 int pid = -1;
380
381 fd_set select_files;
382 int i;
383
384 /*
385 * Block signals.
386 */
387 #if !defined(HAVE_SIGPROCMASK) && defined(HAVE_SIGSETMASK)
388 signal_mask = 0;
389 #endif
390 block_signal(SIGHUP);
391 block_signal(SIGINT);
392 block_signal(SIGTERM);
393
394 /*
395 * Reset restart trigger.
396 */
397 restart_trigger = 0;
398
399 /*
400 * Kill child processes.
401 */
402 if (once_started) {
403 #ifdef HAVE_KILLPG
404 killpg(process_group_id, SIGINT);
405 #else
406 kill(-process_group_id, SIGINT);
407 #endif
408 syslog(LOG_DEBUG, "debug: kill all child processes");
409 }
410
411 /*
412 * Close unwanted files.
413 */
414 if (!once_started) {
415 closelog();
416 for (fd = get_open_max() - 1; 0 <= fd; fd--)
417 close(fd);
418 #ifdef LOG_DAEMON
419 openlog(program_name, LOG_NDELAY | LOG_PID, syslog_facility);
420 #else
421 openlog(program_name, LOG_NDELAY | LOG_PID);
422 #endif
423 syslog(LOG_DEBUG, "debug: reopen syslog");
424 }
425
426 /*
427 * Re-initinalize variables.
428 */
429 if (once_started) {
430 finalize_global_variables();
431 initialize_global_variables();
432 }
433
434 /*
435 * Read a configuration file.
436 */
437 if (read_configuration(configuration_file_name, configuration_table) < 0) {
438 syslog(LOG_ERR, "configuration failure");
439 goto die;
440 }
441
442 /*
443 * Reopen syslog.
444 */
445 closelog();
446 #ifdef LOG_DAEMON
447 openlog(program_name, LOG_NDELAY | LOG_PID, syslog_facility);
448 #else
449 openlog(program_name, LOG_NDELAY | LOG_PID);
450 #endif
451 /*
452 * Run as standalone daemon.
453 */
454 if (!once_started) {
455 if (daemonize() < 0)
456 goto die;
457 #ifdef GETPGRP_VOID
458 process_group_id = getpgrp();
459 #else
460 process_group_id = getpgrp(getpid());
461 #endif
462 }
463
464 /*
465 * Change the current working directory.
466 */
467 if (chdir(work_path) < 0) {
468 syslog(LOG_ERR, "failed to change the directory, %s: %s",
469 strerror(errno), work_path);
470 goto die;
471 }
472
473 /*
474 * Shutdown old connections if the server port is changed.
475 */
476 if (once_started && listening_port != old_listening_port) {
477 /* shutdown multi sockets */
478 if (shutdown_fdset(&listening_files, &max_listening_file, SHUT_RDWR)
479 < 0) {
480 syslog(LOG_ERR, "shutdown() failed, %s", strerror(errno));
481 goto die;
482 }
483 /* close multi sockets */
484 close_fdset(&listening_files, &max_listening_file);
485 syslog(LOG_DEBUG, "debug: shutdown the old socket: %d/tcp",
486 listening_port);
487 }
488
489
490 /*
491 * Bind and listen to the server port.
492 */
493 if (max_listening_file < 0) {
494 if (set_server_ports(listening_port, LISTENING_BACKLOG,
495 &listening_files, &max_listening_file) < 0)
496 goto die;
497 old_listening_port = listening_port;
498 }
499 /*
500 * Set UID and GID.
501 */
502 if (set_privilege(user_id, group_id) < 0)
503 goto die;
504
505 /*
506 * Activate all books.
507 */
508 if (activate_book_registry() == 0)
509 syslog(LOG_ERR, "no book is available");
510
511 /*
512 * Unlink an old PID file if exists.
513 */
514 if (once_started)
515 remove_pid_file(old_pid_file_name);
516 strcpy(old_pid_file_name, pid_file_name);
517
518 /*
519 * Bind a ticket stock.
520 */
521 if (max_clients != 0 && bind_ticket_stock(&connection_ticket_stock,
522 connection_lock_file_name, max_clients) < 0)
523 goto die;
524
525 /*
526 * Log pid to the file.
527 */
528 if (log_pid_file(pid_file_name) < 0)
529 goto die;
530
531 /*
532 * Set signal handlers.
533 */
534 set_signal_handler(SIGBUS, abort_parent);
535 set_signal_handler(SIGSEGV, abort_parent);
536 set_signal_handler(SIGINT, SIG_IGN);
537 set_signal_handler(SIGQUIT, SIG_IGN);
538 set_signal_handler(SIGTERM, terminate_parent);
539 set_signal_handler(SIGCHLD, wait_child);
540 set_signal_handler(SIGHUP, restart_parent);
541
542 /*
543 * Set `once_started' flag.
544 */
545 if (once_started)
546 syslog(LOG_NOTICE, "server restarted");
547 else
548 syslog(LOG_NOTICE, "server started");
549 once_started = 1;
550
551 /*
552 * Main loop for the parent process.
553 */
554 for (;;) {
555 /*
556 * Unblock fatal signals.
557 */
558 unblock_signal(SIGHUP);
559 unblock_signal(SIGINT);
560 unblock_signal(SIGTERM);
561 unblock_signal(SIGCHLD);
562
563 /*
564 * Wait a connection from a client.
565 */
566 if (wait_server_ports(&listening_files, &select_files,
567 &max_listening_file) < 0) {
568 if (errno != EINTR) {
569 syslog(LOG_DEBUG, "failed to wait a connection, %s",
570 strerror(errno));
571 goto die;
572 }
573 else if (restart_trigger) {
574 return;
575 } else {
576 continue;
577 }
578
579 }
580 /*
581 * Block fatal signals.
582 */
583 block_signal(SIGHUP);
584 block_signal(SIGINT);
585 block_signal(SIGTERM);
586 block_signal(SIGCHLD);
587
588 /*
589 * Accept a connection.
590 */
591 #if defined(ENABLE_IPV6)
592 address_length = sizeof(struct sockaddr_storage);
593 #else
594 address_length = sizeof(struct sockaddr_in);
595 #endif
596
597 /*
598 * TODO: nonblocking I/O (not yet)
599 */
600 for (i = 0; i <= max_listening_file; i++) {
601 if (FD_ISSET(i, &select_files)) {
602 accepted_in_file = accept(i, (struct sockaddr *)&address,
603 &address_length);
604 accepted_out_file = accepted_in_file;
605 if (accepted_in_file < 0) {
606 syslog(LOG_ERR, "accept() failed, %s", strerror(errno));
607 continue;
608 }
609
610 syslog(LOG_DEBUG, "debug: accept the connection");
611
612 /*
613 * Fork. The child process talk to the client.
614 */
615 pid = fork();
616 if (pid < 0) {
617 syslog(LOG_ERR, "fork() failed, %s", strerror(errno));
618 continue;
619 } else if (pid == 0) {
620 syslog(LOG_DEBUG, "debug: forked");
621 break;
622 }
623
624 /*
625 * Close an accepted socket (at the parent process).
626 */
627 if (close(accepted_in_file) < 0) {
628 syslog(LOG_ERR, "close() failed, %s", strerror(errno));
629 goto die;
630 }
631 }
632 }
633
634 if (pid == 0) {
635 break;
636 }
637
638 }
639
640 /*
641 * Set signal handlers.
642 */
643 set_signal_handler(SIGBUS, abort_child);
644 set_signal_handler(SIGSEGV, abort_child);
645 set_signal_handler(SIGINT, terminate_child);
646 set_signal_handler(SIGTERM, terminate_child);
647 set_signal_handler(SIGCHLD, SIG_IGN);
648 set_signal_handler(SIGHUP, terminate_child);
649 set_signal_handler(SIGPIPE, SIG_IGN);
650
651 /*
652 * Unblock fatal signals.
653 */
654 unblock_signal(SIGHUP);
655 unblock_signal(SIGINT);
656 unblock_signal(SIGTERM);
657 unblock_signal(SIGCHLD);
658
659 /*
660 * Close the file to listen to the server port.
661 */
662 close_fdset(&listening_files, &max_listening_file);
663
664 /*
665 * Get the client host name and address.
666 */
667 if (identify_remote_host(accepted_in_file, client_host_name,
668 client_address) < 0) {
669 syslog(LOG_ERR, "connection denied: host=%s(%s)", client_host_name,
670 client_address);
671 shutdown(accepted_in_file, SHUT_RDWR);
672 exit(1);
673 }
674 /*
675 * Check for the access permission to the client.
676 */
677 if (!test_permission(&permissions, client_host_name, client_address,
678 match_wildcard)) {
679 syslog(LOG_ERR, "connection denied: host=%s(%s)",
680 client_host_name, client_address);
681 shutdown(accepted_in_file, SHUT_RDWR);
682 exit(0);
683 }
684 /*
685 * Get a ticket for the client.
686 */
687 if (max_clients != 0) {
688 if (get_ticket(&connection_ticket_stock) < 0) {
689 syslog(LOG_INFO, "full of clients");
690 shutdown(accepted_in_file, SHUT_RDWR);
691 exit(0);
692 }
693 }
694
695 syslog(LOG_INFO, "connected: host=%s(%s)", client_host_name,
696 client_address);
697
698 /*
699 * Set book permissions to the current client.
700 */
701 check_book_permissions();
702
703 /*
704 * Communicate with the client.
705 */
706 protocol_main();
707 shutdown(accepted_in_file, SHUT_RDWR);
708
709 /*
710 * Clear lists and buffers.
711 */
712 finalize_global_variables();
713 eb_finalize_library();
714
715 syslog(LOG_INFO, "the child server process exits");
716 exit(0);
717
718 /*
719 * A fatal error occurrs on a parent...
720 */
721 die:
722 shutdown_fdset(&listening_files, &max_listening_file, SHUT_RDWR);
723 close_fdset(&listening_files, &max_listening_file);
724 if (once_started)
725 remove_pid_file(old_pid_file_name);
726
727 if (once_started) {
728 set_signal_handler(SIGINT, SIG_IGN);
729 #ifdef HAVE_KILLPG
730 killpg(process_group_id, SIGINT);
731 #else
732 kill(-process_group_id, SIGINT);
733 #endif
734 }
735
736 finalize_global_variables();
737 eb_finalize_library();
738
739 syslog(LOG_CRIT, "the server exits");
740 exit(1);
741 }
742
743
744 /*
745 * Main routine for inetd mode.
746 */
747 static void
inetd_main()748 inetd_main()
749 {
750 accepted_in_file = 0;
751 accepted_out_file = 1;
752
753 /*
754 * Set signal handlers.
755 */
756 set_signal_handler(SIGBUS, abort_parent);
757 set_signal_handler(SIGSEGV, abort_parent);
758 set_signal_handler(SIGINT, SIG_IGN);
759 set_signal_handler(SIGQUIT, SIG_IGN);
760 set_signal_handler(SIGTERM, terminate_parent);
761 set_signal_handler(SIGHUP, terminate_parent);
762 set_signal_handler(SIGPIPE, SIG_IGN);
763
764 /*
765 * Read a configuration file.
766 */
767 if (read_configuration(configuration_file_name, configuration_table) < 0) {
768 syslog(LOG_ERR, "configuration failure");
769 goto die;
770 }
771
772 /*
773 * Reopen syslog.
774 */
775 closelog();
776 #ifdef LOG_DAEMON
777 openlog(program_name, LOG_NDELAY | LOG_PID, syslog_facility);
778 #else
779 openlog(program_name, LOG_NDELAY | LOG_PID);
780 #endif
781
782 /*
783 * Change the current working directory.
784 */
785 if (chdir(work_path) < 0) {
786 syslog(LOG_ERR, "failed to change the directory, %s: %s",
787 strerror(errno), work_path);
788 goto die;
789 }
790
791 /*
792 * Set UID and GID.
793 */
794 if (set_privilege(user_id, group_id) < 0) {
795 syslog(LOG_ERR,
796 "failed to set owner and group of the process");
797 goto die;
798 }
799
800 /*
801 * Get the client host name and address.
802 */
803 if (identify_remote_host(accepted_in_file, client_host_name,
804 client_address) < 0) {
805 syslog(LOG_ERR, "connection denied: host=%s(%s)", client_host_name,
806 client_address);
807 goto die;
808 }
809 /*
810 * Check for the access permission to the client.
811 */
812 if (!test_permission(&permissions, client_host_name, client_address,
813 match_wildcard)) {
814 syslog(LOG_ERR, "connection denied: host=%s(%s)",
815 client_host_name, client_address);
816 shutdown(accepted_in_file, SHUT_RDWR);
817 exit(0);
818 }
819
820 /*
821 * Get a ticket for the client.
822 */
823 if (max_clients != 0) {
824 bind_ticket_stock(&connection_ticket_stock, connection_lock_file_name,
825 max_clients);
826 if (get_ticket(&connection_ticket_stock) < 0) {
827 syslog(LOG_INFO, "full of clients");
828 goto die;
829 }
830 }
831
832 syslog(LOG_INFO, "connected: host=%s(%s)",
833 client_host_name, client_address);
834
835 /*
836 * Activate all books.
837 */
838 if (activate_book_registry() == 0)
839 syslog(LOG_ERR, "no book is available");
840
841 /*
842 * Check book permissions to the current client.
843 */
844 check_book_permissions();
845
846 /*
847 * Communicate with the client.
848 */
849 protocol_main();
850
851 /*
852 * Clear lists and buffers.
853 */
854 finalize_global_variables();
855 eb_finalize_library();
856
857 syslog(LOG_INFO, "the server exits");
858 exit(0);
859
860 /*
861 * A fatal error occurrs...
862 */
863 die:
864 fflush(stderr);
865 shutdown(accepted_in_file, SHUT_RDWR);
866 finalize_global_variables();
867 eb_finalize_library();
868
869 syslog(LOG_INFO, "the server exits");
870 exit(1);
871 }
872
873
874 /*
875 * Main routine for inetd mode.
876 */
877 static void
test_main()878 test_main()
879 {
880 accepted_in_file = 0;
881 accepted_out_file = 1;
882
883 /*
884 * Read a configuration file.
885 */
886 if (read_configuration(configuration_file_name, configuration_table) < 0) {
887 fprintf(stderr, "configuration failure\n");
888 syslog(LOG_ERR, "configuration failure");
889 exit(1);
890 }
891
892 /*
893 * Activate all books.
894 */
895 if (activate_book_registry() == 0)
896 syslog(LOG_ERR, "no book is available");
897
898 /*
899 * Set dummy host name and address.
900 */
901 strcpy(client_address, "test-mode");
902 if (isatty(0))
903 strncpy(client_host_name, ttyname(0), MAX_HOST_NAME_LENGTH);
904 else
905 strncpy(client_host_name, "stdin", MAX_HOST_NAME_LENGTH);
906 *(client_host_name + MAX_HOST_NAME_LENGTH) = '\0';
907
908 idle_timeout = 0;
909
910 /*
911 * Reopen syslog.
912 */
913 closelog();
914 #ifdef LOG_DAEMON
915 openlog(program_name, LOG_NDELAY | LOG_PID, syslog_facility);
916 #else
917 openlog(program_name, LOG_NDELAY | LOG_PID);
918 #endif
919
920 syslog(LOG_INFO, "connected: host=%s(%s)", client_host_name,
921 client_address);
922
923 /*
924 * Set book permissions.
925 */
926 set_all_book_permissions();
927
928 /*
929 * Communicate with the client.
930 */
931 printf("# %s version %s\n", program_name, program_version);
932 printf("# test mode\n");
933 fflush(stdout);
934 protocol_main();
935
936 /*
937 * Clear lists and buffers.
938 */
939 finalize_global_variables();
940 eb_finalize_library();
941
942 exit(0);
943 }
944
945
946 /*
947 * Output usage to standard out.
948 */
949 static void
output_help()950 output_help()
951 {
952 printf("Usage: %s [option...]\n", program_name);
953 printf("Options:\n");
954 printf(" -c FILE --configuration-file FILE\n");
955 printf(" specify a configuration file\n");
956 printf(" (default: %s)\n",
957 DEFAULT_CONFIGURATION_FILE_NAME);
958 printf(" -h --help display this help, then exit\n");
959 printf(" -i --inetd inetd mode\n");
960 printf(" -t --test test mode\n");
961 printf(" -v --version display version number, then exit\n");
962 printf("\nDefault value used in a configuration file:\n");
963 printf(" work-path %s\n", DEFAULT_WORK_PATH);
964 printf("\nOptional feature:\n");
965 #ifdef ENABLE_IPV6
966 printf(" IPv6 support enabled\n");
967 #else
968 printf(" IPv6 disabled\n\n");
969 #endif
970
971 printf("\nReport bugs to %s.\n", MAILING_ADDRESS);
972 fflush(stdout);
973 }
974
975
976 /*
977 * Set a signal handler.
978 * `signal' on some SystemV based systems is not reliable.
979 * We use `sigaction' if available.
980 */
981 static void
set_signal_handler(signal_number,function)982 set_signal_handler(signal_number, function)
983 int signal_number;
984 RETSIGTYPE (*function) EBNETD_P((int));
985 {
986 #ifdef HAVE_SIGPROCMASK
987 struct sigaction action;
988
989 action.sa_handler = function;
990 sigemptyset(&action.sa_mask);
991 action.sa_flags = SA_NOCLDSTOP;
992
993 if (signal_number == SIGALRM) {
994 #ifdef SA_INTERRUPT
995 action.sa_flags |= SA_INTERRUPT;
996 #endif
997 } else {
998 #ifdef SA_RESTART
999 action.sa_flags |= SA_RESTART;
1000 #endif
1001 }
1002 sigaction(signal_number, &action, NULL);
1003
1004 #else /* not HAVE_SIGPROCMASK */
1005 signal(signal_number, function);
1006 #endif /* not HAVE_SIGPROCMASK */
1007 }
1008
1009
1010 /*
1011 * Block signals of `signal_number' type (SIGHUP, SIGINT, ...).
1012 *
1013 * `sigprocmask' is used, if available.
1014 * Otherwise, `sigsetmask' is used if the system has it.
1015 * If neither `sigprocmask' nor `sigsetmask' is available, we give up
1016 * blocking a signal.
1017 */
1018 static void
block_signal(signal_number)1019 block_signal(signal_number)
1020 int signal_number;
1021 {
1022 #ifdef HAVE_SIGPROCMASK
1023 sigset_t signal_set;
1024 #endif
1025
1026 #ifdef HAVE_SIGPROCMASK
1027 sigemptyset(&signal_set);
1028 sigaddset(&signal_set, signal_number);
1029 sigprocmask(SIG_BLOCK, &signal_set, NULL);
1030 #else /* not HAVE_SIGPROCMASK */
1031 #ifdef HAVE_SIGSETMASK
1032 signal_mask |= sigmask(signal_number);
1033 sigsetmask(signal_mask);
1034 #endif /* HAVE_SIGSETMASK */
1035 #endif /* not HAVE_SIGPROCMASK */
1036 }
1037
1038
1039 /*
1040 * Block signals of `signal_number' type (SIGHUP, SIGINT, ...).
1041 *
1042 * `sigprocmask' is used, if available.
1043 * Otherwise, `sigsetmask' is used if the system has it.
1044 * If neither `sigprocmask' nor `sigsetmask' is available, we give up
1045 * blocking a signal.
1046 */
1047 static void
unblock_signal(signal_number)1048 unblock_signal(signal_number)
1049 int signal_number;
1050 {
1051 #ifdef HAVE_SIGPROCMASK
1052 sigset_t signal_set;
1053 #endif
1054
1055 #ifdef HAVE_SIGPROCMASK
1056 sigemptyset(&signal_set);
1057 sigaddset(&signal_set, signal_number);
1058 sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
1059 #else /* not HAVE_SIGPROCMASK */
1060 #ifdef HAVE_SIGSETMASK
1061 signal_mask = (signal_mask | sigmask(signal_number))
1062 ^ sigmask(signal_number);
1063 sigsetmask(signal_mask);
1064 #endif /* HAVE_SIGSETMASK */
1065 #endif /* not HAVE_SIGPROCMASK */
1066 }
1067
1068
1069 /*
1070 * Signal handler for SIGBUS and SIGSEGV. (for parent)
1071 */
1072 static RETSIGTYPE
abort_parent(signal_number)1073 abort_parent(signal_number)
1074 int signal_number;
1075 {
1076 if (server_mode == SERVER_MODE_STANDALONE) {
1077 syslog(LOG_CRIT, "the server process aborts, receives SIG%s",
1078 signal_name(signal_number));
1079 } else {
1080 syslog(LOG_ERR, "the server process aborts, receives SIG%s",
1081 signal_name(signal_number));
1082 }
1083 abort();
1084
1085 #ifndef RETSIGTYPE_VOID
1086 return 0;
1087 #endif
1088 }
1089
1090
1091 /*
1092 * Signal handler for SIGBUS and SIGSEGV. (for child)
1093 */
1094 static RETSIGTYPE
abort_child(signal_number)1095 abort_child(signal_number)
1096 int signal_number;
1097 {
1098 syslog(LOG_ERR, "the child server process aborts, receives SIG%s",
1099 signal_name(signal_number));
1100 abort();
1101
1102 #ifndef RETSIGTYPE_VOID
1103 return 0;
1104 #endif
1105 }
1106
1107
1108 /*
1109 * Signal handler for SIGTERM, SIGINT SIGQUIT, and SIGHUP. (for parent)
1110 */
1111 static RETSIGTYPE
terminate_parent(signal_number)1112 terminate_parent(signal_number)
1113 int signal_number;
1114 {
1115 if (server_mode == SERVER_MODE_STANDALONE) {
1116 syslog(LOG_CRIT, "the server process exits, receives SIG%s",
1117 signal_name(signal_number));
1118 } else {
1119 syslog(LOG_ERR, "the server process exits, receives SIG%s",
1120 signal_name(signal_number));
1121 }
1122
1123 /*
1124 * Kill child processes.
1125 */
1126 set_signal_handler(SIGINT, SIG_IGN);
1127 if (server_mode == SERVER_MODE_STANDALONE) {
1128 #ifdef HAVE_KILLPG
1129 killpg(process_group_id, SIGINT);
1130 #else
1131 kill(-process_group_id, SIGINT);
1132 #endif
1133 }
1134
1135 /*
1136 * Shutdown a server port.
1137 */
1138 shutdown_fdset(&listening_files, &max_listening_file, SHUT_RDWR);
1139 close_fdset(&listening_files, &max_listening_file);
1140
1141 /*
1142 * Remove a PID file.
1143 */
1144 if (server_mode == SERVER_MODE_STANDALONE)
1145 remove_pid_file(old_pid_file_name);
1146
1147 _exit(1);
1148
1149 #ifndef RETSIGTYPE_VOID
1150 return 0;
1151 #endif
1152 }
1153
1154
1155 /*
1156 * Signal handler for SIGHUP, SIGINT, SIGQUIT and SIGTERM. (for child)
1157 */
1158 static RETSIGTYPE
terminate_child(signal_number)1159 terminate_child(signal_number)
1160 int signal_number;
1161 {
1162 syslog(LOG_ERR, "the child server process exits, receives SIG%s",
1163 signal_name(signal_number));
1164 shutdown(accepted_in_file, SHUT_RDWR);
1165
1166 /*
1167 * Clear lists and buffers.
1168 */
1169 finalize_global_variables();
1170 eb_finalize_library();
1171
1172 _exit(0);
1173
1174 #ifndef RETSIGTYPE_VOID
1175 return 0;
1176 #endif
1177 }
1178
1179
1180 /*
1181 * Signal handler for SIGCHLD.
1182 */
1183 static RETSIGTYPE
wait_child(signal_number)1184 wait_child(signal_number)
1185 int signal_number;
1186 {
1187 #ifdef HAVE_UNION_WAIT
1188 union wait status;
1189 #else
1190 int status;
1191 #endif
1192
1193 syslog(LOG_INFO, "receives SIGCHLD");
1194
1195 #ifdef HAVE_WAITPID
1196 while (0 < waitpid(-1, &status, WNOHANG))
1197 ;
1198 #else /* not HAVE WAITPID */
1199 while (0 < wait3(&status, WNOHANG, NULL))
1200 ;
1201 #endif /* not HAVE WAITPID */
1202
1203 /*
1204 * Set a signal handler again.
1205 */
1206 set_signal_handler(SIGCHLD, wait_child);
1207
1208 #ifndef RETSIGTYPE_VOID
1209 return 0;
1210 #endif
1211 }
1212
1213
1214 /*
1215 * Signal handler for SIGHUP (for parent).
1216 */
1217 static RETSIGTYPE
restart_parent(signal_number)1218 restart_parent(signal_number)
1219 int signal_number;
1220 {
1221 syslog(LOG_ERR, "the server restart, receives SIGHUP");
1222 restart_trigger++;
1223
1224 #ifndef RETSIGTYPE_VOID
1225 return 0;
1226 #endif
1227 }
1228