|
|
1.1 ! root 1: /* ntsvcs.c */ ! 2: ! 3: /* Synchronet BBS as a set of Windows NT Services */ ! 4: ! 5: /* $Id: ntsvcs.c,v 1.35 2006/12/31 00:07:50 rswindell 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: /* Synchronet-specific headers */ ! 39: #include "sbbs.h" /* various */ ! 40: #include "sbbs_ini.h" /* sbbs_read_ini() */ ! 41: #include "ftpsrvr.h" /* ftp_startup_t, ftp_server */ ! 42: #include "websrvr.h" /* web_startup_t, web_server */ ! 43: #include "mailsrvr.h" /* mail_startup_t, mail_server */ ! 44: #include "services.h" /* services_startup_t, services_thread */ ! 45: #include "ntsvcs.h" /* NT service names */ ! 46: ! 47: /* Windows-specific headers */ ! 48: #include <winsvc.h> ! 49: ! 50: #define NTSVC_TIMEOUT_STARTUP 30000 /* Milliseconds */ ! 51: #define NTSVC_TIMEOUT_TERMINATE 30000 /* Milliseconds */ ! 52: ! 53: #define STRLEN_MAX_DISPLAY_NAME 35 ! 54: ! 55: #define STRLEN_SYNCHRONET 10 /* this number ain't change'n */ ! 56: ! 57: #define SERVICE_NOT_INSTALLED (SERVICE_DISABLED+1) ! 58: ! 59: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode); ! 60: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode); ! 61: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode); ! 62: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode); ! 63: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode); ! 64: ! 65: /* Global variables */ ! 66: ! 67: char ini_file[MAX_PATH+1]; ! 68: bbs_startup_t bbs_startup; ! 69: ftp_startup_t ftp_startup; ! 70: mail_startup_t mail_startup; ! 71: services_startup_t services_startup; ! 72: web_startup_t web_startup; ! 73: ! 74: typedef struct { ! 75: char* name; ! 76: char* display_name; ! 77: char* description; ! 78: void* startup; ! 79: DWORD* options; ! 80: BOOL* recycle_now; ! 81: int* log_level; ! 82: void DLLCALL (*thread)(void* arg); ! 83: void DLLCALL (*terminate)(void); ! 84: void (WINAPI *ctrl_handler)(DWORD); ! 85: HANDLE log_handle; ! 86: HANDLE event_handle; ! 87: BOOL autostart; ! 88: BOOL debug; ! 89: SERVICE_STATUS status; ! 90: SERVICE_STATUS_HANDLE status_handle; ! 91: } sbbs_ntsvc_t; ! 92: ! 93: sbbs_ntsvc_t bbs ={ ! 94: NTSVC_NAME_BBS, ! 95: "Synchronet Telnet/RLogin/SSH Server", ! 96: "Provides support for Telnet, RLogin, and SSH clients and executes timed events. " \ ! 97: "This service provides the critical functions of your Synchronet BBS.", ! 98: &bbs_startup, ! 99: &bbs_startup.options, ! 100: &bbs_startup.recycle_now, ! 101: &bbs_startup.log_level, ! 102: bbs_thread, ! 103: bbs_terminate, ! 104: bbs_ctrl_handler, ! 105: INVALID_HANDLE_VALUE ! 106: }; ! 107: ! 108: /* This is not (currently) a separate service, use this for logging only */ ! 109: sbbs_ntsvc_t event ={ ! 110: NTSVC_NAME_EVENT, ! 111: NULL, ! 112: NULL, ! 113: NULL, ! 114: NULL, ! 115: NULL, ! 116: &bbs_startup.log_level, ! 117: NULL, ! 118: NULL, ! 119: NULL, ! 120: INVALID_HANDLE_VALUE ! 121: }; ! 122: ! 123: sbbs_ntsvc_t ftp = { ! 124: NTSVC_NAME_FTP, ! 125: "Synchronet FTP Server", ! 126: "Provides support for FTP clients (including web browsers) for file transfers.", ! 127: &ftp_startup, ! 128: &ftp_startup.options, ! 129: &ftp_startup.recycle_now, ! 130: &ftp_startup.log_level, ! 131: ftp_server, ! 132: ftp_terminate, ! 133: ftp_ctrl_handler, ! 134: INVALID_HANDLE_VALUE ! 135: }; ! 136: ! 137: sbbs_ntsvc_t web = { ! 138: NTSVC_NAME_WEB, ! 139: "Synchronet Web Server", ! 140: "Provides support for Web (HTML/HTTP) clients (browsers).", ! 141: &web_startup, ! 142: &web_startup.options, ! 143: &web_startup.recycle_now, ! 144: &web_startup.log_level, ! 145: web_server, ! 146: web_terminate, ! 147: web_ctrl_handler, ! 148: INVALID_HANDLE_VALUE ! 149: }; ! 150: ! 151: sbbs_ntsvc_t mail = { ! 152: NTSVC_NAME_MAIL, ! 153: "Synchronet SMTP/POP3 Mail Server", ! 154: "Sends and receives Internet e-mail (using SMTP) and allows users to remotely " \ ! 155: "access their e-mail using an Internet mail client (using POP3).", ! 156: &mail_startup, ! 157: &mail_startup.options, ! 158: &mail_startup.recycle_now, ! 159: &mail_startup.log_level, ! 160: mail_server, ! 161: mail_terminate, ! 162: mail_ctrl_handler, ! 163: INVALID_HANDLE_VALUE ! 164: }; ! 165: ! 166: sbbs_ntsvc_t services = { ! 167: NTSVC_NAME_SERVICES, ! 168: "Synchronet Services", ! 169: "Plugin servers (usually in JavaScript) for any TCP/UDP protocol. " \ ! 170: "Stock services include Finger, Gopher, NNTP, and IRC. Edit your ctrl/services.ini " \ ! 171: "file for configuration of individual Synchronet Services.", ! 172: &services_startup, ! 173: &services_startup.options, ! 174: &services_startup.recycle_now, ! 175: &services_startup.log_level, ! 176: services_thread, ! 177: services_terminate, ! 178: services_ctrl_handler, ! 179: INVALID_HANDLE_VALUE ! 180: }; ! 181: ! 182: /* This list is used for enumerating all services */ ! 183: sbbs_ntsvc_t* ntsvc_list[] = { ! 184: &bbs, ! 185: &ftp, ! 186: &web, ! 187: &mail, ! 188: &services, ! 189: NULL ! 190: }; ! 191: ! 192: /****************************************/ ! 193: /* Service Control Handlers (Callbacks) */ ! 194: /****************************************/ ! 195: ! 196: /* Common control handler for all services */ ! 197: static void svc_ctrl_handler(sbbs_ntsvc_t* svc, DWORD dwCtrlCode) ! 198: { ! 199: switch(dwCtrlCode) { ! 200: case SERVICE_CONTROL_RECYCLE: ! 201: *svc->recycle_now=TRUE; ! 202: break; ! 203: case SERVICE_CONTROL_MUTE: ! 204: *svc->options|=BBS_OPT_MUTE; ! 205: break; ! 206: case SERVICE_CONTROL_UNMUTE: ! 207: *svc->options&=~BBS_OPT_MUTE; ! 208: break; ! 209: case SERVICE_CONTROL_STOP: ! 210: case SERVICE_CONTROL_SHUTDOWN: ! 211: svc->terminate(); ! 212: svc->status.dwWaitHint=NTSVC_TIMEOUT_TERMINATE; ! 213: svc->status.dwCurrentState=SERVICE_STOP_PENDING; ! 214: break; ! 215: } ! 216: SetServiceStatus(svc->status_handle, &svc->status); ! 217: } ! 218: ! 219: /* Service-specific control handler stub functions */ ! 220: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode) ! 221: { ! 222: switch(dwCtrlCode) { ! 223: case SERVICE_CONTROL_SYSOP_AVAILABLE: ! 224: bbs_startup.options|=BBS_OPT_SYSOP_AVAILABLE; ! 225: break; ! 226: case SERVICE_CONTROL_SYSOP_UNAVAILABLE: ! 227: bbs_startup.options&=~BBS_OPT_SYSOP_AVAILABLE; ! 228: break; ! 229: default: ! 230: svc_ctrl_handler(&bbs, dwCtrlCode); ! 231: break; ! 232: } ! 233: } ! 234: ! 235: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode) ! 236: { ! 237: svc_ctrl_handler(&ftp, dwCtrlCode); ! 238: } ! 239: ! 240: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode) ! 241: { ! 242: svc_ctrl_handler(&web, dwCtrlCode); ! 243: } ! 244: ! 245: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode) ! 246: { ! 247: svc_ctrl_handler(&mail, dwCtrlCode); ! 248: } ! 249: ! 250: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode) ! 251: { ! 252: svc_ctrl_handler(&services, dwCtrlCode); ! 253: } ! 254: ! 255: static WORD event_type(int level) ! 256: { ! 257: switch(level) { ! 258: case LOG_WARNING: ! 259: return(EVENTLOG_WARNING_TYPE); ! 260: case LOG_NOTICE: ! 261: case LOG_INFO: ! 262: case LOG_DEBUG: ! 263: return(EVENTLOG_INFORMATION_TYPE); /* same as EVENT_LOG_SUCCESS */ ! 264: } ! 265: /* ! 266: LOG_EMERG ! 267: LOG_ALERT ! 268: LOG_CRIT ! 269: LOG_ERR ! 270: */ ! 271: return(EVENTLOG_ERROR_TYPE); ! 272: } ! 273: ! 274: /**************************************/ ! 275: /* Common Service Log Ouptut Function */ ! 276: /**************************************/ ! 277: static int svc_lputs(void* p, int level, char* str) ! 278: { ! 279: char debug[1024]; ! 280: char fname[256]; ! 281: DWORD len; ! 282: DWORD wr; ! 283: sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p; ! 284: ! 285: /* Debug Logging */ ! 286: if(svc==NULL || svc->debug) { ! 287: snprintf(debug,sizeof(debug),"%s: %s",svc==NULL ? "Synchronet" : svc->name, str); ! 288: OutputDebugString(debug); ! 289: } ! 290: if(svc==NULL) ! 291: return(0); ! 292: ! 293: len = strlen(str); ! 294: ! 295: /* Mailslot Logging (for sbbsctrl) */ ! 296: if(svc->log_handle != INVALID_HANDLE_VALUE /* Invalid log handle? */ ! 297: && !GetMailslotInfo(svc->log_handle, NULL, NULL, NULL, NULL)) { ! 298: /* Close and try to re-open */ ! 299: CloseHandle(svc->log_handle); ! 300: svc->log_handle=INVALID_HANDLE_VALUE; ! 301: } ! 302: ! 303: if(svc->log_handle == INVALID_HANDLE_VALUE) { ! 304: sprintf(fname,"\\\\.\\mailslot\\%s.log",svc->name); ! 305: svc->log_handle = CreateFile( ! 306: fname, /* pointer to name of the file */ ! 307: GENERIC_WRITE, /* access (read-write) mode */ ! 308: FILE_SHARE_READ, /* share mode */ ! 309: NULL, /* pointer to security attributes */ ! 310: OPEN_EXISTING, /* how to create */ ! 311: FILE_ATTRIBUTE_NORMAL, /* file attributes */ ! 312: NULL /* handle to file with attributes to copy */ ! 313: ); ! 314: } ! 315: if(svc->log_handle != INVALID_HANDLE_VALUE) { ! 316: if(!WriteFile(svc->log_handle,str,len,&wr,NULL) || wr!=len) { ! 317: /* This most likely indicates the server closed the mailslot */ ! 318: sprintf(debug,"!ERROR %d writing %u bytes to %s pipe (wr=%d)" ! 319: ,GetLastError(),len,svc->name,wr); ! 320: OutputDebugString(debug); ! 321: /* So close the handle and attempt re-open next time */ ! 322: CloseHandle(svc->log_handle); ! 323: svc->log_handle=INVALID_HANDLE_VALUE; ! 324: } ! 325: } ! 326: ! 327: /* Event Logging */ ! 328: if(level <= (*svc->log_level)) { ! 329: if(svc->event_handle == NULL) ! 330: svc->event_handle = RegisterEventSource( ! 331: NULL, /* server name for source (NULL = local computer) */ ! 332: svc->name /* source name for registered handle */ ! 333: ); ! 334: if(svc->event_handle != NULL) ! 335: ReportEvent(svc->event_handle, /* event log handle */ ! 336: event_type(level), /* event type */ ! 337: 0, /* category zero */ ! 338: 0, /* event identifier */ ! 339: NULL, /* no user security identifier */ ! 340: 1, /* one string */ ! 341: 0, /* no data */ ! 342: (LPCSTR*)&str, /* pointer to string array */ ! 343: NULL); /* pointer to data */ ! 344: } ! 345: ! 346: return(0); ! 347: } ! 348: ! 349: /****************************************************************************/ ! 350: /* Event thread local/log print routine */ ! 351: /****************************************************************************/ ! 352: static int event_lputs(int level, char *str) ! 353: { ! 354: svc_lputs(&event,level,str); ! 355: return(0); ! 356: } ! 357: ! 358: /************************************/ ! 359: /* Shared Service Callback Routines */ ! 360: /************************************/ ! 361: ! 362: static void svc_started(void* p) ! 363: { ! 364: sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p; ! 365: ! 366: svc->status.dwCurrentState=SERVICE_RUNNING; ! 367: svc->status.dwControlsAccepted|=SERVICE_ACCEPT_STOP; ! 368: SetServiceStatus(svc->status_handle, &svc->status); ! 369: } ! 370: ! 371: static void read_ini(sbbs_ntsvc_t* svc) ! 372: { ! 373: char str[MAX_PATH*2]; ! 374: FILE* fp; ! 375: bbs_startup_t* bbs_startup=NULL; ! 376: ftp_startup_t* ftp_startup=NULL; ! 377: mail_startup_t* mail_startup=NULL; ! 378: services_startup_t* services_startup=NULL; ! 379: web_startup_t* web_startup=NULL; ! 380: ! 381: if(svc==&bbs) ! 382: bbs_startup=svc->startup; ! 383: else if(svc==&ftp) ! 384: ftp_startup=svc->startup; ! 385: else if(svc==&web) ! 386: web_startup=svc->startup; ! 387: else if(svc==&mail) ! 388: mail_startup=svc->startup; ! 389: else if(svc==&services) ! 390: services_startup=svc->startup; ! 391: ! 392: if((fp=fopen(ini_file,"r"))!=NULL) { ! 393: sprintf(str,"Reading %s",ini_file); ! 394: svc_lputs(NULL,LOG_INFO,str); ! 395: } ! 396: ! 397: /* We call this function to set defaults, even if there's no .ini file */ ! 398: sbbs_read_ini(fp ! 399: ,NULL /* global_startup */ ! 400: ,NULL ,bbs_startup ! 401: ,NULL ,ftp_startup ! 402: ,NULL ,web_startup ! 403: ,NULL ,mail_startup ! 404: ,NULL ,services_startup ! 405: ); ! 406: ! 407: /* close .ini file here */ ! 408: if(fp!=NULL) ! 409: fclose(fp); ! 410: } ! 411: ! 412: static void svc_recycle(void *p) ! 413: { ! 414: read_ini((sbbs_ntsvc_t*)p); ! 415: } ! 416: ! 417: static void svc_terminated(void* p, int code) ! 418: { ! 419: sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p; ! 420: ! 421: if(code) { ! 422: svc->status.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR; ! 423: svc->status.dwServiceSpecificExitCode=code; ! 424: SetServiceStatus(svc->status_handle, &svc->status); ! 425: } ! 426: } ! 427: ! 428: static void svc_clients(void* p, int active) ! 429: { ! 430: sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p; ! 431: } ! 432: ! 433: /***************/ ! 434: /* ServiceMain */ ! 435: /***************/ ! 436: ! 437: /* Common ServiceMain for all services */ ! 438: static void WINAPI svc_main(sbbs_ntsvc_t* svc, DWORD argc, LPTSTR *argv) ! 439: { ! 440: char str[256]; ! 441: DWORD i; ! 442: char* arg; ! 443: ! 444: for(i=0;i<argc;i++) { ! 445: arg=argv[i]; ! 446: if(*arg=='-' || *arg=='/') ! 447: arg++; ! 448: if(!stricmp(arg,"debug")) ! 449: svc->debug=TRUE; ! 450: if(!stricmp(arg,"loglevel") && i+1<argc) ! 451: (*svc->log_level)=strtol(argv[++i],NULL,0); ! 452: } ! 453: ! 454: sprintf(str,"Starting NT Service: %s",svc->display_name); ! 455: svc_lputs(svc,LOG_INFO,str); ! 456: ! 457: if((svc->status_handle = RegisterServiceCtrlHandler(svc->name, svc->ctrl_handler))==0) { ! 458: sprintf(str,"!ERROR %d registering service control handler",GetLastError()); ! 459: svc_lputs(NULL,LOG_ERR,str); ! 460: return; ! 461: } ! 462: ! 463: memset(&svc->status,0,sizeof(SERVICE_STATUS)); ! 464: svc->status.dwServiceType=SERVICE_WIN32_SHARE_PROCESS; ! 465: svc->status.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN; ! 466: svc->status.dwWaitHint=NTSVC_TIMEOUT_STARTUP; ! 467: ! 468: svc->status.dwCurrentState=SERVICE_START_PENDING; ! 469: SetServiceStatus(svc->status_handle, &svc->status); ! 470: ! 471: read_ini(svc); ! 472: ! 473: svc->thread(svc->startup); ! 474: ! 475: svc->status.dwCurrentState=SERVICE_STOPPED; ! 476: SetServiceStatus(svc->status_handle, &svc->status); ! 477: ! 478: if(svc->log_handle!=INVALID_HANDLE_VALUE) { ! 479: CloseHandle(svc->log_handle); ! 480: svc->log_handle=INVALID_HANDLE_VALUE; ! 481: } ! 482: ! 483: if(svc->event_handle!=NULL) { ! 484: DeregisterEventSource(svc->event_handle); ! 485: svc->event_handle=NULL; ! 486: } ! 487: } ! 488: ! 489: /* Service-specific ServiceMain stub functions */ ! 490: ! 491: static void WINAPI bbs_start(DWORD dwArgc, LPTSTR *lpszArgv) ! 492: { ! 493: svc_main(&bbs, dwArgc, lpszArgv); ! 494: ! 495: /* Events are (currently) part of the BBS service */ ! 496: if(event.log_handle!=INVALID_HANDLE_VALUE) { ! 497: CloseHandle(event.log_handle); ! 498: event.log_handle=INVALID_HANDLE_VALUE; ! 499: } ! 500: } ! 501: ! 502: static void WINAPI ftp_start(DWORD dwArgc, LPTSTR *lpszArgv) ! 503: { ! 504: svc_main(&ftp, dwArgc, lpszArgv); ! 505: } ! 506: ! 507: static void WINAPI web_start(DWORD dwArgc, LPTSTR *lpszArgv) ! 508: { ! 509: svc_main(&web, dwArgc, lpszArgv); ! 510: } ! 511: ! 512: static void WINAPI mail_start(DWORD dwArgc, LPTSTR *lpszArgv) ! 513: { ! 514: svc_main(&mail, dwArgc, lpszArgv); ! 515: } ! 516: ! 517: static void WINAPI services_start(DWORD dwArgc, LPTSTR *lpszArgv) ! 518: { ! 519: svc_main(&services, dwArgc, lpszArgv); ! 520: } ! 521: ! 522: /******************************************/ ! 523: /* NT Serivce Install/Uninstall Functions */ ! 524: /******************************************/ ! 525: ! 526: /* ChangeServiceConfig2 is a Win2K+ API function, must call dynamically */ ! 527: typedef WINADVAPI BOOL (WINAPI *ChangeServiceConfig2_t)(SC_HANDLE, DWORD, LPCVOID); ! 528: ! 529: static void describe_service(HANDLE hSCMlib, SC_HANDLE hService, char* description) ! 530: { ! 531: ChangeServiceConfig2_t changeServiceConfig2; ! 532: static SERVICE_DESCRIPTION service_desc; ! 533: ! 534: if(hSCMlib==NULL) ! 535: return; ! 536: ! 537: service_desc.lpDescription=description; ! 538: ! 539: if((changeServiceConfig2 = (ChangeServiceConfig2_t)GetProcAddress(hSCMlib, "ChangeServiceConfig2A"))!=NULL) ! 540: changeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &service_desc); ! 541: } ! 542: ! 543: static BOOL register_event_source(char* name, char* path) ! 544: { ! 545: char keyname[256]; ! 546: HKEY hKey; ! 547: DWORD type; ! 548: DWORD disp; ! 549: LONG retval; ! 550: char* value; ! 551: ! 552: sprintf(keyname,"system\\CurrentControlSet\\services\\eventlog\\application\\%s",name); ! 553: ! 554: retval=RegCreateKeyEx( ! 555: HKEY_LOCAL_MACHINE, /* handle to an open key */ ! 556: keyname, /* address of subkey name */ ! 557: 0, /* reserved */ ! 558: "", /* address of class string */ ! 559: 0, /* special options flag */ ! 560: KEY_ALL_ACCESS, /* desired security access */ ! 561: NULL, /* address of key security structure */ ! 562: &hKey, /* address of buffer for opened handle */ ! 563: &disp /* address of disposition value buffer */ ! 564: ); ! 565: ! 566: if(retval!=ERROR_SUCCESS) { ! 567: fprintf(stderr,"!Error %d creating/opening registry key (HKLM\\%s)\n" ! 568: ,retval,keyname); ! 569: return(FALSE); ! 570: } ! 571: ! 572: value="EventMessageFile"; ! 573: retval=RegSetValueEx( ! 574: hKey, /* handle to key to set value for */ ! 575: value, /* name of the value to set */ ! 576: 0, /* reserved */ ! 577: REG_SZ, /* flag for value type */ ! 578: path, /* address of value data */ ! 579: strlen(path) /* size of value data */ ! 580: ); ! 581: ! 582: if(retval!=ERROR_SUCCESS) { ! 583: RegCloseKey(hKey); ! 584: fprintf(stderr,"!Error %d setting registry key value (%s)\n" ! 585: ,retval,value); ! 586: return(FALSE); ! 587: } ! 588: ! 589: value="TypesSupported"; ! 590: type=EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; ! 591: retval=RegSetValueEx( ! 592: hKey, /* handle to key to set value for */ ! 593: value, /* name of the value to set */ ! 594: 0, /* reserved */ ! 595: REG_DWORD, /* flag for value type */ ! 596: (BYTE*)&type, /* address of value data */ ! 597: sizeof(type) /* size of value data */ ! 598: ); ! 599: ! 600: RegCloseKey(hKey); ! 601: ! 602: if(retval!=ERROR_SUCCESS) { ! 603: fprintf(stderr,"!Error %d setting registry key value (%s)\n" ! 604: ,retval,value); ! 605: return(FALSE); ! 606: } ! 607: ! 608: return(TRUE); ! 609: } ! 610: ! 611: static const char* start_type_desc(DWORD start_type) ! 612: { ! 613: static char str[128]; ! 614: ! 615: switch(start_type) { ! 616: case SERVICE_AUTO_START: return("Startup: Automatic"); ! 617: case SERVICE_DEMAND_START: return("Startup: Manual"); ! 618: case SERVICE_DISABLED: return("Disabled"); ! 619: case SERVICE_NOT_INSTALLED: return("Not installed"); ! 620: } ! 621: ! 622: sprintf(str,"Start_type: %d", start_type); ! 623: return(str); ! 624: } ! 625: ! 626: static const char* state_desc(DWORD state) ! 627: { ! 628: static char str[128]; ! 629: ! 630: switch(state) { ! 631: case SERVICE_STOPPED: return("Stopped"); ! 632: case SERVICE_START_PENDING: return("Start Pending"); ! 633: case SERVICE_STOP_PENDING: return("Stop Pending"); ! 634: case SERVICE_RUNNING: return("Running"); ! 635: case SERVICE_CONTINUE_PENDING: return("Continue Pending"); ! 636: case SERVICE_PAUSE_PENDING: return("Pause Pending"); ! 637: case SERVICE_PAUSED: return("Paused"); ! 638: } ! 639: ! 640: sprintf(str,"State: %d", state); ! 641: return(str); ! 642: } ! 643: ! 644: static const char* control_desc(DWORD ctrl) ! 645: { ! 646: static char str[128]; ! 647: ! 648: switch(ctrl) { ! 649: case SERVICE_CONTROL_STOP: ! 650: return("Stopping"); ! 651: case SERVICE_CONTROL_PAUSE: ! 652: return("Pausing"); ! 653: case SERVICE_CONTROL_CONTINUE: ! 654: return("Continuing"); ! 655: case SERVICE_CONTROL_INTERROGATE: ! 656: return("Interrogating"); ! 657: case SERVICE_CONTROL_SHUTDOWN: ! 658: return("Shutting-down"); ! 659: ! 660: /* Synchronet-specific */ ! 661: case SERVICE_CONTROL_RECYCLE: ! 662: return("Recycling"); ! 663: case SERVICE_CONTROL_MUTE: ! 664: return("Muting"); ! 665: case SERVICE_CONTROL_UNMUTE: ! 666: return("Un-muting"); ! 667: case SERVICE_CONTROL_SYSOP_AVAILABLE: ! 668: return("Sysop Available"); ! 669: case SERVICE_CONTROL_SYSOP_UNAVAILABLE: ! 670: return("Sysop Unavailable"); ! 671: } ! 672: sprintf(str,"Control: %d", ctrl); ! 673: return(str); ! 674: } ! 675: ! 676: /****************************************************************************/ ! 677: /* Utility function to detect if a service is currently disabled */ ! 678: /****************************************************************************/ ! 679: static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state) ! 680: { ! 681: SC_HANDLE hService; ! 682: DWORD size; ! 683: DWORD err; ! 684: SERVICE_STATUS status; ! 685: LPQUERY_SERVICE_CONFIG service_config; ! 686: ! 687: if(state!=NULL) ! 688: *state=SERVICE_STOPPED; ! 689: ! 690: if((hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS))==NULL) { ! 691: if((err=GetLastError())==ERROR_SERVICE_DOES_NOT_EXIST) ! 692: return(SERVICE_NOT_INSTALLED); ! 693: printf("\n!ERROR %d opening service: %s\n",err,name); ! 694: return(-1); ! 695: } ! 696: ! 697: if(QueryServiceConfig( ! 698: hService, /* handle of service */ ! 699: NULL, /* address of service config. structure */ ! 700: 0, /* size of service configuration buffer */ ! 701: &size /* address of variable for bytes needed */ ! 702: ) || GetLastError()!=ERROR_INSUFFICIENT_BUFFER) { ! 703: printf("\n!Unexpected QueryServiceConfig ERROR %u\n",err=GetLastError()); ! 704: return(-1); ! 705: } ! 706: ! 707: if(state!=NULL && QueryServiceStatus(hService,&status)) ! 708: *state=status.dwCurrentState; ! 709: ! 710: if((service_config=alloca(size))==NULL) { ! 711: printf("\n!ERROR allocating %u bytes of memory\n", size); ! 712: return(-1); ! 713: } ! 714: ! 715: if(!QueryServiceConfig( ! 716: hService, /* handle of service */ ! 717: service_config, /* address of service config. structure */ ! 718: size, /* size of service configuration buffer */ ! 719: &size /* address of variable for bytes needed */ ! 720: )) { ! 721: printf("\n!QueryServiceConfig ERROR %u\n",GetLastError()); ! 722: return(-1); ! 723: } ! 724: CloseServiceHandle(hService); ! 725: ! 726: return(service_config->dwStartType); ! 727: } ! 728: ! 729: /****************************************************************************/ ! 730: /* Utility function to create a service with description (on Win2K+) */ ! 731: /****************************************************************************/ ! 732: static SC_HANDLE create_service(HANDLE hSCMlib, SC_HANDLE hSCManager ! 733: ,char* name, char* display_name, char* description, char* path ! 734: ,BOOL autostart) ! 735: { ! 736: SC_HANDLE hService; ! 737: DWORD err; ! 738: DWORD start_type = autostart ? SERVICE_AUTO_START : SERVICE_DEMAND_START; ! 739: ! 740: printf("Installing service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, display_name); ! 741: ! 742: hService = CreateService( ! 743: hSCManager, /* SCManager database */ ! 744: name, /* name of service */ ! 745: display_name, /* name to display */ ! 746: SERVICE_ALL_ACCESS, /* desired access */ ! 747: SERVICE_WIN32_SHARE_PROCESS, /* service type */ ! 748: start_type, /* start type (auto or manual) */ ! 749: SERVICE_ERROR_NORMAL, /* error control type */ ! 750: path, /* service's binary */ ! 751: NULL, /* no load ordering group */ ! 752: NULL, /* no tag identifier */ ! 753: "", /* dependencies */ ! 754: NULL, /* LocalSystem account */ ! 755: NULL); /* no password */ ! 756: ! 757: if(hService==NULL) { ! 758: if((err=GetLastError())==ERROR_SERVICE_EXISTS) ! 759: printf("Already installed\n"); ! 760: else ! 761: printf("!ERROR %d\n",err); ! 762: } ! 763: else { ! 764: describe_service(hSCMlib, hService,description); ! 765: CloseServiceHandle(hService); ! 766: printf("%s\n", start_type_desc(start_type)); ! 767: ! 768: register_event_source(name,path); ! 769: register_event_source(NTSVC_NAME_EVENT,path); /* Create SynchronetEvent event source */ ! 770: } ! 771: ! 772: return(hService); ! 773: } ! 774: ! 775: /****************************************************************************/ ! 776: /* Install one or all services */ ! 777: /****************************************************************************/ ! 778: static int install(const char* svc_name) ! 779: { ! 780: int i; ! 781: HANDLE hSCMlib; ! 782: SC_HANDLE hSCManager; ! 783: char path[MAX_PATH+1]; ! 784: ! 785: printf("Installing Synchronet NT Services...\n"); ! 786: ! 787: hSCMlib = LoadLibrary("ADVAPI32.DLL"); ! 788: ! 789: if(GetModuleFileName(NULL,path,sizeof(path))==0) ! 790: { ! 791: fprintf(stderr,"!ERROR %d getting module file name\n",GetLastError()); ! 792: return(-1); ! 793: } ! 794: ! 795: hSCManager = OpenSCManager( ! 796: NULL, /* machine (NULL == local) */ ! 797: NULL, /* database (NULL == default) */ ! 798: SC_MANAGER_ALL_ACCESS /* access required */ ! 799: ); ! 800: if(hSCManager==NULL) { ! 801: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 802: return(-1); ! 803: } ! 804: ! 805: for(i=0;ntsvc_list[i]!=NULL;i++) ! 806: if(svc_name==NULL /* All? */ ! 807: || !stricmp(ntsvc_list[i]->name, svc_name) ! 808: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) ! 809: create_service(hSCMlib ! 810: ,hSCManager ! 811: ,ntsvc_list[i]->name ! 812: ,ntsvc_list[i]->display_name ! 813: ,ntsvc_list[i]->description ! 814: ,path ! 815: ,ntsvc_list[i]->autostart); ! 816: ! 817: if(hSCMlib!=NULL) ! 818: FreeLibrary(hSCMlib); ! 819: ! 820: CloseServiceHandle(hSCManager); ! 821: ! 822: return(0); ! 823: } ! 824: ! 825: static SC_HANDLE open_service(SC_HANDLE hSCManager, char* name) ! 826: { ! 827: SC_HANDLE hService; ! 828: DWORD err; ! 829: ! 830: if((hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS))==NULL) { ! 831: if((err=GetLastError())==ERROR_SERVICE_DOES_NOT_EXIST) ! 832: printf("Not installed\n"); ! 833: else ! 834: printf("\n!ERROR %d opening service: %s\n",err,name); ! 835: return(NULL); ! 836: } ! 837: ! 838: return(hService); ! 839: } ! 840: ! 841: /****************************************************************************/ ! 842: /* Utility function to remove a service cleanly (stopping if necessary) */ ! 843: /****************************************************************************/ ! 844: static void remove_service(SC_HANDLE hSCManager, char* name, char* disp_name) ! 845: { ! 846: SC_HANDLE hService; ! 847: SERVICE_STATUS status; ! 848: ! 849: printf("Removing: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name); ! 850: ! 851: if((hService=open_service(hSCManager, name))==NULL) ! 852: return; ! 853: ! 854: /* try to stop the service */ ! 855: if(ControlService( hService, SERVICE_CONTROL_STOP, &status)) ! 856: { ! 857: printf("\nStopping: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name); ! 858: ! 859: while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING) ! 860: Sleep(1000); ! 861: ! 862: if(status.dwCurrentState == SERVICE_STOPPED) ! 863: printf("Stopped, "); ! 864: else ! 865: printf("FAILED!, "); ! 866: } ! 867: ! 868: /* now remove the service */ ! 869: if(DeleteService(hService)) ! 870: printf("Removed\n"); ! 871: else ! 872: printf("!ERROR %d\n",GetLastError()); ! 873: CloseServiceHandle(hService); ! 874: } ! 875: ! 876: /****************************************************************************/ ! 877: /* Utility function to stop a service */ ! 878: /****************************************************************************/ ! 879: static void stop_service(SC_HANDLE hSCManager, char* name, char* disp_name) ! 880: { ! 881: SC_HANDLE hService; ! 882: SERVICE_STATUS status; ! 883: ! 884: printf("Stopping service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name); ! 885: if((hService=open_service(hSCManager, name))==NULL) ! 886: return; ! 887: ! 888: /* try to stop the service */ ! 889: if(ControlService( hService, SERVICE_CONTROL_STOP, &status)) ! 890: { ! 891: while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING) ! 892: Sleep(1000); ! 893: ! 894: if(status.dwCurrentState == SERVICE_STOPPED) ! 895: printf("Stopped\n"); ! 896: else ! 897: printf("FAILED!\n"); ! 898: } else ! 899: printf("Already stopped\n"); ! 900: ! 901: CloseServiceHandle(hService); ! 902: } ! 903: ! 904: /****************************************************************************/ ! 905: /* Utility function to stop a service */ ! 906: /****************************************************************************/ ! 907: static void control_service(SC_HANDLE hSCManager, char* name, char* disp_name, DWORD ctrl) ! 908: { ! 909: SC_HANDLE hService; ! 910: SERVICE_STATUS status; ! 911: DWORD err; ! 912: ! 913: printf("%s service: %-*s ... ", control_desc(ctrl), STRLEN_MAX_DISPLAY_NAME, disp_name); ! 914: if((hService=open_service(hSCManager, name))==NULL) ! 915: return; ! 916: ! 917: /* try to stop the service */ ! 918: if(!ControlService( hService, SERVICE_CONTROL_STOP, &status)) { ! 919: if((err=GetLastError())==ERROR_SERVICE_NOT_ACTIVE) ! 920: printf("Not active\n"); ! 921: else ! 922: printf("!ERROR %d\n",err); ! 923: } else ! 924: printf("Successful\n"); ! 925: ! 926: CloseServiceHandle(hService); ! 927: } ! 928: ! 929: ! 930: ! 931: /****************************************************************************/ ! 932: /* Control one or all services */ ! 933: /****************************************************************************/ ! 934: static int control(const char* svc_name, DWORD ctrl) ! 935: { ! 936: int i; ! 937: SC_HANDLE hSCManager; ! 938: ! 939: hSCManager = OpenSCManager( ! 940: NULL, /* machine (NULL == local) */ ! 941: NULL, /* database (NULL == default) */ ! 942: SC_MANAGER_ALL_ACCESS /* access required */ ! 943: ); ! 944: if(hSCManager==NULL) { ! 945: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 946: return(-1); ! 947: } ! 948: ! 949: for(i=0;ntsvc_list[i]!=NULL;i++) { ! 950: #if 0 ! 951: if(svc_name==NULL ! 952: && get_service_info(hSCManager, ntsvc_list[i]->name,NULL)==SERVICE_DISABLED) ! 953: continue; ! 954: #endif ! 955: if(svc_name==NULL /* All? */ ! 956: || !stricmp(ntsvc_list[i]->name, svc_name) ! 957: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) ! 958: switch(ctrl) { ! 959: case SERVICE_CONTROL_STOP: ! 960: stop_service(hSCManager ! 961: ,ntsvc_list[i]->name ! 962: ,ntsvc_list[i]->display_name); ! 963: break; ! 964: default: ! 965: control_service(hSCManager ! 966: ,ntsvc_list[i]->name ! 967: ,ntsvc_list[i]->display_name ! 968: ,ctrl); ! 969: break; ! 970: } ! 971: } ! 972: ! 973: CloseServiceHandle(hSCManager); ! 974: ! 975: return(0); ! 976: } ! 977: ! 978: /****************************************************************************/ ! 979: /* Utility function to start a service */ ! 980: /****************************************************************************/ ! 981: static void start_service(SC_HANDLE hSCManager, char* name, char* disp_name ! 982: ,int argc, char** argv) ! 983: { ! 984: SC_HANDLE hService; ! 985: SERVICE_STATUS status; ! 986: ! 987: printf("Starting service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name); ! 988: if((hService=open_service(hSCManager, name))==NULL) ! 989: return; ! 990: ! 991: if(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_RUNNING) ! 992: printf("Already running\n"); ! 993: else { ! 994: /* Start the service */ ! 995: if(StartService(hService, argc, (LPCTSTR*)argv)) ! 996: { ! 997: while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_START_PENDING) ! 998: Sleep(1000); ! 999: ! 1000: if(status.dwCurrentState == SERVICE_RUNNING) ! 1001: printf("Started\n"); ! 1002: else ! 1003: printf("FAILED!\n"); ! 1004: } else ! 1005: printf("!ERROR %u\n", GetLastError()); ! 1006: } ! 1007: ! 1008: CloseServiceHandle(hService); ! 1009: } ! 1010: ! 1011: /****************************************************************************/ ! 1012: /* Uninstall one or all services */ ! 1013: /****************************************************************************/ ! 1014: static int uninstall(const char* svc_name) ! 1015: { ! 1016: int i; ! 1017: SC_HANDLE hSCManager; ! 1018: ! 1019: hSCManager = OpenSCManager( ! 1020: NULL, /* machine (NULL == local) */ ! 1021: NULL, /* database (NULL == default) */ ! 1022: SC_MANAGER_ALL_ACCESS /* access required */ ! 1023: ); ! 1024: if(hSCManager==NULL) { ! 1025: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 1026: return(-1); ! 1027: } ! 1028: ! 1029: for(i=0;ntsvc_list[i]!=NULL;i++) ! 1030: if(svc_name==NULL /* All? */ ! 1031: || !stricmp(ntsvc_list[i]->name, svc_name) ! 1032: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) ! 1033: remove_service(hSCManager ! 1034: ,ntsvc_list[i]->name ! 1035: ,ntsvc_list[i]->display_name); ! 1036: ! 1037: CloseServiceHandle(hSCManager); ! 1038: ! 1039: return(0); ! 1040: } ! 1041: ! 1042: /****************************************************************************/ ! 1043: /* Utility function to disable a service */ ! 1044: /****************************************************************************/ ! 1045: static void set_service_start_type(SC_HANDLE hSCManager, char* name ! 1046: ,char* disp_name, DWORD start_type) ! 1047: { ! 1048: SC_HANDLE hService; ! 1049: ! 1050: printf("%s service: %-*s ... " ! 1051: ,start_type==SERVICE_DISABLED ? "Disabling" : "Enabling" ! 1052: ,STRLEN_MAX_DISPLAY_NAME, disp_name); ! 1053: ! 1054: if((hService=open_service(hSCManager, name))==NULL) ! 1055: return; ! 1056: ! 1057: if(!ChangeServiceConfig( ! 1058: hService, /* handle to service */ ! 1059: SERVICE_NO_CHANGE, /* type of service */ ! 1060: start_type, /* when to start service */ ! 1061: SERVICE_NO_CHANGE, /* severity if service fails to start */ ! 1062: NULL, /* pointer to service binary file name */ ! 1063: NULL, /* pointer to load ordering group name */ ! 1064: NULL, /* pointer to variable to get tag identifier */ ! 1065: NULL, /* pointer to array of dependency names */ ! 1066: NULL, /* pointer to account name of service */ ! 1067: NULL, /* pointer to password for service account */ ! 1068: NULL /* pointer to display name */ ! 1069: )) ! 1070: printf("\n!ERROR %d changing service config for: %s\n",GetLastError(),name); ! 1071: else ! 1072: printf("%s\n", start_type_desc(start_type)); ! 1073: ! 1074: CloseServiceHandle(hService); ! 1075: } ! 1076: ! 1077: /****************************************************************************/ ! 1078: /* Enable (set to auto-start) or disable one or all services */ ! 1079: /****************************************************************************/ ! 1080: static int enable(const char* svc_name, BOOL enabled) ! 1081: { ! 1082: int i; ! 1083: SC_HANDLE hSCManager; ! 1084: ! 1085: hSCManager = OpenSCManager( ! 1086: NULL, /* machine (NULL == local) */ ! 1087: NULL, /* database (NULL == default) */ ! 1088: SC_MANAGER_ALL_ACCESS /* access required */ ! 1089: ); ! 1090: if(hSCManager==NULL) { ! 1091: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 1092: return(-1); ! 1093: } ! 1094: ! 1095: for(i=0;ntsvc_list[i]!=NULL;i++) ! 1096: if(svc_name==NULL /* All? */ ! 1097: || !stricmp(ntsvc_list[i]->name, svc_name) ! 1098: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) ! 1099: set_service_start_type(hSCManager ! 1100: ,ntsvc_list[i]->name ! 1101: ,ntsvc_list[i]->display_name ! 1102: ,enabled ? (ntsvc_list[i]->autostart ? SERVICE_AUTO_START : SERVICE_DEMAND_START) ! 1103: : SERVICE_DISABLED); ! 1104: ! 1105: CloseServiceHandle(hSCManager); ! 1106: ! 1107: return(0); ! 1108: } ! 1109: ! 1110: /****************************************************************************/ ! 1111: /* List one or all services */ ! 1112: /****************************************************************************/ ! 1113: static int list(const char* svc_name) ! 1114: { ! 1115: int i; ! 1116: SC_HANDLE hSCManager; ! 1117: DWORD state; ! 1118: DWORD start_type; ! 1119: ! 1120: hSCManager = OpenSCManager( ! 1121: NULL, /* machine (NULL == local) */ ! 1122: NULL, /* database (NULL == default) */ ! 1123: SC_MANAGER_ALL_ACCESS /* access required */ ! 1124: ); ! 1125: if(hSCManager==NULL) { ! 1126: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 1127: return(-1); ! 1128: } ! 1129: ! 1130: for(i=0;ntsvc_list[i]!=NULL;i++) { ! 1131: if(svc_name==NULL ! 1132: || !stricmp(ntsvc_list[i]->name, svc_name) ! 1133: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) { ! 1134: start_type = get_service_info(hSCManager, ntsvc_list[i]->name, &state); ! 1135: printf("%-*s ... %s, %s\n" ! 1136: ,STRLEN_MAX_DISPLAY_NAME, ntsvc_list[i]->display_name ! 1137: ,start_type_desc(start_type) ! 1138: ,state_desc(state)); ! 1139: } ! 1140: } ! 1141: ! 1142: CloseServiceHandle(hSCManager); ! 1143: ! 1144: return(0); ! 1145: } ! 1146: ! 1147: /****************************************************************************/ ! 1148: /* Start one or all services */ ! 1149: /****************************************************************************/ ! 1150: static int start(const char* svc_name, int argc, char** argv) ! 1151: { ! 1152: int i; ! 1153: SC_HANDLE hSCManager; ! 1154: ! 1155: hSCManager = OpenSCManager( ! 1156: NULL, /* machine (NULL == local) */ ! 1157: NULL, /* database (NULL == default) */ ! 1158: SC_MANAGER_ALL_ACCESS /* access required */ ! 1159: ); ! 1160: if(hSCManager==NULL) { ! 1161: fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError()); ! 1162: return(-1); ! 1163: } ! 1164: ! 1165: for(i=0;ntsvc_list[i]!=NULL;i++) { ! 1166: if(svc_name==NULL ! 1167: && get_service_info(hSCManager, ntsvc_list[i]->name,NULL)==SERVICE_DISABLED) ! 1168: continue; ! 1169: if(svc_name==NULL ! 1170: || !stricmp(ntsvc_list[i]->name, svc_name) ! 1171: || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) ! 1172: start_service(hSCManager,ntsvc_list[i]->name,ntsvc_list[i]->display_name ! 1173: ,argc,argv); ! 1174: } ! 1175: ! 1176: CloseServiceHandle(hSCManager); ! 1177: ! 1178: return(0); ! 1179: } ! 1180: ! 1181: /****************************************************************************/ ! 1182: /* Main Entry Point */ ! 1183: /****************************************************************************/ ! 1184: int main(int argc, char** argv) ! 1185: { ! 1186: char* ctrl_dir; ! 1187: char* arg; ! 1188: char* p; ! 1189: char str[MAX_PATH+1]; ! 1190: int i; ! 1191: FILE* fp=NULL; ! 1192: BOOL start_services=TRUE; ! 1193: ! 1194: SERVICE_TABLE_ENTRY ServiceDispatchTable[] = ! 1195: { ! 1196: { NTSVC_NAME_BBS, bbs_start }, ! 1197: { NTSVC_NAME_FTP, ftp_start }, ! 1198: { NTSVC_NAME_WEB, web_start }, ! 1199: { NTSVC_NAME_MAIL, mail_start }, ! 1200: { NTSVC_NAME_SERVICES, services_start }, ! 1201: { NULL, NULL } /* Terminator */ ! 1202: }; ! 1203: ! 1204: printf("\nSynchronet NT Services Version %s%c %s\n\n" ! 1205: ,VERSION,REVISION,COPYRIGHT_NOTICE); ! 1206: ! 1207: ctrl_dir=getenv("SBBSCTRL"); /* read from environment variable */ ! 1208: if(ctrl_dir==NULL || ctrl_dir[0]==0) { ! 1209: ctrl_dir="\\sbbs\\ctrl"; /* Not set? Use default */ ! 1210: printf("!SBBSCTRL environment variable not set, using default value: %s\n\n" ! 1211: ,ctrl_dir); ! 1212: } ! 1213: ! 1214: sbbs_get_ini_fname(ini_file, ctrl_dir, NULL /* auto-host_name */); ! 1215: ! 1216: /* Initialize BBS startup structure */ ! 1217: memset(&bbs_startup,0,sizeof(bbs_startup)); ! 1218: bbs_startup.size=sizeof(bbs_startup); ! 1219: bbs_startup.cbdata=&bbs; ! 1220: bbs_startup.lputs=svc_lputs; ! 1221: bbs_startup.event_lputs=event_lputs; ! 1222: bbs_startup.started=svc_started; ! 1223: bbs_startup.recycle=svc_recycle; ! 1224: bbs_startup.terminated=svc_terminated; ! 1225: bbs_startup.clients=svc_clients; ! 1226: strcpy(bbs_startup.ctrl_dir,ctrl_dir); ! 1227: ! 1228: /* Initialize FTP startup structure */ ! 1229: memset(&ftp_startup,0,sizeof(ftp_startup)); ! 1230: ftp_startup.cbdata=&ftp; ! 1231: ftp_startup.size=sizeof(ftp_startup); ! 1232: ftp_startup.lputs=svc_lputs; ! 1233: ftp_startup.started=svc_started; ! 1234: ftp_startup.recycle=svc_recycle; ! 1235: ftp_startup.terminated=svc_terminated; ! 1236: ftp_startup.clients=svc_clients; ! 1237: strcpy(ftp_startup.ctrl_dir,ctrl_dir); ! 1238: ! 1239: /* Initialize Web Server startup structure */ ! 1240: memset(&web_startup,0,sizeof(web_startup)); ! 1241: web_startup.cbdata=&web; ! 1242: web_startup.size=sizeof(web_startup); ! 1243: web_startup.lputs=svc_lputs; ! 1244: web_startup.started=svc_started; ! 1245: web_startup.recycle=svc_recycle; ! 1246: web_startup.terminated=svc_terminated; ! 1247: web_startup.clients=svc_clients; ! 1248: strcpy(web_startup.ctrl_dir,ctrl_dir); ! 1249: ! 1250: /* Initialize Mail Server startup structure */ ! 1251: memset(&mail_startup,0,sizeof(mail_startup)); ! 1252: mail_startup.cbdata=&mail; ! 1253: mail_startup.size=sizeof(mail_startup); ! 1254: mail_startup.lputs=svc_lputs; ! 1255: mail_startup.started=svc_started; ! 1256: mail_startup.recycle=svc_recycle; ! 1257: mail_startup.terminated=svc_terminated; ! 1258: mail_startup.clients=svc_clients; ! 1259: strcpy(mail_startup.ctrl_dir,ctrl_dir); ! 1260: ! 1261: /* Initialize Services startup structure */ ! 1262: memset(&services_startup,0,sizeof(services_startup)); ! 1263: services_startup.cbdata=&services; ! 1264: services_startup.size=sizeof(services_startup); ! 1265: services_startup.lputs=svc_lputs; ! 1266: services_startup.started=svc_started; ! 1267: services_startup.recycle=svc_recycle; ! 1268: services_startup.terminated=svc_terminated; ! 1269: services_startup.clients=svc_clients; ! 1270: strcpy(services_startup.ctrl_dir,ctrl_dir); ! 1271: ! 1272: /* Read .ini file here */ ! 1273: if((fp=fopen(ini_file,"r"))!=NULL) { ! 1274: sprintf(str,"Reading %s",ini_file); ! 1275: svc_lputs(NULL,LOG_INFO,str); ! 1276: } ! 1277: ! 1278: /* We call this function to set defaults, even if there's no .ini file */ ! 1279: sbbs_read_ini(fp ! 1280: ,NULL /* global_startup */ ! 1281: ,&bbs.autostart ,NULL ! 1282: ,&ftp.autostart ,NULL ! 1283: ,&web.autostart ,NULL ! 1284: ,&mail.autostart ,NULL ! 1285: ,&services.autostart ,NULL ! 1286: ); ! 1287: ! 1288: /* close .ini file here */ ! 1289: if(fp!=NULL) ! 1290: fclose(fp); ! 1291: ! 1292: if(chdir(ctrl_dir)!=0) { ! 1293: sprintf(str,"!ERROR %d changing directory to: %s", errno, ctrl_dir); ! 1294: svc_lputs(NULL,LOG_ERR,str); ! 1295: } ! 1296: ! 1297: for(i=1;i<argc;i++) { ! 1298: arg=argv[i]; ! 1299: while(*arg=='-' || *arg=='/') ! 1300: arg++; ! 1301: if(!stricmp(arg,"help") || *arg=='?') ! 1302: start_services=FALSE; ! 1303: ! 1304: if(!stricmp(arg,"list")) ! 1305: return list(argv[i+1]); ! 1306: ! 1307: if(!stricmp(arg,"install")) ! 1308: return install(argv[i+1]); ! 1309: ! 1310: if(!stricmp(arg,"remove")) ! 1311: return uninstall(argv[i+1]); ! 1312: ! 1313: if(!stricmp(arg,"disable")) ! 1314: return enable(argv[i+1], FALSE); ! 1315: ! 1316: if(!stricmp(arg,"enable")) ! 1317: return enable(argv[i+1], TRUE); ! 1318: ! 1319: if(!stricmp(arg,"stop")) ! 1320: return control(argv[i+1],SERVICE_CONTROL_STOP); ! 1321: ! 1322: if(!stricmp(arg,"start")) ! 1323: return start(argv[i+1],argc,argv); ! 1324: ! 1325: if(!stricmp(arg,"recycle")) ! 1326: return control(argv[i+1],SERVICE_CONTROL_RECYCLE); ! 1327: ! 1328: if(!stricmp(arg,"mute")) ! 1329: return control(argv[i+1],SERVICE_CONTROL_MUTE); ! 1330: ! 1331: if(!stricmp(arg,"unmute")) ! 1332: return control(argv[i+1],SERVICE_CONTROL_UNMUTE); ! 1333: } ! 1334: ! 1335: if(start_services) { ! 1336: printf("Starting service control dispatcher.\n" ); ! 1337: printf("This may take several seconds. Please wait.\n" ); ! 1338: ! 1339: if(StartServiceCtrlDispatcher(ServiceDispatchTable)) ! 1340: return(0); ! 1341: ! 1342: sprintf(str,"!ERROR %u starting service control dispatcher",GetLastError()); ! 1343: printf("%s\n\n",str); ! 1344: OutputDebugString(str); ! 1345: } ! 1346: ! 1347: SAFECOPY(str,getfname(argv[0])); ! 1348: if((p=getfext(str))!=NULL) ! 1349: *p=0; ! 1350: ! 1351: printf("Usage: %s [command] [service]\n", str); ! 1352: ! 1353: printf("\nIf service name not specified, default is ALL services.\n"); ! 1354: ! 1355: printf("\nAvailable Commands:\n\n"); ! 1356: printf("%-20s %s\n","list","to list services"); ! 1357: printf("%-20s %s\n","install","to install services"); ! 1358: printf("%-20s %s\n","remove","to remove serivces"); ! 1359: printf("%-20s %s\n","disable","to disable services"); ! 1360: printf("%-20s %s\n","enable","to re-enable disabled services"); ! 1361: printf("%-20s %s\n","start","to start services"); ! 1362: printf("%-20s %s\n","stop","to stop services"); ! 1363: printf("%-20s %s\n","recycle","to recycle services"); ! 1364: printf("%-20s %s\n","mute","to mute (sounds of) services"); ! 1365: printf("%-20s %s\n","unmute","to unmute (sounds of) services"); ! 1366: ! 1367: printf("\nAvailable Services:\n\n"); ! 1368: printf("%-20s %s\n","Name","Description"); ! 1369: printf("%-20s %s\n","----","-----------"); ! 1370: for(i=0;ntsvc_list[i]!=NULL;i++) ! 1371: printf("%-20s %s\n",ntsvc_list[i]->name+STRLEN_SYNCHRONET,ntsvc_list[i]->display_name); ! 1372: ! 1373: return(0); ! 1374: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.