8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/*
7c38d4781fd4c5b146503b0dad7f0a2d58bfd00bTinderbox User * Copyright (C) 1999-2002, 2004, 2006, 2007, 2009, 2011, 2013-2017 Internet Systems Consortium, Inc. ("ISC")
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
23520508907e91343f52e3772bceec9d7855cd32Automatic Updater/* $Id: ntservice.c,v 1.16 2011/01/13 08:50:29 tbox Exp $ */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer#include <config.h>
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer#include <stdio.h>
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer#include <isc/app.h>
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#include <isc/commandline.h>
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer#include <isc/log.h>
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont#include <isc/print.h>
4f851656c4d0837dbcceb345838ec74568a11aeeMark Andrews#include <isc/string.h>
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer#include <named/globals.h>
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer#include <named/ntservice.h>
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer#include <named/main.h>
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer#include <named/server.h>
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/* Handle to SCM for updating service status */
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafssonstatic SERVICE_STATUS_HANDLE hServiceStatus = 0;
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayerstatic BOOL foreground = FALSE;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayerstatic char ConsoleTitle[128];
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/*
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer * Forward declarations
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayervoid ServiceControl(DWORD dwCtrlCode);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrewsint bindmain(int, char *[]); /* From main.c */
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/*
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson * Initialize the Service by registering it.
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayervoid
b454c0319685041db3f3e8fd7671e1b364fd20c5Evan Huntntservice_init(void) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer if (!foreground) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer /* Register handler with the SCM */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME,
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer (LPHANDLER_FUNCTION)ServiceControl);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer if (!hServiceStatus) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ns_main_earlyfatal(
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson "could not register service control handler");
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer UpdateSCM(SERVICE_STOPPED);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer exit(1);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer }
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer UpdateSCM(SERVICE_RUNNING);
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson } else {
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcpy(ConsoleTitle, "BIND Version ", sizeof(ConsoleTitle));
5a93d3be4e0c652f455066bb764416173a00c951Mark Andrews strlcat(ConsoleTitle, VERSION, sizeof(ConsoleTitle));
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer SetConsoleTitle(ConsoleTitle);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer }
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer}
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayervoid
b454c0319685041db3f3e8fd7671e1b364fd20c5Evan Huntntservice_shutdown(void) {
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson UpdateSCM(SERVICE_STOPPED);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer}
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayer/*
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayer * Routine to check if this is a service or a foreground program
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayer */
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny MayerBOOL
b454c0319685041db3f3e8fd7671e1b364fd20c5Evan Huntntservice_isservice(void) {
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayer return(!foreground);
0956e3d6074b197eb6aeadd6aa985e60e0dbd15dDanny Mayer}
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater/*
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer * ServiceControl(): Handles requests from the SCM and passes them on
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer * to named.
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayervoid
8423783bd0292301d78ad19be580fbc4deafd441Danny MayerServiceControl(DWORD dwCtrlCode) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer /* Handle the requested control code */
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson switch(dwCtrlCode) {
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater case SERVICE_CONTROL_INTERROGATE:
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer UpdateSCM(0);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer break;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater case SERVICE_CONTROL_SHUTDOWN:
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater case SERVICE_CONTROL_STOP:
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
102e532c659cce054449b5df7850dccc1e8f0ebfDanny Mayer isc_app_shutdown();
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer UpdateSCM(SERVICE_STOPPED);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer break;
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater default:
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer break;
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson }
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer}
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/*
9bf5a10fbd38128613f86c9143ee8f8a38b06779Andreas Gustafsson * Tell the Service Control Manager the state of the service.
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayervoid UpdateSCM(DWORD state) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer SERVICE_STATUS ss;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer static DWORD dwState = SERVICE_STOPPED;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer if (hServiceStatus) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer if (state)
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer dwState = state;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer memset(&ss, 0, sizeof(SERVICE_STATUS));
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwCurrentState = dwState;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer SERVICE_ACCEPT_SHUTDOWN;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwCheckPoint = 0;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwServiceSpecificExitCode = 0;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwWin32ExitCode = NO_ERROR;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer if (!SetServiceStatus(hServiceStatus, &ss)) {
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer ss.dwCurrentState = SERVICE_STOPPED;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer SetServiceStatus(hServiceStatus, &ss);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer }
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer }
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer}
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews/* unhook main */
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#undef main
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer/*
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews * This is the entry point for the executable
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews * We can now call bindmain() explicitly or via StartServiceCtrlDispatcher()
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews * as we need to.
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrewsint main(int argc, char *argv[])
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer{
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews int rc, ch;
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews /* Command line users should put -f in the options. */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews isc_commandline_errprint = ISC_FALSE;
5a505fc4c2e99842052d9409790c7da0b5663bceMukund Sivaraman while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews switch (ch) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews case 'f':
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews case 'g':
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews case 'v':
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews case 'V':
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews foreground = TRUE;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews break;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews default:
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews break;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews isc_commandline_reset = ISC_TRUE;
0382130cdce988c61d54a225f7aa0be9e2b3429bAutomatic Updater
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews if (foreground) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews /* run in console window */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews exit(bindmain(argc, argv));
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews } else {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews /* Start up as service */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews char *SERVICE_NAME = BIND_SERVICE_NAME;
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews SERVICE_TABLE_ENTRY dispatchTable[] = {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews { TEXT(SERVICE_NAME),
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews (LPSERVICE_MAIN_FUNCTION)bindmain },
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews { NULL, NULL }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews };
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews rc = StartServiceCtrlDispatcher(dispatchTable);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews if (!rc) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews fprintf(stderr,
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews "Use -f to run from the command line.\n");
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews /* will be 1063 when launched as a console app */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews exit(GetLastError());
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews exit(0);
8423783bd0292301d78ad19be580fbc4deafd441Danny Mayer}