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