diff --git a/src/sexpots/sexpots.c b/src/sexpots/sexpots.c
index 31aa58520b64a079097b653fb2bec6c2188b3328..69e2c487aeaf48eb736f9ded674507bff3357f2f 100644
--- a/src/sexpots/sexpots.c
+++ b/src/sexpots/sexpots.c
@@ -55,7 +55,7 @@
 
 /* constants */
 #define NAME					"SexPOTS"
-#define TITLE					"Synchronet External POTS<->TCP Service"
+#define TITLE					"Synchronet External POTS Support"
 #define DESCRIPTION				"Connects a communications port (e.g. COM1) to a TCP port (e.g. Telnet)"
 #define MDM_TILDE_DELAY			500	/* milliseconds */
 
@@ -124,14 +124,24 @@ int usage(const char* fname)
 {
 	printf("usage: %s [ini file] [options]\n"
 		"\nOptions:"
+		"\n"
 		"\n-null                 No 'AT commands' sent to modem"
 		"\n-com <device>         Specify communications port device"
-		"\n-baud <rate>          Specify baud rate for communications port\n"
+		"\n-baud <rate>          Specify baud rate for communications port"
 		"\n-live [handle]        Communications port is already open/connected"
 		"\n-nohangup             Do not hangup (drop DTR) after call"
 		"\n-host <addr | name>   Specify TCP server hostname or IP address"
 		"\n-port <number>        Specify TCP port number"
-		,getfname(fname));
+#if defined(_WIN32)
+		"\n\nNT Service\n"
+		"\n-install              install and enable NT service (%s)"
+		"\n-service              run as an NT service (background execution)"
+		"\n-remove               remove NT service"
+		"\n-enable               enable NT service"
+		"\n-disable              disable NT service"
+#endif
+		,getfname(fname)
+		,NAME);
 
 	return 0;
 }
@@ -283,7 +293,6 @@ static void describe_service(HANDLE hSCMlib, SC_HANDLE hService, char* descripti
 		changeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &service_desc);
 }
 
-
 static BOOL register_event_source(char* name, char* path)
 {
 	char	keyname[256];
@@ -419,6 +428,134 @@ static int install(void)
 
 	return(0);
 }
+
+/****************************************************************************/
+/* Utility function to remove a service cleanly (stopping if necessary)		*/
+/****************************************************************************/
+static void remove_service(SC_HANDLE hSCManager, SC_HANDLE hService, char* name, char* disp_name)
+{
+	SERVICE_STATUS	status;
+
+	printf("Removing service: %-40s ... ", disp_name);
+
+	if(hService==NULL) {
+
+		hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS);
+
+		if(hService==NULL) {
+			printf("\n!ERROR %d opening service: %s\n",GetLastError(),name);
+			return;
+		}
+	}
+
+    // try to stop the service
+    if(ControlService( hService, SERVICE_CONTROL_STOP, &status))
+    {
+        printf("\nStopping: %s ... ",name);
+
+        while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING)
+			Sleep(1000);
+
+        if(status.dwCurrentState == SERVICE_STOPPED)
+            printf("Stopped.\n");
+        else
+            printf("FAILED!\n");
+    }
+
+    // now remove the service
+    if(DeleteService(hService))
+		printf("Successful\n");
+	else
+		printf("!ERROR %d\n",GetLastError());
+    CloseServiceHandle(hService);
+}
+
+/****************************************************************************/
+/* Uninstall one or all services											*/
+/****************************************************************************/
+static int uninstall(void)
+{
+    SC_HANDLE   hSCManager;
+
+    hSCManager = OpenSCManager(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == default)
+                        SC_MANAGER_ALL_ACCESS   // access required
+                        );
+    if(hSCManager==NULL) {
+		fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
+		return(-1);
+	}
+
+	remove_service(hSCManager,NULL,NAME,TITLE);
+
+	CloseServiceHandle(hSCManager);
+
+	return(0);
+}
+
+/****************************************************************************/
+/* Utility function to disable a service									*/
+/****************************************************************************/
+static void set_service_start_type(SC_HANDLE hSCManager, DWORD start_type)
+{
+    SC_HANDLE		hService;
+
+	printf("%s service: %-40s ... "
+		,start_type==SERVICE_DISABLED ? "Disabling" : "Enabling", TITLE);
+
+    hService = OpenService(hSCManager, NAME, SERVICE_ALL_ACCESS);
+
+	if(hService==NULL) {
+		printf("\n!ERROR %d opening service: %s\n",GetLastError(),NAME);
+		return;
+	}
+
+	if(!ChangeServiceConfig(
+		hService,				// handle to service
+		SERVICE_NO_CHANGE,		// type of service
+		start_type,				// when to start service
+		SERVICE_NO_CHANGE,		// severity if service fails to start
+		NULL,					// pointer to service binary file name
+		NULL,					// pointer to load ordering group name
+		NULL,					// pointer to variable to get tag identifier
+		NULL,					// pointer to array of dependency names
+		NULL,					// pointer to account name of service
+		NULL,					// pointer to password for service account
+		NULL					// pointer to display name
+		))
+		printf("\n!ERROR %d changing service config for: %s\n",GetLastError(),NAME);
+	else
+		printf("Successful\n");
+
+    CloseServiceHandle(hService);
+}
+
+/****************************************************************************/
+/* Enable (set to auto-start) or disable one or all services				*/
+/****************************************************************************/
+static int enable(BOOL enabled)
+{
+    SC_HANDLE   hSCManager;
+
+    hSCManager = OpenSCManager(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == default)
+                        SC_MANAGER_ALL_ACCESS   // access required
+                        );
+    if(hSCManager==NULL) {
+		fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
+		return(-1);
+	}
+
+	set_service_start_type(hSCManager
+		,enabled ? SERVICE_AUTO_START : SERVICE_DISABLED);
+
+	CloseServiceHandle(hSCManager);
+
+	return(0);
+}
+
 #endif
 
 #ifdef _WINSOCKAPI_
@@ -560,6 +697,13 @@ void cleanup(void)
 #endif
 
 	lprintf(LOG_INFO,"Done (handled %lu calls).", total_calls);
+
+#if defined(_WIN32)
+	if(daemonize && svc_status_handle!=0) {
+		svc_status.dwCurrentState=SERVICE_STOPPED;
+		SetServiceStatus(svc_status_handle, &svc_status);
+	} else
+#endif
 	if(pause_on_exit) {
 		printf("Hit enter to continue...");
 		getchar();
@@ -1188,10 +1332,9 @@ service_loop(int argc, char** argv)
 	for(argn=1; argn<(int)argc; argn++) {
 		arg=argv[argn];
 		if(*arg!='-') {	/* .ini file specified */
-			arg++;
 			if(!fexist(arg)) {
-				perror(arg);
-				return usage(argv[0]);
+				lprintf(LOG_ERR,"Initialization file does not exist: %s", arg);
+				exit(usage(argv[0]));
 			}
 			parse_ini_file(arg);
 			continue;
@@ -1222,10 +1365,10 @@ service_loop(int argc, char** argv)
 			com_hangup=FALSE;
 		}
 		else if(stricmp(arg,"help")==0 || *arg=='?')
-			return usage(argv[0]);
+			exit(usage(argv[0]));
 		else {
 			fprintf(stderr,"Invalid option: %s\n", arg);
-			return usage(argv[0]);
+			exit(usage(argv[0]));
 		}
 	}
 
@@ -1264,7 +1407,7 @@ service_loop(int argc, char** argv)
 	/************************************/
 
 	if(!winsock_startup())
-		return -1;
+		exit(1);
 
 	/* Install clean-up callback */
 	atexit(cleanup);
@@ -1276,7 +1419,7 @@ service_loop(int argc, char** argv)
 		lprintf(LOG_INFO,"Opening Communications Device: %s", com_dev);
 		if((com_handle=comOpen(com_dev)) == COM_HANDLE_INVALID) {
 			lprintf(LOG_ERR,"ERROR %u opening %s", COM_ERROR_VALUE, com_dev);
-			return -1;
+			exit(1);
 		}
 	}
 	if(com_baudrate!=0) {
@@ -1322,15 +1465,9 @@ service_loop(int argc, char** argv)
 			break;
 	}
 
-#if defined(_WIN32)
-	if(daemonize) {
-		svc_status.dwCurrentState=SERVICE_STOPPED;
-		SetServiceStatus(svc_status_handle, &svc_status);
-	}
-#endif
+	exit(0);
 }
 
-
 /****************************************************************************/
 /****************************************************************************/
 int main(int argc, char** argv)
@@ -1357,22 +1494,6 @@ int main(int argc, char** argv)
 
 	fprintf(stdout,"%s\n\n", banner);
 
-	/******************/
-	/* Read .ini file */
-	/******************/
-	/* Generate path/sexpots[.host].ini from path/sexpots[.exe] */
-	SAFECOPY(path,argv[0]);
-	p=getfname(path);
-	SAFECOPY(fname,p);
-	*p=0;
-	if((p=getfext(fname))!=NULL) 
-		*p=0;
-	SAFECOPY(termtype,fname);
-	strcat(fname,".ini");
-
-	iniFileName(ini_fname,sizeof(ini_fname),path,fname);
-	parse_ini_file(ini_fname);
-
 	/**********************/
 	/* Parse command-line */
 	/**********************/
@@ -1385,16 +1506,31 @@ int main(int argc, char** argv)
 			daemonize=TRUE;
 		else if(stricmp(arg,"install")==0)
 			return install();
+		else if(stricmp(arg,"remove")==0)
+			return uninstall();
+		else if(stricmp(arg,"disable")==0)
+			return enable(FALSE);
+		else if(stricmp(arg,"enable")==0)
+			return enable(TRUE);
 		else if(stricmp(arg,"help")==0 || *arg=='?')
 			return usage(argv[0]);
-#if 0
-		else {
-			fprintf(stderr,"Invalid option: %s\n", arg);
-			return usage(argv[0]);
-		}
-#endif
 	}
 
+	/******************/
+	/* Read .ini file */
+	/******************/
+	/* Generate path/sexpots[.host].ini from path/sexpots[.exe] */
+	SAFECOPY(path,argv[0]);
+	p=getfname(path);
+	SAFECOPY(fname,p);
+	*p=0;
+	if((p=getfext(fname))!=NULL) 
+		*p=0;
+	SAFECOPY(termtype,fname);
+	strcat(fname,".ini");
+
+	iniFileName(ini_fname,sizeof(ini_fname),path,fname);
+	parse_ini_file(ini_fname);
 
 #if defined(_WIN32)
 	if(daemonize) {