root/wconsd.c @ 66a63de2
62045e98 | Hamish Coleman | /*
|
|
* wconsd.c - serial port server service for Windows NT
|
|||
*
|
|||
83cf653a | Hamish Coleman | * Copyright (c) 2008 Hamish Coleman <hamish@zot.org>
|
|
* 2003 Benjamin Schweizer <gopher at h07 dot org>
|
|||
62045e98 | Hamish Coleman | * 1998 Stephen Early <Stephen.Early@cl.cam.ac.uk>
|
|
*
|
|||
*
|
|||
* This program is free software; you can redistribute it and/or modify
|
|||
* it under the terms of the GNU General Public License as published by
|
|||
* the Free Software Foundation; either version 2 of the License, or
|
|||
* (at your option) any later version.
|
|||
*
|
|||
* This program is distributed in the hope that it will be useful,
|
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
* GNU General Public License for more details.
|
|||
*
|
|||
* You should have received a copy of the GNU General Public License
|
|||
* along with this program; if not, write to the Free Software
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|||
*/
|
|||
78d4c0b0 | Hamish Coleman | ||
b6970c98 | Hamish Coleman | /* Note: winsock2.h MUST be included before windows.h */
|
|
#include <winsock2.h>
|
|||
08ceb73b | Hamish Coleman | #include <ws2tcpip.h>
|
|
b6970c98 | Hamish Coleman | #include <windows.h>
|
|
#include <winsvc.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
e592f8f7 | Hamish Coleman | #include "scm.h"
|
|
5ddf869b | Hamish Coleman | #include "libcli/libcli.h"
|
|
479f1136 | Hamish Coleman | #define VERSION "0.2.6"
|
|
62045e98 | Hamish Coleman | ||
78d4c0b0 | Hamish Coleman | /* Size of buffers for send and receive */
|
|
#define BUFSIZE 1024
|
|||
62045e98 | Hamish Coleman | #define MAXLEN 1024
|
|
78d4c0b0 | Hamish Coleman | ||
/* Sockets for listening and communicating */
|
|||
3eb633b1 | Hamish Coleman | SOCKET ls=INVALID_SOCKET;
|
|
78d4c0b0 | Hamish Coleman | ||
/* Event objects */
|
|||
3eb633b1 | Hamish Coleman | HANDLE stopEvent;
|
|
78d4c0b0 | Hamish Coleman | HANDLE readEvent, writeEvent;
|
|
WSAEVENT listenSocketEvent;
|
|||
/* COM port */
|
|||
DCB dcb;
|
|||
62045e98 | Hamish Coleman | COMMTIMEOUTS timeouts;
|
|
61b53eda | Hamish Coleman | ||
/* Port default settings are here */
|
|||
int com_port=1;
|
|||
DWORD com_speed=9600;
|
|||
BYTE com_data=8;
|
|||
BYTE com_parity=NOPARITY;
|
|||
BYTE com_stop=ONESTOPBIT;
|
|||
78d4c0b0 | Hamish Coleman | ||
b9a4e090 | Hamish Coleman | int default_tcpport = 23;
|
|
61b53eda | Hamish Coleman | ||
4cb40453 | Hamish Coleman | /* TODO - these buffers are ugly and large */
|
|
char *hostname[BUFSIZE];
|
|||
struct hostent *host_entry;
|
|||
78d4c0b0 | Hamish Coleman | /* Service status: our current status, and handle on service manager */
|
|
SERVICE_STATUS wconsd_status;
|
|||
SERVICE_STATUS_HANDLE wconsd_statusHandle;
|
|||
25fa1d20 | Hamish Coleman | int debug_mode = 0;
|
|
479f1136 | Hamish Coleman | /* these match the official telnet codes */
|
|
#define TELNET_OPTION_SB 0xfa
|
|||
#define TELNET_OPTION_WILL 0xfb
|
|||
#define TELNET_OPTION_WONT 0xfc
|
|||
#define TELNET_OPTION_DO 0xfd
|
|||
#define TELNET_OPTION_DONT 0xfe
|
|||
#define TELNET_OPTION_IAC 0xff
|
|||
/* these are my local state-tracking codes */
|
|||
#define TELNET_OPTION_SBXX 0xfa00 /* received IAC SB xx */
|
|||
ef78cec5 | Hamish Coleman | #define MAXCONNECTIONS 8
|
|
2d552dd4 | Hamish Coleman | int next_connection_id = 1; /* lifetime unique connection id */
|
|
aaba0a4c | Hamish Coleman | int next_connection_slot = 0; /* next slot to look at for new connection */
|
|
ef78cec5 | Hamish Coleman | struct connection {
|
|
884971fc | Hamish Coleman | int active; /* an active entry cannot be reused */
|
|
int id; /* connection identifier */
|
|||
ef78cec5 | Hamish Coleman | HANDLE menuThread;
|
|
SOCKET net;
|
|||
aaba0a4c | Hamish Coleman | int serialconnected;
|
|
ef78cec5 | Hamish Coleman | HANDLE serial;
|
|
HANDLE serialThread;
|
|||
3fa88c6f | Hamish Coleman | int option_runmenu; /* are we at the menu? */
|
|
479f1136 | Hamish Coleman | int option_binary; /* binary transmission requested */
|
|
int option_echo; /* will we echo chars received? */
|
|||
3fa88c6f | Hamish Coleman | int option_keepalive; /* will we send IAC NOPs all the time? */
|
|
ef78cec5 | Hamish Coleman | int net_bytes_rx;
|
|
int net_bytes_tx;
|
|||
3fa88c6f | Hamish Coleman | struct sockaddr *sa;
|
|
479f1136 | Hamish Coleman | int telnet_option; /* Set to indicate option processing status */
|
|
int telnet_option_param;/* saved parameters from telnet options */
|
|||
ef78cec5 | Hamish Coleman | };
|
|
struct connection connection[MAXCONNECTIONS];
|
|||
5ddf869b | Hamish Coleman | struct cli_def *cli;
|
|
4dcb97c2 | Hamish Coleman | ||
int wconsd_init(int argc, char **argv);
|
|||
int wconsd_main(int param1);
|
|||
int wconsd_stop(int param1);
|
|||
struct SCM_def sd = {
|
|||
"wconsd","wconsd - Telnet to Serial server",
|
|||
wconsd_init, wconsd_main, wconsd_stop
|
|||
};
|
|||
61b53eda | Hamish Coleman | /*
|
|
e6a4efc5 | Hamish Coleman | * output from OutputDebugStringA can be seen using sysinternals debugview
|
|
61b53eda | Hamish Coleman | * http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx
|
|
*/
|
|||
e6a4efc5 | Hamish Coleman | ||
/*
|
|||
* log a debug message
|
|||
*/
|
|||
int dprintf_level = 1;
|
|||
int dprintf(unsigned char severity, const char *fmt, ...) {
|
|||
va_list args;
|
|||
c7c4a6f7 | Hamish Coleman | char buf[MAXLEN];
|
|
e6a4efc5 | Hamish Coleman | int i;
|
|
if (severity > dprintf_level)
|
|||
return 0;
|
|||
va_start(args,fmt);
|
|||
c0d1e8fe | Hamish Coleman | i=vsnprintf(buf,sizeof(buf),fmt,args);
|
|
e6a4efc5 | Hamish Coleman | va_end(args);
|
|
25fa1d20 | Hamish Coleman | if (debug_mode) {
|
|
printf("%s",buf);
|
|||
} else {
|
|||
OutputDebugStringA(buf);
|
|||
}
|
|||
e6a4efc5 | Hamish Coleman | ||
return i;
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
c7c4a6f7 | Hamish Coleman | /*
|
|
884971fc | Hamish Coleman | * format a string and send it to a net connection
|
|
c7c4a6f7 | Hamish Coleman | */
|
|
884971fc | Hamish Coleman | int netprintf(struct connection *conn, const char *fmt, ...) {
|
|
c7c4a6f7 | Hamish Coleman | va_list args;
|
|
char buf[MAXLEN];
|
|||
int i;
|
|||
884971fc | Hamish Coleman | int bytes;
|
|
c7c4a6f7 | Hamish Coleman | ||
va_start(args,fmt);
|
|||
i=vsnprintf(buf,sizeof(buf),fmt,args);
|
|||
va_end(args);
|
|||
884971fc | Hamish Coleman | bytes = send(conn->net,buf,(i>MAXLEN)?MAXLEN-1:i,0);
|
|
if (bytes==-1) {
|
|||
08ceb73b | Hamish Coleman | dprintf(1,"wconsd[%i]: netprintf: send error %i\n",conn->id,GetLastError());
|
|
884971fc | Hamish Coleman | } else {
|
|
conn->net_bytes_tx += bytes;
|
|||
}
|
|||
c7c4a6f7 | Hamish Coleman | return i;
|
|
}
|
|||
62045e98 | Hamish Coleman | /* open the com port */
|
|
4991f810 | Hamish Coleman | int open_com_port(struct connection *conn) {
|
|
62045e98 | Hamish Coleman | /* Open the COM port */
|
|
char portstr[12];
|
|||
aaba0a4c | Hamish Coleman | ||
if (conn->serialconnected) {
|
|||
dprintf(1,"wcons[%i]: open_com_port: serialconnected\n",conn->id);
|
|||
}
|
|||
62045e98 | Hamish Coleman | sprintf(portstr, "\\\\.\\COM%d", com_port);
|
|
aaba0a4c | Hamish Coleman | conn->serial = CreateFile(portstr,
|
|
62045e98 | Hamish Coleman | GENERIC_READ | GENERIC_WRITE,
|
|
0, // Exclusive access
|
|||
NULL,
|
|||
OPEN_EXISTING,
|
|||
FILE_FLAG_OVERLAPPED,
|
|||
NULL);
|
|||
aaba0a4c | Hamish Coleman | if (conn->serial == INVALID_HANDLE_VALUE) {
|
|
4991f810 | Hamish Coleman | return -1;
|
|
62045e98 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | if (!GetCommState(conn->serial, &dcb)) {
|
|
4991f810 | Hamish Coleman | return -1;
|
|
62045e98 | Hamish Coleman | }
|
|
// Fill in the device control block
|
|||
dcb.BaudRate=com_speed;
|
|||
dcb.ByteSize=com_data;
|
|||
dcb.Parity=com_parity; // NOPARITY, ODDPARITY, EVENPARITY
|
|||
dcb.StopBits=com_stop; // ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS
|
|||
dcb.fBinary=TRUE;
|
|||
dcb.fOutxCtsFlow=FALSE;
|
|||
dcb.fOutxDsrFlow=FALSE;
|
|||
dcb.fDtrControl=DTR_CONTROL_ENABLE; // Always on
|
|||
dcb.fDsrSensitivity=FALSE;
|
|||
dcb.fTXContinueOnXoff=FALSE;
|
|||
dcb.fOutX=FALSE;
|
|||
dcb.fInX=FALSE;
|
|||
dcb.fErrorChar=FALSE;
|
|||
dcb.fNull=FALSE;
|
|||
dcb.fRtsControl=RTS_CONTROL_ENABLE; // Always on
|
|||
dcb.fAbortOnError=FALSE;
|
|||
aaba0a4c | Hamish Coleman | if (!SetCommState(conn->serial, &dcb)) {
|
|
4991f810 | Hamish Coleman | return -1;
|
|
62045e98 | Hamish Coleman | }
|
|
4cb40453 | Hamish Coleman | /* FIXME - these values need much more tuning */
|
|
62045e98 | Hamish Coleman | timeouts.ReadIntervalTimeout=20;
|
|
timeouts.ReadTotalTimeoutMultiplier=0;
|
|||
4cb40453 | Hamish Coleman | /*
|
|
* Note that this means that the serial to net thread wakes
|
|||
* each and ever 50 milliseconds
|
|||
*/
|
|||
timeouts.ReadTotalTimeoutConstant=50;
|
|||
62045e98 | Hamish Coleman | timeouts.WriteTotalTimeoutMultiplier=0;
|
|
timeouts.WriteTotalTimeoutConstant=0;
|
|||
aaba0a4c | Hamish Coleman | if (!SetCommTimeouts(conn->serial, &timeouts)) {
|
|
4991f810 | Hamish Coleman | return -1;
|
|
62045e98 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | conn->serialconnected=1;
|
|
62045e98 | Hamish Coleman | return 0;
|
|
}
|
|||
/* close the com port */
|
|||
aaba0a4c | Hamish Coleman | void close_com_port(struct connection *conn) {
|
|
CloseHandle(conn->serial);
|
|||
2d552dd4 | Hamish Coleman | conn->serial=INVALID_HANDLE_VALUE;
|
|
aaba0a4c | Hamish Coleman | conn->serialconnected=0;
|
|
62045e98 | Hamish Coleman | }
|
|
2d552dd4 | Hamish Coleman | /*
|
|
* Given an active connection, force close its
|
|||
* serial port. waiting for all relevant resources
|
|||
*/
|
|||
void close_serial_connection(struct connection *conn) {
|
|||
if (!conn->active) {
|
|||
dprintf(1,"wconsd: closing closed connection %i\n",conn->id);
|
|||
return;
|
|||
}
|
|||
3fa88c6f | Hamish Coleman | conn->option_runmenu=1;
|
|
2d552dd4 | Hamish Coleman | close_com_port(conn);
|
|
WaitForSingleObject(conn->serialThread,INFINITE);
|
|||
CloseHandle(conn->serialThread);
|
|||
conn->serialThread=NULL;
|
|||
}
|
|||
4dcb97c2 | Hamish Coleman | int wconsd_stop(int param1) {
|
|
SetEvent(stopEvent);
|
|||
return 0;
|
|||
}
|
|||
62045e98 | Hamish Coleman | ||
5ddf869b | Hamish Coleman | int libcli_test(struct cli_def *cli, char *command, char *argv[], int argc) {
|
|
int i;
|
|||
cli_print(cli, "called %s with \"%s\"", __FUNCTION__, command);
|
|||
cli_print(cli, "%d arguments:", argc);
|
|||
for (i = 0; i < argc; i++)
|
|||
cli_print(cli, " %s", argv[i]);
|
|||
return CLI_OK;
|
|||
}
|
|||
78d4c0b0 | Hamish Coleman | /* Initialise wconsd: open a listening socket and the COM port, and
|
|
* create lots of event objects. */
|
|||
4dcb97c2 | Hamish Coleman | int wconsd_init(int argc, char **argv) {
|
|
78d4c0b0 | Hamish Coleman | struct sockaddr_in sin;
|
|
WORD wVersionRequested;
|
|||
WSADATA wsaData;
|
|||
int err;
|
|||
/* Start up sockets */
|
|||
wVersionRequested = MAKEWORD( 2, 2 );
|
|||
err = WSAStartup( wVersionRequested, &wsaData );
|
|||
if ( err != 0 ) {
|
|||
/* Tell the user that we could not find a usable */
|
|||
/* WinSock DLL. */
|
|||
return 1;
|
|||
}
|
|||
/* Confirm that the WinSock DLL supports 2.2.*/
|
|||
/* Note that if the DLL supports versions greater */
|
|||
/* than 2.2 in addition to 2.2, it will still return */
|
|||
/* 2.2 in wVersion since that is the version we */
|
|||
/* requested. */
|
|||
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|
|||
HIBYTE( wsaData.wVersion ) != 2 ) {
|
|||
/* Tell the user that we could not find a usable */
|
|||
/* WinSock DLL. */
|
|||
WSACleanup( );
|
|||
return 2;
|
|||
}
|
|||
/* The WinSock DLL is acceptable. Proceed. */
|
|||
// Create the event object used to signal service shutdown
|
|||
stopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|||
if (stopEvent==NULL) {
|
|||
return 3;
|
|||
}
|
|||
// Event objects for overlapped IO
|
|||
readEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|||
if (readEvent==NULL) {
|
|||
return 6;
|
|||
}
|
|||
writeEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|||
if (writeEvent==NULL) {
|
|||
return 7;
|
|||
}
|
|||
// Create the event object for socket operations
|
|||
listenSocketEvent = WSACreateEvent();
|
|||
if (listenSocketEvent==WSA_INVALID_EVENT) {
|
|||
return 8;
|
|||
}
|
|||
306304a2 | Hamish Coleman | if (gethostname((char *)hostname,sizeof(hostname))==SOCKET_ERROR) {
|
|
return 1;
|
|||
}
|
|||
dprintf(1,"wconsd: Hostname is %s\n",hostname);
|
|||
host_entry=gethostbyname((char *)hostname);
|
|||
if (host_entry->h_addrtype==AF_INET) {
|
|||
dprintf(1,"wconsd: IP Address is %s\n",inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list));
|
|||
/* FIXME - enumerate all the IP addresses from the list */
|
|||
} else {
|
|||
host_entry=0;
|
|||
return 0;
|
|||
}
|
|||
78d4c0b0 | Hamish Coleman | /* Create a socket to listen for connections. */
|
|
memset(&sin,0,sizeof(sin));
|
|||
sin.sin_family=AF_INET;
|
|||
62727af2 | Hamish Coleman | sin.sin_port=htons(default_tcpport);
|
|
78d4c0b0 | Hamish Coleman | ls=socket(AF_INET,SOCK_STREAM,0);
|
|
if (ls==INVALID_SOCKET) {
|
|||
return 9;
|
|||
}
|
|||
ef78cec5 | Hamish Coleman | #ifndef MS_WINDOWS
|
|
{
|
|||
int one=1;
|
|||
setsockopt(ls,SOL_SOCKET,SO_REUSEADDR,(void*)&one,sizeof(one));
|
|||
}
|
|||
#endif
|
|||
78d4c0b0 | Hamish Coleman | if (bind(ls,(struct sockaddr *)&sin,sizeof(sin))==SOCKET_ERROR) {
|
|
ef78cec5 | Hamish Coleman | dprintf(1,"wconsd: wconsd_init: failed to bind socket\n");
|
|
78d4c0b0 | Hamish Coleman | return 10;
|
|
}
|
|||
if (listen(ls,1)==SOCKET_ERROR) {
|
|||
return 11;
|
|||
}
|
|||
306304a2 | Hamish Coleman | dprintf(1,"wconsd: listening on port %i\n",default_tcpport);
|
|
78d4c0b0 | Hamish Coleman | ||
/* Mark the socket as non-blocking */
|
|||
if (WSAEventSelect(ls,listenSocketEvent,FD_ACCEPT)==SOCKET_ERROR) {
|
|||
return 12;
|
|||
}
|
|||
4cb40453 | Hamish Coleman | ||
5ddf869b | Hamish Coleman | if (!(cli = cli_init())) {
|
|
dprintf(1,"wconsd: wconsd_init: failed run cli_init\n");
|
|||
return 13;
|
|||
}
|
|||
cli_set_banner(cli, "wconsd serial to telnet");
|
|||
cli_set_hostname(cli, (char *)hostname);
|
|||
cli_set_idle_timeout(cli, 60);
|
|||
cli_register_command(cli, NULL, "test", libcli_test, PRIVILEGE_UNPRIVILEGED,
|
|||
MODE_EXEC, NULL);
|
|||
#if 0
|
|||
cli_set_auth_callback(cli, check_auth);
|
|||
cli_set_enable_callback(cli, check_enable);
|
|||
#endif
|
|||
f3f4759e | Hamish Coleman | modules_init(cli);
|
|
5ddf869b | Hamish Coleman | ||
78d4c0b0 | Hamish Coleman | return 0;
|
|
}
|
|||
3eb633b1 | Hamish Coleman | /*
|
|
479f1136 | Hamish Coleman | * telnet option receiver state machine.
|
|
* Called with the current char, it saves the intermediate state in the
|
|||
* conn struct.
|
|||
*
|
|||
* Returns 0 to indicate no echo of this char, or 0xff to indicate that the
|
|||
* char should be echoed.
|
|||
3eb633b1 | Hamish Coleman | */
|
|
479f1136 | Hamish Coleman | unsigned char process_telnet_option(struct connection*conn, unsigned char ch) {
|
|
dprintf(2,"wconsd[%i]: debug option (0x%02x) 0x%02x\n",conn->id,conn->telnet_option,ch);
|
|||
switch (conn->telnet_option) {
|
|||
case 0: /* received nothing */
|
|||
if (ch==TELNET_OPTION_IAC) {
|
|||
conn->telnet_option=ch;
|
|||
return 0; /* dont echo */
|
|||
997564ce | Hamish Coleman | }
|
|
479f1136 | Hamish Coleman | return 0xff; /* ECHO */
|
|
case TELNET_OPTION_IAC: /* recived IAC */
|
|||
switch(ch) {
|
|||
case 0xf0: /* suboption end */
|
|||
case 0xf1: /* NOP */
|
|||
case 0xf2: /* Data Mark */
|
|||
case 0xf5: /* abort output */
|
|||
case 0xf7: /* erase character */
|
|||
case 0xf8: /* erase line */
|
|||
case 0xf9: /* go ahead */
|
|||
dprintf(1,"wconsd[%i]: option IAC %i\n",conn->id,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case 0xf3: /* Break */
|
|||
if (conn->serialconnected) {
|
|||
dprintf(2,"wconsd[%i]: send break\n",conn->id);
|
|||
Sleep(1000);
|
|||
SetCommBreak(conn->serial);
|
|||
Sleep(1000);
|
|||
ClearCommBreak(conn->serial);
|
|||
}
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case 0xf4: /* Interrupt */
|
|||
conn->option_runmenu=1;
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case 0xf6: /* are you there */
|
|||
dprintf(1,"wconsd[%i]: option IAC AYT\n",conn->id);
|
|||
netprintf(conn,"yes\r\n");
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case TELNET_OPTION_SB:
|
|||
case TELNET_OPTION_WILL:
|
|||
case TELNET_OPTION_WONT:
|
|||
case TELNET_OPTION_DO:
|
|||
case TELNET_OPTION_DONT:
|
|||
conn->telnet_option=ch;
|
|||
return 0; /* dont echo */
|
|||
case 0xff: /* send ff */
|
|||
conn->telnet_option=0;
|
|||
return ch; /* ECHO */
|
|||
default:
|
|||
dprintf(1,"wconsd[%i]: option IAC %i invalid\n",conn->id,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
3eb633b1 | Hamish Coleman | }
|
|
479f1136 | Hamish Coleman | ||
case TELNET_OPTION_SB: /* received IAC SB 0xfa */
|
|||
conn->telnet_option=TELNET_OPTION_SBXX;
|
|||
conn->telnet_option_param=ch;
|
|||
return 0; /* dont echo */
|
|||
case TELNET_OPTION_WILL: /* received IAC WILL 0xfb */
|
|||
dprintf(2,"wconsd[%i]: option IAC WILL %i\n",conn->id,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case TELNET_OPTION_WONT: /* received IAC WONT 0xfc */
|
|||
dprintf(1,"wconsd[%i]: option IAC WONT %i\n",conn->id,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
case TELNET_OPTION_DO: /* received IAC DO 0xfd */
|
|||
switch (ch) {
|
|||
case 0x00: /* Binary */
|
|||
dprintf(2,"wconsd[%i]: DO Binary\n",conn->id);
|
|||
conn->option_binary=1;
|
|||
3eb633b1 | Hamish Coleman | case 0x01: /* ECHO */
|
|
4cb40453 | Hamish Coleman | dprintf(2,"wconsd[%i]: DO ECHO\n",conn->id);
|
|
3eb633b1 | Hamish Coleman | conn->option_echo=1;
|
|
break;
|
|||
479f1136 | Hamish Coleman | default:
|
|
dprintf(2,"wconsd[%i]: option IAC DO %i\n",conn->id,ch);
|
|||
3eb633b1 | Hamish Coleman | break;
|
|
}
|
|||
479f1136 | Hamish Coleman | conn->telnet_option=0;
|
|
return 0; /* dont echo */
|
|||
case TELNET_OPTION_DONT: /* received IAC DONT 0xfe */
|
|||
switch (ch) {
|
|||
case 0x00: /* Binary */
|
|||
dprintf(2,"wconsd[%i]: DONT Binary\n",conn->id);
|
|||
conn->option_binary=0;
|
|||
3eb633b1 | Hamish Coleman | case 0x01: /* ECHO */
|
|
dprintf(1,"wconsd[%i]: DONT ECHO\n",conn->id);
|
|||
conn->option_echo=0;
|
|||
break;
|
|||
default:
|
|||
479f1136 | Hamish Coleman | dprintf(2,"wconsd[%i]: option IAC DONT %i\n",conn->id,ch);
|
|
break;
|
|||
3eb633b1 | Hamish Coleman | }
|
|
479f1136 | Hamish Coleman | conn->telnet_option=0;
|
|
return 0; /* dont echo */
|
|||
3eb633b1 | Hamish Coleman | default:
|
|
479f1136 | Hamish Coleman | if (conn->telnet_option==TELNET_OPTION_SBXX) {
|
|
/* received IAC SB x */
|
|||
int option = conn->telnet_option_param;
|
|||
if (ch==0) {
|
|||
/* IS */
|
|||
dprintf(1,"wconsd[%i]: option IAC SB %i IS\n",
|
|||
conn->id,option);
|
|||
/*
|
|||
* TODO - stay in telnet option mode while
|
|||
* absorbing the IS buffer
|
|||
*/
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
} else if (ch>1) {
|
|||
/* error ? */
|
|||
dprintf(1,"wconsd[%i]: option IAC SB %i %i\n",
|
|||
conn->id,option,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
}
|
|||
/* SEND */
|
|||
if (option == 5) {
|
|||
dprintf(1,"wconsd[%i]: option IAC SB 5 SEND\n",conn->id);
|
|||
/* FIXME - add option_binary */
|
|||
netprintf(conn,"%s%c%s%s%s",
|
|||
"\xff\xfa\x05",
|
|||
0,
|
|||
"\xfb\x05",
|
|||
conn->option_echo?"\xfb\x01":"",
|
|||
"\xff\xf0");
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
} else {
|
|||
/* error ? */
|
|||
dprintf(1,"wconsd[%i]: option IAC SB %i %i\n",
|
|||
conn->id,option,ch);
|
|||
conn->telnet_option=0;
|
|||
return 0; /* dont echo */
|
|||
}
|
|||
}
|
|||
dprintf(1,"wconsd[%i]: invalid conn->telnet_option==%i \n",conn->id,conn->telnet_option);
|
|||
3eb633b1 | Hamish Coleman | }
|
|
/* not normally reached */
|
|||
return 3;
|
|||
}
|
|||
/*
|
|||
* Wrap up all the crazy file writing process in a function
|
|||
*/
|
|||
int serial_writefile(struct connection *conn,OVERLAPPED *o,unsigned char *buf,int size) {
|
|||
DWORD wsize;
|
|||
if (!conn->serialconnected) {
|
|||
dprintf(1,"wconsd[%i]: serial_writefile but serial closed\n",conn->id);
|
|||
return 0;
|
|||
}
|
|||
if (!WriteFile(conn->serial,buf,size,&wsize,o)) {
|
|||
if (GetLastError()==ERROR_IO_PENDING) {
|
|||
// Wait for it...
|
|||
if (!GetOverlappedResult(conn->serial,o,&wsize,TRUE)) {
|
|||
dprintf(1,"wconsd[%i]: Error %d (overlapped) writing to COM port\n",conn->id,GetLastError());
|
|||
}
|
|||
} else {
|
|||
dprintf(1,"wconsd[%i]: Error %d writing to COM port\n",conn->id,GetLastError());
|
|||
}
|
|||
}
|
|||
if (wsize!=size) {
|
|||
dprintf(1,"wconsd[%i]: Eeek! WriteFile: wrote %d of %d\n",conn->id,wsize,size);
|
|||
}
|
|||
return wsize;
|
|||
}
|
|||
78d4c0b0 | Hamish Coleman | DWORD WINAPI wconsd_net_to_com(LPVOID lpParam)
|
|
{
|
|||
aaba0a4c | Hamish Coleman | struct connection * conn = (struct connection*)lpParam;
|
|
c0d1e8fe | Hamish Coleman | unsigned char buf[BUFSIZE];
|
|
3eb633b1 | Hamish Coleman | unsigned char *pbuf;
|
|
int bytes_to_scan;
|
|||
DWORD size;
|
|||
78d4c0b0 | Hamish Coleman | unsigned long zero=0;
|
|
fd_set s;
|
|||
aaba0a4c | Hamish Coleman | struct timeval tv;
|
|
78d4c0b0 | Hamish Coleman | OVERLAPPED o={0};
|
|
4cb40453 | Hamish Coleman | dprintf(1,"wconsd[%i]: debug: start wconsd_net_to_com\n",conn->id);
|
|
884971fc | Hamish Coleman | ||
78d4c0b0 | Hamish Coleman | o.hEvent = writeEvent;
|
|
f6cc8fbf | Hamish Coleman | while (conn->serialconnected) {
|
|
78d4c0b0 | Hamish Coleman | /* There's a bug in some versions of Windows which leads
|
|
* to recv() returning -1 and indicating error WSAEWOULDBLOCK,
|
|||
* even on a blocking socket. This select() is here to work
|
|||
* around that bug. */
|
|||
aaba0a4c | Hamish Coleman | /*
|
|
* These sockets are non-blocking, so I am unsure that the
|
|||
* above statement is still true
|
|||
*/
|
|||
FD_SET(conn->net,&s);
|
|||
3eb633b1 | Hamish Coleman | tv.tv_sec = 2;
|
|
aaba0a4c | Hamish Coleman | tv.tv_usec = 0;
|
|
select(0,&s,NULL,NULL,&tv);
|
|||
306304a2 | Hamish Coleman | /* TODO - examine the retval for the select */
|
|
aaba0a4c | Hamish Coleman | size=recv(conn->net,(void*)&buf,BUFSIZE,0);
|
|
78d4c0b0 | Hamish Coleman | if (size==0) {
|
|
aaba0a4c | Hamish Coleman | closesocket(conn->net);
|
|
conn->net=INVALID_SOCKET;
|
|||
dprintf(1,"wconsd[%i]: wconsd_net_to_com size==0\n",conn->id);
|
|||
f6cc8fbf | Hamish Coleman | return 0;
|
|
78d4c0b0 | Hamish Coleman | }
|
|
if (size==SOCKET_ERROR) {
|
|||
306304a2 | Hamish Coleman | int err = WSAGetLastError();
|
|
switch (err) {
|
|||
case WSAEWOULDBLOCK:
|
|||
/* ignore */
|
|||
3fa88c6f | Hamish Coleman | if (conn->option_keepalive) {
|
|
netprintf(conn,"\xff\xf1");
|
|||
}
|
|||
306304a2 | Hamish Coleman | continue;
|
|
3fa88c6f | Hamish Coleman | case WSAECONNRESET:
|
|
closesocket(conn->net);
|
|||
conn->net=INVALID_SOCKET;
|
|||
479f1136 | Hamish Coleman | return 0;
|
|
306304a2 | Hamish Coleman | default:
|
|
dprintf(1,"wconsd[%i]: net_to_com socket error (%i)\n",conn->id,err);
|
|||
/* General paranoia about blocking sockets */
|
|||
ioctlsocket(conn->net,FIONBIO,&zero);
|
|||
}
|
|||
aaba0a4c | Hamish Coleman | continue;
|
|
78d4c0b0 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | conn->net_bytes_rx+=size;
|
|
3eb633b1 | Hamish Coleman | /*
|
|
* Scan for telnet options and process then remove them
|
|||
* This loop is reasonably fast if there are no options,
|
|||
* but recursively slow if there are options
|
|||
479f1136 | Hamish Coleman | *
|
|
* TODO - if an option is mid packet, this could change
|
|||
* the semantics of processing at the wrong point
|
|||
3eb633b1 | Hamish Coleman | */
|
|
pbuf=buf;
|
|||
bytes_to_scan=size;
|
|||
479f1136 | Hamish Coleman | while(bytes_to_scan--) {
|
|
/* TODO - use ->telnet_option || 0xff to chose to call process_telnet_option */
|
|||
if(!process_telnet_option(conn,*pbuf)) {
|
|||
/* remove this byte from the buffer */
|
|||
memmove(pbuf,pbuf+1,bytes_to_scan);
|
|||
size--;
|
|||
continue;
|
|||
3eb633b1 | Hamish Coleman | }
|
|
479f1136 | Hamish Coleman | pbuf++;
|
|
3eb633b1 | Hamish Coleman | }
|
|
/*
|
|||
* Scan for CR NUL sequences and uncook them
|
|||
201f6e65 | Hamish Coleman | * it also appears that I need to uncook CR LF sequences
|
|
3eb633b1 | Hamish Coleman | */
|
|
479f1136 | Hamish Coleman | if (!conn->option_binary) {
|
|
pbuf=buf;
|
|||
bytes_to_scan=size;
|
|||
while ((pbuf=memchr(pbuf,0x0d,bytes_to_scan))!=NULL) {
|
|||
pbuf++;
|
|||
if (*pbuf!=0x00&&*pbuf!=0x0a) {
|
|||
continue;
|
|||
}
|
|||
3eb633b1 | Hamish Coleman | ||
479f1136 | Hamish Coleman | bytes_to_scan = size-(pbuf-buf)+1;
|
|
size -= 1;
|
|||
memmove(pbuf,pbuf+1,bytes_to_scan);
|
|||
}
|
|||
/* TODO - emulate cisco's ctrl-^,x sequence for exit to menu */
|
|||
3eb633b1 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | ||
3fa88c6f | Hamish Coleman | if (conn->option_runmenu) {
|
|
f6cc8fbf | Hamish Coleman | /*
|
|
* If processing the telnet options has caused
|
|||
* runmenu to be set, we exit the loop here
|
|||
*/
|
|||
3eb633b1 | Hamish Coleman | return 0;
|
|
aaba0a4c | Hamish Coleman | }
|
|
if (!conn->serialconnected) {
|
|||
dprintf(1,"wconsd[%i]: data to send, but serial closed\n",conn->id);
|
|||
continue;
|
|||
}
|
|||
3eb633b1 | Hamish Coleman | /*
|
|
* we could check the return value to see if there was a
|
|||
* short write, but what would our options be?
|
|||
*/
|
|||
serial_writefile(conn,&o,buf,size);
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
4cb40453 | Hamish Coleman | dprintf(1,"wconsd[%i]: debug: finish wconsd_net_to_com\n",conn->id);
|
|
78d4c0b0 | Hamish Coleman | return 0;
|
|
}
|
|||
DWORD WINAPI wconsd_com_to_net(LPVOID lpParam)
|
|||
{
|
|||
aaba0a4c | Hamish Coleman | struct connection * conn = (struct connection*)lpParam;
|
|
c0d1e8fe | Hamish Coleman | unsigned char buf[BUFSIZE];
|
|
78d4c0b0 | Hamish Coleman | DWORD size;
|
|
OVERLAPPED o={0};
|
|||
o.hEvent=readEvent;
|
|||
4cb40453 | Hamish Coleman | dprintf(1,"wconsd[%i]: debug: start wconsd_com_to_net\n",conn->id);
|
|
884971fc | Hamish Coleman | ||
f6cc8fbf | Hamish Coleman | while (conn->serialconnected) {
|
|
aaba0a4c | Hamish Coleman | if (!ReadFile(conn->serial,buf,BUFSIZE,&size,&o)) {
|
|
78d4c0b0 | Hamish Coleman | if (GetLastError()==ERROR_IO_PENDING) {
|
|
// Wait for overlapped operation to complete
|
|||
aaba0a4c | Hamish Coleman | if (!GetOverlappedResult(conn->serial,&o,&size,TRUE)) {
|
|
9b2f3609 | Hamish Coleman | dprintf(1,"wconsd: Error %d (overlapped) reading from COM port\n",GetLastError());
|
|
78d4c0b0 | Hamish Coleman | }
|
|
} else {
|
|||
aaba0a4c | Hamish Coleman | dprintf(1,"wconsd[%i]: Error %d reading from COM port\n",conn->id,GetLastError());
|
|
conn->serialconnected=0;
|
|||
continue;
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
}
|
|||
3eb633b1 | Hamish Coleman | /* We might not have any data if the ReadFile timed out */
|
|
78d4c0b0 | Hamish Coleman | if (size>0) {
|
|
f6cc8fbf | Hamish Coleman | if (send(conn->net,(void*)&buf,size,0)==-1) {
|
|
dprintf(1,"wconsd[%i]: wconsd_com_to_net send failed\n",conn->id);
|
|||
return 0;
|
|||
3eb633b1 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | conn->net_bytes_tx+=size;
|
|
78d4c0b0 | Hamish Coleman | }
|
|
}
|
|||
4cb40453 | Hamish Coleman | dprintf(1,"wconsd[%i]: debug: finish wconsd_com_to_net\n",conn->id);
|
|
78d4c0b0 | Hamish Coleman | return 0;
|
|
62045e98 | Hamish Coleman | }
|
|
f6cc8fbf | Hamish Coleman | void cmd_open(struct connection *conn) {
|
|
dprintf(1,"wconsd[%i]: debug: start cmd_open\n",conn->id);
|
|||
4991f810 | Hamish Coleman | ||
if (!conn->serialconnected) {
|
|||
if (open_com_port(conn)) {
|
|||
netprintf(conn,"error: cannot open port\r\n\n");
|
|||
f6cc8fbf | Hamish Coleman | return;
|
|
4991f810 | Hamish Coleman | }
|
|
}
|
|||
netprintf(conn,"\r\n\n");
|
|||
PurgeComm(conn->serial,PURGE_RXCLEAR|PURGE_RXABORT);
|
|||
if (conn->serialThread==NULL) {
|
|||
/* we might already have a com_to_net thread */
|
|||
conn->serialThread=CreateThread(NULL,0,wconsd_com_to_net,conn,0,NULL);
|
|||
}
|
|||
f6cc8fbf | Hamish Coleman | conn->option_runmenu=0;
|
|
wconsd_net_to_com(conn);
|
|||
4991f810 | Hamish Coleman | conn->option_runmenu=1;
|
|
}
|
|||
884971fc | Hamish Coleman | void send_help(struct connection *conn) {
|
|
aaba0a4c | Hamish Coleman | netprintf(conn,
|
|
4cb40453 | Hamish Coleman | "NOTE: the commands will be changing in the next version\r\n"
|
|
"\r\n"
|
|||
"available commands:\r\n"
|
|||
aaba0a4c | Hamish Coleman | "\r\n"
|
|
479f1136 | Hamish Coleman | "binary - toggle the binary comms mode\r\n"
|
|
4cb40453 | Hamish Coleman | "close - Stop serial communications\r\n"
|
|
"copyright - Print the copyright notice\r\n"
|
|||
"data - Set number of data bits\r\n"
|
|||
"help - This guff\r\n"
|
|||
"kill_conn - Stop a given connection's serial communications\r\n"
|
|||
479f1136 | Hamish Coleman | "keepalive - toggle the generation of keepalive packets\r\n"
|
|
4cb40453 | Hamish Coleman | "open - Connect or resume communications with a serial port\r\n"
|
|
"parity - Set the serial parity\r\n"
|
|||
"port - Set serial port number\r\n"
|
|||
"quit - exit from this session\r\n"
|
|||
"show_conn_table - Show the connections table\r\n"
|
|||
"speed - Set serial port speed\r\n"
|
|||
"status - Show current serial port status\r\n"
|
|||
"stop - Set number of stop bits\r\n"
|
|||
9c5b7bd0 | Hamish Coleman | "\r\n"
|
|
"see http://wob.zot.org/2/wiki/wconsd for more information\r\n"
|
|||
4cb40453 | Hamish Coleman | "\r\n");
|
|
53110989 | Hamish Coleman | }
|
|
c7c4a6f7 | Hamish Coleman | void show_status(struct connection* conn) {
|
|
/* print the status to the net connection */
|
|||
884971fc | Hamish Coleman | netprintf(conn, "status:\r\n\n"
|
|
4cb40453 | Hamish Coleman | " port=%d speed=%d data=%d parity=%d stop=%d\r\n",
|
|
c7c4a6f7 | Hamish Coleman | com_port, com_speed, com_data, com_parity, com_stop);
|
|
aaba0a4c | Hamish Coleman | if(conn->serialconnected) {
|
|
4cb40453 | Hamish Coleman | netprintf(conn, " state=open\r\n\n");
|
|
c7c4a6f7 | Hamish Coleman | } else {
|
|
4cb40453 | Hamish Coleman | netprintf(conn, " state=closed\r\n\n");
|
|
c7c4a6f7 | Hamish Coleman | }
|
|
3fa88c6f | Hamish Coleman | netprintf(conn," connectionid=%i hostname=%s\r\n",conn->id,hostname);
|
|
479f1136 | Hamish Coleman | netprintf(conn," echo=%i binary=%i keepalive=%i\r\n",
|
|
conn->option_echo,conn->option_binary,conn->option_keepalive);
|
|||
3fa88c6f | Hamish Coleman | netprintf(conn,"\r\n");
|
|
c7c4a6f7 | Hamish Coleman | }
|
|
/*
|
|||
* I thought that I would need this a lot, but it turns out that there
|
|||
* was a lot of duplicated code
|
|||
*/
|
|||
884971fc | Hamish Coleman | int check_atoi(char *p,int old_value,struct connection *conn,char *error) {
|
|
c7c4a6f7 | Hamish Coleman | if (!p) {
|
|
884971fc | Hamish Coleman | netprintf(conn,error);
|
|
c7c4a6f7 | Hamish Coleman | return old_value;
|
|
}
|
|||
return atoi(p);
|
|||
53110989 | Hamish Coleman | }
|
|
2d552dd4 | Hamish Coleman | void process_menu_line(struct connection*conn, char *line) {
|
|
d51f658a | Hamish Coleman | char *command;
|
|
char *parameter1;
|
|||
c7c4a6f7 | Hamish Coleman | /*
|
|
* FIXME - non re-entrant code
|
|||
*
|
|||
4450bbca | Hamish Coleman | * my windows build environment does not have strtok_r
|
|
c7c4a6f7 | Hamish Coleman | * and thus I am running these two strtok as close as possible.
|
|
* I am definitely not going to re-invent the wheel with my own
|
|||
* code.
|
|||
*/
|
|||
d51f658a | Hamish Coleman | command = strtok(line," ");
|
|
parameter1 = strtok(NULL," ");
|
|||
if (!strcmp(command, "help") || !strcmp(command, "?")) {
|
|||
// help
|
|||
884971fc | Hamish Coleman | send_help(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "status")) {
|
|
// status
|
|||
c7c4a6f7 | Hamish Coleman | show_status(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "copyright")) { // copyright
|
|
884971fc | Hamish Coleman | netprintf(conn,
|
|
c7c4a6f7 | Hamish Coleman | " Copyright (c) 2008 by Hamish Coleman <hamish@zot.org>\r\n"
|
|
" 2003 by Benjamin Schweizer <gopher at h07 dot org>\r\n"
|
|||
" 1998 by Stephen Early <Stephen.Early@cl.cam.ac.uk>\r\n"
|
|||
"\r\n"
|
|||
"\r\n"
|
|||
" This program is free software; you can redistribute it and/or modify\r\n"
|
|||
" it under the terms of the GNU General Public License as published by\r\n"
|
|||
" the Free Software Foundation; either version 2 of the License, or\r\n"
|
|||
" (at your option) any later version.\r\n"
|
|||
"\r\n"
|
|||
" This program is distributed in the hope that it will be useful,\r\n"
|
|||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n"
|
|||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n"
|
|||
" GNU General Public License for more details.\r\n"
|
|||
"\r\n"
|
|||
" You should have received a copy of the GNU General Public License\r\n"
|
|||
" along with this program; if not, write to the Free Software\r\n"
|
|||
" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r\n"
|
|||
"\n");
|
|||
d51f658a | Hamish Coleman | } else if (!strcmp(command, "port")) { // port
|
|
884971fc | Hamish Coleman | int new = check_atoi(parameter1,com_port,conn,"must specify a port\r\n");
|
|
c7c4a6f7 | Hamish Coleman | ||
if (new >= 1 && new <= 16) {
|
|||
com_port=new;
|
|||
d51f658a | Hamish Coleman | }
|
|
} else if (!strcmp(command, "speed")) { // speed
|
|||
884971fc | Hamish Coleman | com_speed = check_atoi(parameter1,com_port,conn,"must specify a speed\r\n");
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "data")) { // data
|
|
4cb40453 | Hamish Coleman | if (!parameter1) {
|
|
netprintf(conn,"Please specify number of data bits {5,6,7,8}\r\n");
|
|||
return;
|
|||
}
|
|||
d51f658a | Hamish Coleman | if (!strcmp(parameter1, "5")) {
|
|
com_data=5;
|
|||
} else if (!strcmp(parameter1, "6")) {
|
|||
com_data=6;
|
|||
} else if (!strcmp(parameter1, "7")) {
|
|||
com_data=7;
|
|||
} else if (!strcmp(parameter1, "8")) {
|
|||
com_data=8;
|
|||
}
|
|||
c7c4a6f7 | Hamish Coleman | show_status(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "parity")) { // parity
|
|
4cb40453 | Hamish Coleman | if (!parameter1) {
|
|
netprintf(conn,"Please specify the parity {no,even,odd,mark,space}\r\n");
|
|||
return;
|
|||
}
|
|||
d51f658a | Hamish Coleman | if (!strcmp(parameter1, "no") || !strcmp(parameter1, "0")) {
|
|
com_parity=NOPARITY;
|
|||
} else if (!strcmp(parameter1, "even") || !strcmp(parameter1, "2")) {
|
|||
com_parity=EVENPARITY;
|
|||
} else if (!strcmp(parameter1, "odd") || !strcmp(parameter1, "1")) {
|
|||
com_parity=ODDPARITY;
|
|||
} else if (!strcmp(parameter1, "mark")) {
|
|||
com_parity=MARKPARITY;
|
|||
} else if (!strcmp(parameter1, "space")) {
|
|||
com_parity=SPACEPARITY;
|
|||
}
|
|||
c7c4a6f7 | Hamish Coleman | show_status(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "stop")) {
|
|
4cb40453 | Hamish Coleman | if (!parameter1) {
|
|
netprintf(conn,"Please specify the number of stop bits {1,1.5,2}\r\n");
|
|||
return;
|
|||
}
|
|||
d51f658a | Hamish Coleman | if (!strcmp(parameter1, "one") || !strcmp(parameter1, "1")) {
|
|
com_stop=ONESTOPBIT;
|
|||
} else if (!strcmp(parameter1, "one5") || !strcmp(parameter1, "1.5")) {
|
|||
com_stop=ONE5STOPBITS;
|
|||
} else if (!strcmp(parameter1, "two") || !strcmp(parameter1, "2")) {
|
|||
com_stop=TWOSTOPBITS;
|
|||
}
|
|||
c7c4a6f7 | Hamish Coleman | show_status(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "open")) { // open
|
|
4cb40453 | Hamish Coleman | int new = check_atoi(parameter1,com_port,conn,"Opening default port\r\n");
|
|
c7c4a6f7 | Hamish Coleman | ||
if (new >= 1 && new <= 16) {
|
|||
com_port=new;
|
|||
d51f658a | Hamish Coleman | }
|
|
f6cc8fbf | Hamish Coleman | cmd_open(conn);
|
|
d51f658a | Hamish Coleman | } else if (!strcmp(command, "close")) { // close
|
|
2d552dd4 | Hamish Coleman | close_serial_connection(conn);
|
|
884971fc | Hamish Coleman | netprintf(conn,"info: actual com port closed\r\n\n");
|
|
b0f1897b | Hamish Coleman | } else if (!strcmp(command, "quit")) {
|
|
// quit the connection
|
|||
3fa88c6f | Hamish Coleman | conn->option_runmenu=0;
|
|
aaba0a4c | Hamish Coleman | closesocket(conn->net);
|
|
conn->net=INVALID_SOCKET;
|
|||
2d552dd4 | Hamish Coleman | return;
|
|
3fa88c6f | Hamish Coleman | } else if (!strcmp(command, "keepalive")) {
|
|
conn->option_keepalive=!conn->option_keepalive;
|
|||
return;
|
|||
479f1136 | Hamish Coleman | } else if (!strcmp(command, "binary")) {
|
|
conn->option_binary=!conn->option_binary;
|
|||
return;
|
|||
884971fc | Hamish Coleman | } else if (!strcmp(command, "show_conn_table")) {
|
|
int i;
|
|||
netprintf(conn,
|
|||
f6cc8fbf | Hamish Coleman | "Flags: A - Active Slot, S - Serial active,\r\n"
|
|
479f1136 | Hamish Coleman | " M - Run Menu, B - Binary transmission, E - Echo enabled,\r\n"
|
|
" K - Telnet Keepalives, * - This connection\r\n"
|
|||
3fa88c6f | Hamish Coleman | "\r\n");
|
|
08ceb73b | Hamish Coleman | netprintf(conn,
|
|
f6cc8fbf | Hamish Coleman | "s flags id mThr net serial serialTh netrx nettx peer address\r\n");
|
|
3fa88c6f | Hamish Coleman | netprintf(conn,
|
|
f6cc8fbf | Hamish Coleman | "- ------ -- ---- ---- ------ -------- ----- ----- ------------\r\n");
|
|
884971fc | Hamish Coleman | for (i=0;i<MAXCONNECTIONS;i++) {
|
|
f6cc8fbf | Hamish Coleman | netprintf(conn,"%i%c%c%c%c%c%c%c %2i %4i ",
|
|
3fa88c6f | Hamish Coleman | i,
|
|
&connection[i]==conn?'*':' ',
|
|||
connection[i].active?'A':' ',
|
|||
connection[i].serialconnected?'S':' ',
|
|||
connection[i].option_runmenu?'M':' ',
|
|||
479f1136 | Hamish Coleman | connection[i].option_binary?'B':' ',
|
|
3fa88c6f | Hamish Coleman | connection[i].option_echo?'E':' ',
|
|
connection[i].option_keepalive?'K':' ',
|
|||
connection[i].id,
|
|||
connection[i].menuThread);
|
|||
f6cc8fbf | Hamish Coleman | netprintf(conn,"%4i ", connection[i].net);
|
|
3fa88c6f | Hamish Coleman | if (connection[i].serialconnected) {
|
|
netprintf(conn,"%6i %8i ",
|
|||
connection[i].serial,
|
|||
connection[i].serialThread);
|
|||
} else {
|
|||
netprintf(conn," ");
|
|||
}
|
|||
netprintf(conn, "%5i %5i ",
|
|||
connection[i].net_bytes_rx,
|
|||
connection[i].net_bytes_tx);
|
|||
if (connection[i].sa) {
|
|||
/* FIXME - IPv4 Specific */
|
|||
netprintf(conn,"%s:%i",
|
|||
inet_ntoa(((struct sockaddr_in*)connection[i].sa)->sin_addr),
|
|||
htons(((struct sockaddr_in*)connection[i].sa)->sin_port));
|
|||
}
|
|||
netprintf(conn, "\r\n");
|
|||
884971fc | Hamish Coleman | }
|
|
2d552dd4 | Hamish Coleman | } else if (!strcmp(command, "kill_conn")) {
|
|
int connid = check_atoi(parameter1,0,conn,"must specify a connection id\r\n");
|
|||
if (connid==0 || connid>next_connection_id) {
|
|||
netprintf(conn,"Connection ID %i out of range\r\n",connid);
|
|||
return;
|
|||
}
|
|||
int i=0;
|
|||
while(connection[i].id!=connid && i<MAXCONNECTIONS) {
|
|||
i++;
|
|||
}
|
|||
if (i>=MAXCONNECTIONS) {
|
|||
netprintf(conn,"Connection ID %i not found\r\n",connid);
|
|||
return;
|
|||
}
|
|||
997564ce | Hamish Coleman | netprintf(&connection[i],"Serial Connection Closed by Connection ID %i\r\n",conn->id);
|
|
2d552dd4 | Hamish Coleman | close_serial_connection(&connection[i]);
|
|
netprintf(conn,"Connection ID %i serial port closed\r\n",connid);
|
|||
5ddf869b | Hamish Coleman | } else if (!strcmp(command, "menu")) {
|
|
cli_loop(cli,conn->net);
|
|||
c7c4a6f7 | Hamish Coleman | } else {
|
|
/* other, unknown commands */
|
|||
4cb40453 | Hamish Coleman | netprintf(conn,"\r\nInvalid Command: '%s'\r\n\r\n",line);
|
|
d51f658a | Hamish Coleman | }
|
|
53110989 | Hamish Coleman | }
|
|
4cb40453 | Hamish Coleman | void show_prompt(struct connection *conn) {
|
|
netprintf(conn,"%s> ",hostname);
|
|||
}
|
|||
2d552dd4 | Hamish Coleman | void run_menu(struct connection * conn) {
|
|
08ceb73b | Hamish Coleman | unsigned char buf[BUFSIZE+5]; /* ensure there is room for our kludge telnet options */
|
|
unsigned char line[MAXLEN];
|
|||
62045e98 | Hamish Coleman | DWORD size, linelen=0;
|
|
WORD i;
|
|||
unsigned long zero=0;
|
|||
89312c37 | Hamish Coleman | fd_set set_read;
|
|
306304a2 | Hamish Coleman | struct timeval tv;
|
|
53110989 | Hamish Coleman | ||
479f1136 | Hamish Coleman | unsigned char last_ch;
|
|
unsigned char ch;
|
|||
08ceb73b | Hamish Coleman | /* IAC WILL ECHO */
|
|
/* IAC WILL suppress go ahead */
|
|||
/* IAC WILL status */
|
|||
201f6e65 | Hamish Coleman | /* IAC WONT linemode */
|
|
netprintf(conn,"\xff\xfb\x01\xff\xfb\x03\xff\xfb\x05\xff\xfc\x22");
|
|||
08ceb73b | Hamish Coleman | ||
aaba0a4c | Hamish Coleman | netprintf(conn,"\r\nwconsd serial port server (version %s)\r\n\r\n",VERSION);
|
|
884971fc | Hamish Coleman | send_help(conn);
|
|
4cb40453 | Hamish Coleman | show_prompt(conn);
|
|
c7c4a6f7 | Hamish Coleman | ||
89312c37 | Hamish Coleman | FD_ZERO(&set_read);
|
|
f6cc8fbf | Hamish Coleman | while (conn->option_runmenu) {
|
|
89312c37 | Hamish Coleman | FD_SET(conn->net,&set_read);
|
|
306304a2 | Hamish Coleman | tv.tv_sec = 2;
|
|
tv.tv_usec = 0;
|
|||
select(conn->net+1,&set_read,NULL,NULL,&tv);
|
|||
/* TODO - examine the retval for the select */
|
|||
c7c4a6f7 | Hamish Coleman | size=recv(conn->net,(void*)&buf,BUFSIZE,0);
|
|
08ceb73b | Hamish Coleman | ||
62045e98 | Hamish Coleman | if (size==0) {
|
|
c7c4a6f7 | Hamish Coleman | closesocket(conn->net);
|
|
conn->net=INVALID_SOCKET;
|
|||
2d552dd4 | Hamish Coleman | return;
|
|
62045e98 | Hamish Coleman | }
|
|
if (size==SOCKET_ERROR) {
|
|||
306304a2 | Hamish Coleman | int err = WSAGetLastError();
|
|
switch (err) {
|
|||
case WSAEWOULDBLOCK:
|
|||
/* ignore */
|
|||
3fa88c6f | Hamish Coleman | if (conn->option_keepalive) {
|
|
netprintf(conn,"\xff\xf1");
|
|||
}
|
|||
306304a2 | Hamish Coleman | continue;
|
|
3fa88c6f | Hamish Coleman | case WSAECONNRESET:
|
|
closesocket(conn->net);
|
|||
conn->net=INVALID_SOCKET;
|
|||
return;
|
|||
306304a2 | Hamish Coleman | default:
|
|
dprintf(1,"wconsd[%i]: run_menu socket error (%i)\n",conn->id,WSAGetLastError());
|
|||
/* General paranoia about blocking sockets */
|
|||
ioctlsocket(conn->net,FIONBIO,&zero);
|
|||
}
|
|||
53110989 | Hamish Coleman | continue;
|
|
62045e98 | Hamish Coleman | }
|
|
884971fc | Hamish Coleman | conn->net_bytes_rx+=size;
|
|
62045e98 | Hamish Coleman | ||
53110989 | Hamish Coleman | for (i = 0; i < size; i++) {
|
|
479f1136 | Hamish Coleman | last_ch=ch;
|
|
ch = buf[i];
|
|||
/* TODO - remove the second call to process_telnet_option */
|
|||
if (conn->telnet_option) {
|
|||
/* We are in the middle of handling an option */
|
|||
process_telnet_option(conn,ch);
|
|||
/*
|
|||
* return value ignored, since we dont care to
|
|||
* print any telnet option values in the menu.
|
|||
*/
|
|||
b9a4e090 | Hamish Coleman | continue;
|
|
479f1136 | Hamish Coleman | }
|
|
if (ch==0) {
|
|||
/*
|
|||
* NULLs could occur as the second char in a
|
|||
* CR NUL telnet sequence
|
|||
*/
|
|||
continue;
|
|||
} else if (ch==127 || ch==8) {
|
|||
b9a4e090 | Hamish Coleman | // backspace
|
|
53110989 | Hamish Coleman | if (linelen > 0) {
|
|
884971fc | Hamish Coleman | netprintf(conn,"\x08 \x08");
|
|
53110989 | Hamish Coleman | linelen--;
|
|
} else {
|
|||
c7c4a6f7 | Hamish Coleman | /* if the linebuf is empty, ring the bell */
|
|
884971fc | Hamish Coleman | netprintf(conn,"\x07");
|
|
53110989 | Hamish Coleman | }
|
|
continue;
|
|||
479f1136 | Hamish Coleman | } else if (ch==0x0d || ch==0x0a) {
|
|
b9a4e090 | Hamish Coleman | // detected cr or lf
|
|
479f1136 | Hamish Coleman | if (last_ch == 0x0d && ch==0x0a) {
|
|
/* skip the second char in CR LF */
|
|||
continue;
|
|||
b9a4e090 | Hamish Coleman | }
|
|
08ceb73b | Hamish Coleman | if (conn->option_echo)
|
|
/* echo the endofline */
|
|||
netprintf(conn,"\r\n");
|
|||
53110989 | Hamish Coleman | ||
0bcbd4d3 | Hamish Coleman | if (linelen!=0) {
|
|
line[linelen]=0; // ensure string is terminated
|
|||
c7c4a6f7 | Hamish Coleman | ||
2d552dd4 | Hamish Coleman | process_menu_line(conn,(char*)line);
|
|
3fa88c6f | Hamish Coleman | if (!conn->option_runmenu) {
|
|
c7c4a6f7 | Hamish Coleman | /* exiting the menu.. */
|
|
2d552dd4 | Hamish Coleman | return;
|
|
0bcbd4d3 | Hamish Coleman | }
|
|
53110989 | Hamish Coleman | }
|
|
4cb40453 | Hamish Coleman | show_prompt(conn);
|
|
53110989 | Hamish Coleman | linelen=0;
|
|
b9a4e090 | Hamish Coleman | continue;
|
|
479f1136 | Hamish Coleman | } else if (ch<0x20) {
|
|
08ceb73b | Hamish Coleman | /* ignore other ctrl chars */
|
|
continue;
|
|||
479f1136 | Hamish Coleman | } else if (ch==TELNET_OPTION_IAC) {
|
|
/* start a telnet option packet */
|
|||
process_telnet_option(conn,ch);
|
|||
3eb633b1 | Hamish Coleman | /*
|
|
479f1136 | Hamish Coleman | * no possible return values, since IAC is
|
|
* just the beginning of a telnet packet
|
|||
3eb633b1 | Hamish Coleman | */
|
|
b9a4e090 | Hamish Coleman | continue;
|
|
53110989 | Hamish Coleman | } else {
|
|
// other chars
|
|||
0bcbd4d3 | Hamish Coleman | ||
53110989 | Hamish Coleman | if (linelen < MAXLEN - 1) {
|
|
479f1136 | Hamish Coleman | line[linelen] = ch;
|
|
53110989 | Hamish Coleman | linelen++;
|
|
08ceb73b | Hamish Coleman | if (conn->option_echo) {
|
|
479f1136 | Hamish Coleman | netprintf(conn,"%c",ch); /* echo */
|
|
08ceb73b | Hamish Coleman | }
|
|
53110989 | Hamish Coleman | } else {
|
|
884971fc | Hamish Coleman | netprintf(conn,"\x07"); /* linebuf full bell */
|
|
62045e98 | Hamish Coleman | }
|
|
b9a4e090 | Hamish Coleman | continue;
|
|
62045e98 | Hamish Coleman | }
|
|
}
|
|||
}
|
|||
c7c4a6f7 | Hamish Coleman | ||
/* not reached */
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
ef78cec5 | Hamish Coleman | DWORD WINAPI thread_new_connection(LPVOID lpParam) {
|
|
c7c4a6f7 | Hamish Coleman | struct connection * conn = (struct connection*)lpParam;
|
|
ef78cec5 | Hamish Coleman | ||
f6cc8fbf | Hamish Coleman | dprintf(1,"wconsd[%i]: debug: start thread_new_connection loop\n",conn->id);
|
|
run_menu(conn);
|
|||
ef78cec5 | Hamish Coleman | ||
c7c4a6f7 | Hamish Coleman | /* cleanup */
|
|
884971fc | Hamish Coleman | dprintf(1,"wconsd[%i]: connection closing\n",conn->id);
|
|
c7c4a6f7 | Hamish Coleman | /* TODO print bytecounts */
|
|
/* maybe close file descriptors? */
|
|||
884971fc | Hamish Coleman | shutdown(conn->net,SD_BOTH);
|
|
closesocket(conn->net);
|
|||
3eb633b1 | Hamish Coleman | ||
2d552dd4 | Hamish Coleman | close_serial_connection(conn);
|
|
3eb633b1 | Hamish Coleman | ||
884971fc | Hamish Coleman | conn->active=0;
|
|
ef78cec5 | Hamish Coleman | ||
aaba0a4c | Hamish Coleman | /* TODO - who closes menuThread ? */
|
|
ef78cec5 | Hamish Coleman | return 0;
|
|
}
|
|||
4dcb97c2 | Hamish Coleman | int wconsd_main(int param1)
|
|
78d4c0b0 | Hamish Coleman | {
|
|
3eb633b1 | Hamish Coleman | HANDLE wait_array[2];
|
|
78d4c0b0 | Hamish Coleman | BOOL run=TRUE;
|
|
DWORD o;
|
|||
SOCKET as;
|
|||
c0d1e8fe | Hamish Coleman | unsigned long zero=0;
|
|
78d4c0b0 | Hamish Coleman | ||
ef78cec5 | Hamish Coleman | struct sockaddr_in sa;
|
|
int salen;
|
|||
int i;
|
|||
aaba0a4c | Hamish Coleman | int count;
|
|
ef78cec5 | Hamish Coleman | ||
/* clear out any bogus data in the connections table */
|
|||
for (i=0;i<MAXCONNECTIONS;i++) {
|
|||
884971fc | Hamish Coleman | connection[i].active = 0;
|
|
ef78cec5 | Hamish Coleman | }
|
|
78d4c0b0 | Hamish Coleman | /* Main loop: wait for a connection, service it, repeat
|
|
* until signalled that the service is terminating */
|
|||
wait_array[0]=stopEvent;
|
|||
wait_array[1]=listenSocketEvent;
|
|||
while (run) {
|
|||
4cb40453 | Hamish Coleman | dprintf(1,"wconsd: debug: start wconsd_main loop\n");
|
|
bd5605dd | Hamish Coleman | ||
3eb633b1 | Hamish Coleman | o=WaitForMultipleObjects(2,wait_array,FALSE,INFINITE);
|
|
78d4c0b0 | Hamish Coleman | ||
switch (o-WAIT_OBJECT_0) {
|
|||
ef78cec5 | Hamish Coleman | case 0: /* stopEvent */
|
|
78d4c0b0 | Hamish Coleman | run=FALSE;
|
|
ResetEvent(stopEvent);
|
|||
break;
|
|||
ef78cec5 | Hamish Coleman | case 1: /* listenSocketEvent */
|
|
/* There is an incoming connection */
|
|||
78d4c0b0 | Hamish Coleman | WSAResetEvent(listenSocketEvent);
|
|
ef78cec5 | Hamish Coleman | salen = sizeof(sa);
|
|
as=accept(ls,(struct sockaddr*)&sa,&salen);
|
|||
if (as==INVALID_SOCKET) {
|
|||
break;
|
|||
}
|
|||
53110989 | Hamish Coleman | ||
4cb40453 | Hamish Coleman | dprintf(1,"wconsd: new connection from %s\n",
|
|
inet_ntoa(sa.sin_addr));
|
|||
53110989 | Hamish Coleman | ||
ef78cec5 | Hamish Coleman | /* search for an empty connection slot */
|
|
aaba0a4c | Hamish Coleman | i=next_connection_slot%MAXCONNECTIONS;
|
|
count=0;
|
|||
while(connection[i].active && count<MAXCONNECTIONS) {
|
|||
count++;
|
|||
i = (i+1)%MAXCONNECTIONS;
|
|||
ef78cec5 | Hamish Coleman | }
|
|
if (i==MAXCONNECTIONS) {
|
|||
dprintf(1,"wconsd: connection table overflow\n");
|
|||
/* FIXME - properly reject the incoming connection */
|
|||
/* for now, just close the socket */
|
|||
closesocket(as);
|
|||
break;
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
aaba0a4c | Hamish Coleman | next_connection_slot = (next_connection_slot+1)%MAXCONNECTIONS;
|
|
884971fc | Hamish Coleman | connection[i].active=1; /* mark this entry busy */
|
|
connection[i].id = next_connection_id++;
|
|||
ef78cec5 | Hamish Coleman | connection[i].menuThread=NULL;
|
|
connection[i].net=as;
|
|||
aaba0a4c | Hamish Coleman | connection[i].serialconnected=0;
|
|
ef78cec5 | Hamish Coleman | connection[i].serial=INVALID_HANDLE_VALUE;
|
|
connection[i].serialThread=NULL;
|
|||
3fa88c6f | Hamish Coleman | connection[i].option_runmenu=1; /* start in the menu */
|
|
479f1136 | Hamish Coleman | connection[i].option_binary=0;
|
|
08ceb73b | Hamish Coleman | connection[i].option_echo=0;
|
|
3fa88c6f | Hamish Coleman | connection[i].option_keepalive=0;
|
|
ef78cec5 | Hamish Coleman | connection[i].net_bytes_rx=0;
|
|
connection[i].net_bytes_tx=0;
|
|||
479f1136 | Hamish Coleman | connection[i].telnet_option=0;
|
|
connection[i].telnet_option_param=0;
|
|||
ef78cec5 | Hamish Coleman | ||
3fa88c6f | Hamish Coleman | if (connection[i].sa) {
|
|
/* Do lazy de-allocation so that the info is
|
|||
* still visible to show conn table */
|
|||
free(connection[i].sa);
|
|||
}
|
|||
if ((connection[i].sa=malloc(salen))==NULL) {
|
|||
dprintf(1,"wconsd[%i]: malloc failed\n",
|
|||
connection[i].id);
|
|||
} else {
|
|||
memcpy(connection[i].sa,&sa,salen);
|
|||
}
|
|||
4cb40453 | Hamish Coleman | dprintf(1,"wconsd[%i]: accepted new connection in slot %i\n",connection[i].id,i);
|
|
ef78cec5 | Hamish Coleman | ||
/* we successfully accepted the connection */
|
|||
aaba0a4c | Hamish Coleman | ioctlsocket(connection[i].net,FIONBIO,&zero);
|
|
ef78cec5 | Hamish Coleman | ||
connection[i].menuThread = CreateThread(NULL,0,thread_new_connection,&connection[i],0,NULL);
|
|||
78d4c0b0 | Hamish Coleman | break;
|
|
default:
|
|||
run=FALSE; // Stop the service - I want to get off!
|
|||
break;
|
|||
}
|
|||
}
|
|||
aaba0a4c | Hamish Coleman | /* TODO - look through the connection table and close everything */
|
|
78d4c0b0 | Hamish Coleman | ||
closesocket(ls);
|
|||
WSACleanup();
|
|||
4dcb97c2 | Hamish Coleman | return 0;
|
|
78d4c0b0 | Hamish Coleman | }
|
|
static void usage(void)
|
|||
{
|
|||
4cb40453 | Hamish Coleman | printf("Usage: wconsd [-i pathname | -r | -d | -p port ]\n");
|
|
printf("Just start with no options to start server\n");
|
|||
4dcb97c2 | Hamish Coleman | printf(" -i install service 'wconsd'\n");
|
|
78d4c0b0 | Hamish Coleman | printf(" -r remove service 'wconsd'\n");
|
|
4cb40453 | Hamish Coleman | printf(" -d run wconsd in foreground mode\n");
|
|
printf(" -p port listen on the given port in foreground mode\n");
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
int main(int argc, char **argv)
|
|||
{
|
|||
DWORD err;
|
|||
62727af2 | Hamish Coleman | int console_application=0;
|
|
e592f8f7 | Hamish Coleman | ||
62727af2 | Hamish Coleman | // debug info for when I test this as a service
|
|
dprintf(1,"wconsd: started with argc==%i\n",argc);
|
|||
62045e98 | Hamish Coleman | if (argc==1 || argc==0) {
|
|
62727af2 | Hamish Coleman | ||
// assume that our messages are going to the debug log
|
|||
53110989 | Hamish Coleman | debug_mode=0;
|
|
62727af2 | Hamish Coleman | ||
e592f8f7 | Hamish Coleman | err = SCM_Start(&sd);
|
|
if (err!=SVC_CONSOLE) {
|
|||
return 0;
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
62727af2 | Hamish Coleman | ||
// fall through and try running as a command-line application
|
|||
console_application=1;
|
|||
78d4c0b0 | Hamish Coleman | }
|
|
53110989 | Hamish Coleman | // We are running in debug mode (or any other command-line mode)
|
|
debug_mode=1;
|
|||
306304a2 | Hamish Coleman | dprintf(1,"\n"
|
|
"wconsd: Serial Console server (version %s)\n",VERSION);
|
|||
dprintf(1,
|
|||
" (see http://wob.zot.org/2/wiki/wconsd for more info)\n\n");
|
|||
62727af2 | Hamish Coleman | ||
c2484981 | Hamish Coleman | if (argc>1) {
|
|
62727af2 | Hamish Coleman | if (strcmp(argv[1],"-i")==0) {
|
|
6f662bc7 | Hamish Coleman | /* request service installation */
|
|
char *path = SCM_Install(&sd);
|
|||
if (!path) {
|
|||
printf("Service installation failed\n");
|
|||
return 1;
|
|||
}
|
|||
printf("Service '%s' installed, binary path '%s'\n",sd.name,path);
|
|||
printf("You should now start the service using the service manager.\n");
|
|||
62727af2 | Hamish Coleman | return 0;
|
|
} else if (strcmp(argv[1],"-r")==0) {
|
|||
// request service removal
|
|||
6f662bc7 | Hamish Coleman | if (SCM_Remove(&sd)==0) {
|
|
printf("Deleted service '%s'\n",sd.name);
|
|||
} else {
|
|||
printf("Service removal failed\n");
|
|||
return 1;
|
|||
}
|
|||
62727af2 | Hamish Coleman | return 0;
|
|
780d7607 | Hamish Coleman | } else if (strcmp(argv[1],"-p")==0) {
|
|
console_application=1;
|
|||
479f1136 | Hamish Coleman | if (argc>2) {
|
|
default_tcpport = atoi(argv[2]);
|
|||
}
|
|||
62727af2 | Hamish Coleman | } else if (strcmp(argv[1],"-d")==0) {
|
|
console_application=1;
|
|||
479f1136 | Hamish Coleman | if (argc>2) {
|
|
dprintf_level = atoi(argv[2]);
|
|||
}
|
|||
62727af2 | Hamish Coleman | } else {
|
|
78d4c0b0 | Hamish Coleman | usage();
|
|
return 1;
|
|||
}
|
|||
62727af2 | Hamish Coleman | }
|
|
// if we have decided to run as a console app..
|
|||
if (console_application) {
|
|||
78d4c0b0 | Hamish Coleman | int r;
|
|
4cb40453 | Hamish Coleman | dprintf(1,"wconsd: Foreground mode\n");
|
|
4dcb97c2 | Hamish Coleman | ||
e592f8f7 | Hamish Coleman | r=wconsd_init(argc,argv);
|
|
78d4c0b0 | Hamish Coleman | if (r!=0) {
|
|
e592f8f7 | Hamish Coleman | dprintf(1,"wconsd: wconsd_init failed, return code %d\n",r);
|
|
78d4c0b0 | Hamish Coleman | return 1;
|
|
}
|
|||
4dcb97c2 | Hamish Coleman | wconsd_main(0);
|
|
62727af2 | Hamish Coleman | }
|
|
return 0;
|
|||
78d4c0b0 | Hamish Coleman | }
|