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