int start_server(int fd){ int child_indx,pid,i,status; int childs,freeservers,used,maxrequests; ci_proc_mutex_init(&accept_mutex); if(!create_childs_queue(&childs_queue,MAX_CHILDS)){ debug_printf(1,"Can't init shared memory.Fatal error, exiting!\n"); exit(0); } pid=1; #ifdef MULTICHILD for(i=0;i< START_CHILDS; i++){ if(pid) pid=start_child(fd); } if(pid!=0){ main_signals(); while(1){ sleep(1); /*Must be replaced by nanosleep. */ childs_queue_stats(&childs_queue,&childs,&freeservers, &used, &maxrequests); debug_printf(10,"Server stats: \n\t Childs:%d\n\t Free servers:%d\n\tUsed servers:%d\n\tRequests served:%d\n", childs, freeservers,used, maxrequests); if( (freeservers<=MIN_FREE_SERVERS && childs<MAX_CHILDS) ||childs<START_CHILDS){ debug_printf(8,"Going to start a child .....\n"); pid=start_child(fd); } else if(freeservers>=MAX_FREE_SERVERS&& childs>START_CHILDS){ child_indx=find_an_idle_child(&childs_queue); childs_queue.childs[child_indx].to_be_killed=GRACEFULLY; kill(childs_queue.childs[child_indx].pid,SIGINT); debug_printf(8,"Going to stop child %d .....\n",childs_queue.childs[child_indx].pid); //kill a server ... } } for(i=0;i<START_CHILDS;i++){ pid=wait(&status); debug_printf(5,"The child %d died with status %d\n",pid,status); } } #else child_data=(child_shared_data_t *)malloc(sizeof(child_shared_data_t)); child_data->pid=0; child_data->freeservers=START_SERVERS; child_data->usedservers=0; child_data->requests=0; child_data->connections=0; child_data->to_be_killed=0; child_data->idle=1; child_main(fd); #endif }
int bbs_entry(void) { KBS_SOCKADDR_IN sin; socklen_t sinlen; setuid(BBSUID); setgid(BBSGID); main_signals(); sinlen=sizeof(KBS_SOCKADDR_IN); atexit(ssh_exit); proxy_getpeername(0,(struct sockaddr*)&sin,&sinlen); KBS_SET_FROMHOST(sin,getSession()->fromhost); return bbs_main(saved_argv[0]); }
int start_server() { int child_indx, pid, i, ctl_socket; int childs, freeservers, used, maxrequests, ret; char command_buffer[COMMANDS_BUFFER_SIZE]; int user_informed = 0; ctl_socket = ci_named_pipe_create(CONF.COMMANDS_SOCKET); if (ctl_socket < 0) { ci_debug_printf(1, "Error opening control socket %s. Fatal error, exiting!\n", CONF.COMMANDS_SOCKET); exit(0); } if (!ci_proc_mutex_init(&accept_mutex)) { ci_debug_printf(1, "Can't init mutex for accepting conenctions. Fatal error, exiting!\n"); exit(0); } childs_queue = malloc(sizeof(struct childs_queue)); if (!create_childs_queue(childs_queue, 2 * CONF.MAX_SERVERS)) { ci_proc_mutex_destroy(&accept_mutex); ci_debug_printf(1, "Can't init shared memory. Fatal error, exiting!\n"); exit(0); } init_commands(); pid = 1; #ifdef MULTICHILD if (CONF.START_SERVERS > CONF.MAX_SERVERS) CONF.START_SERVERS = CONF.MAX_SERVERS; for (i = 0; i < CONF.START_SERVERS; i++) { if (pid) pid = start_child(LISTEN_SOCKET); } if (pid != 0) { main_signals(); while (1) { if ((ret = wait_for_commands(ctl_socket, command_buffer, 1)) > 0) { ci_debug_printf(5, "I received the command: %s\n", command_buffer); handle_monitor_process_commands(command_buffer); } if (ret < 0) { /*Eof received on pipe. Going to reopen ... */ ci_named_pipe_close(ctl_socket); ctl_socket = ci_named_pipe_open(CONF.COMMANDS_SOCKET); if (ctl_socket < 0) { ci_debug_printf(1, "Error opening control socket. We are unstable and going down!"); c_icap_going_to_term = 1; } } if (c_icap_going_to_term) break; childs_queue_stats(childs_queue, &childs, &freeservers, &used, &maxrequests); ci_debug_printf(10, "Server stats: \n\t Children: %d\n\t Free servers: %d\n" "\tUsed servers:%d\n\tRequests served:%d\n", childs, freeservers, used, maxrequests); if (MAX_REQUESTS_PER_CHILD > 0 && (child_indx = find_a_child_nrequests (childs_queue, MAX_REQUESTS_PER_CHILD)) >= 0) { ci_debug_printf(8, "Max requests reached for child :%d of pid :%d\n", child_indx, childs_queue->childs[child_indx].pid); pid = start_child(LISTEN_SOCKET); // usleep(500); childs_queue->childs[child_indx].father_said = GRACEFULLY; /*kill a server ... */ kill(childs_queue->childs[child_indx].pid, SIGTERM); } else if ((freeservers <= CONF.MIN_SPARE_THREADS && childs < CONF.MAX_SERVERS) || childs < CONF.START_SERVERS) { ci_debug_printf(8, "Free Servers: %d, children: %d. Going to start a child .....\n", freeservers, childs); pid = start_child(LISTEN_SOCKET); } else if (freeservers >= CONF.MAX_SPARE_THREADS && childs > CONF.START_SERVERS && (freeservers - CONF.THREADS_PER_CHILD) > CONF.MIN_SPARE_THREADS) { if ((child_indx = find_an_idle_child(childs_queue)) >= 0) { childs_queue->childs[child_indx].father_said = GRACEFULLY; ci_debug_printf(8, "Free Servers: %d, children: %d. Going to stop child %d(index: %d)\n", freeservers, childs, childs_queue->childs[child_indx].pid, child_indx); /*kill a server ... */ kill(childs_queue->childs[child_indx].pid, SIGTERM); user_informed = 0; } } else if (childs == CONF.MAX_SERVERS && freeservers < CONF.MIN_SPARE_THREADS) { if(! user_informed) { ci_debug_printf(1, "ATTENTION!!!! Not enough available servers (children %d, free servers %d, used servers %d)!!!!! " "Maybe you should increase the MaxServers and the " "ThreadsPerChild values in c-icap.conf file!!!!!!!!!",childs , freeservers, used); user_informed = 1; } } if (c_icap_going_to_term) break; check_for_exited_childs(); if (c_icap_reconfigure) { c_icap_reconfigure = 0; if (!server_reconfigure()) { ci_debug_printf(1, "Error while reconfiguring, exiting!\n"); break; } } } /*Main process exit point */ ci_debug_printf(1, "Possibly a term signal received. Monitor process going to term all children\n"); kill_all_childs(); system_shutdown(); ci_debug_printf(1, "Exiting....\n"); return 1; } #else child_data = (child_shared_data_t *) malloc(sizeof(child_shared_data_t)); child_data->pid = 0; child_data->freeservers = CONF.THREADS_PER_CHILD; child_data->usedservers = 0; child_data->requests = 0; child_data->connections = 0; child_data->to_be_killed = 0; child_data->father_said = 0; child_data->idle = 1; child_data->stats_size = ci_stat_memblock_size(); child_data->stats = malloc(child_data->stats_size); child_data->stats->sig = MEMBLOCK_SIG; ci_stat_attach_mem(child_data->stats, child_data->stats_size, NULL); child_main(LISTEN_SOCKET, 0); ci_proc_mutex_destroy(&accept_mutex); destroy_childs_queue(childs_queue); #endif return 1; }
static int bbs_standalone_main(char* argv) { KBS_SOCKADDR_IN sin; socklen_t sinlen; char addr_buf[IPLEN]; int sockfd,count; time_t lasttime,now; lasttime=time(NULL); count=0; while (1) { sinlen=sizeof(KBS_SOCKADDR_IN); #ifdef SMTH if ((now=time(NULL))!=lasttime) count=0; else { if (count>5) sleep(1); } #endif /* SMTH */ sockfd=accept(SOCKFD,(struct sockaddr*)&sin,&sinlen); count++; if (sockfd==-1) continue; proxy_getpeername(sockfd,(struct sockaddr*)&sin,&sinlen); #ifdef CHECK_IP_LINK #ifdef HAVE_IPV6_SMTH if (check_IP_lists(sin.sin6_addr)==1) { #else /* ! HAVE_IPV6_SMTH */ if (check_IP_lists(sin.sin_addr.s_addr)==1) { #endif /* HAVE_IPV6_SMTH */ close(sockfd); continue; } #endif /* CHECK_IP_LINK */ if (!no_fork) { switch (fork()) { case -1: exit(3); case 0: break; default: close(sockfd); continue; } } KBS_SET_FROMHOST(sin,addr_buf); bbslog("0Connect","connect from %d (%d) in port %d",addr_buf,htons(KBS_SIN_MEMBER(sin,port)),mport); setsid(); if (dup2(sockfd,0)==-1) /* dup tcp link to fd 0 and then in the main_bbs func also to fd 1 */ exit(2); close(3); /* close listen sock fd in child session */ close(4); /* close pid file fd in child session */ close(sockfd); /* close accept peer fd in child session */ break; /* leave fd 2 still open holding /dev/null */ } KBS_SET_FROMHOST(sin,getSession()->fromhost); telnet_init(); return bbs_main(argv); } int main(int argc,char **argv) { char addr[STRLEN]; int ret,inetd,port; addr[0]=0;inetd=0;port=23; while ((ret=getopt(argc,argv,"idha:p:"))!=-1) { switch (ret) { case 'i': inetd=1; break; case 'd': no_fork=1; break; case 'h': puts("usage: bbsd [-i] [-d] [-h] [-a <addr>] [-p <port>]"); return 0; case 'a': if (optarg[0]) snprintf(addr,STRLEN,"%s",optarg); break; case 'p': if (!isdigit(optarg[0])) return -1; port=atoi(optarg); break; case '?': return -1; } } #ifndef HAVE_IPV6_SMTH inaddr_any.s_addr=htonl(INADDR_ANY); #endif /* HAVE_IPV6_SMTH */ start_daemon(inetd,port,(!addr[0]?NULL:addr)); main_signals(); return (!inetd?bbs_standalone_main(argv[0]):bbs_inet_main(argv[0])); }