Annotation of sbbs/src/sbbs3/sbbscon.c, revision 1.1.1.1

1.1       root        1: /* sbbscon.c */
                      2: 
                      3: /* Synchronet vanilla/console-mode "front-end" */
                      4: 
                      5: /* $Id: sbbscon.c,v 1.217 2006/09/20 21:30:56 deuce Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: /* ANSI headers */
                     39: #include <stdio.h>
                     40: #include <string.h>
                     41: #include <signal.h>
                     42: #include <ctype.h>
                     43: #ifdef __QNX__
                     44: #include <locale.h>
                     45: #endif
                     46: 
                     47: /* Synchronet-specific headers */
                     48: #undef SBBS    /* this shouldn't be defined unless building sbbs.dll/libsbbs.so */
                     49: #include "sbbs.h"              /* load_cfg() */
                     50: #include "sbbs_ini.h"  /* sbbs_read_ini() */
                     51: #include "ftpsrvr.h"   /* ftp_startup_t, ftp_server */
                     52: #include "mailsrvr.h"  /* mail_startup_t, mail_server */
                     53: #include "services.h"  /* services_startup_t, services_thread */
                     54: 
                     55: /* XPDEV headers */
                     56: #include "conwrap.h"   /* kbhit/getch */
                     57: #include "threadwrap.h"        /* pthread_mutex_t */
                     58: 
                     59: #ifdef __unix__
                     60: 
                     61: #include <sys/types.h>
                     62: #include <unistd.h>
                     63: #include <pwd.h>
                     64: #include <grp.h>
                     65: #include <stdarg.h>
                     66: #include <stdlib.h>  /* Is this included from somewhere else? */
                     67: #include <syslog.h>
                     68: 
                     69: #endif
                     70: 
                     71: /* Services doesn't work without JavaScript support */
                     72: #if !defined(JAVASCRIPT)
                     73:        #define NO_SERVICES
                     74: #endif
                     75: 
                     76: /* Global variables */
                     77: BOOL                           terminated=FALSE;
                     78: 
                     79: BOOL                           run_bbs=FALSE;
                     80: BOOL                           bbs_running=FALSE;
                     81: BOOL                           bbs_stopped=FALSE;
                     82: BOOL                           has_bbs=FALSE;
                     83: bbs_startup_t          bbs_startup;
                     84: BOOL                           run_ftp=FALSE;
                     85: BOOL                           ftp_running=FALSE;
                     86: BOOL                           ftp_stopped=FALSE;
                     87: BOOL                           has_ftp=FALSE;
                     88: ftp_startup_t          ftp_startup;
                     89: BOOL                           run_mail=FALSE;
                     90: BOOL                           mail_running=FALSE;
                     91: BOOL                           mail_stopped=FALSE;
                     92: BOOL                           has_mail=FALSE;
                     93: mail_startup_t         mail_startup;
                     94: BOOL                           run_services=FALSE;
                     95: BOOL                           services_running=FALSE;
                     96: BOOL                           services_stopped=FALSE;
                     97: BOOL                           has_services=FALSE;
                     98: services_startup_t     services_startup;
                     99: BOOL                           run_web=FALSE;
                    100: BOOL                           web_running=FALSE;
                    101: BOOL                           web_stopped=FALSE;
                    102: BOOL                           has_web=FALSE;
                    103: web_startup_t          web_startup;
                    104: uint                           thread_count=1;
                    105: uint                           socket_count=0;
                    106: uint                           client_count=0;
                    107: int                                    prompt_len=0;
                    108: static scfg_t          scfg;                                   /* To allow rerun */
                    109: static ulong           served=0;
                    110: char                           ini_file[MAX_PATH+1];
                    111: 
                    112: #ifdef __unix__
                    113: char                           new_uid_name[32];
                    114: char                           new_gid_name[32];
                    115: uid_t                          new_uid;
                    116: uid_t                          old_uid;
                    117: gid_t                          new_gid;
                    118: gid_t                          old_gid;
                    119: BOOL                           is_daemon=FALSE;
                    120: char                           log_facility[2];
                    121: char                           log_ident[128];
                    122: BOOL                           std_facilities=FALSE;
                    123: FILE *                         pidf;
                    124: char                           pid_fname[MAX_PATH+1];
                    125: #endif
                    126: 
                    127: static const char* prompt;
                    128: 
                    129: static const char* usage  = "\nusage: %s [[setting] [...]] [path/ini_file]\n"
                    130:                                                        "\n"
                    131:                                                        "Global settings:\n"
                    132:                                                        "\n"
                    133:                                                        "\thn[host]   set hostname for this instance\n"
                    134:                                                        "\t           if host not specified, uses gethostname\n"
                    135: #ifdef __unix__
                    136:                                                        "\tun<user>   set username for BBS to run as\n"
                    137:                                                        "\tug<group>  set group for BBS to run as\n"
                    138:                                                        "\td[x]       run as daemon, log using syslog\n"
                    139:                                                        "\t           x is the optional LOCALx facility to use\n"
                    140:                                                        "\t           if none is specified, uses USER\n"
                    141:                                                        "\t           if 'S' is specified, uses standard facilities\n"
                    142: #endif
                    143:                                                        "\tgi         get user identity (using IDENT protocol)\n"
                    144:                                                        "\tnh         disable hostname lookups\n"
                    145:                                                        "\tnj         disable JavaScript support\n"
                    146:                                                        "\tne         disable event thread\n"
                    147:                                                        "\tni         do not read settings from .ini file\n"
                    148: #ifdef __unix__
                    149:                                                        "\tnd         do not read run as daemon - overrides .ini file\n"
                    150: #endif
                    151:                                                        "\tlt         use local timezone (do not force UTC/GMT)\n"
                    152:                                                        "\tdefaults   show default settings and options\n"
                    153:                                                        "\n"
                    154:                                                        ;
                    155: static const char* telnet_usage  = "Telnet server settings:\n\n"
                    156:                                                        "\ttf<node>   set first Telnet node number\n"
                    157:                                                        "\ttl<node>   set last Telnet node number\n"
                    158:                                                        "\ttp<port>   set Telnet server port\n"
                    159:                                                        "\trp<port>   set RLogin server port (and enable RLogin server)\n"
                    160:                                                        "\tr2         use second RLogin name in BSD RLogin\n"
                    161:                                                        "\tto<value>  set Telnet server options value (advanced)\n"
                    162:                                                        "\tta         enable auto-logon via IP address\n"
                    163:                                                        "\ttd         enable Telnet command debug output\n"
                    164:                                                        "\ttc         emabble sysop availability for chat\n"
                    165:                                                        "\ttq         disable QWK events\n"
                    166:                                                        "\tt-         disable Telnet/RLogin server\n"
                    167:                                                        "\n"
                    168:                                                        ;
                    169: static const char* ftp_usage  = "FTP server settings:\n"
                    170:                                                        "\n"
                    171:                                                        "\tfp<port>   set FTP server port\n"
                    172:                                                        "\tfo<value>  set FTP server options value (advanced)\n"
                    173:                                                        "\tf-         disable FTP server\n"
                    174:                                                        "\n"
                    175:                                                        ;
                    176: static const char* mail_usage  = "Mail server settings:\n"
                    177:                                                        "\n"
                    178:                                                        "\tms<port>   set SMTP server port\n"
                    179:                                                        "\tmp<port>   set POP3 server port\n"
                    180:                                                        "\tmr<addr>   set SMTP relay server (and enable SMTP relay)\n"
                    181:                                                        "\tmd<addr>   set DNS server address for MX-record lookups\n"
                    182:                                                        "\tmo<value>  set Mail server options value (advanced)\n"
                    183:                                                        "\tma         allow SMTP relays from authenticated users\n"
                    184:                                                        "\tm-         disable Mail server (entirely)\n"
                    185:                                                        "\tmp-        disable POP3 server\n"
                    186:                                                        "\tms-        disable SendMail thread\n"
                    187:                                                        "\n"
                    188:                                                        ;
                    189: static const char* services_usage  = "Services settings:\n"
                    190:                                                        "\n"
                    191:                                                        "\tso<value>  set Services option value (advanced)\n"
                    192:                                                        "\ts-         disable Services (no services module)\n"
                    193:                                                        "\n"
                    194:                                                        ;
                    195: static const char* web_usage  = "Web server settings:\n"
                    196:                                                        "\n"
                    197:                                                        "\twp<port>   set HTTP server port\n"
                    198:                                                        "\two<value>  set Web server option value (advanced)\n"
                    199:                                                        "\tw-         disable Web server (no services module)\n"
                    200:                                                        "\n"
                    201:                                                        ;
                    202: static int lputs(int level, char *str)
                    203: {
                    204:        static pthread_mutex_t mutex;
                    205:        static BOOL mutex_initialized;
                    206:        char    *p;
                    207: 
                    208: #ifdef __unix__
                    209: 
                    210:        if (is_daemon)  {
                    211:                if(str!=NULL) {
                    212:                        if (std_facilities)
                    213:                                syslog(level|LOG_AUTH,"%s",str);
                    214:                        else
                    215:                                syslog(level,"%s",str);
                    216:                }
                    217:                return(0);
                    218:        }
                    219: #endif
                    220:        if(!mutex_initialized) {
                    221:                pthread_mutex_init(&mutex,NULL);
                    222:                mutex_initialized=TRUE;
                    223:        }
                    224:        pthread_mutex_lock(&mutex);
                    225:        /* erase prompt */
                    226:        printf("\r%*s\r",prompt_len,"");
                    227:        if(str!=NULL) {
                    228:                for(p=str; *p; p++) {
                    229:                        if(iscntrl(*p))
                    230:                                printf("^%c",'@'+*p);
                    231:                        else
                    232:                                printf("%c",*p);
                    233:                }
                    234:                puts("");
                    235:        }
                    236:        /* re-display prompt with current stats */
                    237:        if(prompt!=NULL)
                    238:                prompt_len = printf(prompt, thread_count, socket_count, client_count, served);
                    239:        fflush(stdout);
                    240:        pthread_mutex_unlock(&mutex);
                    241: 
                    242:     return(prompt_len);
                    243: }
                    244: 
                    245: static int lprintf(int level, char *fmt, ...)
                    246: {
                    247:        va_list argptr;
                    248:        char sbuf[1024];
                    249: 
                    250:     va_start(argptr,fmt);
                    251:     vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
                    252:        sbuf[sizeof(sbuf)-1]=0;
                    253:     va_end(argptr);
                    254:     return(lputs(level,sbuf));
                    255: }
                    256: 
                    257: #ifdef __unix__
                    258: static pthread_mutex_t setid_mutex;
                    259: static BOOL setid_mutex_initialized=0;
                    260: /**********************************************************
                    261: * Change uid of the calling process to the user if specified
                    262: * **********************************************************/
                    263: static BOOL do_seteuid(BOOL to_new) 
                    264: {
                    265:        BOOL    result=FALSE;
                    266: 
                    267:        if(new_uid_name[0]==0)  /* not set? */
                    268:                return(TRUE);           /* do nothing */
                    269: 
                    270:        if(old_uid==new_uid && old_gid==new_gid)
                    271:                return(TRUE);           /* do nothing */
                    272: 
                    273:        if(!setid_mutex_initialized) {
                    274:                pthread_mutex_init(&setid_mutex,NULL);
                    275:                setid_mutex_initialized=TRUE;
                    276:        }
                    277: 
                    278:        pthread_mutex_lock(&setid_mutex);
                    279: 
                    280:        if(to_new) {
                    281:                if((new_gid==getegid() || setregid(-1,new_gid)==0)
                    282:                                && (new_uid==geteuid() || setreuid(-1,new_uid)==0))
                    283:                        result=TRUE;
                    284:                else
                    285:                        result=FALSE;
                    286:        }
                    287:        else {
                    288:                if((old_gid==getegid() || setregid(-1,old_gid)==0)
                    289:                                && (old_uid==geteuid() || setreuid(-1,old_uid)==0))
                    290:                        result=TRUE;
                    291:                else
                    292:                        result=FALSE;
                    293:        }
                    294: 
                    295:        pthread_mutex_unlock(&setid_mutex);
                    296: 
                    297:        if(!result) {
                    298:                lputs(LOG_ERR,"!seteuid FAILED");
                    299:                lputs(LOG_ERR,strerror(errno));
                    300:        }
                    301:        return result;
                    302: }
                    303: 
                    304: /**********************************************************
                    305: * Change uid of the calling process to the user if specified
                    306: * **********************************************************/
                    307: BOOL do_setuid(BOOL force)
                    308: {
                    309:        BOOL result=TRUE;
                    310: #if defined(DONT_BLAME_SYNCHRONET)
                    311:        if(!force)
                    312:                return(do_seteuid(TRUE));
                    313: #endif
                    314: 
                    315: #if defined(_THREAD_SUID_BROKEN)
                    316:        if(thread_suid_broken && (!force))
                    317:                return(do_seteuid(TRUE));
                    318: #endif
                    319: 
                    320:        if(old_uid==new_uid && old_gid==new_gid)
                    321:                return(TRUE);           /* do nothing */
                    322: 
                    323:        if(!setid_mutex_initialized) {
                    324:                pthread_mutex_init(&setid_mutex,NULL);
                    325:                setid_mutex_initialized=TRUE;
                    326:        }
                    327: 
                    328:        pthread_mutex_lock(&setid_mutex);
                    329: 
                    330:        if(getegid()!=old_gid)
                    331:                setregid(-1,old_gid);
                    332:        if(geteuid()!=old_gid)
                    333:                setreuid(-1,old_uid);
                    334:        if(getgid() != new_gid || getegid() != new_gid) {
                    335:                if(setregid(new_gid,new_gid))
                    336:                {
                    337:                        lputs(LOG_ERR,"!setgid FAILED");
                    338:                        lputs(LOG_ERR,strerror(errno));
                    339:                        result=FALSE;
                    340:                }
                    341:        }
                    342: 
                    343:        if(getuid() != new_uid || geteuid() != new_uid) {
                    344:                if(setreuid(new_uid,new_uid))
                    345:                {
                    346:                        lputs(LOG_ERR,"!setuid FAILED");
                    347:                        lputs(LOG_ERR,strerror(errno));
                    348:                        result=FALSE;
                    349:                }
                    350:        }
                    351: 
                    352:        pthread_mutex_unlock(&setid_mutex);
                    353: 
                    354:        if(force && (!result))
                    355:                exit(1);
                    356: 
                    357:        return(result);
                    358: }
                    359: #endif   /* __unix__ */
                    360: 
                    361: #ifdef _WINSOCKAPI_
                    362: 
                    363: static WSADATA WSAData;
                    364: 
                    365: static BOOL winsock_startup(void)
                    366: {
                    367:        int             status;             /* Status Code */
                    368: 
                    369:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0)
                    370:                return(TRUE);
                    371: 
                    372:     lprintf(LOG_ERR,"!WinSock startup ERROR %d", status);
                    373:        return(FALSE);
                    374: }
                    375: 
                    376: static BOOL winsock_cleanup(void)      
                    377: {
                    378:        if(WSACleanup()==0)
                    379:                return(TRUE);
                    380: 
                    381:        lprintf(LOG_ERR,"!WinSock cleanup ERROR %d",ERROR_VALUE);
                    382:        return(FALSE);
                    383: }
                    384: 
                    385: #else /* No WINSOCK */
                    386: 
                    387: #define winsock_startup()      (TRUE)  
                    388: #define winsock_cleanup()      (TRUE)
                    389: 
                    390: #endif
                    391: 
                    392: static void thread_up(void* p, BOOL up, BOOL setuid)
                    393: {
                    394:        static pthread_mutex_t mutex;
                    395:        static BOOL mutex_initialized;
                    396: 
                    397: #ifdef _THREAD_SUID_BROKEN
                    398:        if(thread_suid_broken && up && setuid) {
                    399:                do_seteuid(FALSE);
                    400:                do_setuid(FALSE);
                    401:        }
                    402: #endif
                    403: 
                    404:        if(!mutex_initialized) {
                    405:                pthread_mutex_init(&mutex,NULL);
                    406:                mutex_initialized=TRUE;
                    407:        }
                    408: 
                    409:        pthread_mutex_lock(&mutex);
                    410: 
                    411:        if(up)
                    412:            thread_count++;
                    413:     else if(thread_count>0)
                    414:        thread_count--;
                    415:        pthread_mutex_unlock(&mutex);
                    416:        lputs(LOG_INFO,NULL); /* update displayed stats */
                    417: }
                    418: 
                    419: static void socket_open(void* p, BOOL open)
                    420: {
                    421:        static pthread_mutex_t mutex;
                    422:        static BOOL mutex_initialized;
                    423: 
                    424:        if(!mutex_initialized) {
                    425:                pthread_mutex_init(&mutex,NULL);
                    426:                mutex_initialized=TRUE;
                    427:        }
                    428: 
                    429:        pthread_mutex_lock(&mutex);
                    430:        if(open)
                    431:            socket_count++;
                    432:     else if(socket_count>0)
                    433:        socket_count--;
                    434:        pthread_mutex_unlock(&mutex);
                    435:        lputs(LOG_INFO,NULL); /* update displayed stats */
                    436: }
                    437: 
                    438: static void client_on(void* p, BOOL on, int sock, client_t* client, BOOL update)
                    439: {
                    440:        static pthread_mutex_t mutex;
                    441:        static BOOL mutex_initialized;
                    442: 
                    443:        if(!mutex_initialized) {
                    444:                pthread_mutex_init(&mutex,NULL);
                    445:                mutex_initialized=TRUE;
                    446:        }
                    447: 
                    448:        pthread_mutex_lock(&mutex);
                    449:        if(on && !update) {
                    450:                client_count++;
                    451:            served++;
                    452:        } else if(!on && client_count>0)
                    453:                client_count--;
                    454:        pthread_mutex_unlock(&mutex);
                    455:        lputs(LOG_INFO,NULL); /* update displayed stats */
                    456: }
                    457: 
                    458: /****************************************************************************/
                    459: /* BBS local/log print routine                                                                                         */
                    460: /****************************************************************************/
                    461: static int bbs_lputs(void* p, int level, char *str)
                    462: {
                    463:        char            logline[512];
                    464:        char            tstr[64];
                    465:        time_t          t;
                    466:        struct tm       tm;
                    467: 
                    468:        if(level > bbs_startup.log_level)
                    469:                return(0);
                    470: 
                    471: #ifdef __unix__
                    472:        if (is_daemon)  {
                    473:                if(str==NULL)
                    474:                        return(0);
                    475:                if (std_facilities)
                    476:                        syslog(level|LOG_AUTH,"%s",str);
                    477:                else
                    478:                        syslog(level,"     %s",str);
                    479:                return(strlen(str));
                    480:        }
                    481: #endif
                    482: 
                    483:        t=time(NULL);
                    484:        if(localtime_r(&t,&tm)==NULL)
                    485:                tstr[0]=0;
                    486:        else
                    487:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    488:                        ,tm.tm_mon+1,tm.tm_mday
                    489:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    490: 
                    491:        sprintf(logline,"%s     %.*s",tstr,(int)sizeof(logline)-32,str);
                    492:        truncsp(logline);
                    493:        lputs(level,logline);
                    494:        
                    495:     return(strlen(logline)+1);
                    496: }
                    497: 
                    498: static void bbs_started(void* p)
                    499: {
                    500:        bbs_running=TRUE;
                    501:        bbs_stopped=FALSE;
                    502:        #ifdef _THREAD_SUID_BROKEN
                    503:                if(thread_suid_broken) {
                    504:                do_seteuid(FALSE);
                    505:                do_setuid(FALSE);
                    506:                }
                    507:        #endif
                    508: }
                    509: 
                    510: static void bbs_terminated(void* p, int code)
                    511: {
                    512:        bbs_running=FALSE;
                    513:        bbs_stopped=TRUE;
                    514: }
                    515: 
                    516: /****************************************************************************/
                    517: /* FTP local/log print routine                                                                                         */
                    518: /****************************************************************************/
                    519: static int ftp_lputs(void* p, int level, char *str)
                    520: {
                    521:        char            logline[512];
                    522:        char            tstr[64];
                    523:        time_t          t;
                    524:        struct tm       tm;
                    525: 
                    526:        if(level > ftp_startup.log_level)
                    527:                return(0);
                    528: 
                    529: #ifdef __unix__
                    530:        if (is_daemon)  {
                    531:                if(str==NULL)
                    532:                        return(0);
                    533:                if (std_facilities)
                    534: #ifdef __solaris__
                    535:                        syslog(level|LOG_DAEMON,"%s",str);
                    536: #else
                    537:                        syslog(level|LOG_FTP,"%s",str);
                    538: #endif
                    539:                else
                    540:                        syslog(level,"ftp  %s",str);
                    541:                return(strlen(str));
                    542:        }
                    543: #endif
                    544: 
                    545:        t=time(NULL);
                    546:        if(localtime_r(&t,&tm)==NULL)
                    547:                tstr[0]=0;
                    548:        else
                    549:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    550:                        ,tm.tm_mon+1,tm.tm_mday
                    551:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    552: 
                    553:        sprintf(logline,"%sftp  %.*s",tstr,(int)sizeof(logline)-32,str);
                    554:        truncsp(logline);
                    555:        lputs(level,logline);
                    556:        
                    557:     return(strlen(logline)+1);
                    558: }
                    559: 
                    560: static void ftp_started(void* p)
                    561: {
                    562:        ftp_running=TRUE;
                    563:        ftp_stopped=FALSE;
                    564:        #ifdef _THREAD_SUID_BROKEN
                    565:                if(thread_suid_broken) {
                    566:                do_seteuid(FALSE);
                    567:                do_setuid(FALSE);
                    568:                }
                    569:        #endif
                    570: }
                    571: 
                    572: static void ftp_terminated(void* p, int code)
                    573: {
                    574:        ftp_running=FALSE;
                    575:        ftp_stopped=TRUE;
                    576: }
                    577: 
                    578: /****************************************************************************/
                    579: /* Mail Server local/log print routine                                                                         */
                    580: /****************************************************************************/
                    581: static int mail_lputs(void* p, int level, char *str)
                    582: {
                    583:        char            logline[512];
                    584:        char            tstr[64];
                    585:        time_t          t;
                    586:        struct tm       tm;
                    587: 
                    588:        if(level > mail_startup.log_level)
                    589:                return(0);
                    590: 
                    591: #ifdef __unix__
                    592:        if (is_daemon)  {
                    593:                if(str==NULL)
                    594:                        return(0);
                    595:                if (std_facilities)
                    596:                        syslog(level|LOG_MAIL,"%s",str);
                    597:                else
                    598:                        syslog(level,"mail %s",str);
                    599:                return(strlen(str));
                    600:        }
                    601: #endif
                    602: 
                    603:        t=time(NULL);
                    604:        if(localtime_r(&t,&tm)==NULL)
                    605:                tstr[0]=0;
                    606:        else
                    607:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    608:                        ,tm.tm_mon+1,tm.tm_mday
                    609:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    610: 
                    611:        sprintf(logline,"%smail %.*s",tstr,(int)sizeof(logline)-32,str);
                    612:        truncsp(logline);
                    613:        lputs(level,logline);
                    614:        
                    615:     return(strlen(logline)+1);
                    616: }
                    617: 
                    618: static void mail_started(void* p)
                    619: {
                    620:        mail_running=TRUE;
                    621:        mail_stopped=FALSE;
                    622:        #ifdef _THREAD_SUID_BROKEN
                    623:                if(thread_suid_broken) {
                    624:                do_seteuid(FALSE);
                    625:                do_setuid(FALSE);
                    626:                }
                    627:        #endif
                    628: }
                    629: 
                    630: static void mail_terminated(void* p, int code)
                    631: {
                    632:        mail_running=FALSE;
                    633:        mail_stopped=TRUE;
                    634: }
                    635: 
                    636: /****************************************************************************/
                    637: /* Services local/log print routine                                                                                    */
                    638: /****************************************************************************/
                    639: static int services_lputs(void* p, int level, char *str)
                    640: {
                    641:        char            logline[512];
                    642:        char            tstr[64];
                    643:        time_t          t;
                    644:        struct tm       tm;
                    645: 
                    646:        if(level > services_startup.log_level)
                    647:                return(0);
                    648: 
                    649: #ifdef __unix__
                    650:        if (is_daemon)  {
                    651:                if(str==NULL)
                    652:                        return(0);
                    653:                if (std_facilities)
                    654:                        syslog(level|LOG_DAEMON,"%s",str);
                    655:                else
                    656:                        syslog(level,"srvc %s",str);
                    657:                return(strlen(str));
                    658:        }
                    659: #endif
                    660: 
                    661:        t=time(NULL);
                    662:        if(localtime_r(&t,&tm)==NULL)
                    663:                tstr[0]=0;
                    664:        else
                    665:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    666:                        ,tm.tm_mon+1,tm.tm_mday
                    667:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    668: 
                    669:        sprintf(logline,"%ssrvc %.*s",tstr,(int)sizeof(logline)-32,str);
                    670:        truncsp(logline);
                    671:        lputs(level,logline);
                    672:        
                    673:     return(strlen(logline)+1);
                    674: }
                    675: 
                    676: static void services_started(void* p)
                    677: {
                    678:        services_running=TRUE;
                    679:        services_stopped=FALSE;
                    680:        #ifdef _THREAD_SUID_BROKEN
                    681:                if(thread_suid_broken) {
                    682:                do_seteuid(FALSE);
                    683:                do_setuid(FALSE);
                    684:                }
                    685:        #endif
                    686: }
                    687: 
                    688: static void services_terminated(void* p, int code)
                    689: {
                    690:        services_running=FALSE;
                    691:        services_stopped=TRUE;
                    692: }
                    693: 
                    694: /****************************************************************************/
                    695: /* Event thread local/log print routine                                                                                */
                    696: /****************************************************************************/
                    697: static int event_lputs(int level, char *str)
                    698: {
                    699:        char            logline[512];
                    700:        char            tstr[64];
                    701:        time_t          t;
                    702:        struct tm       tm;
                    703: 
                    704:        if(level > bbs_startup.log_level)
                    705:                return(0);
                    706: 
                    707: #ifdef __unix__
                    708:        if (is_daemon)  {
                    709:                if(str==NULL)
                    710:                        return(0);
                    711:                if (std_facilities)
                    712:                        syslog(level|LOG_CRON,"%s",str);
                    713:                else
                    714:                        syslog(level,"evnt %s",str);
                    715:                return(strlen(str));
                    716:        }
                    717: #endif
                    718: 
                    719:        t=time(NULL);
                    720:        if(localtime_r(&t,&tm)==NULL)
                    721:                tstr[0]=0;
                    722:        else
                    723:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    724:                        ,tm.tm_mon+1,tm.tm_mday
                    725:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    726: 
                    727:        sprintf(logline,"%sevnt %.*s",tstr,(int)sizeof(logline)-32,str);
                    728:        truncsp(logline);
                    729:        lputs(level,logline);
                    730:        
                    731:     return(strlen(logline)+1);
                    732: }
                    733: 
                    734: /****************************************************************************/
                    735: /* web local/log print routine                                                                                 */
                    736: /****************************************************************************/
                    737: static int web_lputs(void* p, int level, char *str)
                    738: {
                    739:        char            logline[512];
                    740:        char            tstr[64];
                    741:        time_t          t;
                    742:        struct tm       tm;
                    743: 
                    744:        if(level > web_startup.log_level)
                    745:                return(0);
                    746: 
                    747: #ifdef __unix__
                    748:        if (is_daemon)  {
                    749:                if(str==NULL)
                    750:                        return(0);
                    751:                if (std_facilities)
                    752:                        syslog(level|LOG_DAEMON,"%s",str);
                    753:                else
                    754:                        syslog(level,"web  %s",str);
                    755:                return(strlen(str));
                    756:        }
                    757: #endif
                    758: 
                    759:        t=time(NULL);
                    760:        if(localtime_r(&t,&tm)==NULL)
                    761:                tstr[0]=0;
                    762:        else
                    763:                sprintf(tstr,"%d/%d %02d:%02d:%02d "
                    764:                        ,tm.tm_mon+1,tm.tm_mday
                    765:                        ,tm.tm_hour,tm.tm_min,tm.tm_sec);
                    766: 
                    767:        sprintf(logline,"%sweb  %.*s",tstr,(int)sizeof(logline)-32,str);
                    768:        truncsp(logline);
                    769:        lputs(level,logline);
                    770:        
                    771:     return(strlen(logline)+1);
                    772: }
                    773: 
                    774: static void web_started(void* p)
                    775: {
                    776:        web_running=TRUE;
                    777:        web_stopped=FALSE;
                    778:        #ifdef _THREAD_SUID_BROKEN
                    779:                if(thread_suid_broken) {
                    780:                do_seteuid(FALSE);
                    781:                do_setuid(FALSE);
                    782:                }
                    783:        #endif
                    784: }
                    785: 
                    786: static void web_terminated(void* p, int code)
                    787: {
                    788:        web_running=FALSE;
                    789:        web_stopped=TRUE;
                    790: }
                    791: 
                    792: static void terminate(void)
                    793: {
                    794:        ulong count=0;
                    795: 
                    796:        if(bbs_running)
                    797:                bbs_terminate();
                    798:        if(ftp_running)
                    799:                ftp_terminate();
                    800: #ifndef NO_WEB_SERVER
                    801:        if(web_running)
                    802:                web_terminate();
                    803: #endif
                    804:        if(mail_running)
                    805:                mail_terminate();
                    806: #ifndef NO_SERVICES
                    807:        if(services_running)
                    808:                services_terminate();
                    809: #endif
                    810: 
                    811:        while(bbs_running || ftp_running || web_running || mail_running || services_running)  {
                    812:                if(count && (count%10)==0) {
                    813:                        if(bbs_running)
                    814:                                lputs(LOG_INFO,"BBS System thread still running");
                    815:                        if(ftp_running)
                    816:                                lputs(LOG_INFO,"FTP Server thread still running");
                    817:                        if(web_running)
                    818:                                lputs(LOG_INFO,"Web Server thread still running");
                    819:                        if(mail_running)
                    820:                                lputs(LOG_INFO,"Mail Server thread still running");
                    821:                        if(services_running)
                    822:                                lputs(LOG_INFO,"Services thread still running");
                    823:                }
                    824:                count++;
                    825:                SLEEP(1000);
                    826:        }
                    827: }
                    828: 
                    829: static void read_startup_ini(BOOL recycle
                    830:                                                         ,bbs_startup_t* bbs, ftp_startup_t* ftp, web_startup_t* web
                    831:                                                         ,mail_startup_t* mail, services_startup_t* services)
                    832: {
                    833:        FILE*   fp=NULL;
                    834: 
                    835:        /* Read .ini file here */
                    836:        if(ini_file[0]!=0) { 
                    837:                if((fp=fopen(ini_file,"r"))==NULL) {
                    838:                        lprintf(LOG_ERR,"!ERROR %d (%s) opening %s",errno,strerror(errno),ini_file);
                    839:                } else {
                    840:                        lprintf(LOG_INFO,"Reading %s",ini_file);
                    841:                }
                    842:        }
                    843:        if(fp==NULL)
                    844:                lputs(LOG_WARNING,"Using default initialization values");
                    845: 
                    846:        /* We call this function to set defaults, even if there's no .ini file */
                    847:        sbbs_read_ini(fp, 
                    848:                NULL,                   /* global_startup */
                    849:                &run_bbs,               bbs,
                    850:                &run_ftp,               ftp, 
                    851:                &run_web,               web,
                    852:                &run_mail,              mail, 
                    853:                &run_services,  services);
                    854: 
                    855:        /* read/default any sbbscon-specific .ini keys here */
                    856: #if defined(__unix__)
                    857:        {
                    858:                char    value[INI_MAX_VALUE_LEN];
                    859:                char*   section="UNIX";
                    860:                SAFECOPY(new_uid_name,iniReadString(fp,section,"User","",value));
                    861:                SAFECOPY(new_gid_name,iniReadString(fp,section,"Group","",value));
                    862:                if(!recycle)
                    863:                        is_daemon=iniReadBool(fp,section,"Daemonize",FALSE);
                    864:                SAFECOPY(log_facility,iniReadString(fp,section,"LogFacility","U",value));
                    865:                SAFECOPY(log_ident,iniReadString(fp,section,"LogIdent","synchronet",value));
                    866:                SAFECOPY(pid_fname,iniReadString(fp,section,"PidFile","/var/run/sbbs.pid",value));
                    867:                umask(iniReadInteger(fp,section,"umask",077));
                    868:        }
                    869: #endif
                    870:        /* close .ini file here */
                    871:        if(fp!=NULL)
                    872:                fclose(fp);
                    873: }
                    874: 
                    875: /* Server recycle callback (read relevant startup .ini file section)           */
                    876: void recycle(void* cbdata)
                    877: {
                    878:        bbs_startup_t* bbs=NULL;
                    879:        ftp_startup_t* ftp=NULL;
                    880:        web_startup_t* web=NULL;
                    881:        mail_startup_t* mail=NULL;
                    882:        services_startup_t* services=NULL;
                    883: 
                    884:        if(cbdata==&bbs_startup)
                    885:                bbs=cbdata;
                    886:        else if(cbdata==&ftp_startup)
                    887:                ftp=cbdata;
                    888:        else if(cbdata==&web_startup)
                    889:                web=cbdata;
                    890:        else if(cbdata==&mail_startup)
                    891:                mail=cbdata;
                    892:        else if(cbdata==&services_startup)
                    893:                services=cbdata;
                    894: 
                    895:        read_startup_ini(/* recycle? */TRUE,bbs,ftp,web,mail,services);
                    896: }
                    897: 
                    898: void cleanup(void)
                    899: {
                    900: #ifdef __unix__
                    901:        unlink(pid_fname);
                    902: #endif
                    903: }
                    904: 
                    905: #if defined(_WIN32)
                    906: BOOL WINAPI ControlHandler(DWORD CtrlType)
                    907: {
                    908:        terminated=TRUE;
                    909:        return TRUE;
                    910: }
                    911: #endif
                    912: 
                    913: 
                    914: #ifdef __unix__
                    915: void _sighandler_quit(int sig)
                    916: {
                    917:        char    str[1024];
                    918:        static pthread_mutex_t mutex;
                    919:        static BOOL mutex_initialized;
                    920: 
                    921:        if(!mutex_initialized) {
                    922:                pthread_mutex_init(&mutex,NULL);
                    923:                mutex_initialized=TRUE;
                    924:        }
                    925:        pthread_mutex_lock(&mutex);
                    926:        /* Can I get away with leaving this locked till exit? */
                    927: 
                    928:        lprintf(LOG_NOTICE,"     Got quit signal (%d)",sig);
                    929:        terminate();
                    930: 
                    931:     exit(0);
                    932: }
                    933: 
                    934: void _sighandler_rerun(int sig)
                    935: {
                    936: 
                    937:        lputs(LOG_NOTICE,"     Got HUP (rerun) signal");
                    938: 
                    939:        bbs_startup.recycle_now=TRUE;
                    940:        ftp_startup.recycle_now=TRUE;
                    941:        web_startup.recycle_now=TRUE;
                    942:        mail_startup.recycle_now=TRUE;
                    943:        services_startup.recycle_now=TRUE;
                    944: }
                    945: 
                    946: static void handle_sigs(void)
                    947: {
                    948:        int                     i;
                    949:        int                     sig=0;
                    950:        sigset_t        sigs;
                    951: 
                    952:        thread_up(NULL,TRUE,TRUE);
                    953: 
                    954:        if (is_daemon) {
                    955:                /* Write the standard .pid file if running as a daemon */
                    956:                /* Must be here so signals are sent to the correct thread */
                    957: 
                    958:                if(pidf!=NULL) {
                    959:                        fprintf(pidf,"%d",getpid());
                    960:                        fclose(pidf);
                    961:                        pidf=NULL;
                    962:                }
                    963:        }
                    964: 
                    965:        /* Set up blocked signals */
                    966:        sigemptyset(&sigs);
                    967:        sigaddset(&sigs,SIGINT);
                    968:        sigaddset(&sigs,SIGQUIT);
                    969:        sigaddset(&sigs,SIGABRT);
                    970:        sigaddset(&sigs,SIGTERM);
                    971:        sigaddset(&sigs,SIGHUP);
                    972:        sigaddset(&sigs,SIGALRM);
                    973:        /* sigaddset(&sigs,SIGPIPE); */
                    974:        pthread_sigmask(SIG_BLOCK,&sigs,NULL);
                    975:        while(1)  {
                    976:                if((i=sigwait(&sigs,&sig))!=0) {   /* wait here until signaled */
                    977:                        lprintf(LOG_ERR,"     !sigwait FAILURE (%d)", i);
                    978:                        continue;
                    979:                }
                    980:                lprintf(LOG_NOTICE,"     Got signal (%d)", sig);
                    981:                switch(sig)  {
                    982:                        /* QUIT-type signals */
                    983:                        case SIGINT:
                    984:                        case SIGQUIT:
                    985:                        case SIGABRT:
                    986:                        case SIGTERM:
                    987:                                _sighandler_quit(sig);
                    988:                                break;
                    989:                        case SIGHUP:    /* rerun */
                    990:                                _sighandler_rerun(sig);
                    991:                                break;
                    992:                        default:
                    993:                                lputs(LOG_NOTICE,"     Signal has no handler (unexpected)");
                    994:                }
                    995:        }
                    996: }
                    997: #endif /* __unix__ */
                    998: 
                    999: /****************************************************************************/
                   1000: /* Displays appropriate usage info                                                                                     */
                   1001: /****************************************************************************/
                   1002: static void show_usage(char *cmd)
                   1003: {
                   1004:        printf(usage,cmd);
                   1005:        if(has_bbs)
                   1006:                printf(telnet_usage);
                   1007:        if(has_ftp)
                   1008:                printf(ftp_usage);
                   1009:        if(has_mail)
                   1010:                printf(mail_usage);
                   1011:        if(has_services)
                   1012:                printf(services_usage);
                   1013:        if(has_web)
                   1014:                printf(web_usage);
                   1015: }
                   1016: 
                   1017: #if SBBS_MAGIC_FILENAMES
                   1018: static int command_is(char *cmdline, char *cmd)
                   1019: {
                   1020:        return(strnicmp(getfname(cmdline),cmd,strlen(cmd))==0);
                   1021: }
                   1022: #endif
                   1023: 
                   1024: /****************************************************************************/
                   1025: /* Main Entry Point                                                                                                                    */
                   1026: /****************************************************************************/
                   1027: int main(int argc, char** argv)
                   1028: {
                   1029:        int             i;
                   1030:        int             n;
                   1031:        int             file;
                   1032:        char    ch;
                   1033:        char*   p;
                   1034:        char*   arg;
                   1035:        char*   ctrl_dir;
                   1036:        char    str[MAX_PATH+1];
                   1037:     char       error[256];
                   1038:        char    host_name[128]="";
                   1039:        node_t  node;
                   1040: #ifdef __unix__
                   1041:        struct passwd*  pw_entry;
                   1042:        struct group*   gr_entry;
                   1043:        sigset_t                sigs;
                   1044: #endif
                   1045: #ifdef _THREAD_SUID_BROKEN
                   1046:        size_t  conflen;
                   1047: #endif
                   1048: 
                   1049: #ifdef __QNX__
                   1050:        setlocale( LC_ALL, "C-TRADITIONAL" );
                   1051: #endif
                   1052: #ifdef __unix__
                   1053:        setsid();       /* Disassociate from controlling terminal */
                   1054:        umask(077);
                   1055: #endif
                   1056:        printf("\nSynchronet Console for %s  Version %s%c  %s\n\n"
                   1057:                ,PLATFORM_DESC,VERSION,REVISION,COPYRIGHT_NOTICE);
                   1058: 
                   1059:        atexit(cleanup);
                   1060: 
                   1061:        ctrl_dir=getenv("SBBSCTRL");    /* read from environment variable */
                   1062:        if(ctrl_dir==NULL || ctrl_dir[0]==0) {
                   1063:                ctrl_dir="/sbbs/ctrl";          /* Not set? Use default */
                   1064:                printf("!SBBSCTRL environment variable not set, using default value: %s\n\n"
                   1065:                        ,ctrl_dir);
                   1066:        }
                   1067: 
                   1068:        if(!winsock_startup())
                   1069:                return(-1);
                   1070: 
                   1071:        gethostname(host_name,sizeof(host_name)-1);
                   1072: 
                   1073:        if(!winsock_cleanup())
                   1074:                return(-1);
                   1075: 
                   1076:        sbbs_get_ini_fname(ini_file, ctrl_dir, host_name);
                   1077: 
                   1078:        /* Initialize BBS startup structure */
                   1079:     memset(&bbs_startup,0,sizeof(bbs_startup));
                   1080:     bbs_startup.size=sizeof(bbs_startup);
                   1081:        bbs_startup.cbdata=&bbs_startup;
                   1082:        bbs_startup.log_level = LOG_DEBUG;
                   1083:        bbs_startup.lputs=bbs_lputs;
                   1084:        bbs_startup.event_lputs=event_lputs;
                   1085:     bbs_startup.started=bbs_started;
                   1086:        bbs_startup.recycle=recycle;
                   1087:     bbs_startup.terminated=bbs_terminated;
                   1088:     bbs_startup.thread_up=thread_up;
                   1089:     bbs_startup.socket_open=socket_open;
                   1090:     bbs_startup.client_on=client_on;
                   1091: #ifdef __unix__
                   1092:        bbs_startup.seteuid=do_seteuid;
                   1093:        bbs_startup.setuid=do_setuid;
                   1094: #endif
                   1095: /*     These callbacks haven't been created yet
                   1096:     bbs_startup.status=bbs_status;
                   1097:     bbs_startup.clients=bbs_clients;
                   1098: */
                   1099:     strcpy(bbs_startup.ctrl_dir,ctrl_dir);
                   1100: 
                   1101:        /* Initialize FTP startup structure */
                   1102:     memset(&ftp_startup,0,sizeof(ftp_startup));
                   1103:     ftp_startup.size=sizeof(ftp_startup);
                   1104:        ftp_startup.cbdata=&ftp_startup;
                   1105:        ftp_startup.log_level = LOG_DEBUG;
                   1106:        ftp_startup.lputs=ftp_lputs;
                   1107:     ftp_startup.started=ftp_started;
                   1108:        ftp_startup.recycle=recycle;
                   1109:     ftp_startup.terminated=ftp_terminated;
                   1110:        ftp_startup.thread_up=thread_up;
                   1111:     ftp_startup.socket_open=socket_open;
                   1112:     ftp_startup.client_on=client_on;
                   1113: #ifdef __unix__
                   1114:        ftp_startup.seteuid=do_seteuid;
                   1115:        ftp_startup.setuid=do_setuid;
                   1116: #endif
                   1117:     strcpy(ftp_startup.index_file_name,"00index");
                   1118:     strcpy(ftp_startup.ctrl_dir,ctrl_dir);
                   1119: 
                   1120:        /* Initialize Web Server startup structure */
                   1121:     memset(&web_startup,0,sizeof(web_startup));
                   1122:     web_startup.size=sizeof(web_startup);
                   1123:        web_startup.cbdata=&web_startup;
                   1124:        web_startup.log_level = LOG_DEBUG;
                   1125:        web_startup.lputs=web_lputs;
                   1126:     web_startup.started=web_started;
                   1127:        web_startup.recycle=recycle;
                   1128:     web_startup.terminated=web_terminated;
                   1129:        web_startup.thread_up=thread_up;
                   1130:     web_startup.socket_open=socket_open;
                   1131:        web_startup.client_on=client_on;
                   1132: #ifdef __unix__
                   1133:        web_startup.seteuid=do_seteuid;
                   1134:        web_startup.setuid=do_setuid;
                   1135: #endif
                   1136:     strcpy(web_startup.ctrl_dir,ctrl_dir);
                   1137: 
                   1138:        /* Initialize Mail Server startup structure */
                   1139:     memset(&mail_startup,0,sizeof(mail_startup));
                   1140:     mail_startup.size=sizeof(mail_startup);
                   1141:        mail_startup.cbdata=&mail_startup;
                   1142:        mail_startup.log_level = LOG_DEBUG;
                   1143:        mail_startup.lputs=mail_lputs;
                   1144:     mail_startup.started=mail_started;
                   1145:        mail_startup.recycle=recycle;
                   1146:     mail_startup.terminated=mail_terminated;
                   1147:        mail_startup.thread_up=thread_up;
                   1148:     mail_startup.socket_open=socket_open;
                   1149:     mail_startup.client_on=client_on;
                   1150: #ifdef __unix__
                   1151:        mail_startup.seteuid=do_seteuid;
                   1152:        mail_startup.setuid=do_setuid;
                   1153: #endif
                   1154:     strcpy(mail_startup.ctrl_dir,ctrl_dir);
                   1155: 
                   1156:        /* Initialize Services startup structure */
                   1157:     memset(&services_startup,0,sizeof(services_startup));
                   1158:     services_startup.size=sizeof(services_startup);
                   1159:        services_startup.cbdata=&services_startup;
                   1160:        services_startup.log_level = LOG_DEBUG;
                   1161:        services_startup.lputs=services_lputs;
                   1162:     services_startup.started=services_started;
                   1163:        services_startup.recycle=recycle;
                   1164:     services_startup.terminated=services_terminated;
                   1165:        services_startup.thread_up=thread_up;
                   1166:     services_startup.socket_open=socket_open;
                   1167:     services_startup.client_on=client_on;
                   1168: #ifdef __unix__
                   1169:        services_startup.seteuid=do_seteuid;
                   1170:        services_startup.setuid=do_setuid;
                   1171: #endif
                   1172:     strcpy(services_startup.ctrl_dir,ctrl_dir);
                   1173: 
                   1174:        /* Pre-INI command-line switches */
                   1175:        for(i=1;i<argc;i++) {
                   1176:                arg=argv[i];
                   1177:                while(*arg=='-')
                   1178:                        arg++;
                   1179:                if(strcspn(arg,"\\/")!=strlen(arg)) {
                   1180:                        strcpy(ini_file,arg);
                   1181:                        continue;
                   1182:                }
                   1183:                if(!stricmp(arg,"ni")) {
                   1184:                        ini_file[0]=0;
                   1185:                        break;
                   1186:                }
                   1187:        }
                   1188: 
                   1189:        read_startup_ini(/* recycle? */FALSE
                   1190:                ,&bbs_startup, &ftp_startup, &web_startup, &mail_startup, &services_startup);
                   1191: 
                   1192: #if SBBS_MAGIC_FILENAMES       /* This stuff is just broken */
                   1193: 
                   1194:        if(!command_is(argv[0],"sbbs"))  {
                   1195:                run_bbs=has_bbs=FALSE;
                   1196:                run_ftp=has_ftp=FALSE;
                   1197:                run_mail=has_mail=FALSE;
                   1198:                run_services=has_services=FALSE;
                   1199:                run_web=has_web=FALSE;
                   1200:        }
                   1201:        if(command_is(argv[0],"sbbs_ftp"))
                   1202:                run_ftp=has_ftp=TRUE;
                   1203:        else if(command_is(argv[0],"sbbs_mail"))
                   1204:                run_mail=has_mail=TRUE;
                   1205:        else if(command_is(argv[0],"sbbs_bbs"))
                   1206:                run_bbs=has_bbs=TRUE;
                   1207: #ifndef NO_SERVICES
                   1208:        else if(command_is(argv[0],"sbbs_srvc"))
                   1209:                run_services=has_services=TRUE;
                   1210: #endif
                   1211: #ifndef NO_WEB_SERVER
                   1212:        else if(command_is(argv[0],"sbbs_web"))
                   1213:                run_web=has_web=TRUE;
                   1214: #endif
                   1215:        else {
                   1216:                run_bbs=has_bbs=TRUE;
                   1217:                run_ftp=has_ftp=TRUE;
                   1218:                run_mail=has_mail=TRUE;
                   1219: #ifndef NO_SERVICES
                   1220:                run_services=has_services=TRUE;
                   1221: #endif
                   1222: #ifndef NO_WEB_SERVER
                   1223:                run_web=has_web=TRUE;
                   1224: #endif
                   1225:        }
                   1226: #else
                   1227:        has_web=has_bbs=has_ftp=has_mail=has_services=TRUE;
                   1228: #endif /* Removed broken stuff */
                   1229: 
                   1230:        /* Post-INI command-line switches */
                   1231:        for(i=1;i<argc;i++) {
                   1232:                arg=argv[i];
                   1233:                while(*arg=='-')
                   1234:                        arg++;
                   1235:                if(strcspn(arg,"\\/")!=strlen(arg))     /* ini_file name */
                   1236:                        continue;
                   1237:                if(!stricmp(arg,"defaults")) {
                   1238:                        printf("Default settings:\n");
                   1239:                        printf("\n");
                   1240:                        printf("Telnet server port:\t%u\n",bbs_startup.telnet_port);
                   1241:                        printf("Telnet first node:\t%u\n",bbs_startup.first_node);
                   1242:                        printf("Telnet last node:\t%u\n",bbs_startup.last_node);
                   1243:                        printf("Telnet server options:\t0x%08lX\n",bbs_startup.options);
                   1244:                        printf("FTP server port:\t%u\n",ftp_startup.port);
                   1245:                        printf("FTP server options:\t0x%08lX\n",ftp_startup.options);
                   1246:                        printf("Mail SMTP server port:\t%u\n",mail_startup.smtp_port);
                   1247:                        printf("Mail SMTP relay port:\t%u\n",mail_startup.relay_port);
                   1248:                        printf("Mail POP3 server port:\t%u\n",mail_startup.pop3_port);
                   1249:                        printf("Mail server options:\t0x%08lX\n",mail_startup.options);
                   1250:                        printf("Services options:\t0x%08lX\n",services_startup.options);
                   1251:                        printf("Web server port:\t%u\n",web_startup.port);
                   1252:                        printf("Web server options:\t0x%08lX\n",web_startup.options);
                   1253:                        return(0);
                   1254:                }
                   1255:                switch(toupper(*(arg++))) {
                   1256: #ifdef __unix__
                   1257:                                case 'D': /* Run as daemon */
                   1258:                                        is_daemon=TRUE;
                   1259:                                        if(*arg)
                   1260:                                                SAFECOPY(log_facility,arg++);
                   1261:                                break;
                   1262: #endif
                   1263:                        case 'T':       /* Telnet settings */
                   1264:                                switch(toupper(*(arg++))) {
                   1265:                                        case '-':       
                   1266:                                                run_bbs=FALSE;
                   1267:                                                break;
                   1268:                                        case 'D': /* debug output */
                   1269:                                                bbs_startup.options|=BBS_OPT_DEBUG_TELNET;
                   1270:                                                break;
                   1271:                                        case 'A': /* Auto-logon via IP */
                   1272:                                                bbs_startup.options|=BBS_OPT_AUTO_LOGON;
                   1273:                                                break;
                   1274:                                        case 'Q': /* No QWK events */
                   1275:                                                bbs_startup.options|=BBS_OPT_NO_QWK_EVENTS;
                   1276:                                                break;
                   1277:                                        case 'C': /* Sysop available for chat */
                   1278:                                                bbs_startup.options|=BBS_OPT_SYSOP_AVAILABLE;
                   1279:                                                break;
                   1280:                                        case 'O': /* Set options */
                   1281:                                                bbs_startup.options=strtoul(arg,NULL,0);
                   1282:                                                break;
                   1283:                                        case 'P':
                   1284:                                                bbs_startup.telnet_port=atoi(arg);
                   1285:                                                break;
                   1286:                                        case 'F':
                   1287:                                                bbs_startup.first_node=atoi(arg);
                   1288:                                                break;
                   1289:                                        case 'L':
                   1290:                                                bbs_startup.last_node=atoi(arg);
                   1291:                                                break;
                   1292:                                        default:
                   1293:                                                show_usage(argv[0]);
                   1294:                                                return(1);
                   1295:                                }
                   1296:                                break;
                   1297:                        case 'R':       /* RLogin */
                   1298:                                bbs_startup.options|=BBS_OPT_ALLOW_RLOGIN;
                   1299:                                switch(toupper(*(arg++))) {
                   1300:                                        case 'P':
                   1301:                                                bbs_startup.rlogin_port=atoi(arg);
                   1302:                                                break;
                   1303:                                        case '2':
                   1304:                                                bbs_startup.options|=BBS_OPT_USE_2ND_RLOGIN;
                   1305:                                                break;
                   1306:                                        default:
                   1307:                                                show_usage(argv[0]);
                   1308:                                                return(1);
                   1309:                                }
                   1310:                                break;
                   1311:                        case 'F':       /* FTP */
                   1312:                                switch(toupper(*(arg++))) {
                   1313:                                        case '-':       
                   1314:                                                run_ftp=FALSE;
                   1315:                                                break;
                   1316:                                        case 'P':
                   1317:                                                ftp_startup.port=atoi(arg);
                   1318:                                                break;
                   1319:                                        case 'O': /* Set options */
                   1320:                                                ftp_startup.options=strtoul(arg,NULL,0);
                   1321:                                                break;
                   1322:                                        default:
                   1323:                                                show_usage(argv[0]);
                   1324:                                                return(1);
                   1325:                                }
                   1326:                                break;
                   1327:                        case 'M':       /* Mail */
                   1328:                                switch(toupper(*(arg++))) {
                   1329:                                        case '-':
                   1330:                                                run_mail=FALSE;
                   1331:                                                break;
                   1332:                                        case 'O': /* Set options */
                   1333:                                                mail_startup.options=strtoul(arg,NULL,0);
                   1334:                                                break;
                   1335:                                        case 'S':       /* SMTP/SendMail */
                   1336:                                                if(isdigit(*arg)) {
                   1337:                                                        mail_startup.smtp_port=atoi(arg);
                   1338:                                                        break;
                   1339:                                                }
                   1340:                                                switch(toupper(*(arg++))) {
                   1341:                                                        case '-':
                   1342:                                                                mail_startup.options|=MAIL_OPT_NO_SENDMAIL;
                   1343:                                                                break;
                   1344:                                                        default:
                   1345:                                                                show_usage(argv[0]);
                   1346:                                                                return(1);
                   1347:                                                }
                   1348:                                                break;
                   1349:                                        case 'P':       /* POP3 */
                   1350:                                                if(isdigit(*arg)) {
                   1351:                                                        mail_startup.pop3_port=atoi(arg);
                   1352:                                                        break;
                   1353:                                                }
                   1354:                                                switch(toupper(*(arg++))) {
                   1355:                                                        case '-':
                   1356:                                                                mail_startup.options&=~MAIL_OPT_ALLOW_POP3;
                   1357:                                                                break;
                   1358:                                                        default:
                   1359:                                                                show_usage(argv[0]);
                   1360:                                                                return(1);
                   1361:                                                }
                   1362:                                                break;
                   1363:                                        case 'R':       /* Relay */
                   1364:                                                mail_startup.options|=MAIL_OPT_RELAY_TX;
                   1365:                                                p=strchr(arg,':');      /* port specified */
                   1366:                                                if(p!=NULL) {
                   1367:                                                        *p=0;
                   1368:                                                        mail_startup.relay_port=atoi(p+1);
                   1369:                                                }
                   1370:                                                SAFECOPY(mail_startup.relay_server,arg);
                   1371:                                                break;
                   1372:                                        case 'D':       /* DNS Server */
                   1373:                                                SAFECOPY(mail_startup.dns_server,arg);
                   1374:                                                break;
                   1375:                                        case 'A':
                   1376:                                                mail_startup.options|=MAIL_OPT_ALLOW_RELAY;
                   1377:                                                break;
                   1378:                                        default:
                   1379:                                                show_usage(argv[0]);
                   1380:                                                return(1);
                   1381:                                }
                   1382:                                break;
                   1383:                        case 'S':       /* Services */
                   1384:                                switch(toupper(*(arg++))) {
                   1385:                                        case '-':
                   1386:                                                run_services=FALSE;
                   1387:                                                break;
                   1388:                                        case 'O': /* Set options */
                   1389:                                                services_startup.options=strtoul(arg,NULL,0);
                   1390:                                                break;
                   1391:                                        default:
                   1392:                                                show_usage(argv[0]);
                   1393:                                                return(1);
                   1394:                                }
                   1395:                                break;
                   1396:                        case 'W':       /* Web server */
                   1397:                                switch(toupper(*(arg++))) {
                   1398:                                        case '-':       
                   1399:                                                run_web=FALSE;
                   1400:                                                break;
                   1401:                                        case 'P':
                   1402:                                                web_startup.port=atoi(arg);
                   1403:                                                break;
                   1404:                                        case 'O': /* Set options */
                   1405:                                                web_startup.options=strtoul(arg,NULL,0);
                   1406:                                                break;
                   1407:                                        default:
                   1408:                                                show_usage(argv[0]);
                   1409:                                                return(1);
                   1410:                                }
                   1411:                                break;
                   1412:                                break;
                   1413:                        case 'G':       /* GET */
                   1414:                                switch(toupper(*(arg++))) {
                   1415:                                        case 'I': /* Identity */
                   1416:                                                bbs_startup.options|=BBS_OPT_GET_IDENT;
                   1417:                                                ftp_startup.options|=BBS_OPT_GET_IDENT;
                   1418:                                                mail_startup.options|=BBS_OPT_GET_IDENT;
                   1419:                                                services_startup.options|=BBS_OPT_GET_IDENT;
                   1420:                                                web_startup.options|=BBS_OPT_GET_IDENT;
                   1421:                                                break;
                   1422:                                        default:
                   1423:                                                show_usage(argv[0]);
                   1424:                                                return(1);
                   1425:                                }
                   1426:                                break;
                   1427:                        case 'H':       /* Host */
                   1428:                                switch(toupper(*(arg++))) {
                   1429:                                        case 'N':       /* Name */
                   1430:                                                if(*arg) {
                   1431:                                                        SAFECOPY(bbs_startup.host_name,arg);
                   1432:                                                        SAFECOPY(ftp_startup.host_name,arg);
                   1433:                                                        SAFECOPY(mail_startup.host_name,arg);
                   1434:                                                        SAFECOPY(services_startup.host_name,arg);
                   1435:                                                        SAFECOPY(web_startup.host_name,arg);
                   1436:                                                } else {
                   1437:                                                        SAFECOPY(bbs_startup.host_name,host_name);
                   1438:                                                        SAFECOPY(ftp_startup.host_name,host_name);
                   1439:                                                        SAFECOPY(mail_startup.host_name,host_name);
                   1440:                                                        SAFECOPY(services_startup.host_name,host_name);
                   1441:                                                        SAFECOPY(web_startup.host_name,host_name);
                   1442:                                                }
                   1443:                                                printf("Setting hostname: %s\n",bbs_startup.host_name);
                   1444:                                                break;
                   1445:                                        default:
                   1446:                                                show_usage(argv[0]);
                   1447:                                                return(1);
                   1448:                                }
                   1449:                                break;
                   1450:                        case 'U':       /* runtime UID */
                   1451:                                switch(toupper(*(arg++))) {
                   1452:                                        case 'N': /* username */
                   1453: #ifdef __unix__
                   1454:                                                if(strlen(arg) > 1)
                   1455:                                                {
                   1456:                                                        SAFECOPY(new_uid_name,arg);
                   1457:                                                }
                   1458: #endif                 
                   1459:                                                break;
                   1460:                                        case 'G': /* groupname */
                   1461: #ifdef __unix__
                   1462:                                                if(strlen(arg) > 1)
                   1463:                                                {
                   1464:                                                        SAFECOPY(new_gid_name,arg);
                   1465:                                                }
                   1466: #endif                 
                   1467:                                                break;
                   1468:                                        default:
                   1469:                                                show_usage(argv[0]);
                   1470:                                                return(1);
                   1471:                                }
                   1472:                                break;
                   1473:                        case 'N':       /* No */
                   1474:                                switch(toupper(*(arg++))) {
                   1475:                                        case 'F':       /* FTP Server */
                   1476:                                                run_ftp=FALSE;
                   1477:                                                break;
                   1478:                                        case 'M':       /* Mail Server */
                   1479:                                                run_mail=FALSE;
                   1480:                                                break;
                   1481:                                        case 'S':       /* Services */
                   1482:                                                run_services=FALSE;
                   1483:                                                break;
                   1484:                                        case 'T':       /* Telnet */
                   1485:                                                run_bbs=FALSE;
                   1486:                                                break;
                   1487:                                        case 'E': /* No Events */
                   1488:                                                bbs_startup.options             |=BBS_OPT_NO_EVENTS;
                   1489:                                                break;
                   1490:                                        case 'Q': /* No QWK events */
                   1491:                                                bbs_startup.options             |=BBS_OPT_NO_QWK_EVENTS;
                   1492:                                                break;
                   1493:                                        case 'H':       /* Hostname lookup */
                   1494:                                                bbs_startup.options             |=BBS_OPT_NO_HOST_LOOKUP;
                   1495:                                                ftp_startup.options             |=BBS_OPT_NO_HOST_LOOKUP;
                   1496:                                                mail_startup.options    |=BBS_OPT_NO_HOST_LOOKUP;
                   1497:                                                services_startup.options|=BBS_OPT_NO_HOST_LOOKUP;
                   1498:                                                break;
                   1499:                                        case 'J':       /* JavaScript */
                   1500:                                                bbs_startup.options             |=BBS_OPT_NO_JAVASCRIPT;
                   1501:                                                ftp_startup.options             |=BBS_OPT_NO_JAVASCRIPT;
                   1502:                                                mail_startup.options    |=BBS_OPT_NO_JAVASCRIPT;
                   1503:                                                services_startup.options|=BBS_OPT_NO_JAVASCRIPT;
                   1504:                                                break;
                   1505:                                        case 'I':       /* no .ini file */
                   1506:                                                break;
                   1507:                                        case 'D':
                   1508: #if defined(__unix__)
                   1509:                                                is_daemon=FALSE;
                   1510: #endif
                   1511:                                                break;
                   1512:                                        case 'W':       /* no web server */
                   1513:                                                run_web=FALSE;
                   1514:                                                break;
                   1515:                                        default:
                   1516:                                                show_usage(argv[0]);
                   1517:                                                return(1);
                   1518:                                }
                   1519:                                break;
                   1520:                        case 'L':       /* Local */
                   1521:                                switch(toupper(*(arg++))) {
                   1522:                                        case 'T': /* timezone */
                   1523:                                                bbs_startup.options             |=BBS_OPT_LOCAL_TIMEZONE;
                   1524:                                                ftp_startup.options             |=BBS_OPT_LOCAL_TIMEZONE;
                   1525:                                                mail_startup.options    |=BBS_OPT_LOCAL_TIMEZONE;
                   1526:                                                services_startup.options|=BBS_OPT_LOCAL_TIMEZONE;
                   1527:                                                break;
                   1528:                                        default:
                   1529:                                                show_usage(argv[0]);
                   1530:                                                return(1);
                   1531:                                }
                   1532:                                break;
                   1533: 
                   1534:                        default:
                   1535:                                show_usage(argv[0]);
                   1536:                                return(1);
                   1537:                }
                   1538:        }
                   1539: 
                   1540:        /* Read in configuration files */
                   1541:     memset(&scfg,0,sizeof(scfg));
                   1542:     SAFECOPY(scfg.ctrl_dir,bbs_startup.ctrl_dir);
                   1543: 
                   1544:        if(chdir(scfg.ctrl_dir)!=0)
                   1545:                lprintf(LOG_ERR,"!ERROR %d changing directory to: %s", errno, scfg.ctrl_dir);
                   1546: 
                   1547:     scfg.size=sizeof(scfg);
                   1548:        SAFECOPY(error,UNKNOWN_LOAD_ERROR);
                   1549:        lprintf(LOG_INFO,"Loading configuration files from %s", scfg.ctrl_dir);
                   1550:        if(!load_cfg(&scfg, NULL /* text.dat */, TRUE /* prep */, error)) {
                   1551:                lprintf(LOG_ERR,"!ERROR Loading Configuration Files: %s", error);
                   1552:         return(-1);
                   1553:     }
                   1554: 
                   1555: /* Daemonize / Set uid/gid */
                   1556: #ifdef __unix__
                   1557: 
                   1558:        switch(toupper(log_facility[0])) {
                   1559:                case '0':
                   1560:                        openlog(log_ident,LOG_CONS,LOG_LOCAL0);
                   1561:                        break;
                   1562:                case '1':
                   1563:                        openlog(log_ident,LOG_CONS,LOG_LOCAL1);
                   1564:                        break;
                   1565:                case '2':
                   1566:                        openlog(log_ident,LOG_CONS,LOG_LOCAL2);
                   1567:                        break;
                   1568:                case '3':
                   1569:                        openlog(log_ident,LOG_CONS,LOG_LOCAL3);
                   1570:                        break;
                   1571:                case '4':
                   1572:                        openlog(log_ident,LOG_CONS,LOG_LOCAL4);
                   1573:                        break;
                   1574:                case '5':
                   1575:                        openlog(log_ident,LOG_CONS,LOG_LOCAL5);
                   1576:                        break;
                   1577:                case '6':
                   1578:                        openlog(log_ident,LOG_CONS,LOG_LOCAL6);
                   1579:                        break;
                   1580:                case '7':
                   1581:                        openlog(log_ident,LOG_CONS,LOG_LOCAL7);
                   1582:                        break;
                   1583:                case 'F':       /* this is legacy */
                   1584:                case 'S':
                   1585:                        /* Use standard facilities */
                   1586:                        openlog(log_ident,LOG_CONS,LOG_USER);
                   1587:                        std_facilities = TRUE;
                   1588:                        break;
                   1589:                default:
                   1590:                        openlog(log_ident,LOG_CONS,LOG_USER);
                   1591:        }
                   1592:        if(is_daemon) {
                   1593: 
                   1594:                lprintf(LOG_INFO,"Running as daemon");
                   1595:                if(daemon(TRUE,FALSE))  { /* Daemonize, DON'T switch to / and DO close descriptors */
                   1596:                        lprintf(LOG_ERR,"!ERROR %d running as daemon",errno);
                   1597:                        is_daemon=FALSE;
                   1598:                }
                   1599: 
                   1600:                /* Open here to use startup permissions to create the file */
                   1601:                pidf=fopen(pid_fname,"w");
                   1602:        }
                   1603:        old_uid = getuid();
                   1604:        if((pw_entry=getpwnam(new_uid_name))!=0)
                   1605:        {
                   1606:                new_uid=pw_entry->pw_uid;
                   1607:                new_gid=pw_entry->pw_gid;
                   1608:        }
                   1609:        else  {
                   1610:                new_uid=getuid();
                   1611:                new_gid=getgid();
                   1612:        }
                   1613:        old_gid = getgid();
                   1614:        if((gr_entry=getgrnam(new_gid_name))!=0)
                   1615:                new_gid=gr_entry->gr_gid;
                   1616:        
                   1617:        do_seteuid(TRUE);
                   1618: #endif
                   1619: 
                   1620: #ifdef _THREAD_SUID_BROKEN
                   1621:        /* check if we're using NPTL */
                   1622: /* Old (2.2) systems don't have this. */
                   1623: #ifdef _CS_GNU_LIBPTHREAD_VERSION
                   1624:        conflen=confstr (_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
                   1625:        if (conflen > 0) {
                   1626:                char *buf = alloca (conflen);
                   1627:                confstr (_CS_GNU_LIBPTHREAD_VERSION, buf, conflen);
                   1628:                if (strstr (buf, "NPTL"))
                   1629:                        thread_suid_broken=FALSE;
                   1630:        }
                   1631: #endif
                   1632: #endif
                   1633: 
                   1634:        /* Install Ctrl-C/Break signal handler here */
                   1635: #if defined(_WIN32)
                   1636:        SetConsoleCtrlHandler(ControlHandler, TRUE /* Add */);
                   1637: #elif defined(__unix__)
                   1638:        /* Set up blocked signals */
                   1639:        sigemptyset(&sigs);
                   1640:        sigaddset(&sigs,SIGINT);
                   1641:        sigaddset(&sigs,SIGQUIT);
                   1642:        sigaddset(&sigs,SIGABRT);
                   1643:        sigaddset(&sigs,SIGTERM);
                   1644:        sigaddset(&sigs,SIGHUP);
                   1645:        sigaddset(&sigs,SIGALRM);
                   1646:        /* sigaddset(&sigs,SIGPIPE); */
                   1647:        pthread_sigmask(SIG_BLOCK,&sigs,NULL);
                   1648:     signal(SIGPIPE, SIG_IGN);       /* Ignore "Broken Pipe" signal (Also used for broken socket etc.) */
                   1649:     signal(SIGALRM, SIG_IGN);       /* Ignore "Alarm" signal */
                   1650:        _beginthread((void(*)(void*))handle_sigs,0,NULL);
                   1651:        if(new_uid_name[0]!=0) {        /*  check the user arg, if we have uid 0 */
                   1652:                /* Can't recycle servers (re-bind ports) as non-root user */
                   1653:                /* If DONT_BLAME_SYNCHRONET is set, keeps root credentials laying around */
                   1654: #if !defined(DONT_BLAME_SYNCHRONET)
                   1655:                if(!thread_suid_broken) {
                   1656:                        if(bbs_startup.telnet_port < IPPORT_RESERVED
                   1657:                                || (bbs_startup.options & BBS_OPT_ALLOW_RLOGIN
                   1658:                                        && bbs_startup.rlogin_port < IPPORT_RESERVED)
                   1659: #ifdef USE_CRYPTLIB
                   1660:                                || (bbs_startup.options & BBS_OPT_ALLOW_SSH
                   1661:                                        && bbs_startup.ssh_port < IPPORT_RESERVED)
                   1662: #endif
                   1663:                                )
                   1664:                                bbs_startup.options|=BBS_OPT_NO_RECYCLE;
                   1665:                        if(ftp_startup.port < IPPORT_RESERVED)
                   1666:                                ftp_startup.options|=FTP_OPT_NO_RECYCLE;
                   1667:                        if(web_startup.port < IPPORT_RESERVED)
                   1668:                                web_startup.options|=BBS_OPT_NO_RECYCLE;
                   1669:                        if((mail_startup.options & MAIL_OPT_ALLOW_POP3
                   1670:                                && mail_startup.pop3_port < IPPORT_RESERVED)
                   1671:                                || mail_startup.smtp_port < IPPORT_RESERVED)
                   1672:                                mail_startup.options|=MAIL_OPT_NO_RECYCLE;
                   1673:                        /* Perhaps a BBS_OPT_NO_RECYCLE_LOW option? */
                   1674:                        services_startup.options|=BBS_OPT_NO_RECYCLE;
                   1675:                }
                   1676: #endif
                   1677:        }
                   1678: #endif
                   1679: 
                   1680:        if(run_bbs)
                   1681:                _beginthread((void(*)(void*))bbs_thread,0,&bbs_startup);
                   1682:        if(run_ftp)
                   1683:                _beginthread((void(*)(void*))ftp_server,0,&ftp_startup);
                   1684:        if(run_mail)
                   1685:                _beginthread((void(*)(void*))mail_server,0,&mail_startup);
                   1686: #ifdef NO_SERVICES
                   1687:        run_services=FALSE;
                   1688: #else
                   1689:        if(run_services)
                   1690:                _beginthread((void(*)(void*))services_thread,0,&services_startup);
                   1691: #endif
                   1692: #ifdef NO_WEB_SERVER
                   1693:        run_web=FALSE;
                   1694: #else
                   1695:        if(run_web)
                   1696:                _beginthread((void(*)(void*))web_server,0,&web_startup);
                   1697: #endif
                   1698: 
                   1699: #ifdef __unix__
                   1700:        if(getuid())  { /*  are we running as a normal user?  */
                   1701:                lprintf(LOG_WARNING
                   1702:                        ,"!Started as non-root user.  Cannot bind() to ports below %u.", IPPORT_RESERVED);
                   1703:        }
                   1704:        
                   1705:        else if(new_uid_name[0]==0)   /*  check the user arg, if we have uid 0 */
                   1706:                lputs(LOG_WARNING,"WARNING: No user account specified, running as root.");
                   1707:        
                   1708:        else 
                   1709:        {
                   1710:                lputs(LOG_INFO,"Waiting for child threads to bind ports...");
                   1711:                while((run_bbs && !(bbs_running || bbs_stopped)) 
                   1712:                                || (run_ftp && !(ftp_running || ftp_stopped)) 
                   1713:                                || (run_web && !(web_running || web_stopped)) 
                   1714:                                || (run_mail && !(mail_running || mail_stopped)) 
                   1715:                                || (run_services && !(services_running || services_stopped)))  {
                   1716:                        mswait(1000);
                   1717:                        if(run_bbs && !(bbs_running || bbs_stopped))
                   1718:                                lputs(LOG_INFO,"Waiting for BBS thread");
                   1719:                        if(run_web && !(web_running || web_stopped))
                   1720:                                lputs(LOG_INFO,"Waiting for Web thread");
                   1721:                        if(run_ftp && !(ftp_running || ftp_stopped))
                   1722:                                lputs(LOG_INFO,"Waiting for FTP thread");
                   1723:                        if(run_mail && !(mail_running || mail_stopped))
                   1724:                                lputs(LOG_INFO,"Waiting for Mail thread");
                   1725:                        if(run_services && !(services_running || services_stopped))
                   1726:                                lputs(LOG_INFO,"Waiting for Services thread");
                   1727:                }
                   1728: 
                   1729:                if(!do_setuid(FALSE))
                   1730:                                /* actually try to change the uid of this process */
                   1731:                        lputs(LOG_ERR,"!Setting new user_id failed!  (Does the user exist?)");
                   1732:        
                   1733:                else {
                   1734:                        char str[256];
                   1735:                        struct passwd *pwent;
                   1736: 
                   1737:                        pwent=getpwnam(new_uid_name);
                   1738:                        if(pwent != NULL) {
                   1739:                                char    uenv[128];
                   1740:                                char    henv[MAX_PATH+6];
                   1741:                                sprintf(uenv,"USER=%s",pwent->pw_name);
                   1742:                                putenv(uenv);
                   1743:                                sprintf(henv,"HOME=%s",pwent->pw_dir);
                   1744:                                putenv(henv);
                   1745:                        }
                   1746:                        if(new_gid_name[0]) {
                   1747:                                char    genv[128];
                   1748:                                sprintf(genv,"GROUP=%s",new_gid_name);
                   1749:                                putenv(genv);
                   1750:                        }
                   1751:                        lprintf(LOG_INFO,"Successfully changed user_id to %s", new_uid_name);
                   1752:                }
                   1753:        }
                   1754: 
                   1755:        if(!isatty(fileno(stdin)))                      /* redirected */
                   1756:                while(1)
                   1757:                        select(0,NULL,NULL,NULL,NULL);  /* Sleep forever - Should this just exit the thread? */
                   1758:        else                                                            /* interactive */
                   1759: #endif
                   1760:        {
                   1761:                prompt = "[Threads: %d  Sockets: %d  Clients: %d  Served: %lu] (?=Help): ";
                   1762:                lputs(LOG_INFO,NULL);   /* display prompt */
                   1763: 
                   1764:                while(!terminated) {
                   1765: #ifdef __unix__
                   1766:                        if(!isatty(STDIN_FILENO))  {            /* Controlling terminal has left us *sniff* */
                   1767:                                int fd;
                   1768:                                openlog(log_ident,LOG_CONS,LOG_USER);
                   1769:                        if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
                   1770:                                (void)dup2(fd, STDIN_FILENO);
                   1771:                                (void)dup2(fd, STDOUT_FILENO);
                   1772:                                (void)dup2(fd, STDERR_FILENO);
                   1773:                                if (fd > 2)
                   1774:                                (void)close(fd);
                   1775:                        }
                   1776:                                is_daemon=TRUE;
                   1777:                                lputs(LOG_WARNING, "STDIN is not a tty anymore... switching to syslog logging");
                   1778:                                select(0,NULL,NULL,NULL,NULL);  /* Sleep forever - Should this just exit the thread? */
                   1779:                        }
                   1780: #endif
                   1781: 
                   1782:                        if(!kbhit()) {
                   1783:                                YIELD();
                   1784:                                continue;
                   1785:                        }
                   1786:                        ch=getch();
                   1787:                        printf("%c\n",ch);
                   1788:                        switch(ch) {
                   1789:                                case 'q':
                   1790:                                        terminated=TRUE;
                   1791:                                        break;
                   1792:                                case 'w':       /* who's online */
                   1793:                                        printf("\nNodes in use:\n");
                   1794:                                case 'n':       /* nodelist */
                   1795:                                        printf("\n");
                   1796:                                        for(i=1;i<=scfg.sys_nodes;i++) {
                   1797:                                                getnodedat(&scfg,i,&node,NULL /* file */);
                   1798:                                                if(ch=='w' && node.status!=NODE_INUSE && node.status!=NODE_QUIET)
                   1799:                                                        continue;
                   1800:                                                printnodedat(&scfg, i,&node);
                   1801:                                        }
                   1802:                                        break;
                   1803:                                case 'l':       /* lock node */
                   1804:                                case 'd':       /* down node */
                   1805:                                case 'i':       /* interrupt node */
                   1806:                                        printf("\nNode number: ");
                   1807:                                        if((n=atoi(fgets(str,sizeof(str),stdin)))<1)
                   1808:                                                break;
                   1809:                                        fflush(stdin);
                   1810:                                        printf("\n");
                   1811:                                        if((i=getnodedat(&scfg,n,&node,&file))!=0) {
                   1812:                                                printf("!Error %d getting node %d data\n",i,n);
                   1813:                                                break;
                   1814:                                        }
                   1815:                                        switch(ch) {
                   1816:                                                case 'l':
                   1817:                                                        node.misc^=NODE_LOCK;
                   1818:                                                        break;
                   1819:                                                case 'd':
                   1820:                                                        node.misc^=NODE_DOWN;
                   1821:                                                        break;
                   1822:                                                case 'i':
                   1823:                                                        node.misc^=NODE_INTR;
                   1824:                                                        break;
                   1825:                                        }
                   1826:                                        putnodedat(&scfg,n,&node,file);
                   1827:                                        printnodedat(&scfg,n,&node);
                   1828:                                        break;
                   1829:                                case 'r':       /* recycle */
                   1830:                                case 's':       /* shutdown */
                   1831:                                case 't':       /* terminate */
                   1832:                                        printf("BBS, FTP, Web, Mail, Services, or [All] ? ");
                   1833:                                        switch(toupper(getch())) {
                   1834:                                                case 'B':
                   1835:                                                        printf("BBS\n");
                   1836:                                                        if(ch=='t')
                   1837:                                                                bbs_terminate();
                   1838:                                                        else if(ch=='s')
                   1839:                                                                bbs_startup.shutdown_now=TRUE;
                   1840:                                                        else
                   1841:                                                                bbs_startup.recycle_now=TRUE;
                   1842:                                                        break;
                   1843:                                                case 'F':
                   1844:                                                        printf("FTP\n");
                   1845:                                                        if(ch=='t')
                   1846:                                                                ftp_terminate();
                   1847:                                                        else if(ch=='s')
                   1848:                                                                ftp_startup.shutdown_now=TRUE;
                   1849:                                                        else
                   1850:                                                                ftp_startup.recycle_now=TRUE;
                   1851:                                                        break;
                   1852:                                                case 'W':
                   1853:                                                        printf("Web\n");
                   1854:                                                        if(ch=='t')
                   1855:                                                                web_terminate();
                   1856:                                                        else if(ch=='s')
                   1857:                                                                web_startup.shutdown_now=TRUE;
                   1858:                                                        else
                   1859:                                                                web_startup.recycle_now=TRUE;
                   1860:                                                        break;
                   1861:                                                case 'M':
                   1862:                                                        printf("Mail\n");
                   1863:                                                        if(ch=='t')
                   1864:                                                                mail_terminate();
                   1865:                                                        else if(ch=='s')
                   1866:                                                                mail_startup.shutdown_now=TRUE;
                   1867:                                                        else
                   1868:                                                                mail_startup.recycle_now=TRUE;
                   1869:                                                        break;
                   1870:                                                case 'S':
                   1871:                                                        printf("Services\n");
                   1872:                                                        if(ch=='t')
                   1873:                                                                services_terminate();
                   1874:                                                        else if(ch=='s')
                   1875:                                                                services_startup.shutdown_now=TRUE;
                   1876:                                                        else
                   1877:                                                                services_startup.recycle_now=TRUE;
                   1878:                                                        break;
                   1879:                                                default:
                   1880:                                                        printf("All\n");
                   1881:                                                        if(ch=='t')
                   1882:                                                                terminate();
                   1883:                                                        else if(ch=='s') {
                   1884:                                                                bbs_startup.shutdown_now=TRUE;
                   1885:                                                                ftp_startup.shutdown_now=TRUE;
                   1886:                                                                web_startup.shutdown_now=TRUE;
                   1887:                                                                mail_startup.shutdown_now=TRUE;
                   1888:                                                                services_startup.shutdown_now=TRUE;
                   1889:                                                        }
                   1890:                                                        else {
                   1891:                                                                bbs_startup.recycle_now=TRUE;
                   1892:                                                                ftp_startup.recycle_now=TRUE;
                   1893:                                                                web_startup.recycle_now=TRUE;
                   1894:                                                                mail_startup.recycle_now=TRUE;
                   1895:                                                                services_startup.recycle_now=TRUE;                                                      
                   1896:                                                        }
                   1897:                                                        break;
                   1898:                                        }
                   1899:                                        break;
                   1900:                                case '!':       /* execute */
                   1901:                                        printf("Command line: ");
                   1902:                                        fgets(str,sizeof(str),stdin);
                   1903:                                        system(str);
                   1904:                                        break;
                   1905:                                default:
                   1906:                                        printf("\nSynchronet Console Version %s%c Help\n\n",VERSION,REVISION);
                   1907:                                        printf("q   = quit\n");
                   1908:                                        printf("n   = node list\n");
                   1909:                                        printf("w   = who's online\n");
                   1910:                                        printf("l   = lock node (toggle)\n");
                   1911:                                        printf("d   = down node (toggle)\n");
                   1912:                                        printf("i   = interrupt node (toggle)\n");
                   1913:                                        printf("r   = recycle servers (when not in use)\n");
                   1914:                                        printf("s   = shutdown servers (when not in use)\n");
                   1915:                                        printf("t   = terminate servers (immediately)\n");
                   1916:                                        printf("!   = execute external command\n");
                   1917: #if 0  /* to do */     
                   1918:                                        printf("c#  = chat with node #\n");
                   1919:                                        printf("s#  = spy on node #\n");
                   1920: #endif
                   1921:                                        break;
                   1922:                        }
                   1923:                        lputs(LOG_INFO,"");     /* redisplay prompt */
                   1924:                }
                   1925:        }
                   1926: 
                   1927:        terminate();
                   1928: 
                   1929:        /* erase the prompt */
                   1930:        printf("\r%*s\r",prompt_len,"");
                   1931: 
                   1932:        return(0);
                   1933: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.