dsalib_updown.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #if defined( XP_WIN32 )
  39. #include <windows.h>
  40. #include <process.h>
  41. #include "regparms.h"
  42. #else
  43. #include <signal.h>
  44. #include <sys/signal.h>
  45. #include <unistd.h>
  46. #endif
  47. #include <sys/types.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <errno.h>
  51. #include "dsalib.h"
  52. #include <string.h>
  53. #include "nspr.h"
  54. #if defined( XP_WIN32 )
  55. SC_HANDLE schService;
  56. SC_HANDLE schSCManager;
  57. int StartServer();
  58. int StopandRestartServer();
  59. int StopServer();
  60. int StopNetscapeProgram();
  61. int StartNetscapeProgram();
  62. int StopNetscapeService();
  63. int StartNetscapeService();
  64. void WaitForServertoStop();
  65. #endif
  66. /*
  67. * Get status for the Directory Server.
  68. * 0 -- down
  69. * 1 -- up
  70. * -1 -- unknown
  71. */
  72. #if !defined( XP_WIN32 )
  73. static pid_t server_pid;
  74. DS_EXPORT_SYMBOL int
  75. ds_get_updown_status()
  76. {
  77. char pid_file_name[BIG_LINE];
  78. char *rundir;
  79. FILE *pidfile;
  80. int ipid = -1;
  81. int status = 0;
  82. if ( (rundir = ds_get_run_dir()) == NULL ) {
  83. fprintf(stderr, "ds_get_updown_status: could not get install root\n");
  84. return(DS_SERVER_UNKNOWN);
  85. }
  86. PR_snprintf(pid_file_name, BIG_LINE, "%s/pid", rundir);
  87. pidfile = fopen(pid_file_name, "r");
  88. if ( pidfile == NULL ) {
  89. /*
  90. fprintf(stderr,
  91. "ds_get_updown_status: could not open pid file=%s errno=%d\n",
  92. pid_file_name, errno);
  93. */
  94. return(DS_SERVER_DOWN);
  95. }
  96. status = fscanf(pidfile, "%d\n", &ipid);
  97. fclose(pidfile);
  98. if ( status == -1 ) {
  99. fprintf(stderr,
  100. "ds_get_updown_status: pidfile=%s server_pid=%d errno=%d\n",
  101. pid_file_name, ipid, errno);
  102. unlink(pid_file_name); /* junk in file? */
  103. return(DS_SERVER_DOWN);
  104. }
  105. server_pid = (pid_t) ipid;
  106. if ( (status = kill(server_pid, 0)) != 0 && errno != EPERM ) {
  107. /* we should get ESRCH if the server is down, anything else may be
  108. a real problem */
  109. if (errno != ESRCH) {
  110. fprintf(stderr,
  111. "ds_get_updown_status: pidfile=%s server_pid=%d status=%d errno=%d\n",
  112. pid_file_name, server_pid, status, errno);
  113. }
  114. unlink(pid_file_name); /* pid does not exist! */
  115. return(DS_SERVER_DOWN);
  116. }
  117. return(DS_SERVER_UP);
  118. }
  119. #else
  120. DS_EXPORT_SYMBOL int
  121. ds_get_updown_status()
  122. {
  123. char *ds_name = ds_get_server_name();
  124. HANDLE hServerDoneEvent = NULL;
  125. /* watchdog.c creates a global event of this same name */
  126. if((hServerDoneEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, ds_name)) != NULL)
  127. {
  128. CloseHandle(hServerDoneEvent);
  129. return(DS_SERVER_UP);
  130. }
  131. if(GetLastError() == ERROR_ACCESS_DENIED) /* it exists */
  132. return(DS_SERVER_UP);
  133. /* assume it's not running. */
  134. return(DS_SERVER_DOWN);
  135. }
  136. #endif
  137. /*
  138. This function does not require calling ds_get_config(), but requires
  139. that that information be passed in. This is very useful for starting
  140. the server during installation, because we already have all of the
  141. configuration information in memory, we don't need to read it in
  142. */
  143. DS_EXPORT_SYMBOL int
  144. ds_bring_up_server_install(int verbose, char *root, char *errorlog)
  145. {
  146. #if !defined( XP_WIN32 )
  147. char startup_line[BIG_LINE];
  148. char statfile[PATH_MAX];
  149. char *tmp_dir;
  150. #endif
  151. int error = -1;
  152. int status = DS_SERVER_DOWN;
  153. int cur_size = 0;
  154. FILE *sf = NULL;
  155. char msgBuf[BIG_LINE] = {0};
  156. int secondsToWaitForServer = 600;
  157. char *serverStartupString = "slapd started.";
  158. status = ds_get_updown_status();
  159. if ( status == DS_SERVER_UP )
  160. return(DS_SERVER_ALREADY_UP);
  161. if (!root || !errorlog)
  162. return(DS_SERVER_UNKNOWN);
  163. if (verbose) {
  164. ds_send_status("starting up server ...");
  165. cur_size = ds_get_file_size(errorlog);
  166. }
  167. #if !defined( XP_WIN32 )
  168. tmp_dir = ds_get_tmp_dir();
  169. PR_snprintf(statfile, PATH_MAX, "%s%cstartup.%d", tmp_dir, FILE_SEP, (int)getpid());
  170. PR_snprintf(startup_line, BIG_LINE, "%s%c%s > %s 2>&1",
  171. root, FILE_SEP, START_SCRIPT, statfile);
  172. alter_startup_line(startup_line);
  173. error = system(startup_line);
  174. if (error == -1)
  175. error = DS_SERVER_DOWN; /* could not start server */
  176. else
  177. error = DS_SERVER_UP; /* started server */
  178. #else
  179. error = StartServer();
  180. #endif
  181. if (error != DS_SERVER_UP)
  182. {
  183. #if !defined( XP_WIN32 )
  184. FILE* fp = fopen(statfile, "r");
  185. if (fp)
  186. {
  187. while(fgets(msgBuf, BIG_LINE, fp))
  188. ds_send_status(msgBuf);
  189. fclose(fp);
  190. }
  191. #endif
  192. return DS_SERVER_COULD_NOT_START;
  193. }
  194. if (verbose)
  195. {
  196. /*
  197. * Stop in N secs or whenever the startup message comes up.
  198. * Do whichever happens first. msgBuf will contain the last
  199. * line read from the errorlog.
  200. */
  201. ds_display_tail(errorlog, secondsToWaitForServer, cur_size,
  202. serverStartupString, msgBuf);
  203. }
  204. if ( error != DS_SERVER_UP ) {
  205. int retval = DS_SERVER_UNKNOWN;
  206. if (strstr(msgBuf, "semget"))
  207. retval = DS_SERVER_MAX_SEMAPHORES;
  208. else if (strstr(msgBuf, "Back-End Initialization Failed"))
  209. retval = DS_SERVER_CORRUPTED_DB;
  210. else if (strstr(msgBuf, "not initialized... exiting"))
  211. retval = DS_SERVER_CORRUPTED_DB;
  212. else if (strstr(msgBuf, "address is in use"))
  213. retval = DS_SERVER_PORT_IN_USE;
  214. #if defined( XP_WIN32 )
  215. /* on NT, if we run out of resources, there will not even be an error
  216. log
  217. */
  218. else if (msgBuf[0] == 0) {
  219. retval = DS_SERVER_NO_RESOURCES;
  220. }
  221. #endif
  222. if (verbose)
  223. ds_send_error("error in starting server.", 1);
  224. return(retval);
  225. }
  226. if (verbose) {
  227. #if !defined( XP_WIN32 )
  228. if( !(sf = fopen(statfile, "r")) ) {
  229. ds_send_error("could not read status file.", 1);
  230. return(DS_SERVER_UNKNOWN);
  231. }
  232. while ( fgets(startup_line, BIG_LINE, sf) )
  233. ds_send_error(startup_line, 0);
  234. fclose(sf);
  235. unlink(statfile);
  236. #endif
  237. status = DS_SERVER_UNKNOWN;
  238. if (strstr(msgBuf, "semget"))
  239. status = DS_SERVER_MAX_SEMAPHORES;
  240. else if (strstr(msgBuf, "Back-End Initialization Failed"))
  241. status = DS_SERVER_CORRUPTED_DB;
  242. else if (strstr(msgBuf, "not initialized... exiting"))
  243. status = DS_SERVER_CORRUPTED_DB;
  244. else if (strstr(msgBuf, "address is in use"))
  245. status = DS_SERVER_PORT_IN_USE;
  246. #if defined( XP_WIN32 )
  247. /* on NT, if we run out of resources, there will not even be an error
  248. log
  249. */
  250. else if (msgBuf[0] == 0) {
  251. status = DS_SERVER_NO_RESOURCES;
  252. }
  253. #endif
  254. } else {
  255. int tries;
  256. for (tries = 0; tries < secondsToWaitForServer; tries++) {
  257. if (ds_get_updown_status() == DS_SERVER_UP) break;
  258. PR_Sleep(PR_SecondsToInterval(1));
  259. }
  260. if (verbose) {
  261. char str[100];
  262. PR_snprintf(str, sizeof(str), "Had to retry %d times", tries);
  263. ds_send_status(str);
  264. }
  265. }
  266. if ( (status == DS_SERVER_DOWN) || (status == DS_SERVER_UNKNOWN) )
  267. status = ds_get_updown_status();
  268. return(status);
  269. }
  270. /*
  271. * Start the Directory Server and return status.
  272. * Do not start if the server is already started.
  273. * 0 -- down
  274. * 1 -- up
  275. * -1 -- unknown
  276. * -2 -- already up
  277. */
  278. DS_EXPORT_SYMBOL int
  279. ds_bring_up_server(int verbose)
  280. {
  281. char *root;
  282. int status;
  283. char *errorlog;
  284. status = ds_get_updown_status();
  285. if ( status == DS_SERVER_UP )
  286. return(DS_SERVER_ALREADY_UP);
  287. if ( (root = ds_get_install_root()) == NULL )
  288. return(DS_SERVER_UNKNOWN);
  289. errorlog = ds_get_config_value(DS_ERRORLOG);
  290. if ( errorlog == NULL ) {
  291. errorlog = ds_get_errors_name(); /* fallback */
  292. }
  293. return ds_bring_up_server_install(verbose, root, errorlog);
  294. }
  295. DS_EXPORT_SYMBOL int
  296. ds_bring_down_server()
  297. {
  298. char *root;
  299. int status;
  300. int cur_size;
  301. char *errorlog;
  302. status = ds_get_updown_status(); /* set server_pid too! */
  303. if ( status != DS_SERVER_UP ) {
  304. ds_send_error("The server is not up.", 0);
  305. return(DS_SERVER_ALREADY_DOWN);
  306. }
  307. if ( (root = ds_get_install_root()) == NULL ) {
  308. ds_send_error("Could not get the server root directory.", 0);
  309. return(DS_SERVER_UNKNOWN);
  310. }
  311. ds_send_status("shutting down server ...");
  312. if (!(errorlog = ds_get_errors_name())) {
  313. ds_send_error("Could not get the error log filename.", 0);
  314. return DS_SERVER_UNKNOWN;
  315. }
  316. cur_size = ds_get_file_size(errorlog);
  317. #if !defined( XP_WIN32 )
  318. if ( (kill(server_pid, SIGTERM)) != 0) {
  319. if (errno == EPERM) {
  320. ds_send_error("Not permitted to kill server.", 0);
  321. fprintf (stdout, "[%s]: kill (%li, SIGTERM) failed with errno = EPERM.<br>\n",
  322. ds_get_server_name(), (long)server_pid);
  323. } else {
  324. ds_send_error("error in killing server.", 1);
  325. }
  326. return(DS_SERVER_UNKNOWN);
  327. }
  328. #else
  329. if( StopServer() == DS_SERVER_DOWN )
  330. {
  331. ds_send_status("shutdown: server shut down");
  332. }
  333. else
  334. {
  335. ds_send_error("error in killing server.", 1);
  336. return(DS_SERVER_UNKNOWN);
  337. }
  338. #endif
  339. /*
  340. * Wait up to SERVER_STOP_TIMEOUT seconds for the stopped message to
  341. * appear in the error log.
  342. */
  343. ds_display_tail(errorlog, SERVER_STOP_TIMEOUT, cur_size, "slapd stopped.", NULL);
  344. /* in some cases, the server will tell us it's down when it's really not,
  345. so give the OS a chance to remove it from the process table */
  346. PR_Sleep(PR_SecondsToInterval(1));
  347. return(ds_get_updown_status());
  348. }
  349. #if defined( XP_WIN32 )
  350. static BOOLEAN
  351. IsService()
  352. {
  353. #if 0
  354. CHAR ServerKey[512], *ValueString;
  355. HKEY hServerKey;
  356. DWORD dwType, ValueLength, Result;
  357. PR_snprintf(ServerKey,sizeof(ServerKey), "%s\\%s", COMPANY_KEY, PRODUCT_KEY);
  358. Result = RegOpenKey(HKEY_LOCAL_MACHINE, ServerKey, &hServerKey);
  359. if (Result != ERROR_SUCCESS) {
  360. return TRUE;
  361. }
  362. ValueLength = 512;
  363. ValueString = (PCHAR)malloc(ValueLength);
  364. Result = RegQueryValueEx(hServerKey, IS_SERVICE_KEY, NULL,
  365. &dwType, ValueString, &ValueLength);
  366. if (Result != ERROR_SUCCESS) {
  367. return TRUE;
  368. }
  369. if (strcmp(ValueString, "yes")) {
  370. return FALSE;
  371. }
  372. else {
  373. return TRUE;
  374. }
  375. #else
  376. return TRUE;
  377. #endif
  378. }
  379. #if 0
  380. NSAPI_PUBLIC BOOLEAN
  381. IsAdminService()
  382. {
  383. CHAR AdminKey[512], *ValueString;
  384. HKEY hAdminKey;
  385. DWORD dwType, ValueLength, Result;
  386. PR_snprintf(AdminKey,sizeof(AdminKey), "%s\\%s", COMPANY_KEY, ADMIN_REGISTRY_ROOT_KEY);
  387. Result = RegOpenKey(HKEY_LOCAL_MACHINE, AdminKey, &hAdminKey);
  388. if (Result != ERROR_SUCCESS) {
  389. return TRUE;
  390. }
  391. ValueLength = 512;
  392. ValueString = (PCHAR)malloc(ValueLength);
  393. Result = RegQueryValueEx(hAdminKey, IS_SERVICE_KEY, NULL,
  394. &dwType, ValueString, &ValueLength);
  395. if (Result != ERROR_SUCCESS) {
  396. return TRUE;
  397. }
  398. if (strcmp(ValueString, "yes")) {
  399. return FALSE;
  400. } else {
  401. return TRUE;
  402. }
  403. }
  404. #endif
  405. int
  406. StartServer()
  407. {
  408. CHAR ErrorString[512];
  409. BOOLEAN Service;
  410. /* Figure out if the server is a service or an exe */
  411. Service = IsService();
  412. if(Service) {
  413. if (!(schSCManager = OpenSCManager(
  414. NULL, // machine (NULL == local)
  415. NULL, // database (NULL == default)
  416. SC_MANAGER_ALL_ACCESS // access required
  417. ))) {
  418. PR_snprintf(ErrorString, sizeof(ErrorString),
  419. "Error: Could not open the ServiceControlManager:%d "
  420. "Please restart the server %s from the Services Program Item "
  421. "in the Control Panel", ds_get_server_name(), GetLastError());
  422. ds_send_error(ErrorString, 0);
  423. return(DS_SERVER_UNKNOWN);
  424. }
  425. return(StartNetscapeService());
  426. } else {
  427. return(StartNetscapeProgram());
  428. }
  429. }
  430. int
  431. StopandRestartServer()
  432. {
  433. CHAR ErrorString[512];
  434. BOOLEAN Service;
  435. /* First figure out if the server is a service or an exe */
  436. Service = IsService();
  437. if(Service) {
  438. if (!(schSCManager = OpenSCManager(
  439. NULL, // machine (NULL == local)
  440. NULL, // database (NULL == default)
  441. SC_MANAGER_ALL_ACCESS // access required
  442. ))) {
  443. PR_snprintf(ErrorString, sizeof(ErrorString),
  444. "Error: Could not restart server."
  445. "Please restart the server %s from the Services Program Item "
  446. "in the Control Panel", ds_get_server_name());
  447. ds_send_error(ErrorString, 0);
  448. return(DS_SERVER_UNKNOWN);
  449. }
  450. if (StopNetscapeService() != DS_SERVER_DOWN)
  451. return(DS_SERVER_UNKNOWN);
  452. return(StartNetscapeService());
  453. } else {
  454. if (StopNetscapeProgram() != DS_SERVER_DOWN)
  455. return(DS_SERVER_UNKNOWN);
  456. return(StartNetscapeProgram());
  457. }
  458. }
  459. int
  460. StopServer()
  461. {
  462. CHAR ErrorString[512];
  463. BOOLEAN Service;
  464. /* First figure out if the server is a service or an exe */
  465. Service = IsService();
  466. if(Service) {
  467. if (!(schSCManager = OpenSCManager(
  468. NULL, // machine (NULL == local)
  469. NULL, // database (NULL == default)
  470. SC_MANAGER_ALL_ACCESS // access required
  471. ))) {
  472. PR_snprintf(ErrorString, sizeof(ErrorString),
  473. "Error: Could not open the ServiceControlManager:%d "
  474. "Please restart the server %s from the Services Program Item "
  475. "in the Control Panel", ds_get_server_name(), GetLastError());
  476. ds_send_error(ErrorString, 0);
  477. return(DS_SERVER_UNKNOWN);
  478. }
  479. return(StopNetscapeService());
  480. } else {
  481. return(StopNetscapeProgram());
  482. }
  483. }
  484. int
  485. StartNetscapeProgram()
  486. {
  487. char line[BIG_LINE], cmd[BIG_LINE];
  488. char *tmp = ds_get_install_root();
  489. CHAR ErrorString[512];
  490. STARTUPINFO siStartInfo;
  491. PROCESS_INFORMATION piProcInfo;
  492. FILE *CmdFile;
  493. ZeroMemory(line, sizeof(line));
  494. PR_snprintf(line, BIG_LINE, "%s\\startsrv.bat", tmp);
  495. CmdFile = fopen(line, "r");
  496. if (!CmdFile)
  497. {
  498. PR_snprintf(ErrorString, sizeof(ErrorString), "Error:Tried to start server %s "
  499. ": Could not open the startup script %s :Error %d. Please "
  500. "run startsrv.bat from the server's root directory.",
  501. ds_get_server_name(), line, errno);
  502. ds_send_error(ErrorString, 0);
  503. return(DS_SERVER_DOWN);
  504. }
  505. ZeroMemory(cmd, sizeof(cmd));
  506. if (!fread(cmd, 1, BIG_LINE, CmdFile))
  507. {
  508. PR_snprintf(ErrorString, sizeof(ErrorString), "Error:Tried to start server %s "
  509. ": Could not read the startup script %s :Error %d. Please "
  510. "run startsrv.bat from the server's root directory.",
  511. ds_get_server_name(), line, errno);
  512. ds_send_error(ErrorString, 0);
  513. return(DS_SERVER_DOWN);
  514. }
  515. ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
  516. siStartInfo.cb = sizeof(STARTUPINFO);
  517. siStartInfo.lpReserved = siStartInfo.lpReserved2 = NULL;
  518. siStartInfo.cbReserved2 = 0;
  519. siStartInfo.lpDesktop = NULL;
  520. if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE,
  521. 0, NULL, NULL, &siStartInfo, &piProcInfo))
  522. {
  523. PR_snprintf(ErrorString, sizeof(ErrorString), "Error:Tried to start server %s "
  524. ": Could not start up the startup script %s :Error %d. Please "
  525. "run startsrv.bat from the server's root directory.",
  526. ds_get_server_name(), line, GetLastError());
  527. ds_send_error(ErrorString, 0);
  528. return(DS_SERVER_DOWN);
  529. }
  530. CloseHandle(piProcInfo.hProcess);
  531. CloseHandle(piProcInfo.hThread);
  532. return(DS_SERVER_UP);
  533. }
  534. int
  535. StopNetscapeProgram()
  536. {
  537. HANDLE hEvent;
  538. CHAR ErrorString[512];
  539. char *servid = ds_get_server_name();
  540. hEvent = CreateEvent(NULL, TRUE, FALSE, servid);
  541. if(!SetEvent(hEvent))
  542. {
  543. PR_snprintf(ErrorString, sizeof(ErrorString), "Tried to stop existing server %s"
  544. ": Could not signal it to stop :Error %d",
  545. servid, GetLastError());
  546. ds_send_error(ErrorString, 0);
  547. return(DS_SERVER_UNKNOWN);
  548. }
  549. return(DS_SERVER_DOWN);
  550. }
  551. int
  552. StopNetscapeService()
  553. {
  554. BOOL ret;
  555. SERVICE_STATUS ServiceStatus;
  556. DWORD Error;
  557. CHAR ErrorString[512];
  558. char *serviceName = ds_get_server_name();
  559. schService = OpenService(schSCManager, serviceName, SERVICE_ALL_ACCESS);
  560. if (schService == NULL)
  561. {
  562. PR_snprintf(ErrorString, sizeof(ErrorString), "Tried to open service"
  563. " %s: Error %d (%s). Please"
  564. " stop the server from the Services Item in the Control Panel",
  565. serviceName, GetLastError(), ds_system_errmsg());
  566. ds_send_error(ErrorString, 0);
  567. return(DS_SERVER_UP);
  568. }
  569. ret = ControlService(schService, SERVICE_CONTROL_STOP, &ServiceStatus);
  570. Error = GetLastError();
  571. /* if ControlService returns with ERROR_SERVICE_CANNOT_ACCEPT_CTRL and
  572. the server status indicates that it is either shutdown or in the process
  573. of shutting down, then just wait for it to stop as usual */
  574. if (ret ||
  575. ((Error == ERROR_SERVICE_CANNOT_ACCEPT_CTRL) &&
  576. ((ServiceStatus.dwCurrentState == SERVICE_STOPPED) ||
  577. (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING))))
  578. {
  579. CloseServiceHandle(schService);
  580. /* We make sure that the service is stopped */
  581. WaitForServertoStop();
  582. return(DS_SERVER_DOWN);
  583. }
  584. else if (Error != ERROR_SERVICE_NOT_ACTIVE)
  585. {
  586. PR_snprintf(ErrorString, sizeof(ErrorString), "Tried to stop service"
  587. " %s: Error %d (%s)."
  588. " Please stop the server from the Services Item in the"
  589. " Control Panel", serviceName, Error, ds_system_errmsg());
  590. ds_send_error(ErrorString, 0);
  591. return(DS_SERVER_UNKNOWN);
  592. }
  593. return(DS_SERVER_DOWN);
  594. }
  595. int
  596. StartNetscapeService()
  597. {
  598. CHAR ErrorString[512];
  599. int retries = 0;
  600. char *serviceName = ds_get_server_name();
  601. schService = OpenService(
  602. schSCManager, // SCManager database
  603. serviceName, // name of service
  604. SERVICE_ALL_ACCESS);
  605. if (schService == NULL)
  606. {
  607. CloseServiceHandle(schService);
  608. PR_snprintf(ErrorString, sizeof(ErrorString),"Tried to start"
  609. " the service %s: Error %d. Please"
  610. " start the server from the Services Item in the Control Panel",
  611. serviceName, GetLastError());
  612. ds_send_error(ErrorString, 0);
  613. return(DS_SERVER_DOWN);
  614. }
  615. if (!StartService(schService, 0, NULL))
  616. {
  617. CloseServiceHandle(schService);
  618. PR_snprintf(ErrorString, sizeof(ErrorString), "StartService:Could not start "
  619. "the Directory service %s: Error %d. Please restart the server "
  620. "from the Services Item in the Control Panel",
  621. serviceName, GetLastError());
  622. ds_send_error(ErrorString, 0);
  623. return(DS_SERVER_DOWN);
  624. }
  625. CloseServiceHandle(schService);
  626. return(DS_SERVER_UP);
  627. }
  628. void
  629. WaitForServertoStop()
  630. {
  631. HANDLE hServDoneSemaphore;
  632. int result,retries = 0;
  633. char *serviceName = ds_get_server_name();
  634. char *newServiceName;
  635. RETRY:
  636. newServiceName = PR_smprintf("NS_%s", serviceName);
  637. hServDoneSemaphore = CreateSemaphore(
  638. NULL, // security attributes
  639. 0, // initial count for semaphore
  640. 1, // maximum count for semaphore
  641. newServiceName);
  642. PR_smprintf_free(newServiceName);
  643. if ( hServDoneSemaphore == NULL) {
  644. result = GetLastError();
  645. if (result == ERROR_INVALID_HANDLE) {
  646. if (retries < SERVER_STOP_TIMEOUT) {
  647. retries++;
  648. Sleep(1000);
  649. goto RETRY;
  650. }
  651. } else {
  652. /* We aren't too interested in why the creation failed
  653. * if it is not because of another instance */
  654. return;
  655. }
  656. } // hServDoneSemaphore == NULL
  657. CloseHandle(hServDoneSemaphore);
  658. return;
  659. }
  660. #endif