Files
sics/remob.c

1099 lines
28 KiB
C

/*-----------------------------------------------------------------------
remob.c
implements remote driveable objects living on an other sics server
M. Zolliker July 04
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <math.h>
#include <netdb.h>
#include "fortify.h"
#include "sics.h"
#include "devexec.h"
#include "remob.h"
#include "splitter.h"
#include "status.h"
#include "site.h"
/*-------------------------------------------------------------------------*/
#define INTERRUPTMODE 0
#define ACCESSCODE 1
/*------------------------------------------------------------------------ */
typedef struct Remob Remob;
typedef struct RemChannel {
mkChannel *chan;
int timeout;
int incomplete;
char line[1024];
} RemChannel;
typedef struct RemServer {
pObjectDescriptor desc;
char *name;
char *host;
int port;
RemChannel rc[2];
Remob *objList;
int matchMap;
int taskActive;
int interestActive;
int forwardMessages;
SConnection *conn;
} RemServer;
struct Remob {
pObjectDescriptor desc;
char *name;
pIDrivable pDrivInt;
pICallBack pCall;
RemServer *server;
int status;
Remob *next;
int markForDel;
};
typedef struct {
float fVal;
char *pName;
} RemobCallback;
typedef struct {
char *pName;
SConnection *pCon;
} RemobInfo;
/*-------------------------------------------------------------------------*/
static char *StartsWith(char *line, char *name)
{
/* if line does not start with name, return NULL
else return a pointer to the next non-white space character
*/
char *str;
int l;
l = strlen(name);
if (0 != strncmp(line, name, l))
return NULL;
str = line + l;
while (*str == ' ') {
str++;
}
return str;
}
/*-------------------------------------------------------------------------*/
static int RemWrite(RemChannel * rc, char *line)
{
int iret;
if (rc->chan) {
/* printf("> %s\n", line); */
iret = NETWrite(rc->chan, line, strlen(line));
if (iret == 0)
iret = -1;
return iret;
} else {
return -1;
}
}
/*-------------------------------------------------------------------------*/
static int RemRead(RemChannel * rc, long tmo)
{
int iRet;
if (rc->chan == NULL)
return 0; /* no data */
iRet = NETReadTillTerm(rc->chan, tmo, "\n", rc->line + rc->incomplete,
sizeof(rc->line) - rc->incomplete);
if (iRet == 0) {
rc->incomplete = strlen(rc->line); /* number of chars already received */
return 0; /* timeout */
} else {
rc->incomplete = 0;
}
return iRet;
}
/*-------------------------------------------------------------------------*/
static int RemHandle(RemServer * remserver)
{
char *line, *par, *str;
Remob *remob;
RemChannel *rc;
rc = &remserver->rc[0]; /* drivstat messages appear only on the spy channel */
/* skip whitespace at the beginning */
line = rc->line;
if (line[0] == '\0')
return 0; /* return when line is empty */
while (*line < ' ' && *line != '\0') {
line++;
}
memmove(rc->line, line, strlen(line));
/* handle drivstat messages */
line = rc->line;
for (remob = remserver->objList; remob != NULL; remob = remob->next) {
par = StartsWith(line, remob->name);
if (par != NULL) {
if ((str = StartsWith(par, "finished"))) {
if (*str == '\0') {
remob->status = HWIdle;
} else {
remob->status = HWFault;
}
line[0] = '\0';
return 1;
}
if ((str = StartsWith(par, "started"))) {
remob->status = HWBusy;
line[0] = '\0';
return 1;
}
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static void RemCopy(RemChannel * rc, SConnection * pCon)
{
if (pCon != NULL && rc->line[0] != '\0') {
SCPrintf(pCon, eValue, " %s", rc->line);
}
}
/*-------------------------------------------------------------------------*/
static void RemDisconnect(RemServer * remserver)
{
int isUser;
RemChannel *rc;
for (isUser = 0; isUser <= 1; isUser++) {
rc = &remserver->rc[isUser];
if (rc->chan != NULL) {
NETClosePort(rc->chan);
free(rc->chan);
rc->chan = NULL;
/* printf("disconnected\n"); */
}
}
}
/*-------------------------------------------------------------------------*/
static int RemSetInterest(RemChannel * rc)
{
int iRet;
if (rc->chan != NULL) { /* already connected */
iRet = RemWrite(rc, "transact listexe interest\n");
if (iRet >= 0) {
iRet = RemRead(rc, 1000);
while (iRet > 0) { /* eat response */
if (StartsWith(rc->line, "TRANSACTIONFINISHED")) {
return 1;
}
iRet = RemRead(rc, 1000);
}
}
}
return 0;
}
/*-------------------------------------------------------------------------*/
static void RemConnect(RemServer * remserver, int both)
{
/* open channel 0 or both channels, if not yet opened */
int iRet;
mkChannel *chan;
int i;
RemChannel *rc;
for (i = 0; i <= both; i++) {
rc = &remserver->rc[i];
if (!rc->chan) {
rc->timeout = 0;
chan = NETConnect(remserver->host, remserver->port);
if (!chan) {
return;
}
rc->chan = chan;
if (i != 0) { /* open the user channel */
iRet = RemWrite(rc, "remuser sesam\n");
} else { /* open spy channel */
iRet = RemWrite(rc, "Spy 007\n");
}
if (iRet < 0)
goto close;
iRet = RemRead(rc, 1000);
while (iRet > 0) { /* eat login response */
if (StartsWith(rc->line, "Login OK")) {
/* printf("connected\n"); */
if (remserver->interestActive && rc == &remserver->rc[0]) { /* open the user channel */
if (!RemSetInterest(rc))
goto close;
}
break;
}
iRet = RemRead(rc, 1000);
}
if (iRet <= 0)
goto close;
}
}
return;
close:
RemDisconnect(remserver);
return;
}
/*-------------------------------------------------------------------------*/
static int RemServerTask(void *data)
{
RemServer *remserver = data;
int iRet;
SConnection *pCon;
int isUser;
RemChannel *rc;
if (!remserver->taskActive)
return 0; /* remove task */
for (isUser = 0; isUser <= 1; isUser++) {
rc = &remserver->rc[isUser];
if (RemRead(rc, 0) <= 0)
continue;
if (strstr(rc->line, " ") == rc->line) {
Log(ERROR,"sys","%s:%s","REMOB", "infinite echo loop detected");
continue;
}
if (isUser == 0) {
if (RemHandle(remserver)) { /* handle drivstat messages */
continue;
}
}
if (remserver->forwardMessages) {
/* forward all other messages */
if (SCisConnected(remserver->conn)) {
RemCopy(rc, remserver->conn);
}
}
}
return 1;
}
/*-------------------------------------------------------------------------*/
static int RemTransact(RemServer * remserver, int nChan,
SConnection * pCon, char *cmd, ...)
{
/* the variable arguments are for filtering:
"<name", &val get float value named name
"!blabla" skip lines starting with blabla
">" write untreated lines to pCon
*/
char *buffer;
int bufferLen;
int iRet;
char *arg, *val, *endp;
float *f;
va_list ap;
int try;
int argMask;
RemChannel *rc = &remserver->rc[nChan];
pDynString errorResult;
try = 3;
if (rc->timeout) { /* eat old responses */
while (RemRead(rc, 0) > 0) {
RemHandle(remserver);
}
}
tryagain:
bufferLen = strlen(cmd) + 16;
buffer = malloc(bufferLen);
if (buffer == NULL) {
SCPrintf(pCon, eError, "ERROR: can not get another %d bytes",
bufferLen);
return 0;
}
snprintf(buffer, bufferLen, "transact %s\n", cmd);
RemConnect(remserver, nChan);
iRet = RemWrite(rc, buffer);
free(buffer);
if (iRet < 0)
goto close;
iRet = RemRead(rc, 2000);
if (iRet <= 0)
goto close;
while (!StartsWith(rc->line, "TRANSACTIONFINISHED")) {
if (StartsWith(rc->line, "ERROR:")) {
errorResult = CreateDynString(60, 64);
do {
RemHandle(remserver);
DynStringConcat(errorResult, rc->line);
DynStringConcat(errorResult, "\n");
iRet = RemRead(rc, 2000);
} while (!StartsWith(rc->line, "TRANSACTIONFINISHED"));
if (pCon != NULL) {
SCPrintf(pCon, eError, "ERROR: in %s:\n%s", remserver->name, GetCharArray(errorResult));
}
DeleteDynString(errorResult);
return -2;
}
RemHandle(remserver);
va_start(ap, cmd);
arg = va_arg(ap, char *);
argMask = 1;
remserver->matchMap = 0;
while (arg != NULL) {
if (*arg == '>') {
RemCopy(rc, pCon);
} else if (*arg == '<') {
f = va_arg(ap, float *);
val = StartsWith(rc->line, arg + 1);
if (val != NULL) {
val = StartsWith(val, "=");
if (val != NULL) {
*f = strtod(val, &endp);
break;
}
}
} else if (*arg == '!') {
if (StartsWith(rc->line, arg + 1)) {
remserver->matchMap |= argMask;
argMask = argMask * 2;
break;
}
} else {
printf("unknown argument in RemTransact: %s\n", arg);
assert(0);
}
arg = va_arg(ap, char *);
}
va_end(ap);
iRet = RemRead(rc, 2000);
if (iRet <= 0)
goto close;
}
return 1;
close:
if (iRet == 0) {
if (try == 1) {
SCPrintf(pCon, eError, "ERROR: timeout on %s", remserver->name);
rc->timeout = 1;
return iRet;
} else {
SCPrintf(pCon, eError, "WARNING: timeout on %s", remserver->name);
}
}
RemDisconnect(remserver);
try--;
if (try > 0)
goto tryagain;
SCPrintf(pCon, eError, "ERROR: no connection to %s", remserver->name);
return iRet;
}
/*-------------------------------------------------------------------------*/
static void *RemobGetInterface(void *pData, int iID)
{
Remob *self = pData;
assert(self);
if (iID == DRIVEID) {
return self->pDrivInt;
} else if (iID == CALLBACKINTERFACE) {
return self->pCall;
}
return NULL;
}
/*------------------------------------------------------------------------*/
static int RemobHalt(void *self)
{
Remob *remob = self;
RemServer *remserver = remob->server;
RemChannel *rc = &remserver->rc[1]; /* Halt is only called with at least user priv. */
char buf[64];
assert(remob);
RemConnect(remserver, 1);
snprintf(buf, sizeof(buf), "stopexe %s\n", remob->name);
remob->status = HWFault;
return RemWrite(rc, buf);
}
/*--------------------------------------------------------------------------*/
static int RemobLimits(void *self, float fVal, char *error, int iErrLen)
{
float fHard;
Remob *remob = self;
assert(remob);
/* check is done on remote server */
return 1;
}
/*---------------------------------------------------------------------------*/
static float RemobGetValue(void *pData, SConnection * pCon)
{
Remob *remob = pData;
RemServer *remserver = remob->server;
char buf[80];
float none, value;
int iRet;
assert(remob);
if (remserver->conn != NULL) {
SCDeleteConnection(remserver->conn);
}
remserver->conn = SCCopyConnection(pCon);
none = -1.234e32;
value = none;
snprintf(buf, sizeof(buf), "<%s", remob->name);
/* get value needs only spy priviledge */
iRet =
RemTransact(remserver, 0, pCon, remob->name, buf, &value, ">", NULL);
/*
if (iRet <= 0) {
return 0.0;
}
*/
if (value != none) {
return value;
}
snprintf(buf, sizeof(buf), "can not get %s", remob->name);
SCWrite(pCon, buf, eWarning);
return 0.0;
}
/*------------------------------------------------------------------------*/
static int RemobSaveStatus(void *pData, char *name, FILE * fil)
{
Remob *self = pData;
assert(self);
assert(fil);
/*
data is stored on remote server
*/
return 1;
}
/*------------------------------------------------------------------------*/
static int RemServerSaveStatus(void *pData, char *name, FILE * fil)
{
RemServer *remserver = pData;
Remob *remob;
assert(remserver);
assert(fil);
for (remob = remserver->objList; remob != NULL; remob = remob->next) {
if (remob->pDrivInt) {
fprintf(fil, "catch { remob drv %s %s }\n", remob->name,
remserver->name);
} else {
fprintf(fil, "catch { remob obj %s %s }\n", remob->name,
remserver->name);
}
}
return 1;
}
/*------------------------------------------------------------------------*/
static int RemobStatus(void *pData, SConnection * pCon)
{
Remob *remob = pData;
assert(remob);
if (remob->server->conn != NULL) {
SCDeleteConnection(remob->server->conn);
}
remob->server->conn = SCCopyConnection(pCon);
return remob->status;
}
/*---------------------------------------------------------------------------*/
static long RemobRun(void *self, SConnection * pCon, float fNew)
{
Remob *remob = self;
float fHard;
int i, iRet, iCode;
char buf[512], sBuf[64];
char pError[132];
Remob *p;
RemServer *remserver;
long lTime;
float fDelta;
int rights;
RemChannel *rc;
int nChan;
assert(remob);
assert(pCon);
remserver = remob->server;
if (remserver->conn != NULL) {
SCDeleteConnection(remserver->conn);
}
remserver->conn = SCCopyConnection(pCon);
rights = SCGetRights(pCon);
nChan = rights <= usUser;
rc = &remserver->rc[nChan];
RemConnect(remserver, 0); /* connect spy for listexe interest */
remob->status = HWIdle;
snprintf(buf, sizeof(buf), "run %s %g", remob->name, fNew);
iRet =
RemTransact(remserver, nChan, pCon, buf, "!ERROR: somebody else",
"!ERROR: cannot", ">", NULL);
if (iRet <= 0)
return 0;
if (remserver->matchMap & 1) { /* already running, stop first */
remob->status = HWBusy;
snprintf(sBuf, sizeof(sBuf), "stopexe %s", remob->name);
iRet = RemTransact(remserver, nChan, pCon, sBuf, ">", NULL);
if (iRet <= 0)
return 0;
while (remob->status == HWBusy) {
iRet = RemRead(rc, 1000);
if (iRet <= 0)
break;
if (!RemHandle(remserver)) {
RemCopy(rc, pCon);
}
}
iRet = RemTransact(remserver, nChan, pCon, buf, ">", NULL);
if (iRet <= 0)
return 0;
}
/* wait for "started" message */
while (remob->status != HWBusy) {
iRet = RemRead(&remserver->rc[0], 1000);
if (iRet <= 0)
break;
if (!RemHandle(remserver)) {
RemCopy(&remserver->rc[0], pCon);
}
}
if (remob->status != HWBusy) {
return 0;
}
return OKOK;
}
/*-----------------------------------------------------------------------*/
static void KillInfo(void *pData)
{
RemobInfo *self = pData;
assert(self);
if (self->pName) {
free(self->pName);
}
if (self->pCon) {
SCDeleteConnection(self->pCon);
}
free(self);
}
/*------------------- The CallBack function for interest ------------------*/
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
{
RemobCallback *psCall = pEvent;
RemobInfo *pInfo = pUser;
char buf[80];
assert(psCall);
assert(pInfo);
snprintf(buf, sizeof(buf), "%s.position = %g ", pInfo->pName,
psCall->fVal);
SCWrite(pInfo->pCon, buf, eEvent);
return 1;
}
/*---------------------------------------------------------------------------*/
int RemobAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
Remob *remob = pData;
RemServer *remserver = remob->server;
char buf[512];
TokenList *pList = NULL;
TokenList *pCurrent;
TokenList *pName;
int iRet;
int i;
int pos;
float fValue;
long lID;
char *endp;
char *cmd;
/*
char acce[128], inte[128];
*/
int rights;
int nChan;
RemChannel *rc;
assert(pCon);
assert(pSics);
assert(remob);
rights = SCGetRights(pCon);
nChan = (rights <= usUser);
rc = &remserver->rc[nChan];
if (rights >= usUser) {
if (remserver->conn != NULL) {
SCDeleteConnection(remserver->conn);
}
remserver->conn = SCCopyConnection(pCon);
}
if (argc == 1) {
/* filter out time stamps !=== */
iRet = RemTransact(remserver, nChan, pCon, remob->name, "!===", ">", NULL);
if (iRet < 0) {
iRet = 0;
} else {
iRet = 1;
}
} else if (strcasecmp(argv[1], "interest") == 0) {
/* ignore interest commands, as they would not work properly */
iRet = 1;
} else if (strcasecmp(argv[1], "list") == 0) {
/*
snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name);
snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name);
*/
cmd = Arg2Tcl0(argc - 1, argv + 1, buf, sizeof buf, remob->name);
if (cmd) {
/* filter out time stamps !=== */
RemTransact(remserver, nChan, pCon, cmd, "!===", ">", NULL);
if (cmd != buf)
free(cmd);
}
iRet = 1;
} else {
pos = snprintf(buf, sizeof(buf), "%s ", remob->name);
for (i = 1; i < argc; i++) {
pos += snprintf(buf + pos, sizeof(buf) - pos, "%s ", argv[i]);
}
iRet = RemTransact(remserver, nChan, pCon, buf, ">", NULL);
}
return iRet;
}
/*--------------------------------------------------------------------------*/
static void RemobKill(void *self)
{
Remob *remob = self;
Remob *p, **last;
assert(remob);
/* remove from object list */
if (remob->server) {
last = &remob->server->objList;
p = *last;
while (p != remob && p != NULL) {
last = &p->next;
p = p->next;
}
if (p != NULL) {
*last = p->next;
}
remob->next = NULL;
}
if (remob->name) {
free(remob->name);
}
if (remob->pDrivInt) {
free(remob->pDrivInt);
}
if (remob->pCall) {
DeleteCallBackInterface(remob->pCall);
}
/* kill Descriptor */
if (remob->desc) {
DeleteDescriptor(remob->desc);
}
free(remob);
}
/*---------------------------------------------------------------------------*/
int RemServerAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
RemServer *remserver = pData;
TokenList *pList = NULL;
TokenList *pCurrent;
TokenList *pName;
int iRet;
socklen_t i;
int pos;
float fValue;
long lID;
char *endp, *serverport, *thishostname;
struct sockaddr_in adr;
struct hostent *thishost;
Remob *p, *next;
int rights, nChan;
RemChannel *rc;
char *args;
assert(pCon);
assert(pSics);
assert(remserver);
rights = SCGetRights(pCon);
nChan = (rights <= usUser);
rc = &remserver->rc[nChan];
if (nChan) {
if (remserver->conn != NULL) {
SCDeleteConnection(remserver->conn);
}
remserver->conn = SCCopyConnection(pCon);
}
if (argc == 1) {
serverport = IFindOption(pSICSOptions, "ServerPort");
i = sizeof adr;
thishostname = NULL;
if (rc->chan) {
if (getsockname(rc->chan->sockid, (void *) &adr, &i) >= 0) {
thishost = gethostbyaddr((char *) &adr.sin_addr,
sizeof adr.sin_addr, AF_INET);
if (thishost) {
thishostname = thishost->h_name;
}
}
}
if (thishostname == NULL)
thishostname = "undef";
SCPrintf(pCon, eValue, "%s = %s:%d %s:%s",
argv[0], remserver->host, remserver->port, thishostname,
serverport);
} else if (argc > 2 && strcasecmp(argv[1], "nowait") == 0) {
RemConnect(remserver, nChan);
args = Arg2Tcl(argc - 2, argv + 2, NULL, 0);
RemWrite(rc, args);
RemWrite(rc, "\n");
free(args);
} else if (argc == 2 && strcasecmp(argv[1], "markForDel") == 0) {
p = remserver->objList;
while (p) {
p->markForDel = 1;
p = p->next;
}
} else if (argc == 2 && strcasecmp(argv[1], "delMarked") == 0) {
p = remserver->objList;
while (p) {
next = p->next;
if (p->markForDel) {
if (p->pDrivInt && pServ->pExecutor
&& isInRunMode(pServ->pExecutor)) {
SCWrite(pCon, "ERROR: cannot delete while running", eError);
return 0;
}
RemoveCommand(pSics, p->name);
}
p = next;
}
} else {
args = Arg2Tcl(argc - 1, argv + 1, NULL, 0);
iRet = RemTransact(remserver, nChan, pCon, args, ">", NULL);
free(args);
return iRet;
}
return 1;
}
/*--------------------------------------------------------------------------*/
static void RemServerKill(void *self)
{
RemServer *remserver = self;
Remob *remob, *next;
assert(remserver);
if (remserver->taskActive) {
remserver->taskActive = 0;
/* let the tasker kill me */
return;
}
remob = remserver->objList;
while (remob) {
next = remob->next;
RemoveCommand(pServ->pSics, remob->name);
remob = next;
}
RemDisconnect(remserver);
DeleteDescriptor(remserver->desc);
if (remserver->name)
free(remserver->name);
if (remserver->host)
free(remserver->host);
if (remserver->conn != NULL) {
SCDeleteConnection(remserver->conn);
}
free(remserver);
}
/*-----------------------------------------------------------------------*/
static int RemobSetDriveable(Remob * remob, int driveable)
{
RemChannel *rc;
if (driveable) {
/* initialise Drivable interface */
remob->pDrivInt = CreateDrivableInterface();
if (!remob->pDrivInt)
return 0;
remob->pDrivInt->SetValue = RemobRun;
remob->pDrivInt->CheckLimits = RemobLimits;
remob->pDrivInt->CheckStatus = RemobStatus;
remob->pDrivInt->GetValue = RemobGetValue;
remob->pDrivInt->Halt = RemobHalt;
if (remob->server->interestActive == 0) {
rc = &remob->server->rc[0];
remob->server->interestActive = 1;
if (!RemSetInterest(rc)) {
RemDisconnect(remob->server); /* disconnect on error, RemSetInterest will be called again on connect */
}
}
} else if (remob->pDrivInt) {
free(remob->pDrivInt);
remob->pDrivInt = NULL;
}
return 1;
}
/*-----------------------------------------------------------------------*/
static Remob *RemobInit(char *name, RemServer * remserver)
{
Remob *remob, *p;
assert(name);
/* get memory */
remob = (Remob *) calloc(1, sizeof(Remob));
if (!remob) {
return NULL;
}
/* copy arguments */
remob->server = remserver;
remob->name = strdup(name);
/* initialise object descriptor */
remob->desc = CreateDescriptor("RemObject");
if (!remob->desc)
goto killit;
remob->desc->GetInterface = RemobGetInterface;
remob->desc->SaveStatus = RemobSaveStatus;
/* initialise callback interface */
remob->pCall = CreateCallBackInterface();
if (!remob->pCall)
goto killit;
/* check if not yet in object list */
for (p = remserver->objList; p != NULL; p = p->next) {
if (p == remob)
break;
}
if (p == NULL) {
remob->next = remserver->objList;
remserver->objList = remob;
}
remob->markForDel = 0;
/* done */
return remob;
killit:
RemobKill(remob);
return NULL;
}
/*-----------------------------------------------------------------------*/
static RemServer *RemServerInit(char *name, char *host, int port)
{
RemServer *remserver = NULL;
RemChannel *rc;
int isUser;
assert(name);
remserver = calloc(1, sizeof(RemServer));
if (!remserver) {
return 0;
}
/* initialise object descriptor */
remserver->desc = CreateDescriptor("RemServer");
if (!remserver->desc) {
free(remserver);
return NULL;
}
remserver->desc->SaveStatus = RemServerSaveStatus;
remserver->name = strdup(name);
remserver->host = strdup(host);
remserver->port = port;
for (isUser = 0; isUser <= 1; isUser++) {
rc = &remserver->rc[isUser];
rc->incomplete = 0;
rc->chan = NULL;
rc->timeout = 0;
}
remserver->objList = NULL;
remserver->conn = NULL;
if (!remserver->name || !remserver->host || !remserver->port) {
/* no success, clean up */
RemServerKill(remserver);
return NULL;
}
remserver->taskActive = 1;
remserver->interestActive = 0;
remserver->forwardMessages = 1;
TaskRegisterN(pServ->pTasker,name, RemServerTask, NULL, RemServerKill,
remserver, TASK_PRIO_HIGH);
return remserver;
}
/*--------------------------------------------------------------------------
The Factory function for creating a remote driveable object.
Usage:
Remob server serverName host:port
Remob obj remobName serverName
Remob drv remobName serverName
Remob del remobName
Remob del serverName
*/
int RemobCreate(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
RemServer *remserver = NULL;
Remob *remob = NULL;
char host[128];
char *p;
int iD, iRet;
char *obj;
int argf;
assert(pCon);
assert(pSics);
argtolower(argc, argv);
if (argc >= 4 && strcmp(argv[1], "server") == 0) {
p = strchr(argv[3], ':');
if (p) {
snprintf(host, sizeof host, "%.*s", (int)(p - argv[3]), argv[3]);
remserver = RemServerInit(argv[2], host, atoi(p + 1));
argf = 4;
} else {
remserver = RemServerInit(argv[2], argv[3], atoi(argv[4]));
argf = 5;
}
if (remserver && argc > argf && strcmp(argv[argf], "0") == 0) {
remserver->forwardMessages = 0;
}
if (!remserver) {
SCPrintf(pCon, eError,
"ERROR: Failure to create remote server connection %s",
argv[2]);
return 0;
}
/* create the interpreter command */
iRet =
AddCommand(pSics, argv[2], RemServerAction, RemServerKill,
remserver);
if (!iRet) {
SCPrintf(pCon, eError, "ERROR: duplicate command %s not created",
argv[2]);
RemServerKill(remserver);
return 0;
}
return 1;
} else if (argc == 4
&& (strcmp(argv[1], "obj") == 0
|| strcmp(argv[1], "drv") == 0)) {
remserver = FindCommandData(pServ->pSics, argv[3], "RemServer");
if (!remserver) {
SCPrintf(pCon, eError, "ERROR: remote server %s not found", argv[3]);
return 0;
}
remob = FindCommandData(pServ->pSics, argv[2], "RemObject");
if (remob) {
if (remob->server == remserver) {
RemobSetDriveable(remob, strcmp(argv[1], "drv") == 0);
remob->markForDel = 0;
return 1; /* object exists already, silent return */
}
}
remob = RemobInit(argv[2], remserver);
if (!remob) {
SCPrintf(pCon, eError, "ERROR: Failure to create remote object %s",
argv[1]);
return 0;
}
RemobSetDriveable(remob, strcmp(argv[1], "drv") == 0);
/* create the interpreter command */
iRet = AddCommand(pSics, argv[2], RemobAction, RemobKill, remob);
SCparChange(pCon);
if (!iRet) {
SCPrintf(pCon, eError, "ERROR: duplicate command %s not created",
argv[2]);
RemobKill(remob);
return 0;
}
return 1;
} else if (argc == 3 && strcmp(argv[1], "del") == 0) {
remob = FindCommandData(pSics, argv[2], "RemObject");
if (remob) { /* its a remob */
if (remob->pDrivInt && pServ->pExecutor
&& isInRunMode(pServ->pExecutor)) {
SCPrintf(pCon, eError, "ERROR: cannot delete %s while running",
argv[2]);
return 0;
}
return RemoveCommand(pSics, argv[2]);
}
if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) {
SCPrintf(pCon, eError, "ERROR: cannot delete %s while running",
argv[2]);
return 0;
}
remserver = FindCommandData(pSics, argv[2], "RemServer");
if (remserver) { /* its a remserver */
return RemoveCommand(pSics, argv[2]);
}
SCWrite(pCon, "ERROR: remob object not found", eError);
return 0;
}
SCPrintf(pCon, eError, "ERROR: illegal arguments for command remob");
return 0;
}