./ MultiCS.r69 / main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/time.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/prctl.h>

#include <netdb.h> 
#include <errno.h>
#include <pthread.h>
#include <poll.h>
#include <signal.h>

#include "common.h"
#include "tools.h"
#include "debug.h"
#include "sockets.h"
#include "threads.h"
#include "convert.h"

#include "des.h"
#include "md5.h"
#include "sha1.h"

#include "msg-newcamd.h"
#ifdef CCCAM
#include "msg-cccam.h"
#endif
#ifdef RADEGAST
#include "msg-radegast.h"
#endif

#include "ecmdata.h"
#include "parser.h"
#include "config.h"
#include "httpserver.h"

char config_file[256] = "/var/etc/multics.cfg";

char cccam_nodeid[8];

int flag_debugscr;
#ifdef DEBUG_NETWORK
int flag_debugnet;
#endif
int flag_debugfile;
char debug_file[256];
char sms_file[256];

///
///
struct config_data cfg;
struct program_data prg;

uint ecm_check_time = 0;

uint cs_dcw_check_time = 0;
#ifdef MGCAMD_SRV
uint mg_dcw_check_time = 0;
#endif
#ifdef CCCAM_SRV
uint cc_dcw_check_time = 0;
#endif
#ifdef FREECCCAM_SRV
uint frcc_dcw_check_time = 0;
#endif
#ifdef RADEGAST_SRV
uint rdgd_dcw_check_time = 0;
#endif


#ifdef CHECK_HACKER

struct ip_hacker_data *iplist_get( uint32 ip )
{
	struct ip_hacker_data *iplist = prg.iplist;
	while (iplist) {
		if (iplist->ip==ip) return iplist;
		iplist = iplist->next;
	}
	iplist = malloc( sizeof(struct ip_hacker_data) );
	memset(iplist, 0, sizeof(struct ip_hacker_data) );
	iplist->ip = ip;
	iplist->next = prg.iplist;
	prg.iplist = iplist;
	return iplist;
}

#endif


///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////

// 0: different ; 1:~equivalent
int cmp_cards( struct cs_card_data* card1, struct cs_card_data* card2)
{
	int i,j,found;
	int nbsame = 0;
	int nbdiff = 0;

	if (card1->caid!=card2->caid) return 0;

/*
	if ( ((card1->caid & 0xff00)==0x1800)
		|| ((card1->caid & 0xff00)==0x0900)
		|| ((card1->caid & 0xff00)==0x0b00) ) return 1;
*/
	if ( ((card1->caid & 0xff00)!=0x0100) && ((card1->caid & 0xff00)!=0x0500) ) return 1;

	for(i=0; i<card1->nbprov;i++) {
		found = 0;
		for(j=0; j<card2->nbprov;j++)
			if (card1->prov[i]==card2->prov[j]) {
				found = 1;
				break;
			}
		if (found) nbsame++; else nbdiff++;
	}

	if ( (nbsame==card1->nbprov)||(nbsame==card2->nbprov) ) return 1;
	return 0;
}


// Get Any card to decode
struct cs_card_data *srv_findcard( struct cs_server_data *srv, struct cardserver_data *cs, uint16 ecmcaid, uint32 ecmprov)
{
	// check for card to decode
	struct cs_card_data *pcard = srv->card;
	struct cs_card_data *selcard = NULL;
	int i;
	while (pcard) {
		if ( ecmcaid == pcard->caid ) {
			for (i=0; i<pcard->nbprov;i++) if (ecmprov==pcard->prov[i]) break;
			if  ( ( i<pcard->nbprov ) || ( cs && cmp_cards(pcard, &cs->card) ) ) {
				if (srv->type==TYPE_NEWCAMD) {
					selcard = pcard;
					break;
				}
				else if (srv->type==TYPE_CCCAM) { // select card on hop1 if is there
					if (selcard) {
						if (pcard->uphops<selcard->uphops) selcard = pcard;
						else if (pcard->uphops==selcard->uphops) {
							// Get Stable Card
							if (pcard->shareid<selcard->shareid) selcard = pcard;
						}
					} else selcard = pcard;
				}
				if (srv->type==TYPE_RADEGAST) {
					selcard = pcard;
					break;
				}
				else break;
			}
		}
		pcard = pcard->next;
	}
	return selcard;
}


void srv_cstatadd( struct cs_server_data *srv, int csid, int ok, uint32 ecmoktime)
{
	int i;
	for(i=0; i<MAX_CSPORTS; i++) {
		if (!srv->cstat[i].csid) {
			srv->cstat[i].csid = csid;
			srv->cstat[i].ecmnb = 1;
			if (ok) {
				srv->cstat[i].ecmok = 1;
				srv->cstat[i].ecmoktime = ecmoktime;
			}
			else {
				srv->cstat[i].ecmok = 0;
				srv->cstat[i].ecmoktime = 0;
			}
			break;
		}
		else if (srv->cstat[i].csid==csid) {
			srv->cstat[i].ecmnb++;
			if (ok) {
				srv->cstat[i].ecmok++;
				srv->cstat[i].ecmoktime += ecmoktime;
			}
			break;
		}
	}
}



int card_sharelimits(struct sharelimit_data sharelimits[100], uint16_t caid, uint32_t provid)
{
	int i;
	int uphops1 = 10; // for 0:0
	int uphops2 = 10; // for caid:0
	for (i=0; i<100; i++) {
		if (sharelimits[i].caid==0xffff) break;
		if (!sharelimits[i].caid) {
			if (!sharelimits[i].provid) uphops1 = sharelimits[i].uphops;
		}
		else if (sharelimits[i].caid==caid) {
			if (sharelimits[i].provid==provid) return sharelimits[i].uphops;
			else if (!sharelimits[i].provid) uphops2 = sharelimits[i].uphops;
		}
	}
	if (uphops2<uphops1) return uphops2; else return uphops1;// Max UPHOPS
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////



#ifdef SID_FILTER


// check for card existance
int istherecard(struct cs_server_data *srv, struct cs_card_data *acard)
{
	struct cs_card_data *card = srv->card;
	while(card) {
		if (card==acard) return 1;
		card = card->next;
	}
	return 0;
}


int match_card( uint16 caid, uint32 prov, struct cs_card_data* card)
{
	if (caid!=card->caid) return 0;
	// Dont care about provider for caid non via/seca
	if ( ((card->caid & 0xff00)!=0x0100) && ((card->caid & 0xff00)!=0x0500) ) return 1;
	int i;
	for(i=0; i<card->nbprov;i++) if (prov==card->prov[i]) return 1;
	return 0;
}

// Search for a card with best sid val.
// TODO: option validecmtime-ecmtime
int sidata_getval(struct cs_server_data *srv, struct cardserver_data *cs, uint16 caid, uint32 prov, uint16 sid, struct cs_card_data **selcard )
{
	struct cs_card_data *card = NULL;

	*selcard = NULL;
	if ( (srv->type==TYPE_NEWCAMD) || (srv->type==TYPE_RADEGAST) ) {
		card = srv->card;
		while (card) {
			if ( match_card(caid,prov,card) ) break;
			card = card->next;
		}
		*selcard = card;
		if (card) {
			struct sid_data *sidata = card->sids[sid>>8];
			while (sidata) {
				if (sidata->sid==sid)
				if (sidata->prov==prov) return sidata->val;
				sidata = sidata->next;			
			}
		}
		return 0; // Channel not found in sid cache
	}
#ifdef CCCAM_CLI
	else if (srv->type==TYPE_CCCAM) {
		// Search for availabe card cannot be found in sids
		*selcard = NULL;
		int selsidvalue = 0;
		card = srv->card;
		while (card) {
			if ( match_card(caid,prov,card)
				|| ( !prov && cs && cmp_cards(card, &cs->card) ) // use for prov=0
			) {
				// Search fo sid
				int sidvalue = 0; // by default

				struct sid_data *sidata = card->sids[sid>>8];
				while (sidata) {
					if ( (sidata->sid==sid)&&(sidata->prov==prov) ) {
						sidvalue = sidata->val;
						break;
					}
					sidata = sidata->next;			
				}

				// Check with Selected card (sidvalue) TODO: classify by ecmtime, decode, stability
				if (*selcard) {
					if ( selsidvalue<0 ) {
						if (sidvalue>=0) { *selcard = card; selsidvalue = sidvalue; }
						else if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
					}
					else if ( selsidvalue==0 ) {
						if (sidvalue>0) { *selcard = card; selsidvalue = sidvalue; }
						else if (sidvalue==0) if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
					}
					else if (sidvalue>0) if (card->uphops<(*selcard)->uphops) { *selcard = card; selsidvalue = sidvalue; }
				}
				else { *selcard = card; selsidvalue = sidvalue; }
			}
			card = card->next;
		}
		return selsidvalue;
	}
#endif
	return 0;
}


void cardsids_add(struct cs_card_data *card, uint32 prov, uint16 sid,int val)
{
	if (!sid) return;
	struct sid_data *sidata = malloc( sizeof(struct sid_data) );
	memset( sidata, 0, sizeof(struct sid_data) );

	sidata->sid=sid;
	sidata->prov=prov;
	sidata->val=val;
	sidata->next = card->sids[sid>>8];
	card->sids[sid>>8] = sidata;
}


int cardsids_update(struct cs_card_data *card, uint32 prov, uint16 sid,int val)
{
	if (!sid) return 0;

	struct sid_data *sidata = card->sids[sid>>8];
	while (sidata) {
		if (sidata->sid==sid)
		if (sidata->prov==prov) {
			if ( (sidata->val<100) && (sidata->val>-100) ) {
				if (sidata->val>0) {
					if (val>0) sidata->val +=val;
					else sidata->val =0;
				}
				else if (sidata->val<0) {
					if (val<0) sidata->val +=val;
					else sidata->val=0;
				}
				else sidata->val +=val; // else a card that has decode success one time cannot return to decode failed
			}
			return 1;
		}
		sidata = sidata->next;
	}

	if ( !sidata && sid ) {
		cardsids_add( card, prov, sid,val);
	}
	return 1;
}

#endif



///////////////////////////////////////////////////////////////////////////////
// Common profile functions
///////////////////////////////////////////////////////////////////////////////

struct cardserver_data *getcsbycaidprov( uint16 caid, uint32 prov)
{
	int i;
	if (!caid) return NULL;
	struct cardserver_data *cs = cfg.cardserver;
	while (cs) {
		if (cs->card.caid==caid) {
			for(i=0; i<cs->card.nbprov;i++) if (cs->card.prov[i]==prov) return cs;
			if ( ((cs->card.caid & 0xff00)==0x1800)
				|| ((cs->card.caid & 0xff00)==0x0900)
				|| ((cs->card.caid & 0xff00)==0x0b00) ) return cs;
		}
		cs = cs->next;
	}
	return NULL;
}


struct cardserver_data *getcsbyid(uint32 id)
{
	if (!id) return NULL;
	struct cardserver_data *cs = cfg.cardserver;
	while (cs) {
		if (cs->id==id) return cs;
		cs = cs->next;
	}
	return NULL;
}


struct cardserver_data *getcsbyport(int port)
{
	struct cardserver_data *cs = cfg.cardserver;
	while (cs) {
		if (cs->newcamd.port==port) return cs;
		cs = cs->next;
	}
	return NULL;
}


///////////////////////////////////////////////////////////////////////////////
// Return
//  0: not accepted
//  1: accepted
int accept_sid(struct cardserver_data *cs, uint16_t sid, uint16_t chid )
{
	int i;
	// Check for Accepted sids
	if (!sid) {
		if (!cs->option.faccept0sid) return 0;
	}
	else {
		if (cs->sids) {
			if (!cs->isdeniedsids) {
				int accepted = 0;
				struct sid_chid_data *sids = cs->sids;
				for(i=0;i<MAX_SIDS;i++,sids++) {
					if (!sids->sid) {
						if (!sids->chid) break; // end of sids
						else if (sids->chid==chid) {
							accepted = 1;
							break;
						}
					}
					else if ( (sids->sid==sid)&&(!sids->chid||(sids->chid==chid)) ) {
						accepted = 1;
						break;
					}
				}
				if (!accepted) return 0;
			}
			else {
				int accepted = 1;
				struct sid_chid_data *sids = cs->sids;
				for(i=0;i<MAX_SIDS;i++,sids++) {
					if (!sids->sid) {
						if (!sids->chid) break; // end of sids
						else if (sids->chid==chid) {
							accepted = 0;
							break;
						}
					}
					else if ( (sids->sid==sid)&&(!sids->chid||(sids->chid==chid)) ) {
						accepted = 0;
						break;
					}
				}
				if (!accepted) return 0;
			}
		}
	}
	return 1;
}

int accept_prov(struct cardserver_data *cs, uint32 prov)
{
	int i;
	// Check for provid, accept provid==0
	if (prov) {
		for (i=0; i<cs->card.nbprov;i++) if (prov==cs->card.prov[i]) break;
		if (i>=cs->card.nbprov) return 0;
	}
	else {
		if (!cs->option.faccept0provider) return 0;
	}
	return 1;
}

int accept_caid(struct cardserver_data *cs, uint16_t caid)
{
	// Check for caid, accept caid=0
	if (caid) {
		if (caid!=cs->card.caid) return 0;
	}
	else {
		if (!cs->option.faccept0caid) return 0;
	}
	return 1;
}

int accept_ecmlen(int ecmlen)
{
	if ( (ecmlen<20)||(ecmlen>300) ) return 0;
	return 1;
}

char *cs_accept_ecm(struct cardserver_data *cs, uint16_t caid, uint32_t provid, uint16_t sid, uint16_t chid )
{
	// Check for caid
	if ( !accept_caid(cs,caid) ) return("Wrong caid");
	// Check for provid
	if ( !accept_prov(cs,provid) ) return("Wrong provider");
	// Check for sid
	if ( !accept_sid(cs,sid,chid) ) return("Channel denied");
	return NULL;
}


///////////////////////////////////////////////////////////////////////////////
void ecm_setdcw( struct cardserver_data *cs, ECM_DATA *ecm, uchar dcw[16], int srctype, int srcid);

#include "dcwfilter.c"

#include "pipe.c"

#include "clustredcache.c"

#include "cli-common.c"
#include "cli-newcamd.c"
#ifdef CCCAM_CLI
#include "cli-cccam.c"
#endif

#include "srv-newcamd.c"
#ifdef MGCAMD_SRV
#include "srv-mgcamd.c"
#endif

#ifdef CCCAM_SRV
#include "srv-cccam.c"
#endif
#ifdef FREECCCAM_SRV
#include "srv-freecccam.c"
#endif

#ifdef RADEGAST_CLI
#include "cli-radegast.c"
#endif
#ifdef RADEGAST_SRV
#include "srv-radegast.c"
#endif


#include "th-srv.c"  // Servers Connnection
#include "th-dns.c"  // Dns Resolving
#include "th-ecm.c"  // Check/send ecm request to servers & Check/send dcw to clients
#include "th-cfg.c"  // Reread Config
#include "th-date.c"


///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////

pthread_t cli_tid;

int checkthread;

unsigned int seed2;

uint8 fastrnd2()
{
  unsigned int offset = 12923+(GetTickCount()&0xff);
  unsigned int multiplier = 4079+(GetTickCount()&0xff);
  seed2 = seed2 * multiplier + offset;
  return (uint8)(seed2 % 0xFF);
}




int mainprocess()
{
	gettimeofday( &startime, NULL );
// INIT
	pthread_mutex_init(&prg.lock, NULL);
	pthread_mutex_init(&prg.lockecm, NULL);

	pthread_mutex_init(&prg.lockcli, NULL);
	pthread_mutex_init(&prg.locksrv, NULL);

#ifdef CCCAM_SRV
	pthread_mutex_init(&prg.locksrvcc, NULL); // CC Client connection
	pthread_mutex_init(&prg.lockcccli, NULL);
#endif
#ifdef FREECCCAM_SRV
	pthread_mutex_init(&prg.locksrvfreecc, NULL); // CC Client connection
	pthread_mutex_init(&prg.lockfreecccli, NULL);
#endif

#ifdef MGCAMD_SRV
	pthread_mutex_init(&prg.locksrvmg, NULL); // Client connection
	pthread_mutex_init(&prg.lockclimg, NULL);
#endif

#ifdef RADEGAST_SRV
	pthread_mutex_init(&prg.lockrdgdsrv, NULL); // Client connection
	pthread_mutex_init(&prg.lockrdgdcli, NULL);
#endif

	// Main Loops(THREADS)
	pthread_mutex_init(&prg.lockdnsth, NULL); // DNS lookup Thread

	pthread_mutex_init(&prg.locksrvth, NULL);	// Connection to cardservers
	pthread_mutex_init(&prg.lockmain, NULL); // Messages Recv

	pthread_mutex_init(&prg.locksrvcs, NULL); // CS Client connection
	pthread_mutex_init(&prg.lockhttp, NULL); // HTTP Server

	pthread_mutex_init(&prg.lockdns, NULL);

	pthread_mutex_init(&prg.lockdcw, NULL);

#ifdef CACHE_ACTION
	pthread_mutex_init(&prg.lockaction, NULL);
#endif

	pthread_mutex_init(&prg.lockcache, NULL);

	pthread_mutex_init(&prg.lockthreaddate, NULL);

	gettimeofday( &prg.exectime, NULL );

	memset(&trace, 0, sizeof(struct trace_data) );

	/* Create the pipe. */
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, srvsocks) < 0) { perror("opening stream socket pair"); exit(1); }

#ifdef CACHE_ACTION
	if (pipe (sendcache_pipe)) { // Cache -> ecm
		printf ("Pipe failed.\n");
		return -1;
	}
#endif

  srand (time(NULL));

#ifdef CCCAM 
// NODE ID: 8675e141 217e6912
	cccam_nodeid[0] = 0x11;
	cccam_nodeid[1] = 0x22;
	cccam_nodeid[2] = 0x33;
	cccam_nodeid[3] = 0x44;
	cccam_nodeid[4] = 0xff & fastrnd2();
	cccam_nodeid[5] = 0xff & fastrnd2();
	cccam_nodeid[6] = 0xff & fastrnd2();
	cccam_nodeid[7] = 0xff & fastrnd2();
#endif

	start_thread_config();
	usleep(100000);

	init_ecmdata();

// THREADS - detached
	start_thread_dns();
	sleep(1);
	start_thread_srv();
	start_thread_date();
#ifdef HTTP_SRV
	start_thread_http();
#endif
	start_thread_recv_msg();
	sleep(1); // wait for dns & servers connections

	start_thread_cache();

	create_prio_thread(&cli_tid, (threadfn)cs_connect_cli_thread,NULL, 50);
#ifdef RADEGAST_SRV
	pthread_t rdgd_cli_tid;
	create_prio_thread(&rdgd_cli_tid, (threadfn)rdgd_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef CCCAM_SRV
	pthread_t cc_cli_tid;
	create_prio_thread(&cc_cli_tid, (threadfn)cc_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef FREECCCAM_SRV
	pthread_t freecc_cli_tid;
	create_prio_thread(&freecc_cli_tid, (threadfn)freecc_connect_cli_thread, NULL, 50); // Lock server
#endif
#ifdef MGCAMD_SRV
	start_thread_mgcamd();
#endif
	return 0;
}


#ifdef SIG_HANDLER

#include <execinfo.h>
#include <ucontext.h>

#ifdef REG_EIP
#define INDEX_IP REG_EIP
#else
#ifdef REG_RIP
#define INDEX_IP REG_RIP
#else
#ifdef PT_NIP
#define INDEX_IP PT_NIP
#endif
#endif
#endif

void sighandler(int sig, siginfo_t *info, void *secret) {

	ucontext_t *uc = (ucontext_t *)secret;
	printf(" Got signal %d ", sig);
	printf(" faulty address is %p ", info->si_addr);
#ifdef PT_NIP
	printf(" from 0x%016X\n", uc->uc_mcontext.uc_regs->gregs[PT_NIP]);
#else
	printf(" from 0x%016X\n", uc->uc_mcontext.gregs[INDEX_IP]);
#endif

	fdebugf(" Got signal %d ", info->si_signo);
	fdebugf(" faulty address is %p ", info->si_addr);
#ifdef PT_NIP
	fdebugf(" from 0x%016X\n", uc->uc_mcontext.uc_regs->gregs[PT_NIP]);
#else
	fdebugf(" from 0x%016X\n", uc->uc_mcontext.gregs[INDEX_IP]);
#endif

	exit(0);
}

void install_handler (void)
{
  struct sigaction sa;
  memset(&sa, 0, sizeof(sigaction));
  sa.sa_sigaction = (void *)sighandler;
  sigemptyset (&sa.sa_mask);
  sa.sa_flags = SA_RESTART | SA_SIGINFO;
  sigaction(SIGSEGV, &sa, NULL);
  sigaction(SIGFPE, &sa, NULL);
}
#endif

int main(int argc, char *argv[])
{
	int option_background = 0; // default
	int fork_return;
	char *args;
	int i,j;

	char pg[] = "Multi CardServer r"REVISION_STR" - by ";
	char evil[] = "evileyes";
	char email[] = " (email:evileyes@live.fr)\n";

	if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
	printf("%s", pg);

#ifdef SIG_HANDLER
	install_handler();
#endif

	if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
	printf("%s", evil );

	flag_debugscr = 0;
	flag_debugfile = 0;
#ifdef DEBUG_NETWORK
	flag_debugnet = 0;
#endif

	printf("%s", email );

	// Extract filename
	char *p = argv[0];
	char *slash = p;
	char *dot = NULL;
	while (*p) {
		if (*p=='/') slash = p+1;
		else if (*p=='.') dot = p;
		p++;
	}
	char path[255];
	if (dot>slash) memcpy( path, slash, dot-slash); else strcpy(path, slash);
	// Set Config name
	sprintf( config_file, "/var/etc/%s.cfg", path);
//	sprintf( sid_file, "/var/etc/%s.sid", path);
//	sprintf( card_file, "/var/etc/%s.card", path);
	sprintf( debug_file, "/var/tmp/%s.log", path);
	sprintf( sms_file, "/var/tmp/%s.sms", path);

	// Parse Options
	for (i=1;i<argc;i++) {
		args = *(argv+i);
		if (args[0]=='-') {
			if (args[1]=='h') {
				printf("USAGE\n\tmultics [-b] [-v] [-f] [-n] [-C <configfile>]\n\
OPTIONS\n\
\t-b               run in background\n\
\t-C <configfile>  use <configfile> instead of default config file (/var/etc/multics.cfg)\n\
\t-f               write to log file (/var/tmp/multics.log)\n\
\t-n               print network packets\n\
\t-v               print on screen\n\
\t-h               this help message\n");
				return 0;
			}
			else if (args[1]=='C') {
				i++;
				if (i<argc) {
					args = *(argv+i);
					strcpy( config_file, args );
				}
			}
			else {
				for(j=1; j<strlen(args); j++) {
					if (args[j]=='b') option_background = 1;
					else if (args[j]=='v') flag_debugscr = 1;
#ifdef DEBUG_NETWORK
					else if (args[j]=='n') flag_debugnet = 1;
#endif
					else if (args[j]=='f') flag_debugfile = 1;
				}
			}
		}
	}

	if (option_background==1) {
		fork_return = fork();
		if( fork_return < 0) {
			debugf(0," unable to create child process, exiting.\n");
			exit(-1);
		}
		if (fork_return>0) {
			//debugf(" main process, exiting.\n");
			exit(0);
		}
		//else mainprocess();
	}

	prg.pid_main = getpid();

	mainprocess();

	sleep(1);

	prg.restart = 0;
	while (1) {
			if (prg.restart==1) { // restart()
				if ( (evil[0]!='e')||(evil[1]!='v')||(evil[2]!='i')||(evil[3]!='l')||(evil[4]!='e')||(evil[5]!='y')||(evil[6]!='e')||(evil[7]!='s') ) exit(0);
				debugf(0," Restarting...\n");
				//TODO:stop threads
				int fork_return;
				done_config(&cfg);
				fork_return = vfork();
				if( fork_return < 0) {
					printf("unable to create child process, exiting.\n");
				}
				else if (fork_return==0) {
					fork_return = vfork();
					if (fork_return < 0) {
						printf("unable to create child process, exiting.\n");
					}
					else if (fork_return==0) {
						execvp( argv[0], argv );
						perror("execvp");
					}
					exit(0);
				}
				debugf(0," Stopped.\n");
				exit(0);
			}
			sleep(2);
	}
	return 0;
}