/* ----------------------------------------------------------------- * Copyright (c) 1997-1998 Hitachi Microsoftware Systems, Inc. All rights reserved. * ----------------------------------------------------------------- */ #include "config.h" #include #include /* getopt() */ #include /* fork(), setsid() */ #ifdef HAVE_ERRNO_H #include #endif /* HAVE_ERRNO_H */ #ifdef HAVE_STRING_H #include /* strncpy(), strerror() */ #endif /* HAVE_STRING_H */ #include "common.h" #include "Config.h" #include "util.h" #include "log.h" #include "sig.h" #include "path.h" /* ================================================================= */ Logger stderrLog(0); int log_level = 1; Logger *elogp = &stderrLog; /* ================================================================= */ /*-----------------------------------------------------------------* =NAME= initApp - initialize application =RETURN= TRUE or FALSE *-----------------------------------------------------------------*/ int initApp() { #ifndef NO_SSL /* prepare SSL communication */ if (!initSSL()) return FALSE; #endif return TRUE; } void sig_default(int sig) { PUTERR(0, ("DEBUG: signal = %d\n", sig)); } /* ----------------------------------------------------------------- * =NAME= help - show help message =RETURN= program exit. * ----------------------------------------------------------------- */ void help() { char msg[] = "USAGE: " TARGET " [options]\n" "\t-a set accept information\n" "\t-c set connect information\n" "\t-f specify config file\n" "\t-h show help\n" "\t-k kill Send signal to running copy and exit\n" "\t-D become daemon\n"; fputs(msg, stderr); exit(0); } /* ----------------------------------------------------------------- */ int main(int argc, char **argv) { char config_file[FILENAMELEN]; /* setup file name */ char *config_file_p = 0; Config *cfg = 0; Config *cfp; int become_daemon = 0; /* 1: become daemon */ PortinfoList accept_port; PortinfoList connect_port; int have_port_info = 0; #if 0 { for(int i = 1; i < 32; i++) { signal(i, sig_default); } } #endif /* getting of argument */ { int opt; extern char *optarg; while ((opt = getopt(argc, argv, "a:c:Cf:hk:D")) != EOF) { switch(opt) { case 'a': { Portinfo *pi = new Portinfo(); if (!pi->set(optarg)) { fprintf(stderr, "argument error : Can't analize accept port information\n"); exit(1); } accept_port.add(pi); have_port_info = 1; } break; case 'c': { Portinfo *pi = new Portinfo(); if (!pi->set(optarg)) { fprintf(stderr, "argument error : Can't analize connect port information\n"); exit(1); } connect_port.add(pi); have_port_info = 1; } break; case 'f': STRNCPY(config_file, optarg, sizeof(config_file)); config_file_p = config_file; if (!checkOpenFileForRead(config_file)) { fprintf(stderr, "Can't open configure file `%s': %s\n", config_file, strerror(errno)); exit(1); } break; case 'k': if (!strcmp(optarg, "kill")) { FILE *fp; char buf[16]; pid_t pid; fp = fopen(PIDFILE, "r"); if (!fp) { fprintf(stderr, "Not found file `" PIDFILE "'. You send signal manually.\n"); exit(1); } fgets(buf, 15, fp); pid = atoi(buf); if (pid > 1) { kill(pid, SIGTERM); } exit(0); } case 'D': become_daemon = 1; break; default: fprintf(stderr, "Invalid argument\n"); case 'h': help(); } } } /* end of "getting of argument" */ if (!initApp()) { exit(1); } /* restart point */ while (1) { int do_restart = 0; set_sig_hup(); set_sig_int(); set_sig_term(); set_sig_cont(); set_sig_child(); set_sig_usr1(); set_sig_usr2(); set_sig_tstp(); cfg = new Config(); /* read config file */ if (!cfg->readFile(config_file_p)) exit(1); #ifdef DO_ACCEPT_AT_MASTER struct ConfigList { Config *cfp; ConfigList *next; } *acfg = 0; #endif if (have_port_info) { cfg->accept_port.set(&accept_port); cfg->connect_port.set(&connect_port); Config *cp = cfg->next; while (cp) { Config *np = cp->next; delete cp; cp = np; } cfg->next = 0; } cfp = cfg; while (cfp) { cfp->init(); /* if cfp is an object for which accept and connect are specified, */ if (cfp->canStart()) { if (!cfp->start()) exit(1); #ifdef DO_ACCEPT_AT_MASTER ConfigList *np = new ConfigList(); np->cfp = cfp; np->next = acfg; acfg = np; #endif } /* end of cfp->canStart() */ cfp = cfp->next; } /* end of while */ PUTERR(1, ("Begin\n")); if (become_daemon) { pid_t pid = fork(); if (pid < 0) { PUTERR(0, ("Can't become daemon\n")); exit(1); } if (pid) _exit(0); /* setsid(); */ } /* make /var/run/bjorb.pid */ { pid_t pid = getpid(); FILE *fp; fp = fopen(PIDFILE, "w"); if (!fp) { PUTERR(0, ("warning: Can't open file for write '%s' : %s\n", PIDFILE, strerror(errno))); } else { fprintf(fp, "%d\n", pid); fclose(fp); } } fd_set rmask; fd_set fds; int max = 64; FD_ZERO(&fds); #ifdef DO_ACCEPT_AT_MASTER ConfigList *cp = acfg; while (cp) { fprintf(stderr, "soc_accept = %d\n", cp->cfp->soc_accept); FD_SET(cp->cfp->soc_accept, &fds); cp = cp->next; } #endif while (1) { memcpy(&rmask, &fds, sizeof(fd_set)); int n = ::select(max, &rmask, 0, 0, 0); if (n < 0) { if (errno == EINTR) { int sigtype = get_caught_sig_type(); if (sigtype == SIGCHLD || sigtype == SIGTSTP || sigtype == SIGCONT || sigtype == SIGUSR1 || sigtype == SIGUSR2 ) continue; if (sigtype == SIGHUP) { do_restart = 1; terminate_all_process(); break; } if (sigtype == SIGINT || sigtype == SIGTERM ) { terminate_all_process(); break; } } break; } #ifdef DO_ACCEPT_AT_MASTER if (!n) continue; ConfigList *cp = acfg; while (cp) { if (FD_ISSET(cp->cfp->soc_accept, &rmask)) { /*cp->cfp->createSpareServer();*/ cp->cfp->_accept(TRUE); } cp = cp->next; } #endif } /* end of while */ if (!do_restart) break; cfp = cfg; while (cfp) { Config *np = cfp->next; cfp->stop(); delete cfp; cfp = np; } PUTERR(1, ("Reconfigure\n")); } /* end of while (restart loop) */ unlink(PIDFILE); exit(0); }