summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/ntwdog
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/slapd/ntwdog
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/slapd/ntwdog')
-rw-r--r--ldap/servers/slapd/ntwdog/Makefile60
-rw-r--r--ldap/servers/slapd/ntwdog/cron_conf.c654
-rw-r--r--ldap/servers/slapd/ntwdog/cron_conf.h86
-rw-r--r--ldap/servers/slapd/ntwdog/ntcron.c156
-rw-r--r--ldap/servers/slapd/ntwdog/ntwatchdog.c1163
5 files changed, 2119 insertions, 0 deletions
diff --git a/ldap/servers/slapd/ntwdog/Makefile b/ldap/servers/slapd/ntwdog/Makefile
new file mode 100644
index 00000000..f727232c
--- /dev/null
+++ b/ldap/servers/slapd/ntwdog/Makefile
@@ -0,0 +1,60 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+#
+# GNU Makefile for LDAP Server NT Service watchdog
+#
+
+LDAP_SRC = ../../..
+MCOM_ROOT = ../../../../..
+
+NOSTDCLEAN=true # don't let nsconfig.mk define target clean
+NOSTDSTRIP=true # don't let nsconfig.mk define target strip
+NSPR20=true # probably should be defined somewhere else (not sure where)
+
+OBJDEST = $(OBJDIR)/ntwdog/obj
+SLAPD_OBJDEST= $(OBJDIR)/obj
+BINDIR = $(LDAP_SERVER_RELDIR)
+LDAP_LIBDIR = $(OBJDIR)/lib
+
+include $(MCOM_ROOT)/ldapserver/nsconfig.mk
+include $(LDAP_SRC)/nsldap.mk
+
+ifeq ($(ARCH), WINNT)
+SUBSYSTEM=windows
+endif
+
+#INCLUDES += -I$(MCOM_ROOT)/ldapserver/include/libadmin
+
+DS_SERVER_DEFS = -DNS_DS
+
+NTWDOG_OBJS= ntwatchdog.o
+
+OBJS = $(addprefix $(OBJDEST)/, $(NTWDOG_OBJS))
+
+LIBS_DEP = $(LDAP_LIBUTIL_DEP) $(LIBADMIN_DEP)
+
+LIBS = $(LDAP_LIBUTIL)
+
+EXTRA_LIBS += $(LIBS)
+
+NTWDOG = $(addprefix $(BINDIR)/, ns-slapd.exe)
+
+all: $(OBJDEST) $(BINDIR) $(NTWDOG)
+
+$(OBJDEST):
+ $(MKDIR) $(OBJDEST)
+
+$(NTWDOG): $(OBJS) $(LIBS_DEP)
+ $(LINK_EXE)
+
+veryclean: clean
+
+clean:
+ $(RM) $(OBJS)
+ $(RM) $(NTWDOG)
+
diff --git a/ldap/servers/slapd/ntwdog/cron_conf.c b/ldap/servers/slapd/ntwdog/cron_conf.c
new file mode 100644
index 00000000..8d60191a
--- /dev/null
+++ b/ldap/servers/slapd/ntwdog/cron_conf.c
@@ -0,0 +1,654 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <process.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "cron_conf.h"
+
+#define NSAPI_PUBLIC
+
+#ifndef BUF_SIZE
+#define BUF_SIZE 4096
+#endif
+
+#ifndef S_BUF_SIZE
+#define S_BUF_SIZE 1024
+#endif
+
+#ifdef XP_WIN32
+#pragma warning (disable: 4005) // macro redifinition //
+#define MALLOC(size) malloc(size)
+#define REALLOC(x, size) realloc(x, size)
+#define FREE(x) free((void*) x)
+#define STRDUP(x) strdup(x)
+#define strcasecmp(x, y) stricmp(x, y)
+#pragma warning (default: 4005) // macro redifinition //
+#endif
+
+static char *admroot;
+static char *nsroot;
+
+#define DAILY "Sun Mon Tue Wed Thu Fri Sat"
+
+static cron_conf_list *cclist = NULL;
+static cron_conf_list *cctail = NULL;
+static char *conffile = NULL;
+
+#ifndef CRON_CONF_STAND_ALONE
+static void set_roots()
+{
+ char *ar = ADMCONFDIR;
+ if(ar)
+ admroot = STRDUP(ar);
+}
+#endif
+
+/* General note: strtok() is not MT safe on Unix , but it is okay to call
+ here because this file is NT only and strtok() is MT safe on NT */
+
+static char *nocr(char *buf)
+{
+ if (buf)
+ {
+ if(buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ }
+
+ return buf;
+}
+
+static int debug(char *fmt, ...)
+{
+ va_list args;
+ char buf[BUF_SIZE];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+
+ fprintf(stdout, "<<DEBUG>> %s <<DEBUG>>\n", buf);
+ fflush(stdout);
+
+ return 1;
+}
+
+static char *get_conf_file()
+{
+ static char conffile [S_BUF_SIZE];
+ char nsconfile[S_BUF_SIZE];
+ char buf [BUF_SIZE];
+ char *r, *p;
+ FILE *fp;
+ int flag = 0;
+
+ if (admroot)
+ sprintf(nsconfile, "%s/ns-cron.conf", admroot);
+ else
+ sprintf(nsconfile, "%s/admin-serv/config/ns-cron.conf", nsroot);
+
+ if (!(fp = fopen(nsconfile, "r")))
+ return NULL;
+
+ while(fgets(buf, sizeof(buf), fp))
+ {
+ r = strtok(buf, " \t\n");
+ if (!r) /* bad line, ignore */
+ continue;
+
+ p = strtok(NULL, " \t\n");
+ if (!p) /* bad line, ignore */
+ continue;
+
+ if (!strcasecmp(r, "ConfFile"))
+ {
+ /* if filename without path is specified, default to admin svr dir */
+ if((strchr(p, '\\') == NULL) &&
+ (strchr(p, '/') == NULL))
+ sprintf(conffile, "%s/%s", admroot, p);
+ else
+ sprintf(conffile, "%s", p);
+ flag++;
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ if (!flag)
+ return NULL;
+
+ return conffile;
+}
+
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+cron_conf_obj *cron_conf_create_obj(char *name, char *command, char *dir,
+ char *user, char *start_time, char *days)
+{
+ cron_conf_obj *object;
+ char *d = NULL;
+
+ object = (cron_conf_obj*)MALLOC(sizeof(cron_conf_obj));
+
+ object->name = (name) ? STRDUP(name) : NULL;
+ object->command = (command) ? STRDUP(command) : NULL;
+ object->dir = (dir) ? STRDUP(dir) : NULL;
+ object->user = (user) ? STRDUP(user) : NULL;
+ object->start_time = (start_time) ? STRDUP(start_time) : NULL;
+
+#if 1
+ if (days)
+ {
+ if (!(strcasecmp(days, "Daily")))
+ d = STRDUP(DAILY);
+ else
+ d = STRDUP(days);
+ }
+#else
+ d = STRDUP("Wed Thu");
+#endif
+
+ object->days = d;
+
+ return object;
+}
+
+
+static void cron_conf_free_listobj(cron_conf_list *lobj)
+{
+ cron_conf_obj *obj = lobj->obj;
+
+
+ if (obj)
+ {
+ if(obj->name) FREE(obj->name);
+ if(obj->command) FREE(obj->command);
+ if(obj->dir) FREE(obj->dir);
+ if(obj->user) FREE(obj->user);
+ if(obj->start_time) FREE(obj->start_time);
+ if(obj->days) FREE(obj->days);
+
+ FREE(obj);
+ }
+
+ FREE(lobj);
+}
+
+
+static cron_conf_obj *get_object(FILE *fp)
+{
+ cron_conf_obj *object;
+ char name [S_BUF_SIZE];
+ char command [S_BUF_SIZE];
+ char dir [S_BUF_SIZE];
+ char user [S_BUF_SIZE];
+ char start_time[S_BUF_SIZE];
+ char days [S_BUF_SIZE];
+ char buf [BUF_SIZE];
+ char *p, *q;
+ int flag = 0;
+ int hascom, hasdir, hasuser, hastime, hasdays;
+
+ p = fgets(buf, sizeof(buf), fp);
+
+ if (!p)
+ return NULL;
+ /* else debug("Read line '%s'", nocr(buf)); */
+
+ if (strncmp(buf, "<Object", 7))
+ return NULL;
+
+ hascom = hasdir = hasuser = hastime = hasdays = 0;
+
+ p = strtok(buf, "<=>\n\t ");
+ if (!p)
+ return NULL;
+
+ p = strtok(NULL, "<=>\n\t ");
+ if (!p)
+ return NULL;
+
+ p = strtok(NULL, "<=>\n\t ");
+ if (!p)
+ return NULL;
+
+ sprintf(name, "%s", p);
+ /* debug("Setting name to '%s'", name); */
+
+ while(fgets(buf, sizeof(buf), fp))
+ {
+ /* debug("Read line '%s'", nocr(buf)); */
+
+ p = strtok(buf, " \t\n");
+
+ if (!p)
+ continue;
+
+ if (!strcasecmp(p, "</Object>"))
+ {
+ flag++;
+ break;
+ }
+
+ if(!strcasecmp(p, "Command"))
+ {
+ q = strtok(NULL, "\n");
+
+ if (q)
+ q = strchr(q, '\"');
+
+ if (q)
+ q++;
+
+ if (q)
+ {
+ if (!hascom)
+ {
+ /* get rid of quotes */
+ p = strrchr(q, '\"');
+
+ if (p)
+ *p = '\0';
+
+ if (q)
+ {
+ sprintf(command, "%s", q);
+ /* debug("Setting command to '%s'", command); */
+ hascom++;
+ }
+ }
+ else /* already has a command */
+ ; /* ignore */
+ }
+ continue;
+ }
+
+ if(!strcasecmp(p, "Dir"))
+ {
+ q = strtok(NULL, "\n");
+
+ if (q)
+ q = strchr(q, '\"');
+
+ if (q)
+ q++;
+
+ if (q)
+ {
+ if (!hasdir)
+ {
+ /* get rid of quotes */
+ p = strrchr(q, '\"');
+
+ if (p)
+ *p = '\0';
+
+ if (q)
+ {
+ sprintf(dir, "%s", q);
+ /* debug("Setting dir to '%s'", dir); */
+ hasdir++;
+ }
+ }
+ else /* already has a dir */
+ ; /* ignore */
+ }
+ continue;
+ }
+
+ else if(!strcasecmp(p, "User"))
+ {
+ q = strtok(NULL, " \t\n");
+
+ if (q)
+ {
+ if (!hasuser)
+ {
+ sprintf(user, "%s", q);
+ /* debug("Setting user to '%s'", user); */
+ hasuser++;
+ }
+ else /* already has a user */
+ ; /* ignore */
+ }
+ continue;
+ }
+
+ else if(!strcasecmp(p, "Time"))
+ {
+ q = strtok(NULL, "\n");
+
+ if (q)
+ {
+ if (!hastime)
+ {
+ sprintf(start_time, "%s", q);
+ /* debug("Setting time to '%s'", start_time); */
+ hastime++;
+ }
+ else /* already has a time */
+ ; /* ignore */
+ }
+ continue;
+ }
+
+ else if(!strcasecmp(p, "Days"))
+ {
+ q = strtok(NULL, "\n");
+
+ if (q)
+ {
+ if (!hasdays)
+ {
+ sprintf(days, "%s", q);
+ /* debug("Setting days to '%s'", days); */
+ hasdays++;
+ }
+ else /* already has days */
+ ; /* ignore */
+ }
+ continue;
+ }
+
+ else
+ {
+ /* gibberish... ignore... will be fixed when
+ file is rewritten */
+ continue;
+ }
+ }
+
+ object = cron_conf_create_obj(name,
+ (hascom) ? command : NULL,
+ (hasdir) ? dir : NULL,
+ (hasuser) ? user : NULL,
+ (hastime) ? start_time : NULL,
+ (hasdays) ? days : NULL);
+
+ return object;
+}
+
+
+static void cron_conf_write_stream(FILE *fp)
+{
+ cron_conf_obj *obj;
+ cron_conf_list *lobj;
+
+ for(lobj = cclist; lobj; lobj = lobj->next)
+ {
+ obj = lobj->obj;
+
+ fprintf(fp, "<Object name=%s>\n", (obj->name) ? obj->name : "?");
+ fprintf(fp, " Command \"%s\"\n", (obj->command) ? obj->command : "?");
+ if (obj->dir)
+ fprintf(fp, " Dir \"%s\"\n", obj->dir);
+ if (obj->user)
+ fprintf(fp, " User %s\n", obj->user);
+ fprintf(fp, " Time %s\n", (obj->start_time) ? obj->start_time : "?");
+ fprintf(fp, " Days %s\n", (obj->days) ? obj->days : "?");
+ fprintf(fp, "</Object>\n");
+ }
+}
+
+
+static void cron_conf_delete(char *name, cron_conf_obj *cco)
+{
+ cron_conf_list *lobj = NULL;
+ cron_conf_list *pobj = NULL;
+
+ if (!cclist)
+ return;
+
+ if (!strcmp(cclist->name, name))
+ {
+ lobj = cclist;
+ cclist = cclist->next;
+ if (cctail == lobj)
+ cctail = cclist;
+
+ cron_conf_free_listobj(lobj);
+ }
+ else
+ {
+ pobj = cclist;
+
+ for(lobj = cclist->next; lobj; lobj = lobj->next)
+ {
+ if(!strcmp(lobj->name, name))
+ {
+ if (lobj == cctail)
+ cctail = pobj;
+
+ pobj->next = lobj->next;
+ cron_conf_free_listobj(lobj);
+
+ break;
+ }
+
+ pobj = lobj;
+ }
+ }
+
+ return;
+}
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+int cron_conf_read()
+{
+ FILE *fp;
+ cron_conf_obj *obj;
+ cron_conf_list *lobj;
+
+#ifndef CRON_CONF_STAND_ALONE
+ set_roots();
+#endif
+
+ if (!(conffile = get_conf_file()))
+ {
+ /* debug("Conffile is null"); */
+ return 0;
+ }
+ /* else debug("Conffile: '%s'", conffile); */
+
+ if (!(fp = fopen(conffile, "r")))
+ {
+ /* debug("Couldn't open conffile"); */
+ return 0;
+ }
+
+ while((obj = get_object(fp)))
+ {
+ lobj = (cron_conf_list*)MALLOC(sizeof(struct cron_conf_list));
+ lobj->name = obj->name;
+ lobj->obj = obj;
+ lobj->next = NULL;
+
+ /* debug("Created a list object named '%s'", lobj->name); */
+
+ if(cclist == NULL) /* first object */
+ {
+ cclist = cctail = lobj;
+ }
+ else
+ {
+ cctail->next = lobj;
+ cctail = lobj;
+ }
+
+ /* debug("List now, head: '%s', tail: '%s'",
+ cclist->name, cctail->name); */
+ }
+
+ fclose(fp);
+
+ return 1;
+}
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+cron_conf_obj *cron_conf_get(char *name)
+{
+ cron_conf_obj *obj = NULL;
+ cron_conf_list *lobj = NULL;
+
+ /* find object */
+ for(lobj = cclist; lobj; lobj = lobj->next)
+ {
+ if(!strcmp(lobj->name, name))
+ {
+ obj = lobj->obj;
+ break;
+ }
+ }
+
+#if 0
+ if (obj)
+ {
+ debug("Found object %s", obj->name);
+ debug("obj->command = %s", (obj->command) ? obj->command : "NULL");
+ debug("obj->dir = %s", (obj->dir) ? obj->dir : "NULL");
+ debug("obj->user = %s", (obj->user) ? obj->user : "NULL");
+ debug("obj->start_time = %s", (obj->start_time) ? obj->start_time : "NULL");
+ debug("obj->days = %s", (obj->days) ? obj->days : "NULL");
+ }
+#endif
+
+ return obj;
+}
+
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+cron_conf_list *cron_conf_get_list()
+{
+ return cclist;
+}
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+cron_conf_obj *cron_conf_set(char *name, cron_conf_obj *cco)
+{
+ cron_conf_obj *obj = NULL;
+ cron_conf_list *lobj = NULL;
+
+ if (!name)
+ return NULL;
+
+ if (!cco)
+ {
+ cron_conf_delete(name, cco);
+ return NULL;
+ }
+ else /* cco exists */
+ {
+ /* find object */
+ obj = cron_conf_get(name);
+
+
+ if (obj) /* found it */
+ {
+ if (cco->command)
+ {
+ FREE(obj->command);
+ obj->command = cco->command;
+ }
+
+ if (cco->dir)
+ {
+ FREE(obj->dir);
+ obj->dir = cco->dir;
+ }
+
+ if (cco->user)
+ {
+ FREE(obj->user);
+ obj->user = cco->user;
+ }
+
+ if (cco->start_time)
+ {
+ FREE(obj->start_time);
+ obj->start_time = cco->start_time;
+ }
+
+ if (cco->days)
+ {
+ FREE(obj->days);
+ obj->days = cco->days;
+ }
+
+ FREE(cco);
+ }
+ else /* couldn't find it */
+ {
+ obj = cco;
+
+ lobj = (cron_conf_list*)MALLOC(sizeof(cron_conf_list));
+ lobj->name = obj->name;
+ lobj->obj = obj;
+ lobj->next = NULL;
+
+ if(cclist == NULL) /* first object */
+ {
+ cclist = cctail = lobj;
+ }
+ else
+ {
+ cctail->next = lobj;
+ cctail = lobj;
+ }
+ }
+ }
+
+ return obj;
+}
+
+void cron_conf_write()
+{
+ FILE *fp;
+
+ if (!conffile)
+ conffile = get_conf_file();
+
+ if(!(fp = fopen(conffile, "w")))
+ return;
+
+ cron_conf_write_stream(fp);
+
+ fclose(fp);
+}
+
+
+#ifndef CRON_CONF_STAND_ALONE
+NSAPI_PUBLIC
+#endif
+void cron_conf_free()
+{
+ cron_conf_list *lobj = NULL;
+
+ /* find object */
+ while(cclist)
+ {
+ lobj = cclist;
+ cclist = cclist->next;
+
+ cron_conf_free_listobj(lobj);
+ }
+
+ cclist = cctail = NULL;
+}
+
diff --git a/ldap/servers/slapd/ntwdog/cron_conf.h b/ldap/servers/slapd/ntwdog/cron_conf.h
new file mode 100644
index 00000000..23a32463
--- /dev/null
+++ b/ldap/servers/slapd/ntwdog/cron_conf.h
@@ -0,0 +1,86 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/***********************************************************************
+** $Id: cron_conf.h,v 1.1 2005/01/21 00:40:52 cvsadm Exp $
+**
+**
+** NAME
+** cron_conf.h
+**
+** DESCRIPTION
+**
+**
+** AUTHOR
+** <robw@netscape.com>
+**
+***********************************************************************/
+
+#ifndef _CRON_CONF_H_
+#define _CRON_CONF_H_
+
+/***********************************************************************
+** Includes
+***********************************************************************/
+/* read and write to cron.conf, cron_conf.c */
+/* Alex Feygin, 3/22/96 */
+typedef struct cron_conf_obj
+{
+ char *name;
+ char *command;
+ char *dir;
+ char *user;
+ char *start_time;
+ char *days;
+}
+cron_conf_obj;
+
+typedef struct cron_conf_list
+{
+ char *name;
+ cron_conf_obj *obj;
+ struct cron_conf_list *next;
+}
+cron_conf_list;
+
+/* Reads cron.conf to a null terminated list of cron_conf_objects; returns
+ 0 if unable to do a read; 1 otherwise */
+int cron_conf_read();
+
+/* gets a cron object, NULL if it doesnt exist */
+cron_conf_obj *cron_conf_get(char *name);
+
+/* returns a NULL-terminated cron_conf_list of all the cron conf objects */
+cron_conf_list *cron_conf_get_list();
+
+/* Creates a cron conf object; all these args get STRDUP'd in the function
+ so make sure to free up the space later if need be */
+cron_conf_obj *cron_conf_create_obj(char *name, char *command,
+ char *dir, char *user,
+ char *start_time, char *days);
+
+/* Puts a cron conf object into list or updates it if it already in there.
+ Returns either the object passed or the object in there already;
+ cco may be FREE'd during this operation so if you need the object
+ back, call it like so:
+
+ cco = cron_conf_set(cco->name, cco);
+
+ calling cron_conf_set with a NULL cco will cause the 'name' object
+ to be deleted.
+*/
+cron_conf_obj *cron_conf_set(char *name, cron_conf_obj *cco);
+
+/* write out current list of cron_conf_objects to cron.conf file */
+void cron_conf_write();
+
+/* free all cron conf data structures */
+void cron_conf_free();
+
+#define MAGNUS_CONF "magnus.conf"
+#define ADMCONFDIR "../config/"
+
+
+#endif /* _CRON_CONF_H_ */
diff --git a/ldap/servers/slapd/ntwdog/ntcron.c b/ldap/servers/slapd/ntwdog/ntcron.c
new file mode 100644
index 00000000..98b4cae3
--- /dev/null
+++ b/ldap/servers/slapd/ntwdog/ntcron.c
@@ -0,0 +1,156 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+// //
+// Name: NTCRON //
+// Platforms: WIN32 //
+// Description: unix cron functionality in a separate thread //
+// Notes: //
+// The following assumptions are made: //
+// - gszServerRoot is set to c:\netscape\server //
+// - ns-cron.conf and cron.conf are available //
+// Todo: //
+// - handle time format variations of hh:mm //
+// - keep track of children //
+// ...................................................................... //
+// Revision History: //
+// 03-26-96 Initial Version, Andy Hakim (ahakim@netscape.com) //
+// 07-10-96 Modified for Directory Server, pkennedy@netscape.com //
+//--------------------------------------------------------------------------//
+#include <windows.h>
+#include "ntwatchdog.h"
+#include "ntslapdmessages.h" // event log msgs constants //
+#include "cron_conf.h"
+
+static cron_conf_list *cclist = NULL;
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL CRON_CheckDay(LPSYSTEMTIME lpstNow, char *szDays)
+{
+ BOOL bReturn = FALSE;
+ char szToday[16];
+ if(GetDateFormat((LCID)NULL, 0, lpstNow, "ddd", szToday, sizeof(szToday)) != 0)
+ {
+ strlwr(szDays);
+ strlwr(szToday);
+ if(strstr(szDays, szToday) != NULL)
+ bReturn = TRUE;
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL CRON_CheckTime(LPSYSTEMTIME lpstNow, char *szTime)
+{
+ BOOL bReturn = FALSE;
+ char szCurrentTime[16];
+ char szStartTime[16];
+
+ strcpy(szStartTime, szTime);
+
+ if(szTime[1] == ':')
+ wsprintf(szStartTime, "0%s", szTime);
+
+ if(GetTimeFormat((LCID)LOCALE_SYSTEM_DEFAULT, TIME_FORCE24HOURFORMAT, lpstNow, "hh:mm", szCurrentTime, sizeof(szCurrentTime)) != 0)
+ {
+ if(strcmp(szCurrentTime, szStartTime) == 0)
+ bReturn = TRUE;
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL CRON_StartJob(PROCESS_INFORMATION *pi, cron_conf_obj *cco)
+{
+ BOOL bReturn = FALSE;
+ STARTUPINFO sui;
+
+ sui.cb = sizeof(STARTUPINFO);
+ sui.lpReserved = 0;
+ sui.lpDesktop = NULL;
+ sui.lpTitle = NULL;
+ sui.dwX = 0;
+ sui.dwY = 0;
+ sui.dwXSize = 0;
+ sui.dwYSize = 0;
+ sui.dwXCountChars = 0;
+ sui.dwYCountChars = 0;
+ sui.dwFillAttribute = 0;
+ sui.dwFlags = STARTF_USESHOWWINDOW;
+ sui.wShowWindow = SW_SHOWMINIMIZED;
+ sui.cbReserved2 = 0;
+ sui.lpReserved2 = 0;
+ sui.hStdInput = 0;
+ sui.hStdOutput = 0;
+ sui.hStdError = 0;
+
+ bReturn = CreateProcess(NULL, cco->command, NULL, NULL,
+ TRUE, 0, NULL, cco->dir, &sui, pi );
+ if(!bReturn)
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_CRON_STARTFAILED, cco->name);
+
+ return(bReturn);
+}
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL CRON_CheckConfFile()
+{
+ BOOL bReturn = FALSE;
+ PROCESS_INFORMATION pi;
+ SYSTEMTIME stNow;
+
+ GetLocalTime(&stNow); // note: this provides time adjusted for local time zone
+
+ if(cron_conf_read())
+ cclist = cron_conf_get_list();
+
+ while((cclist) && (cclist->obj))
+ {
+ cron_conf_obj *cco = cclist->obj;
+ if((cco->days) && (cco->start_time) && (cco->command))
+ {
+ if(CRON_CheckDay(&stNow, cco->days) && CRON_CheckTime(&stNow, cco->start_time))
+ {
+ bReturn = CRON_StartJob(&pi, cco);
+ CLOSEHANDLE(pi.hProcess);
+ CLOSEHANDLE(pi.hThread);
+ }
+ }
+ cclist = cclist->next;
+ }
+ cron_conf_free();
+ return bReturn;
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+LPTHREAD_START_ROUTINE CRON_ThreadProc(HANDLE hevWatchDogExit)
+{
+ BOOL bExit = FALSE;
+ while(!bExit)
+ {
+ CRON_CheckConfFile();
+ if(WaitForSingleObject(hevWatchDogExit, 1000*DEFAULT_CRON_TIME) != WAIT_TIMEOUT)
+ bExit = TRUE;
+ }
+ return 0;
+}
diff --git a/ldap/servers/slapd/ntwdog/ntwatchdog.c b/ldap/servers/slapd/ntwdog/ntwatchdog.c
new file mode 100644
index 00000000..ef8e795c
--- /dev/null
+++ b/ldap/servers/slapd/ntwdog/ntwatchdog.c
@@ -0,0 +1,1163 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#pragma warning(disable : 4001)
+// disable warning C4001: nonstandard extension 'single line comment' was used
+
+// //
+// Name: NTWATCHDOG //
+// Platforms: WIN32 //
+// Description: shell for nt directory server, runs as service, launches //
+// server, monitors it, re-launches if server crashes, //
+// Notes: //
+// ...................................................................... //
+// Watchdog can be run as an application or a service. When run as a //
+// service, it uses the service name from the SCM for the server name. //
+// When run as an application, it uses the command line to determine //
+// the server name. The command line can be one of two formats: //
+// c:\navgold\server\slapd-kennedy\config //
+// or //
+// slapd-kennedy //
+// ...................................................................... //
+// server file "lib\base\servssl.c" was changed //
+// - added code to get password from WatchDog process //
+// ...................................................................... //
+// server file "httpd\src\ntmain.c" was changed //
+// - server always runs as an application //
+// - changed hServerDoneEvent global name to "NS_service_name" //
+// this was necessary so that WatchDog can trap the "service_name" event //
+// - above changes were also made in MultipleInstances() //
+// ...................................................................... //
+// server file "lib\libmessages\messages.mc" was changed //
+// - added a couple of extra messages for watchdog event logging //
+// - watchdog is dependent on the server's eventlog source name //
+// ...................................................................... //
+// Revision History: //
+// 01-12-96 Initial Version, Andy Hakim (ahakim@netscape.com) //
+// 02-01-96 changed restart logic, now based on infant mortality time //
+// instead of server exit code //
+// 07-10-96 Modified for Directory Server, pkennedy@netscape.com //
+// //
+//--------------------------------------------------------------------------//
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <process.h>
+#include "ntslapdmessages.h" // event log msgs constants //
+#include "regparms.h" // product name, etc //
+#include "ntwatchdog.h"
+#include "version.h"
+#include "ntresource.h"
+#include "proto-ntutil.h"
+
+#ifdef PUMPKIN_HOUR
+#include <time.h>
+#endif
+
+//--------------------------------------------------------------------------//
+// global variables //
+//--------------------------------------------------------------------------//
+SERVICE_STATUS_HANDLE gsshServiceStatus = 0L;
+HWND ghWndMain = NULL;
+HANDLE ghevWatchDogExit = NULL;
+HINSTANCE ghInstance = NULL;
+HANDLE ghdlgPassword = NULL; // handle to password dialog window
+HANDLE ghDuplicateProcess = NULL; // process handle with PROCESS_VM_READ access
+HANDLE ghServerProcess = NULL; // used by app window in TerminateProcess()
+HANDLE ghServerThread0 = NULL; // used by app window in Suspend/ResumeThread()
+HANDLE ghWdogProcess = NULL;
+char gszServerConfig[MAX_LINE]; // ex: c:\netscape\server\slapd-kennedy\config
+char gszServerName[MAX_LINE]; // ex: slapd-kennedy
+char gszServerRoot[MAX_LINE]; // ex: c:\netscape\server
+char gszPassword[2048];
+DWORD gdwServiceError = NO_ERROR; // return error code for service
+DWORD gdwLastStatus = SERVICE_RUNNING;
+
+//--------------------------------------------------------------------------//
+// This is the shutdown handler we register via SetConsoleCtrlHandler()
+// It is really the only guaranteed means we have of shutting down gracefully
+// when the sytem is shutting down. The Service Manager mechanism is not
+// guaranteed to work.
+//--------------------------------------------------------------------------//
+
+BOOL WINAPI WD_ControlHandler(DWORD dwCtrlType)
+{
+ if (dwCtrlType == CTRL_SHUTDOWN_EVENT) {
+ SetEvent(ghevWatchDogExit);
+ WaitForSingleObject(ghWdogProcess, 1000 * DEFAULT_KILL_TIME);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+//--------------------------------------------------------------------------//
+// calc szServerRoot given szServerName //
+//--------------------------------------------------------------------------//
+BOOL WD_GetServerConfig(char *szServerId, char *szServerRoot, LPDWORD cbServerRoot)
+{
+ BOOL bReturn = FALSE;
+ HANDLE hSlapdKey = 0;
+ char szSlapdKey[MAX_PATH];
+ DWORD dwValueType;
+ DWORD dwResult = 0;
+
+ // don't want to monitor Admin server
+ if(strcmp(ADM_KEY_ROOT, szServerId) == 0)
+ return(bReturn);
+
+ // query registry key to figure out config directory
+ sprintf(szSlapdKey, "%s\\%s\\%s", KEY_SOFTWARE_NETSCAPE, SVR_KEY_ROOT,
+ szServerId);
+
+ dwResult = RegOpenKey(HKEY_LOCAL_MACHINE, szSlapdKey, &hSlapdKey);
+ if(dwResult == ERROR_SUCCESS)
+ {
+ dwResult = RegQueryValueEx(hSlapdKey, VALUE_CONFIG_PATH, NULL,
+ &dwValueType, (LPBYTE)szServerRoot, cbServerRoot);
+ if(dwResult == ERROR_SUCCESS)
+ bReturn = TRUE;
+ RegCloseKey(hSlapdKey);
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// get server's id based on index value that corresponds to the order in //
+// which it is listed under the the registry \SOFTWARE\Netscape\.. //
+//--------------------------------------------------------------------------//
+BOOL WD_GetServerId(IN DWORD dwSubKey, OUT char *szServerId, IN OUT LPDWORD cbServerId)
+{
+ BOOL bReturn = FALSE;
+ static HANDLE hSlapdKey = 0;
+ DWORD dwResult = ERROR_SUCCESS;
+ FILETIME ftLastWrite;
+ char szSlapdKey[MAX_LINE];
+
+ if(dwSubKey == 0) {
+ sprintf(szSlapdKey, "%s\\%s", KEY_SOFTWARE_NETSCAPE, SVR_KEY_ROOT);
+ dwResult = RegOpenKey(HKEY_LOCAL_MACHINE, szSlapdKey,
+ &hSlapdKey);
+ }
+
+ if(dwResult == ERROR_SUCCESS)
+ {
+ dwResult = RegEnumKeyEx(hSlapdKey, dwSubKey, szServerId,
+ cbServerId, NULL, NULL, NULL, &ftLastWrite);
+ if(dwResult == ERROR_SUCCESS)
+ {
+ bReturn = TRUE;
+ }
+ else
+ {
+ RegCloseKey(hSlapdKey);
+ hSlapdKey = 0;
+ }
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_IsServiceRunning(char *szServerId)
+{
+ BOOL bReturn = FALSE;
+ SC_HANDLE hscManager;
+ SC_HANDLE hscService;
+ SERVICE_STATUS ssServiceStatus;
+
+ if(hscManager = OpenSCManager(NULL, NULL, GENERIC_READ))
+ {
+ if(hscService = OpenService(hscManager, szServerId, SERVICE_QUERY_STATUS))
+ {
+ if(QueryServiceStatus(hscService, &ssServiceStatus))
+ {
+ if(ssServiceStatus.dwCurrentState != SERVICE_STOPPED)
+ {
+ bReturn = TRUE;
+ }
+ }
+ CloseServiceHandle(hscService);
+ }
+ CloseServiceHandle(hscManager);
+ }
+ return(bReturn);
+}
+
+
+
+
+
+//--------------------------------------------------------------------------//
+// get a list of installed servers //
+//--------------------------------------------------------------------------//
+int WD_GetRunningServerCount(void)
+{
+ int nServerCount = 0;
+ int nEnumIndex = 0;
+ char szServerId[MAX_PATH];
+ DWORD cbServerId = sizeof(szServerId);
+ char szServerRoot[MAX_PATH];
+ DWORD cbServerRoot = sizeof(szServerRoot);
+
+ while(WD_GetServerId(nEnumIndex++, szServerId, &cbServerId))
+ {
+ cbServerId = sizeof(szServerId);
+ // we have an entry that MIGHT be a server, but check to see if it really is one
+ if(WD_GetServerConfig(szServerId, szServerRoot, &cbServerRoot))
+ {
+ if(WD_IsServiceRunning(szServerId))
+ nServerCount++;
+ }
+ cbServerRoot = sizeof(szServerRoot);
+ }
+
+ return(nServerCount);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+DWORD WD_GetDefaultKeyValue(char *szServerName, char *szKeyName, DWORD dwDefault)
+{
+ HANDLE hSlapdKey = 0;
+ char szSlapdKey[MAX_LINE];
+ DWORD dwValueType;
+ DWORD dwValue = dwDefault;
+ DWORD cbValue = sizeof(dwValue);
+
+ // query registry key to figure out config directory
+ sprintf(szSlapdKey, "%s\\%s\\%s", KEY_SOFTWARE_NETSCAPE, SVR_KEY_ROOT,
+ szServerName);
+ if(RegOpenKey(HKEY_LOCAL_MACHINE, szSlapdKey, &hSlapdKey) == ERROR_SUCCESS)
+ {
+ RegQueryValueEx(hSlapdKey, szKeyName, NULL, &dwValueType,
+ (LPBYTE)&dwValue, &cbValue);
+ RegCloseKey(hSlapdKey);
+ }
+
+ return(dwValue);
+}
+
+
+//--------------------------------------------------------------------------//
+// figure out if we are running under Windows NT //
+//--------------------------------------------------------------------------//
+BOOL WD_IsWindowsNT(void)
+{
+ BOOL bReturn = FALSE;
+ OSVERSIONINFO osVersionInfo;
+
+ osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if(GetVersionEx(&osVersionInfo))
+ {
+ bReturn = (osVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// figure out if we have enough physical memory to operate server //
+//--------------------------------------------------------------------------//
+BOOL WD_IsEnoughResources(void)
+{
+ BOOL bReturn = TRUE;
+ MEMORYSTATUS ms;
+ DWORD dwMinRamFree = 0;
+ DWORD dwMinRamTotal = DEFAULT_MINRAMTOTAL;
+ DWORD dwMinRamPerServer = DEFAULT_MINRAMPERSERVER;
+
+ dwMinRamFree = WD_GetDefaultKeyValue(gszServerName, MINRAMFREE_KEY, DEFAULT_MINRAMFREE);
+ dwMinRamTotal = WD_GetDefaultKeyValue(gszServerName, MINRAMTOTAL_KEY, DEFAULT_MINRAMTOTAL);
+ dwMinRamPerServer = WD_GetDefaultKeyValue(gszServerName, MINRAMPERSERVER_KEY, DEFAULT_MINRAMPERSERVER);
+
+ ZeroMemory((PVOID)&ms, sizeof(ms));
+ GlobalMemoryStatus(&ms);
+
+ if((ms.dwTotalPhys < (dwMinRamTotal * 1024)) || (ms.dwAvailPhys < (dwMinRamFree * 1024)))
+ bReturn = FALSE;
+
+ if(ms.dwTotalPhys < (WD_GetRunningServerCount() * dwMinRamPerServer * 1024))
+ bReturn = FALSE;
+
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// write error to EventLog service //
+//--------------------------------------------------------------------------//
+BOOL WD_SysLog(WORD fwEventType, DWORD IDEvent, char *szData)
+{
+ BOOL bReturn = FALSE;
+ HANDLE hEventSource;
+ WORD fwCategory = 0; // event category
+ PSID pUserSid = NULL; // user security identifier (optional)
+ WORD cStrings = 1; // number of strings to merge with message
+ DWORD cbData = 0; // size of binary data, in bytes
+ LPCTSTR lpszStrings[64]; // array of strings to merge with message
+ LPVOID lpvData = 0; // address of binary data
+
+ hEventSource = RegisterEventSource(NULL, TEXT(EVENTLOG_APPNAME));
+ if( hEventSource != NULL)
+ {
+ lpszStrings[0] = (LPCTSTR)gszServerName;
+ if(szData != NULL)
+ {
+ lpszStrings[1] = (LPCTSTR)szData;
+ cStrings++;
+ }
+
+ bReturn = ReportEvent(hEventSource, fwEventType, fwCategory,
+ IDEvent, pUserSid, cStrings, cbData,
+ lpszStrings, lpvData);
+ DeregisterEventSource(hEventSource);
+ }
+
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// converts '/' chars to '\' //
+//--------------------------------------------------------------------------//
+void WD_UnixToDosPath(char *szText)
+{
+ if(szText)
+ {
+ while(*szText)
+ {
+ if(*szText == '/')
+
+ *szText = '\\';
+ szText++;
+ }
+ }
+}
+
+
+
+//--------------------------------------------------------------------------//
+// calc szServerRoot given szServerConfig, and store szServerRoot in //
+// SLAPD_ROOT environment variable. //
+//--------------------------------------------------------------------------//
+BOOL WD_GetServerRoot(char *szServerRoot, char *szServerConfig)
+{
+ char szTemp[MAX_LINE], szServerRootEnvVar[MAX_LINE];
+ BOOL bReturn = FALSE;
+ char *szChar = NULL;
+
+ strcpy(szTemp, szServerConfig);
+ // szTemp should be something like c:\navgold\server\slapd-kennedy\config
+ if(szChar = strrchr(szTemp,'\\'))
+ {
+ *szChar = 0;
+ // szTemp should be c:\navgold\server\slapd-kennedy
+ if(szChar = strrchr(szTemp, '\\'))
+ {
+ *szChar = 0;
+ // szTemp should be c:\navgold\server
+ strcpy( szServerRoot, szTemp );
+ wsprintf(szServerRootEnvVar, "%s=%s", SLAPD_ROOT, szTemp);
+ putenv(szServerRootEnvVar);
+ bReturn = TRUE;
+ }
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// calc szServerConfig given szServerName //
+//--------------------------------------------------------------------------//
+BOOL WD_GetConfigFromRegistry(char *szServerConfig, char *szServerName)
+{
+ BOOL bReturn = FALSE;
+ HANDLE hSlapdKey = 0;
+ char szSlapdKey[MAX_LINE];
+ DWORD dwValueType;
+ char szValueString[MAX_LINE];
+ DWORD cbValueString = sizeof(szValueString);
+ DWORD dwResult = 0;
+
+ // query registry key to figure out config directory
+ sprintf(szSlapdKey, "%s\\%s\\%s", KEY_SOFTWARE_NETSCAPE, SVR_KEY_ROOT,
+ szServerName);
+
+ dwResult = RegOpenKey(HKEY_LOCAL_MACHINE, szSlapdKey, &hSlapdKey);
+ if(dwResult != ERROR_SUCCESS)
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_REGISTRY, szSlapdKey);
+ return(bReturn);
+ }
+
+ dwResult = RegQueryValueEx(hSlapdKey, VALUE_CONFIG_PATH, NULL,
+ &dwValueType, szValueString, &cbValueString);
+ if(dwResult != ERROR_SUCCESS)
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_REGISTRY, szSlapdKey);
+ }
+ else
+ {
+ strcpy(szServerConfig, szValueString);
+ WD_UnixToDosPath(szServerConfig);
+ WD_GetServerRoot(gszServerRoot, szServerConfig);
+ bReturn = TRUE;
+ }
+ RegCloseKey(hSlapdKey);
+ return(bReturn);
+}
+
+
+//--------------------------------------------------------------------------//
+// calc szServerConfig and szServerName given szCmdLine //
+//--------------------------------------------------------------------------//
+BOOL WD_GetConfigFromCmdline(char *szServerConfig, char *szServerName, char *szCmdLine)
+{
+ BOOL bReturn = FALSE;
+ char *szChar = NULL;
+
+ if(!szCmdLine || !(strcmp(szCmdLine, "")) )
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_BADCMDLINE, szCmdLine);
+ return(bReturn);
+ }
+
+ strcpy(szServerConfig, szCmdLine);
+ WD_UnixToDosPath(szCmdLine);
+ WD_GetServerRoot(gszServerRoot, szCmdLine);
+
+ // szCmdLine should be something like c:\navgold\server\slapd-kennedy\config
+ if(szChar = strrchr(szCmdLine, '\\'))
+ {
+ *szChar = 0;
+ // szCmdLine should be c:\navgold\server\slapd-kennedy
+ if(szChar = strrchr(szCmdLine, '\\'))
+ {
+ szChar++;
+ // szChar should point to slapd-kennedy
+ strcpy(szServerName, szChar);
+ WD_GetConfigFromRegistry(szServerConfig, szServerName);
+ bReturn = TRUE;
+
+ }
+ }
+ else
+ {
+ // szCmdLine should be something like slapd-kennedy
+ strcpy(szServerName, szCmdLine);
+ bReturn = WD_GetConfigFromRegistry(szServerConfig, szServerName);
+ }
+
+ if(strlen(szServerName) == 0)
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_BADCMDLINE, szCmdLine);
+ bReturn = FALSE;
+ }
+
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// parse server config file to see if it security is enabled //
+//--------------------------------------------------------------------------//
+BOOL WD_IsServerSecure(void)
+{
+ BOOL bReturn = FALSE;
+ char szFileName[MAX_PATH];
+ char szText[MAX_LINE];
+ char szSeperators[] = " \t\n";
+ char *szTemp;
+ FILE *fh = NULL;
+
+ sprintf(szFileName, "%s\\%s", gszServerConfig, SLAPD_CONF);
+ if(fh = fopen(szFileName, "r"))
+ {
+ while(!feof(fh))
+ {
+ if(fgets(szText, sizeof(szText), fh))
+ {
+ strlwr(szText);
+
+ /* strtok() is not MT safe on Unix , but it is okay to call
+ here because this file is NT only and strtok() is MT safe on NT */
+
+ if(szTemp = strtok(szText, szSeperators))
+ {
+ if(strcmp(szTemp, "security") == 0)
+ {
+ if(szTemp = strtok(NULL, szSeperators))
+ {
+ if(strcmp(szTemp, "on") == 0)
+ bReturn = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ }
+ fclose(fh);
+ }
+
+ return(bReturn);
+}
+
+//--------------------------------------------------------------------------//
+// message proc window for app window //
+//--------------------------------------------------------------------------//
+LONG APIENTRY WD_MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam)
+{
+ switch(message)
+ {
+ case WM_CREATE:
+ break;
+
+ case WM_CLOSE:
+ SetEvent(ghevWatchDogExit);
+ break;
+
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case ID_SERVER_SHUTDOWN:
+ {
+ HANDLE hevShutdown = NULL;
+ char szShutdownEvent[MAX_LINE];
+
+ // shutdown web server, it should exit with 0, WatchDog won't restart it
+ sprintf(szShutdownEvent, "NS_%s", gszServerName);
+ hevShutdown = OpenEvent(EVENT_MODIFY_STATE, FALSE, szShutdownEvent);
+ if(hevShutdown)
+ {
+ SetEvent(hevShutdown); // try to exit gracefully
+ CLOSEHANDLE(hevShutdown);
+ }
+ break;
+ }
+
+ case ID_SERVER_RESTART:
+ {
+ // shutdown web server, it should exit with 2, WatchDog will restart it
+ if(ghServerProcess)
+ {
+ CLOSEHANDLE(ghServerProcess);
+ TerminateProcess(ghServerProcess, 2);
+ }
+ break;
+ }
+
+ case ID_SERVER_SUSPEND:
+ {
+ if(ghServerThread0)
+ SuspendThread(ghServerThread0);
+ break;
+ }
+
+ case ID_SERVER_RESUME:
+ {
+ if(ghServerThread0)
+ ResumeThread(ghServerThread0);
+ break;
+ }
+
+ case ID_FILE_EXIT:
+ PostMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ }
+ break;
+ }
+
+ default:
+ return(DefWindowProc(hWnd, message, wParam, lParam));
+ }
+ return(0);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// This window serves as an IPC method with the server process. It has //
+// pointers in it's storage area that the server uses to access the SSL //
+// password. Quite strange, but it works perfectly well. //
+//--------------------------------------------------------------------------//
+HWND WD_CreateWindow()
+{
+ HWND hWndMain = NULL;
+ WNDCLASS wc;
+
+ wc.style = 0;
+ wc.lpfnWndProc = (WNDPROC)WD_MainWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(LONG) * 4;
+ wc.hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_LOGO));
+ wc.hInstance = ghInstance;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(GRAY_BRUSH);
+ wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
+ wc.lpszClassName = "slapd";
+
+ RegisterClass(&wc); // class may be registered if more than one instance
+
+ hWndMain = CreateWindow(
+ wc.lpszClassName, /* See RegisterClass() call. */
+ gszServerName, /* Text for window title bar. */
+ WS_OVERLAPPEDWINDOW | /* Window style. */
+ WS_POPUP, /* Window style. */
+ CW_USEDEFAULT, /* Default horizontal position. */
+ CW_USEDEFAULT, /* Default vertical position. */
+ 320, /* Default width. */
+ 0, /* Default height. */
+ NULL, /* Overlapped windows have no parent. */
+ NULL, /* Use the window class menu. */
+ ghInstance, /* This instance owns this window. */
+ NULL /* Pointer not needed. */
+ );
+
+ if(hWndMain)
+ {
+#ifdef SHOW_DEBUG_WINDOW
+ ShowWindow(hWndMain, SW_SHOWDEFAULT);
+#else
+ ShowWindow(hWndMain, SW_HIDE);
+#endif
+ UpdateWindow(hWndMain);
+ }
+ return hWndMain;
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+void WD_WindowThreadProc(LPDWORD lpdwParam)
+{
+ HANDLE hevWindowCreated = (HANDLE)lpdwParam;
+ MSG msg;
+
+ // the ghWndMain global is used all over the place
+ ghWndMain = WD_CreateWindow();
+
+ // inform parent that window creation is complete because it is waiting on us
+ SetEvent(hevWindowCreated);
+
+ if(ghWndMain)
+ {
+ while(GetMessage(&msg, ghWndMain, 0, 0) == TRUE)
+ {
+ TranslateMessage(&msg); // Translates virtual key codes
+ DispatchMessage(&msg); // Dispatches message to window
+ }
+ }
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+void WD_PasswordThreadProc(LPDWORD lpdwParam)
+{
+ // app window must be created sometime during initialization
+ if(ghWndMain)
+ {
+ ZeroMemory(gszPassword, sizeof(gszPassword));
+ SetWindowLong(ghWndMain, GWL_PASSWORD_ADDR, (LONG)gszPassword);
+ SetWindowLong(ghWndMain, GWL_PASSWORD_LENGTH, (LONG)0);
+ }
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_StartServer(PROCESS_INFORMATION *pi)
+{
+ BOOL bReturn = FALSE;
+ char szCmdLine[MAX_LINE];
+ char szServerPath[MAX_PATH];
+ char szInstancePath [MAX_PATH];
+ char *szChar;
+ STARTUPINFO sui;
+ DWORD fdwCreate = DETACHED_PROCESS; /* flags for CreateProcess */
+ int i;
+ char *posfile;
+ UNALIGNED long *posfhnd;
+
+ if(!WD_IsEnoughResources())
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_STRING, MSG_RESOURCES);
+ gdwServiceError = ERROR_SERVICE_NOT_ACTIVE;
+ return(FALSE);
+ }
+
+ strcpy(szServerPath, gszServerConfig);
+ WD_UnixToDosPath(szServerPath);
+
+ // szServerPath should now be something similar to
+ // c:\navgold\server\slapd-kennedy\config
+ if(szChar = strrchr(szServerPath, '\\'))
+ {
+ *szChar = 0;
+ strcpy (szInstancePath, szServerPath);
+ if(szChar = strrchr(szServerPath, '\\'))
+ {
+ *szChar = 0;
+ }
+ }
+
+ // For Directory Server, service-name is defined as slapd.exe,
+ // in ldapserver/include/nt/regpargms.h
+ sprintf( szCmdLine, "%s\\bin\\%s\\server\\%s -D \"%s\"", szServerPath,
+ PRODUCT_NAME, SERVICE_EXE, szInstancePath );
+ // szCmdLine ex: c:\navgold\server\bin\slapd\slapd.exe
+ // -f c:\navgold\server\slapd-kennedy\config
+
+ memset(&sui,0,sizeof(sui));
+ sui.cb = sizeof(STARTUPINFO);
+
+ /* All of this, to CreateProcess(), allows us to run a console
+ app (slapd.exe) from the service (ns-slapd.exe), without a
+ new console being opened for the app.
+ See dospawn.c in the crt src for more details.
+ */
+ sui.cbReserved2 = (WORD)(sizeof( int ) + (3 *
+ (sizeof( char ) + sizeof( long ))));
+
+ sui.lpReserved2 = calloc( sui.cbReserved2, 1 );
+
+ *((UNALIGNED int *)(sui.lpReserved2)) = 3;
+
+ posfile = (char *)(sui.lpReserved2 + sizeof( int ));
+
+ posfhnd = (UNALIGNED long *)(sui.lpReserved2 + sizeof( int ) +
+ (3 * sizeof( char )));
+
+ for ( i = 0,
+ posfile = (char *)(sui.lpReserved2 + sizeof( int )),
+ posfhnd = (UNALIGNED long *)(sui.lpReserved2 + sizeof( int )
+ + (3 * sizeof( char ))) ;
+ i < 3 ;
+ i++, posfile++, posfhnd++ )
+ {
+ *posfile = 0;
+ *posfhnd = (long)INVALID_HANDLE_VALUE;
+ }
+
+ fdwCreate |= CREATE_SUSPENDED;
+ bReturn = CreateProcess(NULL, szCmdLine, NULL, NULL,
+ TRUE, fdwCreate, NULL, NULL, &sui, pi );
+ if(bReturn)
+ {
+ ghServerProcess = pi->hProcess; // used by app window
+ ghServerThread0 = pi->hThread; // used by app window
+ if(DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
+ pi->hProcess, (LPHANDLE)&ghDuplicateProcess,
+ (DWORD)PROCESS_VM_READ | PROCESS_VM_WRITE |
+ PROCESS_ALL_ACCESS, FALSE, (DWORD)0))
+ {
+ SetWindowLong(ghWndMain, GWL_PROCESS_HANDLE,
+ (LONG)ghDuplicateProcess);
+ }
+ ResumeThread(pi->hThread);
+ }
+ else
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_STARTFAILED, szCmdLine);
+ }
+
+ free( sui.lpReserved2 );
+
+ return(bReturn);
+}
+
+
+
+
+//------------------------------------------------------z--------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_CreatePasswordThread(void)
+{
+ #define NUM_WAIT_OBJECTS 2
+ enum { CHILD_PROCESS, EXIT_EVENT };
+
+ BOOL bReturn = FALSE;
+ HANDLE lphObject[NUM_WAIT_OBJECTS];
+ HANDLE hPasswordThread;
+ DWORD dwThreadID;
+ DWORD dwResult;
+
+ lphObject[EXIT_EVENT] = ghevWatchDogExit;
+
+ hPasswordThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
+ (LPTHREAD_START_ROUTINE)WD_PasswordThreadProc, NULL, 0, &dwThreadID);
+ if(hPasswordThread)
+ {
+ lphObject[CHILD_PROCESS] = hPasswordThread;
+ dwResult = WaitForMultipleObjects(NUM_WAIT_OBJECTS, lphObject, FALSE, INFINITE);
+ CLOSEHANDLE(hPasswordThread);
+ if(dwResult == WAIT_OBJECT_0 + EXIT_EVENT) // user stopped service
+ {
+ EndDialog(ghdlgPassword, 1);
+ }
+ bReturn = TRUE;
+ }
+ else
+ {
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_BADPASSWORD, NULL);
+ }
+ return(bReturn);
+}
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_CreateWindowThread(void)
+{
+ BOOL bReturn = FALSE;
+ DWORD dwThreadID;
+ HANDLE hWindowThread;
+ HANDLE hevWindowCreated = NULL;
+
+ if(hevWindowCreated = CreateEvent(NULL, FALSE, FALSE, NULL))
+ {
+ if(hWindowThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
+ (LPTHREAD_START_ROUTINE)WD_WindowThreadProc, (LPVOID)hevWindowCreated, 0, &dwThreadID))
+ {
+ // make sure ghHwndMain is created otherwise
+ // SetWindowLong(ghWndMain) will fail in other threads
+ WaitForSingleObject(hevWindowCreated, INFINITE);
+ CLOSEHANDLE(hWindowThread);
+ bReturn = TRUE;
+ }
+ }
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_CreateCronThread(HANDLE hevWatchDogExit)
+{
+ BOOL bReturn = FALSE;
+ DWORD dwThreadID = 0;
+ HANDLE hWindowThread = NULL;
+#if 0
+ if(hWindowThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
+ (LPTHREAD_START_ROUTINE)CRON_ThreadProc, (LPVOID)hevWatchDogExit, 0, &dwThreadID))
+ {
+ CLOSEHANDLE(hWindowThread);
+ bReturn = TRUE;
+ }
+#endif
+ return(bReturn);
+}
+
+
+//--------------------------------------------------------------------------//
+// signals event create by SNMP agent for notification of server shutdown //
+//--------------------------------------------------------------------------//
+#if 0
+BOOL WS_SendSNMPTrapSignal(void)
+{
+ BOOL bReturn = FALSE;
+ HANDLE hevShutdown = NULL;
+ char szShutdownEvent[MAX_LINE];
+
+ sprintf(szShutdownEvent, NSEV_SNMPTRAP_HTTP);
+ hevShutdown = OpenEvent(EVENT_MODIFY_STATE, FALSE, szShutdownEvent);
+ if(hevShutdown)
+ {
+ SetEvent(hevShutdown);
+ CLOSEHANDLE(hevShutdown);
+ bReturn = TRUE;
+ }
+ return(bReturn);
+}
+#endif
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_MonitorServer(void)
+{
+ #define NUM_WAIT_OBJECTS 2
+ enum { SERVER_PROCESS, WATCHDOG_EXIT };
+
+ BOOL bReturn = FALSE;
+ HANDLE lphObject[NUM_WAIT_OBJECTS];
+ DWORD dwResult = 0;
+ DWORD dwExitCode = 0;
+ PROCESS_INFORMATION pi;
+ HANDLE hevServerDone = NULL;
+ char szServerDoneEvent[MAX_LINE];
+ char szText[MAX_LINE];
+ DWORD dwTickCount = 0;
+
+ lphObject[WATCHDOG_EXIT] = ghevWatchDogExit;
+
+ while(WD_StartServer(&pi))
+ {
+ dwTickCount = GetTickCount();
+ lphObject[SERVER_PROCESS] = pi.hProcess;
+ dwResult = WaitForMultipleObjects(NUM_WAIT_OBJECTS, lphObject, FALSE, INFINITE);
+
+ //WS_SendSNMPTrapSignal();
+
+ if(dwResult == WAIT_OBJECT_0 + WATCHDOG_EXIT)
+ {
+ // shutdown web server
+ //CLOSEHANDLE(pi.hProcess); // XXXahakim close them after TerminateProcess()
+ //CLOSEHANDLE(pi.hThread);
+ sprintf(szServerDoneEvent, "NS_%s", gszServerName);
+ hevServerDone = OpenEvent(EVENT_MODIFY_STATE, FALSE, szServerDoneEvent);
+ if(hevServerDone)
+ {
+ SetEvent(hevServerDone); // try to exit gracefully
+ CLOSEHANDLE(hevServerDone);
+ WaitForSingleObject(lphObject[SERVER_PROCESS], 1000 * DEFAULT_KILL_TIME);
+ }
+ // but just in case it's still alive, swat it again, harder!
+ TerminateProcess(lphObject[SERVER_PROCESS], 1);
+ CLOSEHANDLE(pi.hProcess); // XXXahakim moved from above 03/06/96
+ CLOSEHANDLE(pi.hThread);
+ bReturn = TRUE;
+ }
+ else
+ if(dwResult == WAIT_OBJECT_0 + SERVER_PROCESS)
+ {
+ // why did web server shutdown?
+ // GetExitCodeProcess(lphObject[SERVER_PROCESS], &dwExitCode);
+ // if(dwExitCode != 0)
+ // checking the exit code is bogus because a crashed process can return
+ // anything, including 0, so we use another method to determine if the
+ // server shutdown legitimately, which is similar to how unix works
+ // according to robm.
+
+ // check to see if a specified amount of time has elapsed since the server
+ // started. If it's "infant mortality" don't bother restarting it
+ // because chances are it will continue to fail (such as when the password
+ // is bad, or if there is some other severe startup problem)
+ if(GetTickCount() - dwTickCount > 1000 * WD_GetDefaultKeyValue(gszServerName, MORTALITY_KEY, DEFAULT_MORTALITY_TIME))
+ {
+ sprintf(szText, "%d", dwExitCode);
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_RESTART, szText);
+ CLOSEHANDLE(pi.hProcess);
+ CLOSEHANDLE(pi.hThread);
+ CLOSEHANDLE(ghDuplicateProcess);
+ Sleep(DEFAULT_RESTART_TIME * 1000);
+ continue;
+ }
+ // server closed legitimately
+ else
+ bReturn = TRUE;
+ }
+ CLOSEHANDLE(pi.hProcess);
+ CLOSEHANDLE(pi.hThread);
+ CLOSEHANDLE(ghDuplicateProcess);
+ break;
+ }
+
+ return(bReturn);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+BOOL WD_SetServiceStatus(DWORD dwCurrentState, DWORD dwError)
+{
+ BOOL bReturn = FALSE;
+ SERVICE_STATUS ssStatus;
+
+ if(gsshServiceStatus)
+ {
+ gdwLastStatus = dwCurrentState;
+ ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ssStatus.dwCurrentState = dwCurrentState;
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_PAUSE_CONTINUE |
+ SERVICE_ACCEPT_SHUTDOWN;
+ ssStatus.dwWin32ExitCode = dwError;
+ ssStatus.dwServiceSpecificExitCode = (NO_ERROR ? 0 : 1);
+ ssStatus.dwCheckPoint = 0;
+ ssStatus.dwWaitHint = (1000 * ((dwCurrentState==SERVICE_STOP_PENDING)?600:DEFAULT_KILL_TIME + 1));
+ bReturn = SetServiceStatus(gsshServiceStatus, &ssStatus);
+ }
+ return(FALSE);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+VOID WINAPI WD_ServiceHandler(DWORD fdwControl)
+{
+ switch(fdwControl)
+ {
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN:
+ WD_SetServiceStatus(SERVICE_STOP_PENDING, gdwServiceError);
+ SetEvent(ghevWatchDogExit);
+ return;
+
+ case SERVICE_CONTROL_PAUSE:
+ if(ghServerThread0)
+ {
+ WD_SetServiceStatus(SERVICE_PAUSE_PENDING, gdwServiceError);
+ SuspendThread(ghServerThread0);
+ WD_SetServiceStatus(SERVICE_PAUSED, gdwServiceError);
+ return;
+ }
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ if(ghServerThread0)
+ {
+ WD_SetServiceStatus(SERVICE_CONTINUE_PENDING, gdwServiceError);
+ ResumeThread(ghServerThread0);
+ WD_SetServiceStatus(SERVICE_RUNNING, gdwServiceError);
+ return;
+ }
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ WD_SetServiceStatus(gdwLastStatus, gdwServiceError);
+ return;
+
+ default:
+ WD_SysLog(EVENTLOG_ERROR_TYPE, MSG_WD_RESTART, "unknown service event");
+ return;
+ }
+ WD_SetServiceStatus(SERVICE_RUNNING, gdwServiceError);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+VOID WD_ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
+{
+ BOOL bOkToProceed = TRUE;
+ // if SCM calls us lpszArgv will not be NULL
+ BOOL bIsService = (lpszArgv != NULL);
+
+ // register our custom control handler to handle shutdown
+ ghWdogProcess = GetCurrentProcess();
+ SetConsoleCtrlHandler(WD_ControlHandler, TRUE);
+
+ if(bIsService)
+ {
+ gsshServiceStatus = RegisterServiceCtrlHandler(lpszArgv[0],
+ (LPHANDLER_FUNCTION)WD_ServiceHandler);
+ bOkToProceed = (gsshServiceStatus != (SERVICE_STATUS_HANDLE)NULL);
+ if(bOkToProceed)
+ {
+ strcpy(gszServerName, lpszArgv[0]);
+ bOkToProceed = WD_GetConfigFromRegistry(gszServerConfig,
+ gszServerName);
+ }
+ }
+
+ WD_SetServiceStatus(SERVICE_START_PENDING, gdwServiceError);
+
+ if(bOkToProceed)
+ {
+ if(ghevWatchDogExit = CreateEvent(NULL, TRUE, FALSE, gszServerName))
+ {
+ WD_SetServiceStatus(SERVICE_RUNNING, gdwServiceError);
+ WD_CreateWindowThread();
+#if 0
+ WD_CreateCronThread(ghevWatchDogExit);
+#endif
+
+ if(WD_IsServerSecure())
+ {
+ bOkToProceed = WD_CreatePasswordThread();
+ }
+
+ if(bOkToProceed)
+ {
+ WD_MonitorServer();
+ }
+ CLOSEHANDLE(ghevWatchDogExit);
+ }
+ }
+ WD_SetServiceStatus(SERVICE_STOPPED, gdwServiceError);
+}
+
+
+
+//--------------------------------------------------------------------------//
+// //
+//--------------------------------------------------------------------------//
+WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ SERVICE_TABLE_ENTRY steServiceTable[2];
+
+#ifdef PUMPKIN_HOUR
+ if(time(NULL) > (PUMPKIN_HOUR - 10))
+ {
+ char szMessage[256];
+ sprintf( szMessage, " ** This beta software has expired **\n");
+ MessageBox(GetDesktopWindow(), szMessage,
+ DS_NAME_FULL_VERSION, MB_ICONEXCLAMATION | MB_OK);
+ exit(1);
+ }
+#endif
+
+ if(!hPrevInstance) // other instances of app running?
+ {
+ ghInstance = hInstance;
+ memset(gszPassword, 0, sizeof(gszPassword));
+ memset(gszServerConfig, 0, sizeof(gszServerConfig));
+ memset(gszServerName, 0, sizeof(gszServerName));
+ if(WD_IsWindowsNT() && (lpCmdLine) && (strlen(lpCmdLine) == 0))
+ {
+ // run as service
+ steServiceTable[0].lpServiceName = TEXT(PRODUCT_NAME);
+ steServiceTable[0].lpServiceProc =
+ (LPSERVICE_MAIN_FUNCTION)WD_ServiceMain;
+ steServiceTable[1].lpServiceName = NULL;
+ steServiceTable[1].lpServiceProc = NULL;
+ StartServiceCtrlDispatcher(steServiceTable);
+ }
+ else
+ {
+ // run as application
+ if(WD_GetConfigFromCmdline(gszServerConfig,
+ gszServerName, lpCmdLine))
+ {
+ WD_ServiceMain(0, (LPTSTR *)NULL);
+ }
+ }
+ }
+ return(FALSE);
+}