512dcd98 |
/*
* $Id$
*/
#include <stdio.h>
|
3e429f5c |
#include <stdlib.h>
|
512dcd98 |
#include <errno.h>
|
3e429f5c |
#include <ctype.h>
|
512dcd98 |
#include <string.h>
|
e60a9728 |
#include <netdb.h>
|
1b1b19d8 |
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/utsname.h>
|
f571aa35 |
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <sys/time.h>
|
e9d701db |
#include <sys/wait.h>
|
512dcd98 |
|
e60a9728 |
#include "config.h"
|
512dcd98 |
#include "dprint.h"
#include "route.h"
|
e60a9728 |
#include "udp_server.h"
|
1b1b19d8 |
#include "globals.h"
|
dda9dab1 |
#include "mem/mem.h"
|
628e3a5a |
#ifdef SHM_MEM
|
dda9dab1 |
#include "mem/shm_mem.h"
|
628e3a5a |
#endif
|
bf08223a |
#include "sr_module.h"
|
cd57180a |
#include "timer.h"
|
40a8d9dd |
#include "msg_parser.h"
|
22d4aa5d |
|
1b1b19d8 |
|
726efa25 |
#include <signal.h>
|
0a974a1d |
|
5b253cc6 |
#include "stats.h"
|
726efa25 |
|
03150098 |
#ifdef DEBUG_DMALLOC
#include <dmalloc.h>
#endif
|
1b1b19d8 |
static char id[]="@(#) $Id$";
|
b2dec9c6 |
static char version[]= NAME " " VERSION " (" ARCH "/" OS ")" ;
|
247c2b65 |
static char compiled[]= __TIME__ __DATE__ ;
|
7db4ee8d |
static char flags[]=
"STATS:"
|
af6fb476 |
#ifdef STATS
"On"
#else
"Off"
#endif
|
f8d46776 |
#ifdef NO_DEBUG
", NO_DEBUG"
#endif
#ifdef NO_LOG
", NO_LOG"
#endif
|
25b49bb4 |
#ifdef EXTRA_DEBUG
", EXTRA_DEBUG"
|
f8d46776 |
#endif
|
104316b6 |
#ifdef DNS_IP_HACK
", DNS_IP_HACK"
#endif
|
25b49bb4 |
#ifdef SHM_MEM
", SHM_MEM"
#endif
|
dcb5f364 |
#ifdef SHM_MMAP
", SHM_MMAP"
#endif
|
25b49bb4 |
#ifdef PKG_MALLOC
", PKG_MALLOC"
#endif
|
dda9dab1 |
#ifdef VQ_MALLOC
", VQ_MALLOC"
#endif
|
b2dec9c6 |
#ifdef F_MALLOC
", F_MALLOC"
#endif
|
25b49bb4 |
#ifdef USE_SHM_MEM
", USE_SHM_MEM"
#endif
#ifdef DBG_QM_MALLOC
", DBG_QM_MALLOC"
#endif
#ifdef DEBUG_DMALLOC
", DEBUG_DMALLOC"
#endif
|
b2dec9c6 |
#ifdef FAST_LOCK
", FAST_LOCK"
|
30f1f956 |
#ifdef BUSY_WAIT
"-BUSY_WAIT"
|
b2dec9c6 |
#endif
|
30f1f956 |
#ifdef ADAPTIVE_WAIT
"-ADAPTIVE_WAIT"
#endif
#ifdef NOSMP
"-NOSMP"
#endif
#endif /*FAST_LOCK*/
|
726efa25 |
;
|
1b1b19d8 |
static char help_msg[]= "\
|
247c2b65 |
Usage: " NAME " -l address [-l address] [options]\n\
|
1b1b19d8 |
Options:\n\
|
0eb1315e |
-c Perform loop checks and compute branches\n\
|
1b1b19d8 |
-f file Configuration file (default " CFG_FILE ")\n\
-p port Listen on the specified port (default: 5060)\n\
-l address Listen on the specified address (multiple -l mean\n\
listening on more addresses). The default behaviour\n\
is to listen on the addresses returned by uname(2)\n\
\n\
-n processes Number of child processes to fork per interface\n\
(default: 8)\n\
\n\
-r Use dns to check if is necessary to add a \"received=\"\n\
field to a via\n\
-R Same as `-r� but use reverse dns;\n\
(to use both use `-rR�)\n\
\n\
-v Turn on \"via:\" host checking when forwarding replies\n\
-d Debugging mode (multiple -d increase the level)\n\
-D Do not fork into daemon mode\n\
-E Log to stderr\n\
-V Version number\n\
-h This help message\n\
|
c3ce2841 |
-b nr Maximum receive buffer size which will not be exceeded by\n\
|
c9ca45b3 |
auto-probing procedure even if OS allows\n\
|
40a8d9dd |
-m nr Size of shared memory allocated in Megabytes\n\
|
c9ca45b3 |
-w dir change the working directory to \"dir\" (default \"/\")\n\
-t dir chroot to \"dir\"\n\
-u uid change uid \n\
-g gid change gid \n"
|
f571aa35 |
#ifdef STATS
" -s file File to which statistics is dumped (disabled otherwise)\n"
#endif
;
|
512dcd98 |
|
af6fb476 |
/* print compile-time constants */
void print_ct_constants()
{
|
30f1f956 |
#ifdef ADAPTIVE_WAIT
printf("ADAPTIVE_WAIT_LOOPS=%d, ", ADAPTIVE_WAIT_LOOPS);
#endif
|
40a8d9dd |
/*
|
30f1f956 |
#ifdef SHM_MEM
printf("SHM_MEM_SIZE=%d, ", SHM_MEM_SIZE);
#endif
|
40a8d9dd |
*/
|
30f1f956 |
printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
" MAX_URI_SIZE %d, MAX_PROCESSES %d\n",
|
4bd1673d |
MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES );
|
af6fb476 |
}
|
512dcd98 |
|
888ca09d |
/* debuging function */
|
e60a9728 |
/*
|
888ca09d |
void receive_stdin_loop()
{
#define BSIZE 1024
char buf[BSIZE+1];
int len;
|
5655ca6f |
|
888ca09d |
while(1){
len=fread(buf,1,BSIZE,stdin);
buf[len+1]=0;
receive_msg(buf, len);
printf("-------------------------\n");
}
}
|
e60a9728 |
*/
|
888ca09d |
|
1b1b19d8 |
/* global vars */
char* cfg_file = 0;
unsigned short port_no = 0; /* port on which we listen */
|
b2e71d5b |
char port_no_str[MAX_PORT_LEN];
int port_no_str_len=0;
|
f571aa35 |
unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do not want to exceed
durig the auto-probing procedure; may be
re-configured */
|
cc2199a9 |
int children_no = 0; /* number of children processing requests */
|
404073d3 |
int *pids=0; /*array with childrens pids, 0= main proc,
|
cbd9fc8b |
alloc'ed in shared mem if possible*/
|
1b1b19d8 |
int debug = 0;
int dont_fork = 0;
int log_stderr = 0;
int check_via = 0; /* check if reply first via host==us */
|
676eb608 |
int loop_checks = 0; /* calculate branches and check for loops/spirals */
|
1b1b19d8 |
int received_dns = 0; /* use dns and/or rdns or to see if we need to
add a ;received=x.x.x.x to via: */
|
c9ca45b3 |
char* working_dir = 0;
char* chroot_dir = 0;
int uid = 0;
int gid = 0;
|
1b1b19d8 |
char* names[MAX_LISTEN]; /* our names */
|
b2e71d5b |
int names_len[MAX_LISTEN]; /* lengths of the names*/
|
1b1b19d8 |
unsigned long addresses[MAX_LISTEN]; /* our ips */
int addresses_no=0; /* number of names/ips */
|
cc2199a9 |
/* ipc related globals */
int process_no = 0;
|
4bd1673d |
process_bm_t process_bit = 0;
|
cc2199a9 |
#ifdef ROUTE_SRV
#endif
|
888ca09d |
|
63fa628f |
/* cfg parsing */
int cfg_errors=0;
|
888ca09d |
|
40a8d9dd |
/* shared memory (in MB) */
unsigned int shm_mem_size=SHM_MEM_SIZE * 1024 * 1024;
|
cc2199a9 |
#define MAX_FD 32 /* maximum number of inherited open file descriptors,
(normally it shouldn't be bigger than 3) */
|
3e429f5c |
extern FILE* yyin;
extern int yyparse();
|
8e759838 |
static int is_main=0; /* flag = is this the "main" process? */
|
3e429f5c |
|
cc2199a9 |
/* daemon init, return 0 on success, -1 on error */
int daemonize(char* name)
{
pid_t pid;
int r;
if (log_stderr==0)
|
cbd9fc8b |
openlog(name, LOG_PID|LOG_CONS, LOG_LOCAL1 /*LOG_DAEMON*/);
/* LOG_CONS, LOG_PERRROR ? */
|
cc2199a9 |
|
c9ca45b3 |
if (chroot_dir&&(chroot(chroot_dir)<0)){
LOG(L_CRIT, "Cannot chroot to %s: %s\n", chroot_dir, strerror(errno));
|
cc2199a9 |
goto error;
}
|
c9ca45b3 |
if (chdir(working_dir)<0){
LOG(L_CRIT,"cannot chdir to %s: %s\n", working_dir, strerror(errno));
goto error;
}
if (gid&&(setgid(gid)<0)){
LOG(L_CRIT, "cannot change gid to %d: %s\n", gid, strerror(errno));
goto error;
}
if(uid&&(setuid(uid)<0)){
LOG(L_CRIT, "cannot change uid to %d: %s\n", uid, strerror(errno));
goto error;
}
|
cc2199a9 |
/* fork to become!= group leader*/
if ((pid=fork())<0){
LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
goto error;
}
if (pid!=0){
/* parent process => exit*/
exit(0);
}
/* become session leader to drop the ctrl. terminal */
if (setsid()<0){
LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
}
/* fork again to drop group leadership */
if ((pid=fork())<0){
LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
goto error;
}
if (pid!=0){
/*parent process => exit */
exit(0);
}
/* close any open file descriptors */
|
676924fb |
if (log_stderr==0)
for (r=0;r<MAX_FD; r++){
if ((r==3) && log_stderr) continue;
close(r);
}
|
cc2199a9 |
return 0;
error:
return -1;
}
/* main loop */
int main_loop()
{
int r, i;
pid_t pid;
/* one "main" process and n children handling i/o */
|
1fb7b1aa |
|
cc2199a9 |
if (dont_fork){
|
f571aa35 |
#ifdef STATS
setstats( 0 );
#endif
|
cc2199a9 |
/* only one address */
if (udp_init(addresses[0],port_no)==-1) goto error;
|
cd57180a |
/* we need another process to act as the timer*/
if (timer_list){
|
cbd9fc8b |
process_no++;
|
cd57180a |
if ((pid=fork())<0){
|
d4f2d8b0 |
LOG(L_CRIT, "ERRROR: main_loop: Cannot fork\n");
|
cd57180a |
goto error;
}
|
cbd9fc8b |
|
cd57180a |
if (pid==0){
/* child */
/* timer!*/
|
4bd1673d |
process_bit = 0;
|
cd57180a |
for(;;){
sleep(TIMER_TICK);
timer_ticker();
}
|
cbd9fc8b |
}else{
pids[process_no]=pid; /*should be shared mem anway*/
|
cd57180a |
}
}
|
8e759838 |
/* main process, receive loop */
is_main=1;
|
cbd9fc8b |
pids[0]=getpid();
|
4bd1673d |
process_bit = 1;
|
cbd9fc8b |
process_no=0; /*main process number*/
|
192ac55b |
/* We will call child_init even if we
* do not fork
*/
|
eedd46b1 |
if (init_child(0) < 0) {
|
192ac55b |
LOG(L_ERR, "init_child failed\n");
goto error;
}
|
eedd46b1 |
|
391fa285 |
return udp_rcv_loop();
|
cc2199a9 |
}else{
for(r=0;r<addresses_no;r++){
|
1fb7b1aa |
/* create the listening socket (for each address)*/
if (udp_init(addresses[r], port_no)==-1) goto error;
|
cc2199a9 |
for(i=0;i<children_no;i++){
if ((pid=fork())<0){
LOG(L_CRIT, "main_loop: Cannot fork\n");
goto error;
}
if (pid==0){
|
192ac55b |
/* child */
|
eedd46b1 |
|
192ac55b |
if (init_child(i) < 0) {
LOG(L_ERR, "init_child failed\n");
goto error;
}
|
eedd46b1 |
|
cbd9fc8b |
process_no=i+1; /*0=main*/
|
4bd1673d |
process_bit = 1 << i;
|
f571aa35 |
#ifdef STATS
setstats( i );
#endif
|
cc2199a9 |
return udp_rcv_loop();
|
cbd9fc8b |
}else{
pids[i+1]=pid; /*should be in shared mem.*/
|
cc2199a9 |
}
}
|
bf0fab3f |
/*parent*/
/*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
|
cc2199a9 |
}
}
|
8e759838 |
/*this is the main process*/
|
cbd9fc8b |
pids[process_no]=getpid();
|
4bd1673d |
process_bit = 0;
|
8e759838 |
is_main=1;
|
cd57180a |
if (timer_list){
for(;;){
/* debug: instead of doing something usefull */
/* (placeholder for timers, etc.) */
sleep(TIMER_TICK);
/* if we received a signal => TIMER_TICK may have not elapsed*/
timer_ticker();
}
}else{
for(;;) sleep(LONG_SLEEP);
|
cc2199a9 |
}
|
51eadd0c |
/*return 0; */
|
cc2199a9 |
error:
return -1;
}
|
726efa25 |
|
f571aa35 |
|
726efa25 |
/* added by jku; allows for regular exit on a specific signal;
good for profiling which only works if exited regularly and
not by default signal handlers
*/
static void sig_usr(int signo)
{
|
e9d701db |
pid_t chld;
int chld_status;
|
dda9dab1 |
if (signo==SIGINT || signo==SIGPIPE) { /* exit gracefuly */
|
e9d701db |
DPrint("INT received, program terminates\n");
# ifdef STATS
|
f571aa35 |
/* print statistics on exit only for the first process */
if (stats->process_index==0 && stat_file )
if (dump_all_statistic()==0)
printf("statistic dumped to %s\n", stat_file );
else
printf("statistics dump to %s failed\n", stat_file );
|
e9d701db |
# endif
|
bf08223a |
/* WARNING: very dangerous, might be unsafe*/
|
8e759838 |
if (is_main)
destroy_modules();
|
02690ea6 |
#ifdef PKG_MALLOC
|
9dfa5dc4 |
LOG(L_INFO, "Memory status (pkg):\n");
|
02690ea6 |
pkg_status();
|
e9d701db |
# endif
|
628e3a5a |
#ifdef SHM_MEM
|
9dfa5dc4 |
if (is_main){
LOG(L_INFO, "Memory status (shm):\n");
|
8e759838 |
shm_status();
|
404073d3 |
/*zero all shmem alloc vars, that will still use*/
pids=0;
|
8e759838 |
shm_mem_destroy();
|
404073d3 |
}
|
628e3a5a |
#endif
|
2c65bd8b |
dprint("Thank you for flying " NAME "\n");
|
dcb5f364 |
exit(0);
|
f571aa35 |
} else if (signo==SIGUSR1) { /* statistic */
|
e4067ffb |
#ifdef STATS
|
f571aa35 |
dump_all_statistic();
|
02690ea6 |
#endif
#ifdef PKG_MALLOC
|
9dfa5dc4 |
LOG(L_INFO, "Memory status (pkg):\n");
|
02690ea6 |
pkg_status();
|
628e3a5a |
#endif
#ifdef SHM_MEM
|
9dfa5dc4 |
LOG(L_INFO, "Memory status (shm):\n");
|
21f03122 |
shm_status();
|
e4067ffb |
#endif
|
e9d701db |
} else if (signo==SIGCHLD) {
while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
if (WIFEXITED(chld_status))
LOG(L_INFO, "child process %d exited normally, status=%d\n",
chld, WEXITSTATUS(chld_status));
else if (WIFSIGNALED(chld_status)) {
LOG(L_INFO, "child process %d exited by a signal %d\n",
chld, WTERMSIG(chld_status));
# ifdef WCOREDUMP
LOG(L_INFO, "core was %sgenerated\n", WCOREDUMP(chld_status) ?
"" : "not" );
# endif
} else if (WIFSTOPPED(chld_status))
LOG(L_INFO, "child process %d stopped by a signal %d\n",
chld, WSTOPSIG(chld_status));
}
|
f571aa35 |
}
|
726efa25 |
}
|
cd57180a |
|
dda9dab1 |
void test();
|
cd57180a |
|
512dcd98 |
int main(int argc, char** argv)
{
FILE* cfg_stream;
|
e60a9728 |
struct hostent* he;
|
1b1b19d8 |
int c,r;
char *tmp;
struct utsname myname;
|
f571aa35 |
char *options;
|
512dcd98 |
|
726efa25 |
/* added by jku: add exit handler */
|
628e3a5a |
if (signal(SIGINT, sig_usr) == SIG_ERR ) {
DPrint("ERROR: no SIGINT signal handler can be installed\n");
goto error;
}
|
dda9dab1 |
/* if we debug and write to a pipe, we want to exit nicely too */
if (signal(SIGPIPE, sig_usr) == SIG_ERR ) {
DPrint("ERROR: no SIGINT signal handler can be installed\n");
goto error;
}
|
628e3a5a |
|
f571aa35 |
if (signal(SIGUSR1, sig_usr) == SIG_ERR ) {
|
628e3a5a |
DPrint("ERROR: no SIGUSR1 signal handler can be installed\n");
goto error;
}
|
e9d701db |
if (signal(SIGCHLD , sig_usr) == SIG_ERR ) {
DPrint("ERROR: no SIGCHLD signal handler can be installed\n");
goto error;
}
|
726efa25 |
|
dda9dab1 |
//memtest();
//hashtest();
|
512dcd98 |
/* process command line (get port no, cfg. file path etc) */
|
1b1b19d8 |
opterr=0;
|
f571aa35 |
options=
#ifdef STATS
"s:"
#endif
|
40a8d9dd |
"f:p:m:b:l:n:rRvcdDEVhw:t:u:g:";
|
f571aa35 |
while((c=getopt(argc,argv,options))!=-1){
|
1b1b19d8 |
switch(c){
case 'f':
cfg_file=optarg;
break;
|
f571aa35 |
case 's':
|
e4067ffb |
#ifdef STATS
|
f571aa35 |
stat_file=optarg;
|
e4067ffb |
#endif
|
f571aa35 |
break;
|
1b1b19d8 |
case 'p':
port_no=strtol(optarg, &tmp, 10);
if (tmp &&(*tmp)){
fprintf(stderr, "bad port number: -p %s\n", optarg);
goto error;
}
break;
|
c3ce2841 |
|
40a8d9dd |
case 'm':
shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
if (tmp &&(*tmp)){
fprintf(stderr, "bad shmem size number: -m %s\n", optarg);
goto error;
};
LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size );
break;
|
c3ce2841 |
case 'b':
maxbuffer=strtol(optarg, &tmp, 10);
if (tmp &&(*tmp)){
fprintf(stderr, "bad max buffer size number: -p %s\n", optarg);
goto error;
}
break;
|
1b1b19d8 |
case 'l':
|
e7671eb9 |
/* add a new addr. to our address list */
|
1b1b19d8 |
if (addresses_no < MAX_LISTEN){
names[addresses_no]=(char*)malloc(strlen(optarg)+1);
if (names[addresses_no]==0){
fprintf(stderr, "Out of memory.\n");
goto error;
}
strncpy(names[addresses_no], optarg, strlen(optarg)+1);
addresses_no++;
}else{
fprintf(stderr,
"Too many addresses (max. %d).\n",
MAX_LISTEN);
goto error;
}
break;
case 'n':
|
3e429f5c |
children_no=strtol(optarg, &tmp, 10);
if ((tmp==0) ||(*tmp)){
|
1b1b19d8 |
fprintf(stderr, "bad process number: -n %s\n", optarg);
goto error;
}
break;
case 'v':
check_via=1;
break;
|
676eb608 |
case 'c':
loop_checks=1;
break;
|
1b1b19d8 |
case 'r':
received_dns|=DO_DNS;
break;
case 'R':
received_dns|=DO_REV_DNS;
case 'd':
debug++;
break;
case 'D':
dont_fork=1;
break;
case 'E':
log_stderr=1;
break;
case 'V':
printf("version: %s\n", version);
|
726efa25 |
printf("flags: %s\n", flags );
|
af6fb476 |
print_ct_constants();
|
3e429f5c |
printf("%s\n",id);
|
e22bbdb8 |
printf("%s compiled on %s with %s\n", __FILE__,
compiled, COMPILER );
|
b2dec9c6 |
|
1b1b19d8 |
exit(0);
break;
case 'h':
printf("version: %s\n", version);
printf("%s",help_msg);
exit(0);
break;
|
c9ca45b3 |
case 'w':
working_dir=optarg;
break;
case 't':
chroot_dir=optarg;
break;
case 'u':
uid=strtol(optarg, &tmp, 10);
if ((tmp==0) ||(*tmp)){
fprintf(stderr, "bad uid number: -u %s\n", optarg);
goto error;
}
/* test if string?*/
break;
case 'g':
gid=strtol(optarg, &tmp, 10);
if ((tmp==0) ||(*tmp)){
fprintf(stderr, "bad gid number: -g %s\n", optarg);
goto error;
}
break;
|
1b1b19d8 |
case '?':
if (isprint(optopt))
|
675b7412 |
fprintf(stderr, "Unknown option `-%c�.\n", optopt);
|
1b1b19d8 |
else
fprintf(stderr,
"Unknown option character `\\x%x�.\n",
optopt);
goto error;
case ':':
fprintf(stderr,
"Option `-%c� requires an argument.\n",
optopt);
goto error;
default:
abort();
}
}
/* fill missing arguments with the default values*/
if (cfg_file==0) cfg_file=CFG_FILE;
|
7268726e |
/* load config file or die */
cfg_stream=fopen (cfg_file, "r");
if (cfg_stream==0){
fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
strerror(errno));
goto error;
}
|
e8e9c7a9 |
|
40a8d9dd |
#ifdef NEW_HNAME
init_htable();
#endif
|
e8e9c7a9 |
/*init mallocs (before parsing cfg !)*/
|
dda9dab1 |
if (init_mallocs()==-1)
|
e8e9c7a9 |
goto error;
|
d4f2d8b0 |
/*init timer, before parsing the cfg!*/
if (init_timer()<0){
LOG(L_CRIT, "could not initialize timer, exiting...\n");
goto error;
}
|
e8e9c7a9 |
|
404073d3 |
/*init builtin modules*/
init_builtin_modules();
|
7268726e |
yyin=cfg_stream;
if ((yyparse()!=0)||(cfg_errors)){
fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
goto error;
}
print_rl();
|
f20a56a2 |
/* fix routing lists */
if ( (r=fix_rls())!=0){
fprintf(stderr, "ERROR: error %x while trying to fix configuration\n",
r);
goto error;
};
|
7268726e |
/* fix parameters */
|
cc2199a9 |
if (port_no<=0) port_no=SIP_PORT;
|
b2e71d5b |
port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d",
(unsigned short) port_no);
if (port_no_str_len<0){
fprintf(stderr, "ERROR: bad port number: %d\n", port_no);
goto error;
}
/* on some system snprintf return really strange things if it does not have
* enough space */
port_no_str_len=
(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
|
cc2199a9 |
if (children_no<=0) children_no=CHILD_NO;
|
4bd1673d |
else if (children_no >= MAX_PROCESSES ) {
|
c4217e61 |
fprintf(stderr, "ERROR: too many children processes configured;"
" maximum is %d\n",
|
4bd1673d |
MAX_PROCESSES-1 );
goto error;
}
|
c9ca45b3 |
if (working_dir==0) working_dir="/";
|
cbd9fc8b |
/*alloc pids*/
#ifdef SHM_MEM
|
b2dec9c6 |
pids=shm_malloc(sizeof(int)*(children_no+1));
|
cbd9fc8b |
#else
|
b2dec9c6 |
pids=malloc(sizeof(int)*(children_no+1));
|
cbd9fc8b |
#endif
if (pids==0){
fprintf(stderr, "ERROR: out of memory\n");
goto error;
}
|
b2dec9c6 |
memset(pids, 0, sizeof(int)*(children_no+1));
|
cbd9fc8b |
|
1b1b19d8 |
if (addresses_no==0) {
/* get our address, only the first one */
if (uname (&myname) <0){
fprintf(stderr, "cannot determine hostname, try -l address\n");
goto error;
}
names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
if (names[addresses_no]==0){
fprintf(stderr, "Out of memory.\n");
goto error;
}
strncpy(names[addresses_no], myname.nodename,
strlen(myname.nodename)+1);
addresses_no++;
}
|
5b253cc6 |
|
b2e71d5b |
/*get name lens*/
for(r=0; r<addresses_no; r++){
names_len[r]=strlen(names[r]);
}
|
1b1b19d8 |
/* get ips */
printf("Listening on ");
for (r=0; r<addresses_no;r++){
he=gethostbyname(names[r]);
if (he==0){
DPrint("ERROR: could not resolve %s\n", names[r]);
goto error;
}
|
51eadd0c |
memcpy(&addresses[r], he->h_addr_list[0], sizeof(int));
/*addresses[r]=*((long*)he->h_addr_list[0]);*/
|
1b1b19d8 |
printf("%s [%s] : %d\n",names[r],
inet_ntoa(*(struct in_addr*)&addresses[r]),
(unsigned short)port_no);
|
e60a9728 |
}
|
512dcd98 |
|
f571aa35 |
#ifdef STATS
if (init_stats( dont_fork ? 1 : children_no )==-1) goto error;
#endif
|
22d4aa5d |
|
e60a9728 |
/* init_daemon? */
|
cc2199a9 |
if (!dont_fork){
if ( daemonize(argv[0]) <0 ) goto error;
}
|
22d4aa5d |
|
cc2199a9 |
return main_loop();
|
888ca09d |
|
512dcd98 |
error:
return -1;
}
|
dda9dab1 |
|