|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.