diff --git a/initializer.c b/initializer.c new file mode 100644 index 00000000..397e0d4d --- /dev/null +++ b/initializer.c @@ -0,0 +1,139 @@ +/*--------------------------------------------------------------------------- +initializer.c + +initializer routines + +Markus Zolliker, March 2005 +---------------------------------------------------------------------------- +*/ + +#include "sics.h" +#include "initializer.h" + +typedef struct Item { + struct Item *next; + const char *type; + const char *name; + Initializer maker; + int startupOnly; +} Item; + +static Item *list = NULL; +static int startup = 1; + +void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly) { + Item *item; + + item = calloc(1, sizeof *item); + assert(item); + item->maker = maker; + item->next = list; + item->type = type; + item->name = name; + item->startupOnly = startupOnly; + list = item; +} + +Initializer GetInitializer(const char *type, const char *name) { + Item *p, **last; + + if (startup && pServ->pReader != NULL) { + /* pServ->pReader exists: startup finished */ + startup = 0; + /* remove startup initializers */ + p = list; + last = &list; + while (p != NULL) { + if (p->startupOnly) { + *last = p->next; + free(p); + p = *last; + } else { + last = &p->next; + p = p->next; + } + } + } + p = list; + while (p != NULL && (strcasecmp(p->name, name) != 0 || strcasecmp(p->type, type) != 0)) { + p = p->next; + } + if (p) { + return p->maker; + } + return NULL; +} + +static int MakeObject(SConnection *con, SicsInterp *sics, + void *data, int argc, char *argv[]) { + CmdInitializer cmdin; + CommandList *command; + char *className; + + if (argc < 3) { + SCPrintf(con, eError, "%s needs more arguments", argv[0]); + return 0; + } + + cmdin = (CmdInitializer)GetInitializer("Object", argv[2]); + if (cmdin) { + return cmdin(con, argc, argv, ! startup); + } else { + SCPrintf(con, eError, "do not know how to make a %s object", argv[2]); + return 0; + } +} + +static int RemoveObject(SConnection *con, SicsInterp *sics, + void *data, int argc, char *argv[]) { + CmdInitializer cmdin; + CommandList *command; + char *className; + + if (argc != 2) { + SCPrintf(con, eError, "%s has 1 argument", argv[0]); + return 0; + } + + command = FindCommand(sics, argv[1]); + if (!command) { + SCPrintf(con, eError, "ERROR: %s not found", argv[1]); + return 0; + } + className = ((pDummy)command->pData)->pDescriptor->name; + cmdin = (CmdInitializer)GetInitializer("Object", className); + if (cmdin) { + /* if we have an initializer, we are allowed to remove */ + if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) { + SCPrintf(con, eError, "ERROR: cannot remove %s while running", argv[1]); + return 0; + } + SCPrintf(con, eValue, "remove %s", argv[1]); + SCparChange(con); + return RemoveCommand(sics, argv[1]); + } else { + SCPrintf(con, eError, "ERROR: %s is not removable", argv[1]); + return 0; + } +} + +static void KillInitializers(void *data) { + KillDummy(data); + Item *item, *next; + + item = list; + while (item) { + next = item->next; + free(item); + item = next; + } + list = NULL; +} + +void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly) { + if (! FindCommand(pServ->pSics, "MakeObject")) { + AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0); + AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0); + } + MakeInitializer("Object", driver, (Initializer)maker, startupOnly); +} diff --git a/initializer.h b/initializer.h new file mode 100644 index 00000000..d156e589 --- /dev/null +++ b/initializer.h @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------- +initializer.h + +initializer list routines + +Markus Zolliker, March 2005 +---------------------------------------------------------------------------- +*/ + +#ifndef SICSINIT_H +#define SICSINIT_H + +typedef void (*Initializer)(void); + +void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly); + +Initializer GetInitializer(const char *type, const char *name); + +/* + MakeObject has the following syntax: + + MakeObject objectName driver [ args ... ] + +*/ +typedef int (*CmdInitializer) (SConnection *pCon, int argc, char *argv[], int dynamic); +/* + make a driver with the initializer function maker + when the dynamic argument is not 0, the command was created after startup, + i.e. the SaveStatus routine has also to write command creation code. +*/ +void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly); + +#endif diff --git a/make_gen b/make_gen index 8ae8a77e..2d4d0943 100644 --- a/make_gen +++ b/make_gen @@ -29,7 +29,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\ hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \ - mcstashm.o + mcstashm.o initializer.o remob.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/remob.c b/remob.c new file mode 100644 index 00000000..a2628c4d --- /dev/null +++ b/remob.c @@ -0,0 +1,854 @@ +/*----------------------------------------------------------------------- +remob.c + +implements remote driveable objects living on an other sics server + +M. Zolliker July 04 + +------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "fortify.h" +#include "sics.h" +#include "devexec.h" +#include "remob.h" +#include "splitter.h" +#include "status.h" +#include "servlog.h" +#include "site.h" +/*-------------------------------------------------------------------------*/ +#define INTERRUPTMODE 0 +#define ACCESSCODE 1 + +/*------------------------------------------------------------------------ */ +typedef struct Remob Remob; + +typedef struct RemServer { + pObjectDescriptor desc; + char *name; + char *host; + int port; + int actChan; /* 0 or 1 */ + mkChannel *chans[2]; /* 0: Spy, 1: User */ + int incomplete; + char line[256]; + Remob *objList; + int matchMap; + int timeout; + int taskActive; + SCStore 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(RemServer *remserver, char *line) { + int iret; + mkChannel *chan; + + chan = remserver->chans[remserver->actChan]; + if (chan) { + /* printf("> %s\n", line); */ + iret = NETWrite(chan, line, strlen(line)); + if (iret == 0) iret = -1; + return iret; + } else { + return -1; + } +} +/*-------------------------------------------------------------------------*/ +static int RemRead(RemServer *remserver, long tmo) { + int iRet; + mkChannel *chan; + + chan = remserver->chans[remserver->actChan]; + if (chan == NULL) return 0; /* no data */ + iRet = NETReadTillTermNew(chan, tmo, "\n", + remserver->line+remserver->incomplete, sizeof(remserver->line)-remserver->incomplete); + if (iRet == 0) { + remserver->incomplete = strlen(remserver->line); /* number of chars already received */ + return 0; /* timeout */ + } else { + remserver->incomplete=0; + } + return iRet; +} +/*-------------------------------------------------------------------------*/ +static int RemHandle(RemServer *remserver) { + char *line, *par, *str; + Remob *remob; + + /* skip whitespace at the beginning */ + line=remserver->line; + while (*line < ' ' && *line != '\0') { + line++; + } + memmove(remserver->line, line, strlen(line)); + + /* handle drivstat messages */ + line = remserver->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(RemServer *remserver, SConnection *pCon) { + if (pCon != NULL && remserver->line[0] != '\0') { + SCPrintf(pCon, eStatus, " %s", remserver->line); + } +} +/*-------------------------------------------------------------------------*/ +static void RemDisconnect(RemServer *remserver) { + int i; + + for (i=0; i<2; i++) { + if (remserver->chans[i] != NULL) { + NETClosePort(remserver->chans[i]); + free(remserver->chans[i]); + remserver->chans[i]=NULL; + /* printf("disconnected\n"); */ + } + } +} +/*-------------------------------------------------------------------------*/ +static void RemConnect(RemServer *remserver) { + int iRet; + char buf[256]; + mkChannel *chan; + + chan = remserver->chans[remserver->actChan]; + if (!chan) { + remserver->timeout = 0; + chan = NETConnect(remserver->host, remserver->port); + if (!chan) { + return; + } + remserver->chans[remserver->actChan] = chan; + if (remserver->actChan == 0) { + iRet = RemWrite(remserver, "Spy 007\ntransact listexe interest\n"); + } else { + iRet = RemWrite(remserver, "remuser sesam\ntransact listexe interest\n"); + } + if (iRet < 0) goto close; + iRet = RemRead(remserver, 1000); + while (iRet > 0) { /* eat login response */ + if (StartsWith(remserver->line, "TRANSACTIONFINISHED")) { + /* printf("connected\n"); */ + return; + } + iRet = RemRead(remserver, 1000); + } + goto close; + } + return; +close: + RemDisconnect(remserver); + return; +} +/*-------------------------------------------------------------------------*/ +static int RemServerTask(void *data) { + RemServer *remserver=data; + int iRet; + SConnection *pCon; + + if (!remserver->taskActive) return 0; /* remove task */ + if (RemRead(remserver, 0) <= 0) return 1; /* continue */ + + /* printf("< %s\n", buf); */ + + if (RemHandle(remserver)) { /* handle drivstat messages */ + return 1; + } + + /* forward oll other messages */ + pCon = SCLoad(&remserver->conn); + if (pCon) { + RemCopy(remserver, pCon); + } + return 1; +} +/*-------------------------------------------------------------------------*/ +static int RemTransact(RemServer *remserver, SConnection *pCon, char *cmd, ...) { + /* the variable arguments are for filtering: + + "" write untreated lines to pCon + */ + char buf[256]; + int iRet; + int i, typ; + char *arg, *val, *endp; + float *f; + va_list ap; + int try; + int argMask; + + try=2; + if (remserver->timeout) { /* eat old responses */ + while (RemRead(remserver, 0) > 0) { + RemHandle(remserver); + } + } +tryagain: + strcpy(buf, "transact "); + strcat(buf, cmd); + strcat(buf,"\n"); + RemConnect(remserver); + iRet = RemWrite(remserver, buf); + if (iRet < 0) goto close; + + iRet = RemRead(remserver, 2000); + if (iRet <= 0) goto close; + while (!StartsWith(remserver->line, "TRANSACTIONFINISHED")) { + RemHandle(remserver); + va_start(ap, cmd); + arg = va_arg(ap, char *); + argMask=1; + remserver->matchMap = 0; + while (arg != NULL) { + if (*arg == '>') { + RemCopy(remserver, pCon); + } else if (*arg == '<') { + f = va_arg(ap, float *); + val = StartsWith(remserver->line, arg+1); + if (val != NULL) { + val = StartsWith(val, "="); + if (val != NULL) { + *f = strtod(val, &endp); + break; + } + } + } else if (*arg == '!') { + if (StartsWith(remserver->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(remserver, 2000); + if (iRet <= 0) goto close; + } + return 1; +close: + if (iRet == 0) { + snprintf(buf, sizeof(buf), "ERROR: timeout on %s", remserver->name); + SCWrite(pCon,buf,eError); + remserver->timeout = 1; + return iRet; + } + RemDisconnect(remserver); + try--; + if (try>0) goto tryagain; + snprintf(buf, sizeof(buf), "ERROR: no connection to %s", remserver->name); + SCWrite(pCon,buf,eError); + 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; + char buf[64]; + + assert(remob); + remserver = remob->server; + RemConnect(remserver); + snprintf(buf, sizeof(buf), "stopexe %s\n", remob->name); + return RemWrite(remserver, buf); +} + +/*--------------------------------------------------------------------------*/ +static int RemobLimits(void *self, float fVal, char *error, int iErrLen) { + float fHard; + Remob *remob=self; + + assert(remob); + /* check is done one remote server */ + return 1; +} +/*---------------------------------------------------------------------------*/ +static float RemobGetValue(void *pData, SConnection *pCon) { + Remob *remob=pData; + char buf[80]; + float none, value; + int iRet; + + assert(remob); + + SCSave(&remob->server->conn, pCon); + none = -1.25e6; + value= none; + snprintf(buf, sizeof(buf), "<%s", remob->name); + iRet = RemTransact(remob->server, 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) { + fprintf(fil, "catch { remob new %s %s }\n", remob->name, remserver->name); + } + return 1; +} +/*------------------------------------------------------------------------*/ +static int RemobStatus(void *pData, SConnection *pCon) { + Remob *remob=pData; + + assert(remob); + + SCSave(&remob->server->conn, 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; + + remserver = remob->server; + SCSave(&remserver->conn, pCon); + assert(remob); + assert(pCon); + + remob->status = HWIdle; + snprintf(buf, sizeof(buf), "run %s %f", remob->name, fNew); + iRet = RemTransact(remserver, 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, pCon, sBuf, ">", NULL); + if (iRet <= 0) return 0; + while (remob->status == HWBusy) { + iRet = RemRead(remserver, 1000); + if (iRet <= 0) break; + RemCopy(remserver, pCon); + } + iRet = RemTransact(remserver, pCon, buf, ">", NULL); + if (iRet <= 0) return 0; + } + if (remob->status != HWBusy) { + return 0; + } + return OKOK; +} +/*-----------------------------------------------------------------------*/ +static void KillInfo(void *pData) { + RemobInfo *self = pData; + + assert(self); + if (self->pName) { + free(self->pName); + } + 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 = %f ", pInfo->pName, psCall->fVal); + SCWrite(pInfo->pCon,buf,eValue); + return 1; +} +/*---------------------------------------------------------------------------*/ +int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) { + Remob *remob = pData; + char buf[512]; + TokenList *pList = NULL; + TokenList *pCurrent; + TokenList *pName; + int iRet; + int i; + int pos; + float fValue; + long lID; + char *endp; + char acce[128], inte[128]; + + assert(pCon); + assert(pSics); + assert(remob); + + if (SCGetRights(pCon) > usUser) { + remob->server->actChan = 0; + } else { + remob->server->actChan = 1; + } + SCSave(&remob->server->conn, pCon); + if (argc == 1) { + iRet = RemTransact(remob->server, pCon, argv[0], ">", NULL); + } else if (strcasecmp(argv[1],"list") == 0) { + snprintf(buf, sizeof(buf), "%s ", remob->name); + i = strlen(buf); + Arg2Text(argc-1, argv+1, buf + i, sizeof buf - i); + /* + snprintf(acce, sizeof(acce), "!%s.accesscode", remob->name); + snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name); + */ + + RemTransact(remob->server, pCon, buf, ">", NULL); + + iRet=1; + } else { + pos=snprintf(buf, sizeof(buf), "%s ", remob->name); + for (i=1; iserver, 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; + char buf[512]; + TokenList *pList = NULL; + TokenList *pCurrent; + TokenList *pName; + int iRet; + int i; + int pos; + float fValue; + long lID; + char *endp, *serverport, *thishostname; + char acce[128], inte[128]; + struct sockaddr_in adr; + struct hostent *thishost; + mkChannel *chan; + Remob *p, *next; + + assert(pCon); + assert(pSics); + assert(remserver); + + if (SCGetRights(pCon) > usUser) { + remserver->actChan = 0; + } else { + remserver->actChan = 1; + } + chan = remserver->chans[remserver->actChan]; + if (argc == 1) { + serverport = IFindOption(pSICSOptions,"ServerPort"); + i = sizeof adr; + thishostname = NULL; + if (chan) { + if (getsockname(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, eStatus, "%s = %s:%d %s:%s", + argv[0], remserver->host, remserver->port, thishostname, serverport); + } else if (argc>2 && strcasecmp(argv[1],"nowait") == 0) { + RemConnect(remserver); + for (i=2; i2) { + RemWrite(remserver, " "); + } + RemWrite(remserver, argv[i]); + } + RemWrite(remserver, "\n"); + } 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 { + pos=0; + for (i=1; i", NULL); + 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); + free(remserver); +} +/*-----------------------------------------------------------------------*/ +static int RemobSetDriveable(Remob *remob, int driveable) { + 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; + } 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; + + 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; + remserver->incomplete = 0; + remserver->objList = NULL; + remserver->chans[0] = NULL; + remserver->chans[1] = NULL; + if (!remserver->name || + !remserver->host || + !remserver->port) { + /* no success, clean up */ + RemServerKill(remserver); + return NULL; + } + remserver->taskActive = 1; + TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill, remserver, 1); + 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; + + assert(pCon); + assert(pSics); + + argtolower(argc,argv); + if (argc >= 4 && strcmp(argv[1], "server") == 0) { + if (argc == 5) { + remserver = RemServerInit(argv[2], argv[3], atoi(argv[4])); + } else { + p = strchr(argv[3], ':'); + if (!p) { + SCPrintf(pCon, eError, "ERROR: illegal host:port"); + return 0; + } + snprintf(host, sizeof host, "%.*s", p-argv[3], argv[3]); + remserver = RemServerInit(argv[2], host, atoi(p+1)); + } + 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; +} + + + diff --git a/remob.h b/remob.h new file mode 100644 index 00000000..fed42c5f --- /dev/null +++ b/remob.h @@ -0,0 +1,19 @@ +/*-------------------------------------------------------------------------- +remote driveable objects + +Markus Zolliker July 04 + +copyright: see implementation file + +----------------------------------------------------------------------------*/ +#ifndef SICSREM +#define SICSREM +#include "Scommon.h" + +/*-------------------------------------------------------------------------*/ + +int RemobCreate(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif +