Index: pg_ctl.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/bin/pg_ctl/pg_ctl.c,v retrieving revision 1.16 diff -c -c -r1.16 pg_ctl.c *** pg_ctl.c 11 Jun 2004 16:36:31 -0000 1.16 --- pg_ctl.c 20 Jun 2004 15:09:30 -0000 *************** *** 52,58 **** RESTART_COMMAND, RELOAD_COMMAND, STATUS_COMMAND, ! KILL_COMMAND } CtlCommand; --- 52,61 ---- RESTART_COMMAND, RELOAD_COMMAND, STATUS_COMMAND, ! KILL_COMMAND, ! REGISTER_COMMAND, ! UNREGISTER_COMMAND, ! RUN_AS_SERVICE_COMMAND } CtlCommand; *************** *** 69,74 **** --- 72,80 ---- static const char *progname; static char *log_file = NULL; static char *postgres_path = NULL; + static char *register_servicename = "PostgreSQL"; /* FIXME: + version ID? */ + static char *register_username = NULL; + static char *register_password = NULL; static char *argv0 = NULL; static void *xmalloc(size_t size); *************** *** 83,88 **** --- 89,104 ---- static void do_reload(void); static void do_status(void); static void do_kill(pgpid_t pid); + #ifdef WIN32 + static bool pgwin32_IsInstalled(SC_HANDLE); + static char* pgwin32_CommandLine(bool); + static void pgwin32_doRegister(); + static void pgwin32_doUnregister(); + static void pgwin32_SetServiceStatus(DWORD); + static void WINAPI pgwin32_ServiceHandler(DWORD); + static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR*); + static void pgwin32_doRunAsService(); + #endif static pgpid_t get_pgpid(void); static char **readfile(char *path); static int start_postmaster(void); *************** *** 93,98 **** --- 109,171 ---- static char pid_file[MAXPGPATH]; static char conf_file[MAXPGPATH]; + + #ifdef WIN32 + static void + write_eventlog(int level, const char *line) + { + static HANDLE evtHandle = INVALID_HANDLE_VALUE; + + if (evtHandle == INVALID_HANDLE_VALUE) { + evtHandle = RegisterEventSource(NULL,"PostgreSQL"); + if (evtHandle == NULL) { + evtHandle = INVALID_HANDLE_VALUE; + return; + } + } + + ReportEvent(evtHandle, + level, + 0, + 0, /* All events are Id 0 */ + NULL, + 1, + 0, + &line, + NULL); + } + #endif + + /* + * Write errors to stderr (or by equal means when stderr is + * not available). + */ + void + write_stderr(const char *fmt,...) + { + va_list ap; + + va_start(ap, fmt); + #ifndef WIN32 + /* On Unix, we just fprintf to stderr */ + vfprintf(stderr, fmt, ap); + #else + /* On Win32, we print to stderr if running on a console, or write to + * eventlog if running as a service */ + if (!isatty(fileno(stderr))) /* Running as a service */ + { + char errbuf[2048]; /* Arbitrary size? */ + + vsnprintf(errbuf, sizeof(errbuf), fmt, ap); + + write_eventlog(EVENTLOG_ERROR_TYPE, errbuf); + } + else /* Not running as service, write to stderr */ + vfprintf(stderr, fmt, ap); + #endif + va_end(ap); + } + /* * routines to check memory allocations and fail noisily. */ *************** *** 105,111 **** result = malloc(size); if (!result) { ! fprintf(stderr, _("%s: out of memory\n"), progname); exit(1); } return result; --- 178,184 ---- result = malloc(size); if (!result) { ! write_stderr( _("%s: out of memory\n"), progname); exit(1); } return result; *************** *** 121,127 **** result = strdup(s); if (!result) { ! fprintf(stderr, _("%s: out of memory\n"), progname); exit(1); } return result; --- 194,200 ---- result = strdup(s); if (!result) { ! write_stderr( _("%s: out of memory\n"), progname); exit(1); } return result; *************** *** 352,358 **** { old_pid = get_pgpid(); if (old_pid != 0) ! fprintf(stderr, _("%s: Another postmaster may be running. " "Trying to start postmaster anyway.\n"), progname); --- 425,431 ---- { old_pid = get_pgpid(); if (old_pid != 0) ! write_stderr( _("%s: Another postmaster may be running. " "Trying to start postmaster anyway.\n"), progname); *************** *** 371,383 **** post_opts = ""; else { ! fprintf(stderr, _("%s: cannot read %s\n"), progname, postopts_file); exit(1); } } else if (optlines[0] == NULL || optlines[1] != NULL) { ! fprintf(stderr, _("%s: option file %s must have exactly 1 line\n"), progname, ctl_command == RESTART_COMMAND ? postopts_file : def_postopts_file); exit(1); --- 444,456 ---- post_opts = ""; else { ! write_stderr( _("%s: cannot read %s\n"), progname, postopts_file); exit(1); } } else if (optlines[0] == NULL || optlines[1] != NULL) { ! write_stderr( _("%s: option file %s must have exactly 1 line\n"), progname, ctl_command == RESTART_COMMAND ? postopts_file : def_postopts_file); exit(1); *************** *** 419,432 **** postmaster_path)) < 0) { if (ret == -1) ! fprintf(stderr, _("The program \"postmaster\" is needed by %s " "but was not found in the same directory as " "\"%s\".\n" "Check your installation.\n"), progname, progname); else ! fprintf(stderr, _("The program \"postmaster\" was found by %s " "but was not the same version as \"%s\".\n" "Check your installation.\n"), --- 492,505 ---- postmaster_path)) < 0) { if (ret == -1) ! write_stderr( _("The program \"postmaster\" is needed by %s " "but was not found in the same directory as " "\"%s\".\n" "Check your installation.\n"), progname, progname); else ! write_stderr( _("The program \"postmaster\" was found by %s " "but was not the same version as \"%s\".\n" "Check your installation.\n"), *************** *** 438,444 **** if (start_postmaster() != 0) { ! fprintf(stderr, _("Unable to run the postmaster binary\n")); exit(1); } --- 511,517 ---- if (start_postmaster() != 0) { ! write_stderr( _("Unable to run the postmaster binary\n")); exit(1); } *************** *** 448,454 **** pid = get_pgpid(); if (pid == old_pid) { ! fprintf(stderr, _("%s: cannot start postmaster\n" "Examine the log output\n"), progname); --- 521,527 ---- pid = get_pgpid(); if (pid == old_pid) { ! write_stderr( _("%s: cannot start postmaster\n" "Examine the log output\n"), progname); *************** *** 485,498 **** if (pid == 0) /* no pid file */ { ! fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file); ! fprintf(stderr, _("Is postmaster running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! fprintf(stderr, _("%s: cannot stop postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); --- 558,571 ---- if (pid == 0) /* no pid file */ { ! write_stderr( _("%s: could not find %s\n"), progname, pid_file); ! write_stderr( _("Is postmaster running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! write_stderr( _("%s: cannot stop postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); *************** *** 501,507 **** if (kill((pid_t) pid, sig) != 0) { ! fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } --- 574,580 ---- if (kill((pid_t) pid, sig) != 0) { ! write_stderr( _("stop signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } *************** *** 540,546 **** if (!silence_echo) printf(_(" failed\n")); ! fprintf(stderr, _("%s: postmaster does not shut down\n"), progname); exit(1); } if (!silence_echo) --- 613,619 ---- if (!silence_echo) printf(_(" failed\n")); ! write_stderr( _("%s: postmaster does not shut down\n"), progname); exit(1); } if (!silence_echo) *************** *** 565,589 **** if (pid == 0) /* no pid file */ { ! fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file); ! fprintf(stderr, _("Is postmaster running?\nstarting postmaster anyway\n")); do_start(); return; } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! fprintf(stderr, _("%s: cannot restart postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); ! fprintf(stderr, _("Please terminate postgres and try again.\n")); exit(1); } if (kill((pid_t) pid, sig) != 0) { ! fprintf(stderr, _("stop signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } --- 638,662 ---- if (pid == 0) /* no pid file */ { ! write_stderr( _("%s: could not find %s\n"), progname, pid_file); ! write_stderr( _("Is postmaster running?\nstarting postmaster anyway\n")); do_start(); return; } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! write_stderr( _("%s: cannot restart postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); ! write_stderr( _("Please terminate postgres and try again.\n")); exit(1); } if (kill((pid_t) pid, sig) != 0) { ! write_stderr( _("stop signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } *************** *** 616,622 **** if (!silence_echo) printf(_(" failed\n")); ! fprintf(stderr, _("%s: postmaster does not shut down\n"), progname); exit(1); } --- 689,695 ---- if (!silence_echo) printf(_(" failed\n")); ! write_stderr( _("%s: postmaster does not shut down\n"), progname); exit(1); } *************** *** 636,659 **** pid = get_pgpid(); if (pid == 0) /* no pid file */ { ! fprintf(stderr, _("%s: could not find %s\n"), progname, pid_file); ! fprintf(stderr, _("Is postmaster running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! fprintf(stderr, _("%s: cannot reload postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); ! fprintf(stderr, _("Please terminate postgres and try again.\n")); exit(1); } if (kill((pid_t) pid, sig) != 0) { ! fprintf(stderr, _("reload signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } --- 709,732 ---- pid = get_pgpid(); if (pid == 0) /* no pid file */ { ! write_stderr( _("%s: could not find %s\n"), progname, pid_file); ! write_stderr( _("Is postmaster running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; ! write_stderr( _("%s: cannot reload postmaster; " "postgres is running (PID: %ld)\n"), progname, pid); ! write_stderr( _("Please terminate postgres and try again.\n")); exit(1); } if (kill((pid_t) pid, sig) != 0) { ! write_stderr( _("reload signal failed (PID: %ld): %s\n"), pid, strerror(errno)); exit(1); } *************** *** 674,680 **** pid = get_pgpid(); if (pid == 0) /* no pid file */ { ! fprintf(stderr, _("%s: postmaster or postgres not running\n"), progname); exit(1); } else if (pid < 0) /* standalone backend */ --- 747,753 ---- pid = get_pgpid(); if (pid == 0) /* no pid file */ { ! write_stderr( _("%s: postmaster or postgres not running\n"), progname); exit(1); } else if (pid < 0) /* standalone backend */ *************** *** 702,719 **** { if (kill((pid_t) pid, sig) != 0) { ! fprintf(stderr, _("signal %d failed (PID: %ld): %s\n"), sig, pid, strerror(errno)); exit(1); } } static void do_advice(void) { ! fprintf(stderr, _("\nTry \"%s --help\" for more information.\n"), progname); } --- 775,1018 ---- { if (kill((pid_t) pid, sig) != 0) { ! write_stderr( _("signal %d failed (PID: %ld): %s\n"), sig, pid, strerror(errno)); exit(1); } } + #ifdef WIN32 + + static bool pgwin32_IsInstalled(SC_HANDLE hSCM) + { + SC_HANDLE hService = OpenService(hSCM, register_servicename, SERVICE_QUERY_CONFIG); + bool bResult = (hService != NULL); + if (bResult) + CloseServiceHandle(hService); + return bResult; + } + + static char* pgwin32_CommandLine(bool registration) + { + static char cmdLine[MAXPGPATH]; + int ret; + if (registration) + ret = find_my_exec(argv0, cmdLine); + else + ret = find_other_exec(argv0, "postmaster", PM_VERSIONSTR, cmdLine); + if (ret != 0) + { + write_stderr( _("Unable to find exe")); + exit(1); + } + + if (registration) + { + if (strcasecmp(cmdLine+strlen(cmdLine)-4,".exe")) + { + /* If commandline does not end in .exe, append it */ + strcat(cmdLine,".exe"); + } + strcat(cmdLine," runservice -N \""); + strcat(cmdLine,register_servicename); + strcat(cmdLine,"\""); + } + + if (pg_data) + { + strcat(cmdLine," -D \""); + strcat(cmdLine,pg_data); + strcat(cmdLine,"\""); + } + + if (post_opts) + { + strcat(cmdLine," "); + if (registration) + strcat(cmdLine," -o \""); + strcat(cmdLine,post_opts); + if (registration) + strcat(cmdLine,"\""); + } + + return cmdLine; + } + + static void + pgwin32_doRegister() + { + SC_HANDLE hService; + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM == NULL) + { + write_stderr(_("Unable to open service manager\n")); + exit(1); + } + if (pgwin32_IsInstalled(hSCM)) + { + CloseServiceHandle(hSCM); + write_stderr(_("Service \"%s\" already registered\n"),register_servicename); + exit(1); + } + if ((hService = CreateService(hSCM, register_servicename, register_servicename, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, + pgwin32_CommandLine(true), + NULL, NULL, "RPCSS\0", register_username, register_password)) == NULL) + { + CloseServiceHandle(hSCM); + write_stderr( _("Unable to register service \"%s\" [%d]\n"), register_servicename, (int)GetLastError()); + exit(1); + } + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + } + + static void + pgwin32_doUnregister() + { + SC_HANDLE hService; + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM == NULL) + { + write_stderr(_("Unable to open service manager\n")); + exit(1); + } + if (!pgwin32_IsInstalled(hSCM)) + { + CloseServiceHandle(hSCM); + write_stderr(_("Service \"%s\" not registered\n"),register_servicename); + exit(1); + } + + if ((hService = OpenService(hSCM, register_servicename, DELETE)) == NULL) + { + CloseServiceHandle(hSCM); + write_stderr( _("Unable to open service \"%s\" [%d]\n"), register_servicename, (int)GetLastError()); + exit(1); + } + if (!DeleteService(hService)) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + write_stderr( _("Unable to unregister service \"%s\" [%d]\n"), register_servicename, (int)GetLastError()); + exit(1); + } + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + } + + + static SERVICE_STATUS status; + static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE)0; + static HANDLE shutdownHandles[2]; + static pid_t postmasterPID = -1; + #define shutdownEvent shutdownHandles[0] + #define postmasterProcess shutdownHandles[1] + + static void pgwin32_SetServiceStatus(DWORD currentState) + { + status.dwCurrentState = currentState; + SetServiceStatus(hStatus, (LPSERVICE_STATUS)&status); + } + + static void WINAPI pgwin32_ServiceHandler(DWORD request) + { + switch (request) + { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + pgwin32_SetServiceStatus(SERVICE_STOP_PENDING); + SetEvent(shutdownEvent); + return; + + case SERVICE_CONTROL_PAUSE: + /* Win32 config reloading */ + kill(postmasterPID,SIGHUP); + return; + + /* FIXME: These could be used to replace other signals etc */ + case SERVICE_CONTROL_CONTINUE: + case SERVICE_CONTROL_INTERROGATE: + default: + break; + } + } + + static void WINAPI pgwin32_ServiceMain(DWORD argc, LPTSTR *argv) + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD ret; + + /* Initialize variables */ + status.dwWin32ExitCode = S_OK; + status.dwCheckPoint = 0; + status.dwWaitHint = 0; + status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE; + status.dwServiceSpecificExitCode = 0; + status.dwCurrentState = SERVICE_START_PENDING; + + memset(&pi,0,sizeof(pi)); + memset(&si,0,sizeof(si)); + si.cb = sizeof(si); + + /* Register the control request handler */ + if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE)0) + return; + + if ((shutdownEvent = CreateEvent(NULL,true,false,NULL)) == NULL) + return; + + /* Start the postmaster */ + pgwin32_SetServiceStatus(SERVICE_START_PENDING); + if (!CreateProcess(NULL,pgwin32_CommandLine(false),NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)) + { + pgwin32_SetServiceStatus(SERVICE_STOPPED); + return; + } + postmasterPID = pi.dwProcessId; + postmasterProcess = pi.hProcess; + CloseHandle(pi.hThread); + pgwin32_SetServiceStatus(SERVICE_RUNNING); + + /* Wait for quit... */ + ret = WaitForMultipleObjects(2,shutdownHandles,FALSE,INFINITE); + pgwin32_SetServiceStatus(SERVICE_STOP_PENDING); + switch (ret) + { + case WAIT_OBJECT_0: /* shutdown event */ + kill(postmasterPID,SIGINT); + WaitForSingleObject(postmasterProcess,INFINITE); + break; + + case (WAIT_OBJECT_0+1): /* postmaster went down */ + break; + + default: + /* assert(false); */ + } + + CloseHandle(shutdownEvent); + CloseHandle(postmasterProcess); + + pgwin32_SetServiceStatus(SERVICE_STOPPED); + } + + static void pgwin32_doRunAsService() + { + SERVICE_TABLE_ENTRY st[] = {{ register_servicename, pgwin32_ServiceMain }, + { NULL, NULL }}; + StartServiceCtrlDispatcher(st); + } + + #endif static void do_advice(void) { ! write_stderr( _("\nTry \"%s --help\" for more information.\n"), progname); } *************** *** 730,738 **** --- 1029,1046 ---- printf(_(" %s reload [-D DATADIR] [-s]\n"), progname); printf(_(" %s status [-D DATADIR]\n"), progname); printf(_(" %s kill SIGNALNAME PROCESSID\n"), progname); + #ifdef WIN32 + printf(_(" %s register [-N servicename] [-U username] [-P password] [-D DATADIR] [-o \"OPTIONS\"]\n"), progname); + printf(_(" %s unregister [-N servicename]\n"), progname); + #endif printf(_("Common options:\n")); printf(_(" -D, --pgdata DATADIR location of the database storage area\n")); printf(_(" -s, --silent only print errors, no informational messages\n")); + #ifdef WIN32 + printf(_(" -N service name with which to register PostgreSQL server\n")); + printf(_(" -P user name of account to register PostgreSQL server\n")); + printf(_(" -U password of account to register PostgreSQL server\n")); + #endif printf(_(" -w wait until operation completes\n")); printf(_(" -W do not wait until operation completes\n")); printf(_(" --help show this help, then exit\n")); *************** *** 778,784 **** } else { ! fprintf(stderr, _("%s: invalid shutdown mode %s\n"), progname, modeopt); do_advice(); exit(1); } --- 1086,1092 ---- } else { ! write_stderr( _("%s: invalid shutdown mode %s\n"), progname, modeopt); do_advice(); exit(1); } *************** *** 811,817 **** sig = SIGUSR2; else { ! fprintf(stderr, _("%s: invalid signal \"%s\"\n"), progname, signame); do_advice(); exit(1); } --- 1119,1125 ---- sig = SIGUSR2; else { ! write_stderr( _("%s: invalid signal \"%s\"\n"), progname, signame); do_advice(); exit(1); } *************** *** 837,842 **** --- 1145,1151 ---- int c; pgpid_t killproc = 0; + #ifdef WIN32 setvbuf(stderr, NULL, _IONBF, 0); #endif *************** *** 879,885 **** /* process command-line options */ while (optind < argc) { ! while ((c = getopt_long(argc, argv, "D:l:m:o:p:swW", long_options, &option_index)) != -1) { switch (c) { --- 1188,1194 ---- /* process command-line options */ while (optind < argc) { ! while ((c = getopt_long(argc, argv, "D:l:m:N:o:p:P:sU:wW", long_options, &option_index)) != -1) { switch (c) { *************** *** 901,915 **** --- 1210,1245 ---- case 'm': set_mode(optarg); break; + case 'N': + register_servicename = xstrdup(optarg); + break; case 'o': post_opts = xstrdup(optarg); break; case 'p': postgres_path = xstrdup(optarg); break; + case 'P': + register_password = xstrdup(optarg); + break; case 's': silence_echo = true; break; + case 'U': + if (strchr(optarg,'\\')) + register_username = xstrdup(optarg); + else /* Prepend .\ for local accounts */ + { + register_username = malloc(strlen(optarg)+3); + if (!register_username) + { + write_stderr( _("%s: out of memory\n"), progname); + exit(1); + } + strcpy(register_username,".\\"); + strcat(register_username,optarg); + } + break; case 'w': do_wait = true; wait_set = true; *************** *** 919,925 **** wait_set = true; break; default: ! fprintf(stderr, _("%s: invalid option %s\n"), progname, optarg); do_advice(); exit(1); } --- 1249,1255 ---- wait_set = true; break; default: ! write_stderr( _("%s: invalid option %s\n"), progname, optarg); do_advice(); exit(1); } *************** *** 930,936 **** { if (ctl_command != NO_COMMAND) { ! fprintf(stderr, _("%s: extra operation mode %s\n"), progname, argv[optind]); do_advice(); exit(1); } --- 1260,1266 ---- { if (ctl_command != NO_COMMAND) { ! write_stderr( _("%s: extra operation mode %s\n"), progname, argv[optind]); do_advice(); exit(1); } *************** *** 949,955 **** { if (argc - optind < 3) { ! fprintf(stderr, _("%s: invalid kill syntax\n"), progname); do_advice(); exit(1); } --- 1279,1285 ---- { if (argc - optind < 3) { ! write_stderr( _("%s: invalid kill syntax\n"), progname); do_advice(); exit(1); } *************** *** 957,965 **** set_sig(argv[++optind]); killproc = atol(argv[++optind]); } else { ! fprintf(stderr, _("%s: invalid operation mode %s\n"), progname, argv[optind]); do_advice(); exit(1); } --- 1287,1303 ---- set_sig(argv[++optind]); killproc = atol(argv[++optind]); } + #ifdef WIN32 + else if (strcmp(argv[optind], "register") == 0) + ctl_command = REGISTER_COMMAND; + else if (strcmp(argv[optind], "unregister") == 0) + ctl_command = UNREGISTER_COMMAND; + else if (strcmp(argv[optind], "runservice") == 0) + ctl_command = RUN_AS_SERVICE_COMMAND; + #endif else { ! write_stderr( _("%s: invalid operation mode %s\n"), progname, argv[optind]); do_advice(); exit(1); } *************** *** 969,985 **** if (ctl_command == NO_COMMAND) { ! fprintf(stderr, _("%s: no operation specified\n"), progname); do_advice(); exit(1); } pg_data = getenv("PGDATA"); canonicalize_path(pg_data); ! if (pg_data == NULL && ctl_command != KILL_COMMAND) { ! fprintf(stderr, _("%s: no database directory specified " "and environment variable PGDATA unset\n"), progname); --- 1307,1324 ---- if (ctl_command == NO_COMMAND) { ! write_stderr( _("%s: no operation specified\n"), progname); do_advice(); exit(1); } pg_data = getenv("PGDATA"); + if (pg_data) canonicalize_path(pg_data); ! if (pg_data == NULL && ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND) { ! write_stderr( _("%s: no database directory specified " "and environment variable PGDATA unset\n"), progname); *************** *** 1034,1039 **** --- 1373,1389 ---- case KILL_COMMAND: do_kill(killproc); break; + #ifdef WIN32 + case REGISTER_COMMAND: + pgwin32_doRegister(); + break; + case UNREGISTER_COMMAND: + pgwin32_doUnregister(); + break; + case RUN_AS_SERVICE_COMMAND: + pgwin32_doRunAsService(); + break; + #endif default: break; }