Annotation of embedaddon/ntp/ports/winnt/ntpd/ntservice.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (C) 1999-2002  Internet Software Consortium.
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
        !            10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
        !            11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
        !            12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
        !            14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
        !            15:  * PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: /* $Id: ntservice.c,v 1.3.2.1.10.3 2004/03/08 04:04:22 marka Exp $ */
        !            19: 
        !            20: #ifdef HAVE_CONFIG_H
        !            21: # include <config.h>
        !            22: #endif
        !            23: 
        !            24: #include <stdio.h>
        !            25: 
        !            26: #include <ntp_cmdargs.h>
        !            27: #include <ntp_stdlib.h>
        !            28: #include "syslog.h"
        !            29: #include "ntservice.h"
        !            30: #include "clockstuff.h"
        !            31: #include "ntp_iocompletionport.h"
        !            32: #include "isc/win32os.h"
        !            33: #include <ssl_applink.c>
        !            34: 
        !            35: 
        !            36: /*
        !            37:  * Globals
        !            38:  */
        !            39: static SERVICE_STATUS_HANDLE hServiceStatus = 0;
        !            40: static BOOL foreground = FALSE;
        !            41: static BOOL computer_shutting_down = FALSE;
        !            42: static int glb_argc;
        !            43: static char **glb_argv;
        !            44: HANDLE hServDoneEvent = NULL;
        !            45: extern volatile int debug;
        !            46: extern int accept_wildcard_if_for_winnt;
        !            47: 
        !            48: /*
        !            49:  * Forward declarations
        !            50:  */
        !            51: void uninit_io_completion_port();
        !            52: int ntpdmain(int argc, char *argv[]);
        !            53: void WINAPI ServiceControl(DWORD dwCtrlCode);
        !            54: void ntservice_exit(void);
        !            55: 
        !            56: #ifdef WRAP_DBG_MALLOC
        !            57: void *wrap_dbg_malloc(size_t s, const char *f, int l);
        !            58: void *wrap_dbg_realloc(void *p, size_t s, const char *f, int l);
        !            59: void wrap_dbg_free(void *p);
        !            60: #endif
        !            61: 
        !            62: void WINAPI service_main( DWORD argc, LPTSTR *argv )
        !            63: {
        !            64:        if ( argc > 1 )
        !            65:        {
        !            66:                /*
        !            67:                 * Let command line parameters from the Windows SCM GUI
        !            68:                 * override the standard parameters from the ImagePath registry key.
        !            69:                 */
        !            70:                glb_argc = argc;
        !            71:                glb_argv = argv;
        !            72:        }
        !            73: 
        !            74:        ntpdmain( glb_argc, glb_argv );
        !            75: }
        !            76: 
        !            77: 
        !            78: /*
        !            79:  * This is the entry point for the executable 
        !            80:  * We can call ntpdmain() explicitly or via StartServiceCtrlDispatcher()
        !            81:  * as we need to.
        !            82:  */
        !            83: int main( int argc, char *argv[] )
        !            84: {
        !            85:        int rc;
        !            86:        int i = 1;
        !            87: 
        !            88: 
        !            89:        ssl_applink();
        !            90: 
        !            91:        /* Save the command line parameters */
        !            92:        glb_argc = argc;
        !            93:        glb_argv = argv;
        !            94: 
        !            95:        /* Under original Windows NT we must not discard the wildcard */
        !            96:        /* socket to workaround a bug in NT's getsockname(). */
        !            97:        if (isc_win32os_majorversion() <= 4)
        !            98:                accept_wildcard_if_for_winnt = TRUE;
        !            99: 
        !           100:        /*
        !           101:         * This is a hack in the Windows port of ntpd.  Before the
        !           102:         * portable ntpd libopts processing of the command line, we
        !           103:         * need to know if we're "daemonizing" (attempting to start as
        !           104:         * a service).  There is undoubtedly a better way.  Legitimate
        !           105:         * option combinations are broken by this code , such as:
        !           106:         *   ntpd -nc debug.conf
        !           107:         */
        !           108:        while (argv[i]) {
        !           109:                if (!_strnicmp(argv[i], "-d", 2)
        !           110:                    || !strcmp(argv[i], "--debug_level")
        !           111:                    || !strcmp(argv[i], "--set-debug_level")
        !           112:                    || !strcmp(argv[i], "-q")
        !           113:                    || !strcmp(argv[i], "--quit")
        !           114:                    || !strcmp(argv[i], "-?")
        !           115:                    || !strcmp(argv[i], "--help")
        !           116:                    || !_strnicmp(argv[i], "-n", 2)
        !           117:                    || !strcmp(argv[i], "--nofork")
        !           118:                    || !strcmp(argv[i], "--saveconfigquit")) {
        !           119:                        foreground = TRUE;
        !           120:                        break;
        !           121:                }
        !           122:                i++;
        !           123:        }
        !           124: 
        !           125:        if (foreground)                 /* run in console window */
        !           126:                rc = ntpdmain(argc, argv);
        !           127:        else {
        !           128:                /* Start up as service */
        !           129: 
        !           130:                SERVICE_TABLE_ENTRY dispatchTable[] = {
        !           131:                        { TEXT(NTP_DISPLAY_NAME), service_main },
        !           132:                        { NULL, NULL }
        !           133:                };
        !           134: 
        !           135:                rc = StartServiceCtrlDispatcher(dispatchTable);
        !           136:                if (rc)
        !           137:                        rc = 0; 
        !           138:                else {
        !           139:                        rc = GetLastError();
        !           140: #ifdef DEBUG
        !           141:                        fprintf(stderr, "%s: unable to start as service, rc: %i\n\n", argv[0], rc);
        !           142: #endif
        !           143:                        fprintf(stderr, "\nUse -d, -q, --help or -n to run from the command line.\n");
        !           144:                }
        !           145:        }
        !           146:        return rc;
        !           147: }
        !           148: 
        !           149: /*
        !           150:  * Initialize the Service by registering it.
        !           151:  */
        !           152: void
        !           153: ntservice_init() {
        !           154:        char ConsoleTitle[256];
        !           155: 
        !           156:        if (!foreground) {
        !           157:                /* Register handler with the SCM */
        !           158:                hServiceStatus = RegisterServiceCtrlHandler(NTP_DISPLAY_NAME,
        !           159:                                        ServiceControl);
        !           160:                if (!hServiceStatus) {
        !           161:                        NTReportError(NTP_SERVICE_NAME,
        !           162:                                "could not register service control handler");
        !           163:                        exit(1);
        !           164:                }
        !           165:                UpdateSCM(SERVICE_RUNNING);
        !           166:        } else {
        !           167:                strcpy(ConsoleTitle, "NTP Version ");
        !           168:                strcat(ConsoleTitle, Version);
        !           169:                SetConsoleTitle(ConsoleTitle);
        !           170:        }
        !           171: 
        !           172: #ifdef _CRTDBG_MAP_ALLOC
        !           173:                /* ask the runtime to dump memory leaks at exit */
        !           174:                _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF
        !           175:                               | _CRTDBG_LEAK_CHECK_DF          /* report on leaks at exit */
        !           176:                               | _CRTDBG_CHECK_ALWAYS_DF        /* Check heap every alloc/dealloc */
        !           177: #ifdef MALLOC_LINT
        !           178:                               | _CRTDBG_DELAY_FREE_MEM_DF      /* Don't actually free memory */
        !           179: #endif
        !           180:                               );
        !           181: #ifdef DOES_NOT_WORK
        !           182:                        /*
        !           183:                         * hart: I haven't seen this work, running ntpd.exe -n from a shell
        !           184:                         * to both a file and the debugger output window.  Docs indicate it
        !           185:                         * should cause leak report to go to stderr, but it's only seen if
        !           186:                         * ntpd runs under a debugger (in the debugger's output), even with
        !           187:                         * this block of code enabled.
        !           188:                         */
        !           189:                        _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
        !           190:                        _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
        !           191: #endif
        !           192: #endif /* using MS debug C runtime heap, _CRTDBG_MAP_ALLOC */
        !           193: 
        !           194:        atexit( ntservice_exit );
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * Routine to check if this is a service or a foreground program
        !           199:  */
        !           200: BOOL
        !           201: ntservice_isservice() {
        !           202:        return(!foreground);
        !           203: }
        !           204: 
        !           205: /*
        !           206:  * Routine to check if the service is stopping
        !           207:  * because the computer is shutting down
        !           208:  */
        !           209: BOOL
        !           210: ntservice_systemisshuttingdown() {
        !           211:        return computer_shutting_down;
        !           212: }
        !           213: 
        !           214: void
        !           215: ntservice_exit( void )
        !           216: {
        !           217:        uninit_io_completion_port();
        !           218:        Sleep( 200 );   //##++ 
        !           219: 
        !           220:        reset_winnt_time();
        !           221: 
        !           222:        msyslog(LOG_INFO, "ntservice: The Network Time Protocol Service is stopping.");
        !           223: 
        !           224:        if (!foreground) {
        !           225:                /* service mode, need to have the service_main routine
        !           226:                 * register with the service control manager that the 
        !           227:                 * service has stopped running, before exiting
        !           228:                 */
        !           229:                UpdateSCM(SERVICE_STOPPED);
        !           230:        }
        !           231: }
        !           232: 
        !           233: /* 
        !           234:  * ServiceControl(): Handles requests from the SCM and passes them on
        !           235:  * to the service.
        !           236:  */
        !           237: void WINAPI
        !           238: ServiceControl(DWORD dwCtrlCode) {
        !           239:        /* Handle the requested control code */
        !           240:        HANDLE exitEvent = get_exit_event();
        !           241: 
        !           242:        switch(dwCtrlCode) {
        !           243: 
        !           244:        case SERVICE_CONTROL_SHUTDOWN:
        !           245:                computer_shutting_down = TRUE;
        !           246:                /* fall through to stop case */
        !           247: 
        !           248:        case SERVICE_CONTROL_STOP:
        !           249:                if (exitEvent != NULL) {
        !           250:                        SetEvent(exitEvent);
        !           251:                        UpdateSCM(SERVICE_STOP_PENDING);
        !           252:                        Sleep( 100 );  //##++
        !           253:                }
        !           254:                return;
        !           255: 
        !           256:        case SERVICE_CONTROL_PAUSE:
        !           257:        case SERVICE_CONTROL_CONTINUE:
        !           258:        case SERVICE_CONTROL_INTERROGATE:
        !           259:        default:
        !           260:                break;
        !           261:        }
        !           262:        UpdateSCM(SERVICE_RUNNING);
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Tell the Service Control Manager the state of the service.
        !           267:  */
        !           268: void UpdateSCM(DWORD state) {
        !           269:        SERVICE_STATUS ss;
        !           270:        static DWORD dwState = SERVICE_STOPPED;
        !           271: 
        !           272:        if (hServiceStatus) {
        !           273:                if (state)
        !           274:                        dwState = state;
        !           275: 
        !           276:                memset(&ss, 0, sizeof(SERVICE_STATUS));
        !           277:                ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
        !           278:                ss.dwCurrentState = dwState;
        !           279:                ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
        !           280:                                        SERVICE_ACCEPT_SHUTDOWN;
        !           281:                ss.dwCheckPoint = 0;
        !           282:                ss.dwServiceSpecificExitCode = 0;
        !           283:                ss.dwWin32ExitCode = NO_ERROR;
        !           284:                ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 5000 : 1000;
        !           285: 
        !           286:                SetServiceStatus(hServiceStatus, &ss);
        !           287:        }
        !           288: }
        !           289: 
        !           290: BOOL WINAPI 
        !           291: OnConsoleEvent(  
        !           292:        DWORD dwCtrlType
        !           293:        )
        !           294: {
        !           295:        HANDLE exitEvent = get_exit_event();
        !           296: 
        !           297:        switch (dwCtrlType) {
        !           298: #ifdef DEBUG
        !           299:                case CTRL_BREAK_EVENT:
        !           300:                        if (debug > 0) {
        !           301:                                debug <<= 1;
        !           302:                        }
        !           303:                        else {
        !           304:                                debug = 1;
        !           305:                        }
        !           306:                        if (debug > 8) {
        !           307:                                debug = 0;
        !           308:                        }
        !           309:                        msyslog(LOG_DEBUG, "debug level %d", debug);
        !           310:                        break;
        !           311: #else
        !           312:                case CTRL_BREAK_EVENT:
        !           313:                        break;
        !           314: #endif
        !           315: 
        !           316:                case CTRL_C_EVENT:
        !           317:                case CTRL_CLOSE_EVENT:
        !           318:                case CTRL_SHUTDOWN_EVENT:
        !           319:                        if (exitEvent != NULL) {
        !           320:                                SetEvent(exitEvent);
        !           321:                                Sleep( 100 );  //##++
        !           322:                        }
        !           323:                        break;
        !           324: 
        !           325:                default :
        !           326:                        /* pass to next handler */
        !           327:                        return FALSE; 
        !           328:        }
        !           329: 
        !           330:        /* we've handled it, no more handlers should be called */
        !           331:        return TRUE;
        !           332: }
        !           333: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>