From d55d4e0df196571eab55bf310eba48a3340a68ac Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sat, 6 Dec 2003 16:35:33 +0000 Subject: [PATCH] More memory leak fixes, added command thread to mbtask --- ChangeLog | 5 + html/programs/mbtask.html | 8 +- lib/clcomm.c | 2 +- mbcico/emsidat.c | 475 +++++++++++++++++++------------------- mbcico/tcpproto.c | 8 +- mbtask/Makefile | 2 +- mbtask/mbtask.c | 321 ++++++++++++++------------ mbtask/outstat.c | 3 + mbtask/ping.c | 9 +- mbtask/ports.c | 1 + mbtask/taskcomm.c | 56 +++++ mbtask/taskcomm.h | 3 +- mbtask/taskutil.c | 6 +- 13 files changed, 500 insertions(+), 399 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87ad077f..e9b7c9b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -59,6 +59,11 @@ v0.39.3 26-Nov-2003 mbtask: The ping function now runs in a separate thread. Changed some ping timer logic. + Added a "secret" commandline parameter to allow mbtask to run + under control of debuggers. + The client command server runs in a separate thread. + Fixed some small memory leaks which had no effect on long term + running of mbtask, only leaks during program stop. mbpasswd: Fixed a small memory leak. diff --git a/html/programs/mbtask.html b/html/programs/mbtask.html index 55e9454a..cd679f41 100644 --- a/html/programs/mbtask.html +++ b/html/programs/mbtask.html @@ -14,12 +14,12 @@
-
Last update 23-Mar-2002
+
Last update 06-Dec-2003

mbtask - MBSE BBS Taskmanager

Sysopsis.

-mbtask +mbtask [-nd]

 

Description.

@@ -119,6 +119,10 @@ the chance that numbers are repeated on your system are almost zero. The first time the counter is initialized it is set to the current unix time in seconds since 1 januari 1970. This counter is used by several programs to create unique .pkt filenames, msgid numbers etc. +

+The commandline option -nd is only for debugging, it allows to start +without becoming a daemon, mbtask will run in the foreground. This +option is only usefull for developers.

 

Environment.

diff --git a/lib/clcomm.c b/lib/clcomm.c index 35b5079a..284a97cf 100644 --- a/lib/clcomm.c +++ b/lib/clcomm.c @@ -489,7 +489,7 @@ char *printable(char *s, int l) len=-l; } - pbuff=(char*)xmalloc(len*4+1); + pbuff=(char*)xmalloc(len*3+1); p=pbuff; while (len--) { if (isprint(*(unsigned char*)s)) diff --git a/mbcico/emsidat.c b/mbcico/emsidat.c index b3f4f3af..be066bec 100644 --- a/mbcico/emsidat.c +++ b/mbcico/emsidat.c @@ -4,7 +4,7 @@ * Purpose ...............: Fidonet mailer * ***************************************************************************** - * Copyright (C) 1997-2002 + * Copyright (C) 1997-2003 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -49,194 +49,199 @@ extern int Loaded; extern int mypid; + +/* + * Encode EMSI string. If called with a NULL pointer memory is freed. + */ char *emsiencode(char *s) { - char Base16Code[]="0123456789ABCDEF"; - static char *buf; - char *p, *q; + char Base16Code[]="0123456789ABCDEF"; + static char *buf; + char *p, *q; - if (buf) - free(buf); - if ((buf = malloc(2 * strlen(s) + 1 * sizeof(char))) == NULL) { - Syslog('+', "emsiencode:out of memory:string too long:\"%s\"", s); - return s; + if (buf) + free(buf); + buf = NULL; + if (s == NULL) + return NULL; + + if ((buf = malloc(2 * strlen(s) + 1 * sizeof(char))) == NULL) { + Syslog('+', "emsiencode:out of memory:string too long:\"%s\"", s); + return s; + } + for (p = s, q = buf; *p != '\0';) { + switch (*p) { + case '\\': *q++ = '\\'; *q++ = *p++; break; + case '[': + case ']': + case '{': + case '}': *q++ = '\\'; + *q++ = Base16Code[(*p >> 4) & 0x0f]; + *q++ = Base16Code[*p & 0x0f]; + p++; break; + default: *q++ = *p++; break; } - for (p = s, q = buf; *p != '\0';) { - switch (*p) { - case '\\': *q++ = '\\'; *q++ = *p++; break; - case '[': - case ']': - case '{': - case '}': *q++ = '\\'; - *q++ = Base16Code[(*p >> 4) & 0x0f]; - *q++ = Base16Code[*p & 0x0f]; - p++; break; - default: *q++ = *p++; break; - } - } - *q = '\0'; + } + *q = '\0'; - return buf; + return buf; } char *mkemsidat(int caller) { - time_t tt; - char cbuf[16]; - char *p; - faddr *primary; - int i; + time_t tt; + char cbuf[16], *p; + faddr *primary; + int i; - p = xstrcpy((char *)"EMSI_DAT0000{EMSI}{"); + p = xstrcpy((char *)"EMSI_DAT0000{EMSI}{"); - primary = bestaka_s(remote->addr); - p = xstrcat(p, ascfnode(primary, 0x1f)); + primary = bestaka_s(remote->addr); + p = xstrcat(p, ascfnode(primary, 0x1f)); - for (i = 0; i < 40; i++) - if ((CFG.aka[i].node) && (CFG.akavalid[i]) && - ((CFG.aka[i].zone != primary->zone) || - (CFG.aka[i].net != primary->net) || - (CFG.aka[i].node != primary->node) || - (CFG.aka[i].point!= primary->point))) { - p = xstrcat(p, (char *)" "); - p = xstrcat(p, aka2str(CFG.aka[i])); - } - - p=xstrcat(p,(char *)"}{"); - tidy_faddr(primary); - - if (emsi_local_password) - p=xstrcat(p,emsi_local_password); - else - if (strlen(nodes.Spasswd)) { - p = xstrcat(p, nodes.Spasswd); - } - - if (emsi_local_opts & OPT_EII) { - p = xstrcat(p, (char *)"}{"); - - if (emsi_local_lcodes & LCODE_FNC) - p = xstrcat(p, (char *)"FNC,"); - if (emsi_local_lcodes & LCODE_RMA) - p = xstrcat(p, (char *)"RMA,"); - if (emsi_local_lcodes & LCODE_RH1) - p = xstrcat(p, (char *)"RH1,"); - - if (emsi_local_lcodes & LCODE_PUA) - p=xstrcat(p,(char *)"PUA,"); - else if (emsi_local_lcodes & LCODE_PUP) - p=xstrcat(p,(char *)"PUP,"); - else if (emsi_local_lcodes & LCODE_NPU) - p=xstrcat(p,(char *)"NPU,"); - if (emsi_local_lcodes & LCODE_HAT) - p=xstrcat(p,(char *)"HAT,"); - if (emsi_local_lcodes & LCODE_HXT) - p=xstrcat(p,(char *)"HXT,"); - if (emsi_local_lcodes & LCODE_HRQ) - p=xstrcat(p,(char *)"HRQ,"); - if (*(p+strlen(p)-1) == ',') - *(p+strlen(p)-1) = '}'; - else - p=xstrcat(p,(char *)"}"); - } else { - p=xstrcat(p,(char *)"}{8N1"); - if (emsi_local_lcodes & LCODE_RH1) - p = xstrcat(p, (char *)",RH1"); - if (caller) { - if (emsi_local_lcodes & LCODE_PUA) - p=xstrcat(p,(char *)",PUA"); - else if (emsi_local_lcodes & LCODE_PUP) - p=xstrcat(p,(char *)",PUP"); - else if (emsi_local_lcodes & LCODE_NPU) - p=xstrcat(p,(char *)",NPU"); - } else { - if (emsi_local_lcodes & LCODE_HAT) - p=xstrcat(p,(char *)",HAT"); - if (emsi_local_lcodes & LCODE_HXT) - p=xstrcat(p,(char *)",HXT"); - if (emsi_local_lcodes & LCODE_HRQ) - p=xstrcat(p,(char *)",HRQ"); - } - - p = xstrcat(p, (char *)"}"); + for (i = 0; i < 40; i++) + if ((CFG.aka[i].node) && (CFG.akavalid[i]) && + ((CFG.aka[i].zone != primary->zone) || (CFG.aka[i].net != primary->net) || + (CFG.aka[i].node != primary->node) || (CFG.aka[i].point!= primary->point))) { + p = xstrcat(p, (char *)" "); + p = xstrcat(p, aka2str(CFG.aka[i])); } - p=xstrcat(p,(char *)"{"); - if (emsi_local_protos & PROT_TCP) - p=xstrcat(p,(char *)"TCP,"); - if (emsi_local_protos & PROT_HYD) - p=xstrcat(p,(char *)"HYD,"); - if (emsi_local_protos & PROT_JAN) - p=xstrcat(p,(char *)"JAN,"); - if (emsi_local_protos & PROT_ZAP) - p=xstrcat(p,(char *)"ZAP,"); - if (emsi_local_protos & PROT_ZMO) - p=xstrcat(p,(char *)"ZMO,"); - if (emsi_local_protos & PROT_DZA); - p=xstrcat(p,(char *)"DZA,"); - if (emsi_local_protos & PROT_KER) - p=xstrcat(p,(char *)"KER,"); - if (emsi_local_protos == 0) - p=xstrcat(p,(char *)"NCP,"); - if (emsi_local_opts & OPT_NRQ) - p=xstrcat(p,(char *)"NRQ,"); - if (emsi_local_opts & OPT_ARC) - p=xstrcat(p,(char *)"ARC,"); - if (emsi_local_opts & OPT_XMA) - p=xstrcat(p,(char *)"XMA,"); - if (emsi_local_opts & OPT_FNC) - p=xstrcat(p,(char *)"FNC,"); - if (emsi_local_opts & OPT_CHT) - p=xstrcat(p,(char *)"CHT,"); - if (emsi_local_opts & OPT_SLK) - p=xstrcat(p,(char *)"SLK,"); - if (emsi_local_opts & OPT_EII) - p=xstrcat(p,(char *)"EII,"); - if (emsi_local_opts & OPT_DFB) - p=xstrcat(p,(char *)"DFB,"); - if (emsi_local_opts & OPT_FRQ) - p=xstrcat(p,(char *)"FRQ,"); + p=xstrcat(p,(char *)"}{"); + tidy_faddr(primary); + + if (emsi_local_password) + p=xstrcat(p,emsi_local_password); + else if (strlen(nodes.Spasswd)) { + p = xstrcat(p, nodes.Spasswd); + } + + if (emsi_local_opts & OPT_EII) { + p = xstrcat(p, (char *)"}{"); + + if (emsi_local_lcodes & LCODE_FNC) + p = xstrcat(p, (char *)"FNC,"); + if (emsi_local_lcodes & LCODE_RMA) + p = xstrcat(p, (char *)"RMA,"); + if (emsi_local_lcodes & LCODE_RH1) + p = xstrcat(p, (char *)"RH1,"); + + if (emsi_local_lcodes & LCODE_PUA) + p=xstrcat(p,(char *)"PUA,"); + else if (emsi_local_lcodes & LCODE_PUP) + p=xstrcat(p,(char *)"PUP,"); + else if (emsi_local_lcodes & LCODE_NPU) + p=xstrcat(p,(char *)"NPU,"); + if (emsi_local_lcodes & LCODE_HAT) + p=xstrcat(p,(char *)"HAT,"); + if (emsi_local_lcodes & LCODE_HXT) + p=xstrcat(p,(char *)"HXT,"); + if (emsi_local_lcodes & LCODE_HRQ) + p=xstrcat(p,(char *)"HRQ,"); if (*(p+strlen(p)-1) == ',') - *(p+strlen(p)-1) = '}'; + *(p+strlen(p)-1) = '}'; else - p=xstrcat(p,(char *)"}"); + p=xstrcat(p,(char *)"}"); + } else { + p=xstrcat(p,(char *)"}{8N1"); + if (emsi_local_lcodes & LCODE_RH1) + p = xstrcat(p, (char *)",RH1"); + if (caller) { + if (emsi_local_lcodes & LCODE_PUA) + p=xstrcat(p,(char *)",PUA"); + else if (emsi_local_lcodes & LCODE_PUP) + p=xstrcat(p,(char *)",PUP"); + else if (emsi_local_lcodes & LCODE_NPU) + p=xstrcat(p,(char *)",NPU"); + } else { + if (emsi_local_lcodes & LCODE_HAT) + p=xstrcat(p,(char *)",HAT"); + if (emsi_local_lcodes & LCODE_HXT) + p=xstrcat(p,(char *)",HXT"); + if (emsi_local_lcodes & LCODE_HRQ) + p=xstrcat(p,(char *)",HRQ"); + } - sprintf(cbuf,"{%X}",PRODCODE); - p=xstrcat(p,cbuf); - p=xstrcat(p,(char *)"{mbcico}{"); - p=xstrcat(p,(char *)VERSION); - p=xstrcat(p,(char *)"}{"); - p=xstrcat(p,(char *)__DATE__); - p=xstrcat(p,(char *)"}{IDENT}{["); - p=xstrcat(p,name?emsiencode(name):(char *)"Unknown"); - p=xstrcat(p,(char *)"]["); - p=xstrcat(p,emsiencode(CFG.location)); - p=xstrcat(p,(char *)"]["); - p=xstrcat(p,emsiencode(CFG.sysop_name)); - p=xstrcat(p,(char *)"]["); - p=xstrcat(p,phone?emsiencode(phone):(char *)"-Unpublished-"); - p=xstrcat(p,(char *)"]["); - if (CFG.Speed) - sprintf(cbuf,"%ld",CFG.Speed); - else - strcpy(cbuf,"9600"); - p=xstrcat(p,cbuf); - p=xstrcat(p,(char *)"]["); - p=xstrcat(p,flags?emsiencode(flags):(char *)""); - p=xstrcat(p,(char *)"]}{TRX#}{["); - tt = time(NULL); - sprintf(cbuf,"%08lX",mtime2sl(tt)); - p=xstrcat(p,cbuf); - p=xstrcat(p,(char *)"]}{TZUTC}{["); - p=xstrcat(p,gmtoffset(tt)); - p=xstrcat(p,(char *)"]}"); + p = xstrcat(p, (char *)"}"); + } - sprintf(cbuf,"%04X",(unsigned int)strlen(p+12)); - memcpy(p+8,cbuf,4); - Syslog('I',"Prepared: \"%s\"",p); - return p; + p=xstrcat(p,(char *)"{"); + if (emsi_local_protos & PROT_TCP) + p=xstrcat(p,(char *)"TCP,"); + if (emsi_local_protos & PROT_HYD) + p=xstrcat(p,(char *)"HYD,"); + if (emsi_local_protos & PROT_JAN) + p=xstrcat(p,(char *)"JAN,"); + if (emsi_local_protos & PROT_ZAP) + p=xstrcat(p,(char *)"ZAP,"); + if (emsi_local_protos & PROT_ZMO) + p=xstrcat(p,(char *)"ZMO,"); + if (emsi_local_protos & PROT_DZA); + p=xstrcat(p,(char *)"DZA,"); + if (emsi_local_protos & PROT_KER) + p=xstrcat(p,(char *)"KER,"); + if (emsi_local_protos == 0) + p=xstrcat(p,(char *)"NCP,"); + if (emsi_local_opts & OPT_NRQ) + p=xstrcat(p,(char *)"NRQ,"); + if (emsi_local_opts & OPT_ARC) + p=xstrcat(p,(char *)"ARC,"); + if (emsi_local_opts & OPT_XMA) + p=xstrcat(p,(char *)"XMA,"); + if (emsi_local_opts & OPT_FNC) + p=xstrcat(p,(char *)"FNC,"); + if (emsi_local_opts & OPT_CHT) + p=xstrcat(p,(char *)"CHT,"); + if (emsi_local_opts & OPT_SLK) + p=xstrcat(p,(char *)"SLK,"); + if (emsi_local_opts & OPT_EII) + p=xstrcat(p,(char *)"EII,"); + if (emsi_local_opts & OPT_DFB) + p=xstrcat(p,(char *)"DFB,"); + if (emsi_local_opts & OPT_FRQ) + p=xstrcat(p,(char *)"FRQ,"); + if (*(p+strlen(p)-1) == ',') + *(p+strlen(p)-1) = '}'; + else + p=xstrcat(p,(char *)"}"); + + sprintf(cbuf,"{%X}",PRODCODE); + p=xstrcat(p,cbuf); + p=xstrcat(p,(char *)"{mbcico}{"); + p=xstrcat(p,(char *)VERSION); + p=xstrcat(p,(char *)"}{"); + p=xstrcat(p,(char *)__DATE__); + p=xstrcat(p,(char *)"}{IDENT}{["); + p=xstrcat(p,name?emsiencode(name):(char *)"Unknown"); + p=xstrcat(p,(char *)"]["); + p=xstrcat(p,emsiencode(CFG.location)); + p=xstrcat(p,(char *)"]["); + p=xstrcat(p,emsiencode(CFG.sysop_name)); + p=xstrcat(p,(char *)"]["); + p=xstrcat(p,phone?emsiencode(phone):(char *)"-Unpublished-"); + p=xstrcat(p,(char *)"]["); + if (CFG.Speed) + sprintf(cbuf,"%ld",CFG.Speed); + else + strcpy(cbuf,"9600"); + p=xstrcat(p,cbuf); + p=xstrcat(p,(char *)"]["); + p=xstrcat(p,flags?emsiencode(flags):(char *)""); + p=xstrcat(p,(char *)"]}{TRX#}{["); + tt = time(NULL); + sprintf(cbuf,"%08lX",mtime2sl(tt)); + p=xstrcat(p,cbuf); + p=xstrcat(p,(char *)"]}{TZUTC}{["); + p=xstrcat(p,gmtoffset(tt)); + p=xstrcat(p,(char *)"]}"); + + sprintf(cbuf,"%04X",(unsigned int)strlen(p+12)); + memcpy(p+8,cbuf,4); + Syslog('I',"Prepared: \"%s\"",p); + emsiencode(NULL); /* Free memory */ + return p; } @@ -244,42 +249,42 @@ char *mkemsidat(int caller) char *sel_brace(char*); char *sel_brace(char *s) { - static char *save; - char *p,*q; - int i; + static char *save; + char *p,*q; + int i; - if (s == NULL) - s=save; - for (;*s && (*s != '{');s++); - if (*s == '\0') { - save=s; - return NULL; - } else - s++; + if (s == NULL) + s=save; + for (;*s && (*s != '{');s++); + if (*s == '\0') { + save=s; + return NULL; + } else + s++; - for (p=s,q=s;*p;p++) - switch (*p) { - case '}': if (*(p+1) == '}') - *q++=*p++; - else { - *q='\0'; - save=p+1; - goto exit; - } - break; - case '\\': if (*(p+1) == '\\') - *q++=*p++; - else { - sscanf(p+1,"%02x",&i); - *q++=i; - p+=2; - } - break; - default: *q++=*p; - break; - } + for (p=s,q=s;*p;p++) + switch (*p) { + case '}': if (*(p+1) == '}') + *q++=*p++; + else { + *q='\0'; + save=p+1; + goto exit; + } + break; + case '\\': if (*(p+1) == '\\') + *q++=*p++; + else { + sscanf(p+1,"%02x",&i); + *q++=i; + p+=2; + } + break; + default: *q++=*p; + break; + } exit: - return s; + return s; } @@ -287,42 +292,42 @@ exit: char *sel_bracket(char*); char *sel_bracket(char *s) { - static char *save; - char *p,*q; - int i; + static char *save; + char *p,*q; + int i; - if (s == NULL) - s=save; - for (;*s && (*s != '[');s++); - if (*s == '\0') { - save=s; - return NULL; - } else - s++; + if (s == NULL) + s=save; + for (;*s && (*s != '[');s++); + if (*s == '\0') { + save=s; + return NULL; + } else + s++; - for (p=s,q=s;*p;p++) - switch (*p) { - case ']': if (*(p+1) == ']') - *q++=*p++; - else { - *q='\0'; - save=p+1; - goto exit; - } - break; - case '\\': if (*(p+1) == '\\') - *q++=*p++; - else { - sscanf(p+1,"%02x",&i); - *q++=i; - p+=2; - } - break; - default: *q++=*p; - break; - } + for (p=s,q=s;*p;p++) + switch (*p) { + case ']': if (*(p+1) == ']') + *q++=*p++; + else { + *q='\0'; + save=p+1; + goto exit; + } + break; + case '\\': if (*(p+1) == '\\') + *q++=*p++; + else { + sscanf(p+1,"%02x",&i); + *q++=i; + p+=2; + } + break; + default: *q++=*p; + break; + } exit: - return s; + return s; } diff --git a/mbcico/tcpproto.c b/mbcico/tcpproto.c index 81127c32..6be24a17 100644 --- a/mbcico/tcpproto.c +++ b/mbcico/tcpproto.c @@ -129,7 +129,7 @@ int tcprcvfiles(void) { int rc, bufl; long filesize, filetime; - char *filename, *p; + char *filename = NULL, *p; Syslog('+', "TCP: start receive files"); if (getsync()) { @@ -155,8 +155,12 @@ next: } else return rc==0?1:rc; - if (strlen(filename) && filesize && filetime) + if (strlen(filename) && filesize && filetime) { rc = receivefile(filename,filetime,filesize); + if (filename) + free(filename); + filename = NULL; + } if (fout) { if (closeit(0)) diff --git a/mbtask/Makefile b/mbtask/Makefile index 15b764f6..72e6f9c6 100644 --- a/mbtask/Makefile +++ b/mbtask/Makefile @@ -33,7 +33,7 @@ install: all @if [ "`id -un`" != "root" ] ; then \ echo; echo " Must be root to install!"; echo; exit 3; \ fi - ${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbtask ${BINDIR} + ${INSTALL} -c -o `id -un` -g `id -gn` -m 6755 mbtask ${BINDIR} @if [ ! -f ${ETCDIR}/issue ]; then \ ${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 issue ${ETCDIR} ; \ echo "${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 issue ${ETCDIR}"; \ diff --git a/mbtask/mbtask.c b/mbtask/mbtask.c index a313b516..d3dcdb10 100644 --- a/mbtask/mbtask.c +++ b/mbtask/mbtask.c @@ -48,7 +48,7 @@ #include "mbtask.h" -#define NUM_THREADS 1 /* Max. nr of threads */ +#define NUM_THREADS 2 /* Max. nr of threads */ /* @@ -110,7 +110,9 @@ extern int ipmailers; /* TCP/IP mail sessions */ extern int tosswait; /* Toss wait timer */ extern pid_t mypid; /* Pid of daemon */ int T_Shutdown = FALSE; /* Shutdown threads */ - +int nodaemon = FALSE; /* Run in foreground */ +extern int cmd_run; /* Cmd running */ +extern int ping_run; /* Ping running */ /* @@ -118,7 +120,7 @@ int T_Shutdown = FALSE; /* Shutdown threads */ */ int thr_id[NUM_THREADS]; /* thread ID's */ pthread_t p_thread[NUM_THREADS]; /* thread's structure */ -pthread_mutex_t p_mutex = PTHREAD_MUTEX_INITIALIZER; /* Ping mutex */ +// pthread_mutex_t p_mutex = PTHREAD_MUTEX_INITIALIZER; /* Ping mutex */ @@ -443,33 +445,33 @@ void load_taskcfg(void) */ pid_t launch(char *cmd, char *opts, char *name, int tasktype) { - char buf[PATH_MAX]; - char *vector[16]; - int i, rc = 0; - pid_t pid = 0; + char buf[PATH_MAX], *vector[16]; + int i, rc = 0; + pid_t pid = 0; - if (checktasks(0) >= MAXTASKS) { - Syslog('?', "Launch: can't execute %s, maximum tasks reached", cmd); - return 0; - } + if (checktasks(0) >= MAXTASKS) { + Syslog('?', "Launch: can't execute %s, maximum tasks reached", cmd); + return 0; + } + memset(vector, 0, sizeof(vector)); - if (opts == NULL) - sprintf(buf, "%s", cmd); - else - sprintf(buf, "%s %s", cmd, opts); + if (opts == NULL) + sprintf(buf, "%s", cmd); + else + sprintf(buf, "%s %s", cmd, opts); - i = 0; - vector[i++] = strtok(buf," \t\n\0"); - while ((vector[i++] = strtok(NULL," \t\n")) && (i<16)); - vector[15] = NULL; + i = 0; + vector[i++] = strtok(buf," \t\n\0"); + while ((vector[i++] = strtok(NULL," \t\n")) && (i<16)); + vector[15] = NULL; - if (file_exist(vector[0], X_OK)) { - Syslog('?', "Launch: can't execute %s, command not found", vector[0]); - return 0; - } + if (file_exist(vector[0], X_OK)) { + Syslog('?', "Launch: can't execute %s, command not found", vector[0]); + return 0; + } - pid = fork(); - switch (pid) { + pid = fork(); + switch (pid) { case -1: Syslog('?', "$Launch: error, can't fork grandchild"); return 0; @@ -478,18 +480,18 @@ pid_t launch(char *cmd, char *opts, char *name, int tasktype) (void)setsid(); /* It doesn't seem to help */ close(0); if (open("/dev/null", O_RDONLY) != 0) { - Syslog('?', "$Launch: \"%s\": reopen of stdin to /dev/null failed", buf); - _exit(MBERR_EXEC_FAILED); + Syslog('?', "$Launch: \"%s\": reopen of stdin to /dev/null failed", buf); + _exit(MBERR_EXEC_FAILED); } close(1); if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) { - Syslog('?', "$Launch: \"%s\": reopen of stdout to /dev/null failed", buf); - _exit(MBERR_EXEC_FAILED); + Syslog('?', "$Launch: \"%s\": reopen of stdout to /dev/null failed", buf); + _exit(MBERR_EXEC_FAILED); } close(2); if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) { - Syslog('?', "$Launch: \"%s\": reopen of stderr to /dev/null failed", buf); - _exit(MBERR_EXEC_FAILED); + Syslog('?', "$Launch: \"%s\": reopen of stderr to /dev/null failed", buf); + _exit(MBERR_EXEC_FAILED); } errno = 0; rc = execv(vector[0],vector); @@ -498,33 +500,33 @@ pid_t launch(char *cmd, char *opts, char *name, int tasktype) default: /* grandchild's daddy's process */ break; + } + + /* + * Add it to the tasklist. + */ + for (i = 0; i < MAXTASKS; i++) { + if (strlen(task[i].name) == 0) { + strcpy(task[i].name, name); + strcpy(task[i].cmd, cmd); + if (opts) + strcpy(task[i].opts, opts); + task[i].pid = pid; + task[i].status = 0; + task[i].running = TRUE; + task[i].rc = 0; + task[i].tasktype = tasktype; + break; } + } - /* - * Add it to the tasklist. - */ - for (i = 0; i < MAXTASKS; i++) { - if (strlen(task[i].name) == 0) { - strcpy(task[i].name, name); - strcpy(task[i].cmd, cmd); - if (opts) - strcpy(task[i].opts, opts); - task[i].pid = pid; - task[i].status = 0; - task[i].running = TRUE; - task[i].rc = 0; - task[i].tasktype = tasktype; - break; - } - } + ptimer = PAUSETIME; - ptimer = PAUSETIME; - - if (opts) - Syslog('+', "Launch: task %d \"%s %s\" success, pid=%d", i, cmd, opts, pid); - else - Syslog('+', "Launch: task %d \"%s\" success, pid=%d", i, cmd, pid); - return pid; + if (opts) + Syslog('+', "Launch: task %d \"%s %s\" success, pid=%d", i, cmd, opts, pid); + else + Syslog('+', "Launch: task %d \"%s\" success, pid=%d", i, cmd, pid); + return pid; } @@ -649,12 +651,13 @@ int checktasks(int onsig) void die(int onsig) { - int i, count; + int i, count; + T_Shutdown = TRUE; signal(onsig, SIG_IGN); - if (onsig == SIGTERM) { - Syslog('+', "Starting normal shutdown"); - T_Shutdown = TRUE; + + if ((onsig == SIGTERM) || (nodaemon && (onsig == SIGINT))) { + Syslog('+', "Starting normal shutdown (%s)", SigName[onsig]); } else { Syslog('+', "Abnormal shutdown on signal %s", SigName[onsig]); } @@ -686,13 +689,28 @@ void die(int onsig) } } + if (cmd_run || ping_run) + Syslog('+', "Waiting for threads to stop"); + + while (cmd_run || ping_run) { + sleep(1); + } + if ((count = checktasks(0))) Syslog('?', "Shutdown with %d tasks still running", count); else Syslog('+', "Good, no more tasks running"); + /* + * Free memory + */ deinitnl(); ulocktask(); + printable(NULL, 0); + + /* + * Close socket + */ if (sock != -1) close(sock); if (ping_isocket != -1) @@ -700,6 +718,7 @@ void die(int onsig) if (!file_exist(spath, R_OK)) { unlink(spath); } + Syslog(' ', "MBTASK finished"); exit(onsig); } @@ -797,6 +816,7 @@ void ulocktask(void) free(lockfile); return; } + if (fscanf(fp, "%u", &oldpid) != 1) { WriteError("$Can't read old pid from \"%s\"", lockfile); fclose(fp); @@ -805,6 +825,8 @@ void ulocktask(void) return; } + fclose(fp); + if (oldpid == getpid()) { (void)unlink(lockfile); } @@ -877,16 +899,15 @@ void check_sema(void) void scheduler(void) { struct passwd *pw; - int running = 0, rc, i, rlen, found; + int running = 0, i, found; static int LOADhi = FALSE, oldmin = 70, olddo = 70, oldsec = 70; char *cmd = NULL, opts[41], port[21]; - static char doing[32], buf[2048]; + static char doing[32]; time_t now; struct tm *tm, *utm; #if defined(__linux__) FILE *fp; #endif - struct pollfd pfd; int call_work = 0; static int call_entry = MAXTASKS; double loadavg[3]; @@ -949,43 +970,16 @@ void scheduler(void) } /* - * Install ping thread + * Install threads */ thr_id[0] = pthread_create(&p_thread[0], NULL, (void (*))ping_thread, NULL); + thr_id[1] = pthread_create(&p_thread[1], NULL, (void (*))cmd_thread, NULL); /* * Enter the mainloop (forever) */ do { - /* - * Poll UNIX Datagram socket until the defined timeout of one second. - * This means we listen of a MBSE BBS client program has something - * to tell. - */ - pfd.fd = sock; - pfd.events = POLLIN | POLLPRI; - pfd.revents = 0; - rc = poll(&pfd, 1, 1000); - if (rc == -1) { - /* - * Poll can be interrupted by a finished child so that's not a real error. - */ - if (errno != EINTR) { - Syslog('?', "$poll() rc=%d sock=%d, events=%04x", rc, sock, pfd.revents); - } - } else if (rc) { - if (pfd.revents & POLLIN) { - /* - * Process the clients request - */ - memset(&buf, 0, sizeof(buf)); - fromlen = sizeof(from); - rlen = recvfrom(sock, buf, sizeof(buf) -1, 0, (struct sockaddr *)&from, &fromlen); - do_cmd(buf); - } else { - Syslog('-', "Return poll rc=%d, events=%04x", rc, pfd.revents); - } - } + sleep(1); /* * Check all registered connections and semafore's @@ -1323,12 +1317,19 @@ int main(int argc, char **argv) for (i = 0; i < NSIG; i++) { if ((i == SIGHUP) || (i == SIGINT) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV) || (i == SIGTERM)) signal(i, (void (*))die); - else + else if ((i != SIGKILL) && (i != SIGSTOP)) signal(i, SIG_IGN); } init_pingsocket(); + /* + * Secret undocumented startup switch, ie: no help available. + */ + if ((argc == 2) && (strcmp(argv[1], "-nd") == 0)) { + nodaemon = TRUE; + } + /* * mbtask is setuid root, drop privileges to user mbse. * This will stay forever like this, no need to become @@ -1341,11 +1342,18 @@ int main(int argc, char **argv) close(ping_isocket); exit(MBERR_INIT_ERROR); } + + /* + * If running in the foreground under valgrind the next call fails. + * Developers should know what they are doing so we are not bailing out. + */ if (setgid(pw->pw_gid)) { perror(""); fprintf(stderr, "can't setgid to bbs\n"); - close(ping_isocket); - exit(MBERR_INIT_ERROR); + if (! nodaemon) { + close(ping_isocket); + exit(MBERR_INIT_ERROR); + } } umask(007); @@ -1360,6 +1368,9 @@ int main(int argc, char **argv) mypid = getpid(); Syslog(' ', " "); Syslog(' ', "MBTASK v%s", VERSION); + if (nodaemon) + Syslog('+', "Starting in no-daemon mode"); + sprintf(tcfgfn, "%s/etc/task.data", getenv("MBSE_ROOT")); load_taskcfg(); status_init(); @@ -1381,63 +1392,71 @@ int main(int argc, char **argv) if (!file_exist(spath, R_OK)) unlink(spath); - /* - * Server initialization is complete. Now we can fork the - * daemon and return to the user. We need to do a setpgrp - * so that the daemon will no longer be assosiated with the - * users control terminal. This is done before the fork, so - * that the child will not be a process group leader. Otherwise, - * if the child were to open a terminal, it would become - * associated with that terminal as its control terminal. - */ - if ((pgrp = setpgid(0, 0)) == -1) { - Syslog('?', "$setpgid failed"); - die(MBERR_INIT_ERROR); - } + if (nodaemon) { + /* + * For debugging, run in foreground mode + */ + mypid = getpid(); + scheduler(); + } else { + /* + * Server initialization is complete. Now we can fork the + * daemon and return to the user. We need to do a setpgrp + * so that the daemon will no longer be assosiated with the + * users control terminal. This is done before the fork, so + * that the child will not be a process group leader. Otherwise, + * if the child were to open a terminal, it would become + * associated with that terminal as its control terminal. + */ + if ((pgrp = setpgid(0, 0)) == -1) { + Syslog('?', "$setpgid failed"); + die(MBERR_INIT_ERROR); + } - frk = fork(); - switch (frk) { - case -1: - Syslog('?', "$Unable to fork daemon"); - die(MBERR_INIT_ERROR); - case 0: - /* - * Starting the deamon child process here. - */ - fclose(stdin); - if (open("/dev/null", O_RDONLY) != 0) { - Syslog('?', "$Reopen of stdin to /dev/null failed"); - _exit(MBERR_EXEC_FAILED); - } - fclose(stdout); - if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) { - Syslog('?', "$Reopen of stdout to /dev/null failed"); - _exit(MBERR_EXEC_FAILED); - } - fclose(stderr); - if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) { - Syslog('?', "$Reopen of stderr to /dev/null failed"); - _exit(MBERR_EXEC_FAILED); - } - mypid = getpid(); - scheduler(); - /* Not reached */ - default: - /* - * Here we detach this process and let the child - * run the deamon process. Put the child's pid - * in the lockfile before leaving. - */ - lockfile = calloc(PATH_MAX, sizeof(char)); - sprintf(lockfile, "%s/var/run/mbtask", pw->pw_dir); - if ((fp = fopen(lockfile, "w"))) { - fprintf(fp, "%10u\n", frk); - fclose(fp); - } - free(lockfile); - Syslog('+', "Starting daemon with pid %d", frk); - pthread_exit(NULL); - exit(MBERR_OK); + frk = fork(); + switch (frk) { + case -1: + Syslog('?', "$Unable to fork daemon"); + die(MBERR_INIT_ERROR); + case 0: + /* + * Starting the deamon child process here. + */ + fclose(stdin); + if (open("/dev/null", O_RDONLY) != 0) { + Syslog('?', "$Reopen of stdin to /dev/null failed"); + _exit(MBERR_EXEC_FAILED); + } + fclose(stdout); + if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) { + Syslog('?', "$Reopen of stdout to /dev/null failed"); + _exit(MBERR_EXEC_FAILED); + } + fclose(stderr); + if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) { + Syslog('?', "$Reopen of stderr to /dev/null failed"); + _exit(MBERR_EXEC_FAILED); + } + mypid = getpid(); + scheduler(); + /* Not reached */ + default: + /* + * Here we detach this process and let the child + * run the deamon process. Put the child's pid + * in the lockfile before leaving. + */ + lockfile = calloc(PATH_MAX, sizeof(char)); + sprintf(lockfile, "%s/var/run/mbtask", pw->pw_dir); + if ((fp = fopen(lockfile, "w"))) { + fprintf(fp, "%10u\n", frk); + fclose(fp); + } + free(lockfile); + Syslog('+', "Starting daemon with pid %d", frk); + pthread_exit(NULL); + exit(MBERR_OK); + } } /* diff --git a/mbtask/outstat.c b/mbtask/outstat.c index b33d0ba6..4bea01e0 100644 --- a/mbtask/outstat.c +++ b/mbtask/outstat.c @@ -620,6 +620,9 @@ int each(faddr *addr, char flavor, int isflo, char *fname) sprintf((*tmp)->addr.domain, "%s", addr->domain); if (nlent->addr.domain) free(nlent->addr.domain); + if (nlent->url) + free(nlent->url); + nlent->url = NULL; (*tmp)->flavors = 0; if (nlent->pflag != NL_DUMMY) { (*tmp)->olflags = nlent->oflags; diff --git a/mbtask/ping.c b/mbtask/ping.c index a159a78e..116b9daa 100644 --- a/mbtask/ping.c +++ b/mbtask/ping.c @@ -48,6 +48,7 @@ extern int internet; /* Internet is down */ extern int rescan; /* Master rescan flag */ struct in_addr paddr; /* Current ping address */ extern int T_Shutdown; /* Program shutdown */ +int ping_run = FALSE; /* Thread runnning */ @@ -244,7 +245,7 @@ int ping_send(struct in_addr addr) int ping_receive(struct in_addr addr) { char buf[1024]; - int len; + int rc, len; struct sockaddr_in ffrom; struct icmphdr icmpp; struct iphdr iph; @@ -253,15 +254,17 @@ int ping_receive(struct in_addr addr) pfd.fd = ping_isocket; pfd.events = POLLIN; + pfd.revents = 0; /* * 100 mSec is enough, this function is called at regular intervals. */ - if (poll(&pfd, 1, 100) < 0) { + if ((rc = poll(&pfd, 1, 100) < 0)) { if (icmp_errs < ICMP_MAX_ERRS) Syslog('?', "$poll/select failed"); return -3; } +// Syslog('p', "poll_thread: poll interrupted rc=%d events=%04x", rc, pfd.revents); if (pfd.revents & POLLIN || pfd.revents & POLLERR || pfd.revents & POLLHUP || pfd.revents & POLLNVAL) { sl = sizeof(ffrom); @@ -339,6 +342,7 @@ void *ping_thread(void) pingresult[1] = pingresult[2] = FALSE; pingnr = 2; internet = FALSE; + ping_run = TRUE; while (! T_Shutdown) { @@ -438,6 +442,7 @@ void *ping_thread(void) } } + ping_run = FALSE; Syslog('+', "Ping thread stopped"); pthread_exit(NULL); } diff --git a/mbtask/ports.c b/mbtask/ports.c index 2ce575ca..bac21b8d 100644 --- a/mbtask/ports.c +++ b/mbtask/ports.c @@ -86,6 +86,7 @@ void fill_portlist(pp_list **fdp, pp_list *new) pp_list *tmp, *ta; tmp = (pp_list *)malloc(sizeof(pp_list)); + memset(tmp, 0, sizeof(tmp)); tmp->next = NULL; strncpy(tmp->tty, new->tty, 6); tmp->mflags = new->mflags; diff --git a/mbtask/taskcomm.c b/mbtask/taskcomm.c index 9cda03f2..a3c6ebb2 100644 --- a/mbtask/taskcomm.c +++ b/mbtask/taskcomm.c @@ -45,6 +45,9 @@ extern int sock; /* Server socket */ extern struct sockaddr_un from; /* From socket address */ extern int fromlen; /* From address length */ extern int logtrans; /* Log transactions */ +extern int T_Shutdown; /* Program shutdown */ +int cmd_run = FALSE;/* cmd running */ + /************************************************************************ @@ -543,6 +546,7 @@ char *exe_cmd(char *in) +void do_cmd(char *); void do_cmd(char *cmd) { char buf[SS_BUFSIZE]; @@ -570,3 +574,55 @@ void do_cmd(char *cmd) } + +/* + * Thread that reads the command socket for new commands. + */ +void *cmd_thread(void) +{ + int rlen, rc; + struct pollfd pfd; + static char buf[2048]; + + Syslog('+', "Starting cmd thread with pid %d", (int)getpid()); + cmd_run = TRUE; + + while (! T_Shutdown) { + /* + * Poll UNIX Datagram socket until the defined timeout of one second. + * This means we listen of a MBSE BBS client program has something + * to tell. + */ + pfd.fd = sock; + pfd.events = POLLIN; + pfd.revents = 0; + rc = poll(&pfd, 1, 1000); +// Syslog('c', "cmd_thread: poll interrupted rc=%d events=%04x", rc, pfd.revents); + if (rc == -1) { + /* + * Poll can be interrupted by a finished child so that's not a real error. + */ +// if (errno != EINTR) { + Syslog('?', "$poll() rc=%d sock=%d, events=%04x", rc, sock, pfd.revents); +// } + } else if (rc) { + if (pfd.revents & POLLIN) { + /* + * Process the clients request + */ + memset(&buf, 0, sizeof(buf)); + fromlen = sizeof(from); + rlen = recvfrom(sock, buf, sizeof(buf) -1, 0, (struct sockaddr *)&from, &fromlen); + do_cmd(buf); + } else { + Syslog('-', "Return poll rc=%d, events=%04x", rc, pfd.revents); + } + } + } + + cmd_run = FALSE; + Syslog('+', "Cmd thread stopped"); + pthread_exit(NULL); +} + + diff --git a/mbtask/taskcomm.h b/mbtask/taskcomm.h index 659eb9df..97d029b3 100644 --- a/mbtask/taskcomm.h +++ b/mbtask/taskcomm.h @@ -3,8 +3,7 @@ /* $Id$ */ - -void do_cmd(char *); +void *cmd_thread(void); #endif diff --git a/mbtask/taskutil.c b/mbtask/taskutil.c index 08af684b..06ffebf9 100644 --- a/mbtask/taskutil.c +++ b/mbtask/taskutil.c @@ -559,10 +559,10 @@ char *printable(char *s, int l) if (len > -l) len=-l; } - pbuff=(char*)xmalloc(len*4+1); + pbuff=(char*)xmalloc(len*3+1); p=pbuff; while (len--) { - if (*(unsigned char*)s >= ' ') + if (isprint(*(unsigned char*)s)) *p++=*s; else switch (*s) { case '\\': *p++='\\'; *p++='\\'; break; @@ -570,7 +570,7 @@ char *printable(char *s, int l) case '\n': *p++='\\'; *p++='n'; break; case '\t': *p++='\\'; *p++='t'; break; case '\b': *p++='\\'; *p++='b'; break; - default: sprintf(p,"\\%03o",*s); p+=4; break; + default: sprintf(p,"\\%02x", (*s & 0xff)); p+=3; break; } s++; }