home *** CD-ROM | disk | FTP | other *** search
- /*
- ** NTMAIN
- **
- ** This is the main driver for the Windows NT Service driver of
- ** the Sambar Server.
- **
- ** Confidential Property of Tod Sambar
- ** (c) Copyright Tod Sambar 1997-2001
- ** All rights reserved.
- **
- **
- ** Syntax:
- **
- ** ntserver [-i] [-u] [-d] [-s service-name] [-c config-dir ]
- **
- ** -i Install the Sambar Server as an NT Service
- ** -u Uninstall the Sambar Server NT Service
- ** -d Start the Sambar Server in debug mode
- ** -s Optional service name argument (for installing multiple)
- ** -c Optional path to the config directory to use.
- **
- **
- ** History:
- ** Chg# Date Description Resp
- ** ---- ------- ------------------------------------------------------- ----
- ** 26JUL97 Created sambar
- */
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <direct.h>
- #include <process.h>
- #include <sambar.h>
-
- /*
- ** Local Defines
- */
- #define SERVICE_NAME "Sambar Server"
- #define SERVICE_TITLE "Sambar Server"
- #define NTSERVER_DEBUG (SA_INT)0x0001
- #define NTSERVER_INSTALL (SA_INT)0x0002
- #define NTSERVER_UNINSTALL (SA_INT)0x0004
-
- #define CK_PIPE 1
-
-
- /*
- ** Local Prototypes
- */
- static SA_RETCODE get_args(int argc, char **argv, SA_INT *flagsp);
- static void syntax_error(char *name, char *argv);
- static SA_RETCODE install_service(void);
- static SA_RETCODE uninstall_service(void);
- VOID service_main(DWORD argc, LPTSTR *argv);
- VOID service_ctrl(DWORD dwCtrlCode);
- static SA_RETCODE service_cd(void);
- static void service_status(int state, int exitCode, int waitHint);
- static void HTTPLog(SA_CTX *ctx, SA_HTTPLOG *httplog);
- static void create_pipe(void);
- static void close_pipe(void);
-
-
- /*
- ** Global Handles
- */
- static SERVICE_STATUS_HANDLE hServiceStatus;
- static int sState;
- static boolean bConnected = FALSE;
- static HANDLE hIOCP = NULL;
- static HANDLE hPipe = NULL;
- static OVERLAPPED o;
- static SA_INIT SaInit;
- static char ConfigDir[256];
- static char ServiceName[256];
- static char ServiceTitle[256];
-
-
-
- int
- main(int argc, char *argv[])
- {
- SA_INT flags;
-
- /* Initialization */
- memset(&SaInit, 0, sizeof(SA_INIT));
- strcpy(ServiceName, SERVICE_NAME);
- strcpy(ServiceTitle, SERVICE_TITLE);
- ConfigDir[0] = '\0';
- SaInit.i_logfunc = HTTPLog;
- SaInit.i_servicename = ServiceName;
-
- /*
- ** Read the command line arguments.
- */
- if (get_args(argc, argv, &flags) != SA_SUCCEED)
- return (0);
-
- if (flags & NTSERVER_INSTALL)
- {
- if (install_service() != SA_SUCCEED)
- return (-1);
-
- fprintf(stdout,
- "The %s NT Service can be started from the Service Panel.\n",
- ServiceName);
-
- return (0);
- }
-
- if (flags & NTSERVER_UNINSTALL)
- {
- if (uninstall_service() != SA_SUCCEED)
- return (-1);
-
- return (0);
- }
-
- /* Change to the appropriate working directory for execution */
- if (service_cd() != SA_SUCCEED)
- return (-1);
-
- if (flags & NTSERVER_DEBUG)
- {
- create_pipe();
-
- /* Execute the Sambar Server Shell */
- if (sa_server2((SA_VOID *)&SaInit) != SA_SUCCEED)
- {
- close_pipe();
- return (-1);
- }
-
- close_pipe();
- }
- else
- {
- SERVICE_TABLE_ENTRY ste[] =
- {
- { ServiceName, (LPSERVICE_MAIN_FUNCTION)service_main },
- { NULL, NULL }
- };
-
- if (StartServiceCtrlDispatcher(ste) != TRUE)
- {
- fprintf(stderr, "Failed to start %s NT Service (%d)\n",
- ServiceName, GetLastError());
- return (-1);
- }
- }
-
- return (0);
- }
-
- /*
- ** GET_ARGS
- **
- ** This routine parses the command line arguments passed to the
- ** NT Server application.
- **
- */
- static SA_RETCODE
- get_args(int argc, char **argv, SA_INT *flagsp)
- {
- int j;
- SA_INT flags;
-
- /* Initialization */
- flags = 0;
-
- /*
- ** Are there any arguments to parse?
- */
- if (argc <= 1)
- {
- /*
- ** We don't have any arguments.
- */
- *flagsp = 0;
- return (SA_SUCCEED);
- }
-
- /* Loop through the arguments */
- j = 1;
-
- while (j < argc)
- {
- if (strcmp(argv[j], "-i") == 0)
- {
- flags |= NTSERVER_INSTALL;
- }
- else if (strcmp(argv[j], "-u") == 0)
- {
- flags |= NTSERVER_UNINSTALL;
- }
- else if (strcmp(argv[j], "-d") == 0)
- {
- flags |= NTSERVER_DEBUG;
- }
- else if (strcmp(argv[j], "-s") == 0)
- {
- j++;
- if (j == argc)
- {
- syntax_error(argv[0], argv[j]);
- return (SA_FAIL);
- }
-
- strcpy(ServiceName, argv[j]);
- strcpy(ServiceTitle, argv[j]);
- }
- else if (strcmp(argv[j], "-c") == 0)
- {
- j++;
- if (j == argc)
- {
- syntax_error(argv[0], argv[j]);
- return (SA_FAIL);
- }
-
- strcpy(ConfigDir, argv[j]);
- SaInit.i_configdir = ConfigDir;
- }
- else
- {
- syntax_error(argv[0], argv[j]);
- return (SA_FAIL);
- }
-
- j++;
- }
-
- *flagsp = flags;
-
- /*
- ** All done.
- */
- return (SA_SUCCEED);
- }
-
- /*
- ** SYNTAX_ERROR
- **
- ** This routine is used to inform the user that a command-line
- ** syntax error occurred.
- */
- static void
- syntax_error(char *name, char *argv)
- {
- /*
- ** Print the error string.
- */
- if (argv != NULL)
- fprintf(stderr, "\nUnexpected flag: %s\n", argv);
-
- fprintf(stderr, "\nCorrect syntax is: %s\n", name);
-
- fprintf(stderr,
- " [-i] # Install the NT Service\n");
- fprintf(stderr,
- " [-u] # Unistall the NT Service\n");
- fprintf(stderr,
- " [-d] # Start the Sambar Server in debug mode\n");
- fprintf(stderr,
- " [-s servicename] # Optional NT Service name (default: Sambar Server)\n");
- fprintf(stderr,
- " [-c configdir] # Optional config directory (default: Sambar install dir)\n");
-
- return;
- }
-
- static SA_RETCODE
- install_service(void)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
- TCHAR szPath[256];
- TCHAR szCmd[512];
-
- if (GetModuleFileName(NULL, szPath, 256) == 0)
- {
- fprintf(stderr, "Failed to get exe for service %s (%d)\n",
- ServiceName, GetLastError());
- return (SA_FAIL);
- }
-
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-
- if (schSCManager == NULL)
- {
- fprintf(stderr, "Failed to open the service manager.\n");
- return (SA_FAIL);
- }
-
- if (ConfigDir[0] != '\0')
- {
- sprintf(szCmd, "\"%s\" -c \"%s\" -s \"%s\"", szPath, ConfigDir,
- ServiceName);
- }
- else if (strcmp(ServiceName, SERVICE_NAME) != 0)
- {
- sprintf(szCmd, "\"%s\" -s \"%s\"", szPath, ServiceName);
- }
- else
- {
- strcpy(szCmd, szPath);
- }
-
- schService = CreateService(schSCManager, ServiceName, ServiceTitle,
- SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
- SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
- szCmd, NULL, NULL, "Tcpip\0", NULL, NULL);
-
-
- if (schService == NULL)
- {
- fprintf(stderr, "Failed to create service %s (%d)\n",
- ServiceName, GetLastError());
- CloseServiceHandle(schSCManager);
- return (SA_FAIL);
- }
-
- fprintf(stdout, "Installed service %s.\n", ServiceName);
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
-
- return (SA_SUCCEED);
- }
-
- static SA_RETCODE
- uninstall_service(void)
- {
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
- SERVICE_STATUS status;
-
- schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-
- if (schSCManager == NULL)
- {
- fprintf(stderr, "Failed to open the service manager.\n");
- return (SA_FAIL);
- }
-
- schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
-
- if (schService == NULL)
- {
- fprintf(stderr, "Failed to open service %s (%d).\n",
- ServiceName, GetLastError());
- CloseServiceHandle(schSCManager);
- return (SA_FAIL);
- }
-
- /* Try to stop the service */
- if (ControlService(schService, SERVICE_CONTROL_STOP, &status))
- {
- Sleep(1000);
- while (QueryServiceStatus(schService, &status))
- {
- if (status.dwCurrentState == SERVICE_STOP_PENDING)
- Sleep(1000);
- else
- break;
- }
- }
-
- /* Delete the service */
- if (DeleteService(schService) != TRUE)
- {
- fprintf(stderr, "Failed in attempt to delete service %s (%d).\n",
- ServiceName, GetLastError());
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
- return (SA_FAIL);
- }
-
- fprintf(stdout, "Deleted service %s.\n", ServiceName);
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
-
- return (SA_SUCCEED);
- }
-
- VOID
- service_main(DWORD argc, LPTSTR *argv)
- {
- SA_INT flags;
-
- /* Get an configuration arguments */
- (void)get_args(argc, argv, &flags);
-
- hServiceStatus = RegisterServiceCtrlHandler(ServiceName,
- (LPHANDLER_FUNCTION)service_ctrl);
- if (!hServiceStatus)
- {
- fprintf(stderr, "Failed to register %s service control handler (%d).\n",
- ServiceName, GetLastError());
- return;
- }
-
- service_status(SERVICE_START_PENDING, NO_ERROR, 16000);
- service_status(SERVICE_RUNNING, NO_ERROR, 0);
-
- /* Start the Sambar Server */
- create_pipe();
- sa_server2((SA_VOID *)&SaInit);
- close_pipe();
-
- service_status(SERVICE_STOPPED, NO_ERROR, 0);
-
- return;
- }
-
- VOID
- service_ctrl(DWORD dwCtrlCode)
- {
- int state;
-
- state = sState;
-
- switch(dwCtrlCode)
- {
- // Stop the service.
- //
- case SERVICE_CONTROL_STOP:
- case SERVICE_CONTROL_SHUTDOWN:
- service_status(SERVICE_STOP_PENDING, NO_ERROR, 20000);
-
- (SA_VOID)sa_shutdown(0);
- return;
-
- // Update the service status.
- //
- case SERVICE_CONTROL_INTERROGATE:
- break;
-
- // invalid control code
- //
- default:
- break;
- }
-
- service_status(state, NO_ERROR, 0);
- }
-
-
- static void
- service_status(int state, int exitCode, int waitHint)
- {
- SERVICE_STATUS status;
-
- status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- status.dwServiceSpecificExitCode = 0;
- status.dwCheckPoint = 0;
-
- if (state == SERVICE_START_PENDING)
- {
- status.dwControlsAccepted = 0;
- }
- else
- {
- status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
- SERVICE_ACCEPT_SHUTDOWN;
- }
-
- sState = state;
- status.dwCurrentState = state;
- status.dwWin32ExitCode = exitCode;
- status.dwWaitHint = waitHint;
-
- (VOID)SetServiceStatus(hServiceStatus, &status);
-
- return;
- }
-
- static SA_RETCODE
- service_cd(void)
- {
- int count;
- DWORD len;
- TCHAR szPath[512];
-
- len = GetModuleFileName(NULL, szPath, 512);
- if (len == 0)
- {
- fprintf(stderr, "Failed to get exe for service %s (%d)\n",
- ServiceName, GetLastError());
- return (SA_FAIL);
- }
-
- /*
- ** Change to the directory above the executable.
- **
- ** The working directory for the Sambar Server application must
- ** be the installation directory.
- */
- count = 0;
- while ((len > 0) && (count < 2))
- {
- len--;
- if (szPath[len] == '\\')
- {
- count++;
- szPath[len] = '\0';
- }
- }
-
- if (count != 2)
- {
- fprintf(stderr,
- "Unable to change to the Sambar Server installation directory.\n");
- return (SA_FAIL);
- }
-
- if (chdir(szPath) != 0)
- {
- fprintf(stderr,
- "Unable to change to the Sambar Server installation directory.\n");
- return (SA_FAIL);
- }
-
- return (SA_SUCCEED);
- }
-
- static void
- create_pipe()
- {
- /* Create the completion port for named-pipe client connection */
- hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, CK_PIPE, 0);
- if (hIOCP == INVALID_HANDLE_VALUE)
- {
- fprintf(stderr, "Failure creating I/O completion port [%d]",
- GetLastError());
- return;
- }
-
- /* Create a pipe that clients can connect to. */
- hPipe = CreateNamedPipe("\\\\.\\pipe\\SambarServer",
- PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE,
- 1, 0, 1024, 1000, (LPSECURITY_ATTRIBUTES)NULL);
- if (hPipe == INVALID_HANDLE_VALUE)
- {
- fprintf(stderr,
- "Failure creating named pipe for interactive display [%d]",
- GetLastError());
- CloseHandle(hIOCP);
- hIOCP = NULL;
- }
-
- /* Associate the pipe */
- CreateIoCompletionPort(hPipe, hIOCP, CK_PIPE, 0);
-
- /* Pend an asynchronous connect against the pipe. */
- memset(&o, 0, sizeof(o));
- ConnectNamedPipe(hPipe, &o);
- }
-
- static void
- close_pipe()
- {
- if ((hIOCP != NULL) && (hIOCP != INVALID_HANDLE_VALUE))
- {
- CloseHandle(hIOCP);
- hIOCP = NULL;
- }
-
- if ((hPipe != NULL) && (hPipe != INVALID_HANDLE_VALUE))
- {
- CloseHandle(hPipe);
- hPipe = NULL;
- }
- }
-
- static void
- HTTPLog(SA_CTX *ctx, SA_HTTPLOG *httplog)
- {
- int i;
- int n;
- DWORD dwComp;
- DWORD dwBytes;
- OVERLAPPED *po;
- char timestr[32];
- char str[2048];
-
- if ((!bConnected) && (hPipe != NULL) && (hPipe != INVALID_HANDLE_VALUE))
- {
- while (GetQueuedCompletionStatus(hIOCP, &dwBytes, &dwComp, &po, 0))
- {
- if (dwComp == CK_PIPE)
- {
- bConnected = TRUE;
- }
- }
- }
-
- if (!bConnected)
- return;
-
- i = 0;
- while ((httplog->timestamp[i] != '\0') && (httplog->timestamp[i] != ':'))
- i++;
-
- n = 0;
- while ((httplog->timestamp[i] != '\0') &&
- (httplog->timestamp[i] != ' ') &&
- (n < 16))
- {
- timestr[n] = httplog->timestamp[i];
- n++;
- i++;
- }
-
- timestr[0] = '[';
- timestr[n] = ']';
- timestr[n+1] = '\0';
-
- sprintf(str, "[%s] %s %s %ld %s %s %ld",
- httplog->vhost, timestr, httplog->user, httplog->status,
- httplog->method, httplog->request, httplog->size);
- if (!WriteFile(hPipe, str, strlen(str), &n, NULL))
- {
- /* Error occurred writing on pipe, client disconnected. */
- bConnected = FALSE;
- DisconnectNamedPipe(hPipe);
- memset(&o, 0, sizeof(o));
- ConnectNamedPipe(hPipe, &o);
- }
- else
- {
- FlushFileBuffers(hPipe);
- }
-
- return;
- }
-