diff --git a/remob.c b/remob.c index 9fdc3b7..29f28a4 100644 --- a/remob.c +++ b/remob.c @@ -10,7 +10,7 @@ M. Zolliker July 04 #include #include #include -#include +#include #include "fortify.h" #include "sics.h" #include "devexec.h" @@ -31,9 +31,8 @@ typedef struct RemServer { char *name; char *host; int port; - char *user; - char *pass; - mkChannel *chan; + int actChan; /* 0 or 1 */ + mkChannel *chans[2]; /* 0: Spy, 1: User */ int incomplete; char line[256]; Remob *objList; @@ -46,12 +45,13 @@ typedef struct RemServer { struct Remob { pObjectDescriptor desc; char *name; - ObPar *ParArray; pIDrivable pDrivInt; pICallBack pCall; RemServer *server; int status; Remob *next; + int access; + int markForDel; }; typedef struct { @@ -81,10 +81,16 @@ static char *StartsWith(char *line, char *name) { return str; } /*-------------------------------------------------------------------------*/ -static int RemWrite(RemServer *remserver, char *line) { - if (remserver->chan) { +static int RemWrite(RemServer *remserver, char *line) { + int iret; + mkChannel *chan; + + chan = remserver->chans[remserver->actChan]; + if (chan) { /* printf("> %s\n", line); */ - return NETWrite(remserver->chan, line, strlen(line)); + iret = NETWrite(chan, line, strlen(line)); + if (iret == 0) iret = -1; + return iret; } else { return -1; } @@ -92,9 +98,11 @@ static int RemWrite(RemServer *remserver, char *line) { /*-------------------------------------------------------------------------*/ static int RemRead(RemServer *remserver, long tmo) { int iRet; + mkChannel *chan; - if (remserver->chan == NULL) return 0; /* no data */ - iRet = NETReadTillTermNew(remserver->chan, tmo, "\n", + 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 */ @@ -141,14 +149,59 @@ static int RemHandle(RemServer *remserver) { } /*-------------------------------------------------------------------------*/ static void RemCopy(RemServer *remserver, SConnection *pCon) { - char buf[256]; if (pCon != NULL && remserver->line[0] != '\0') { - snprintf(buf, sizeof(buf), " %s", remserver->line); - /* snprintf(buf, sizeof(buf), "%s (%s)", remserver->line, remserver->name); */ - SCWrite(pCon, buf, eStatus); + 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; @@ -171,49 +224,10 @@ static int RemServerTask(void *data) { return 1; } /*-------------------------------------------------------------------------*/ -static void RemDisconnect(RemServer *remserver) { - if (remserver->chan != NULL) { - NETClosePort(remserver->chan); - free(remserver->chan); - remserver->chan=NULL; - /* printf("disconnected\n"); */ - } -} -/*-------------------------------------------------------------------------*/ -static void RemConnect(RemServer *remserver) { - int iRet; - char buf[256]; - - if (!remserver->chan) { - remserver->timeout = 0; - remserver->chan = NETConnect(remserver->host, remserver->port); - if (!remserver->chan) { - return; - } - snprintf(buf, sizeof(buf), "%s %s\ntransact listexe interest\n" - , remserver->user, remserver->pass); - iRet = RemWrite(remserver, buf); - 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 RemTransact(RemServer *remserver, SConnection *pCon, char *cmd, ...) { /* the variable arguments are for filtering: - "" write untreated lines to pCon */ @@ -285,11 +299,11 @@ close: remserver->timeout = 1; return iRet; } - snprintf(buf, sizeof(buf), "ERROR: no connection to %s", remserver->name); - SCWrite(pCon,buf,eError); 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; } /*-------------------------------------------------------------------------*/ @@ -351,12 +365,11 @@ static float RemobGetValue(void *pData, SConnection *pCon) { return 0.0; } /*------------------------------------------------------------------------*/ -static int RemobSaveStatus(void *pData, char *name, FILE *fd) { +static int RemobSaveStatus(void *pData, char *name, FILE *fil) { Remob *self = pData; - char buf[512]; assert(self); - assert(fd); + assert(fil); /* data is stored on remote server @@ -364,6 +377,19 @@ static int RemobSaveStatus(void *pData, char *name, FILE *fd) { 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; @@ -389,11 +415,9 @@ static long RemobRun(void *self, SConnection *pCon, float fNew) { assert(remob); assert(pCon); - /* check if I'am allowed to move this motor */ - if (!SCMatchRights(pCon,(int)ObVal(remob->ParArray,ACCESSCODE))) { - snprintf(buf,sizeof(buf), "ERROR: You are not authorised to run %s", - remob->name); - SCWrite(pCon,buf,eError); + /* check if I'am allowed to drive this object */ + if (remob->access < SCGetRights(pCon)) { + SCPrintf(pCon, eError, "ERROR: You are not authorised to run %s", remob->name); SCSetInterrupt(pCon,eAbortBatch); return 0; } @@ -458,91 +482,40 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, float fValue; long lID; char *endp; - ObPar *par; char acce[128], inte[128]; assert(pCon); assert(pSics); assert(remob); - argtolower(argc,argv); - + 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 (strcmp(argv[1],"list") == 0) { - snprintf(buf, sizeof(buf), "%s list", remob->name); + } 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, acce, inte, ">", NULL); + RemTransact(remob->server, pCon, buf, ">", NULL); - snprintf(buf, sizeof(buf), "%s = %.0f", acce+1, ObVal(remob->ParArray,ACCESSCODE)); - SCWrite(pCon, buf, eStatus); - snprintf(buf, sizeof(buf), "%s = %.0f", inte+1, ObVal(remob->ParArray,INTERRUPTMODE)); - SCWrite(pCon, buf, eStatus); iRet=1; } else { - par=ObParFind(remob->ParArray, argv[1]); - if (par != NULL) { - if (argc == 3) { - fValue = strtod(argv[2], &endp); - if (endp == argv[2]) { - snprintf(buf, sizeof(buf), "number expected instead of %s", argv[2]); - SCWrite(pCon, buf, eError); - return 0; - } - iRet = ObParSet(remob->ParArray,argv[0],argv[1],fValue,pCon); - } - if (iRet) { - snprintf(buf, sizeof(buf), "%s.%s = %.0f", argv[0], argv[1], par->fVal); - SCWrite(pCon, buf, eStatus); - } - } else { - pos=snprintf(buf, sizeof(buf), "%s ", remob->name); - for (i=1; iserver, pCon, buf, ">", NULL); - } - } - return iRet; -} -/*---------------------------------------------------------------------------*/ -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; - ObPar *par; - char acce[128], inte[128]; - - assert(pCon); - assert(pSics); - assert(remserver); - - argtolower(argc,argv); - - if (argc == 1) { - snprintf(buf, sizeof(buf), "%s = %s:%d", argv[0], remserver->host, remserver->port); - SCWrite(pCon, buf, eStatus); - } else { - pos=0; + pos=snprintf(buf, sizeof(buf), "%s ", remob->name); for (i=1; i", NULL); - return iRet; + iRet = RemTransact(remob->server, pCon, buf, ">", NULL); } - return 1; + return iRet; } /*--------------------------------------------------------------------------*/ static void RemobKill(void *self) { @@ -574,19 +547,100 @@ static void RemobKill(void *self) { DeleteCallBackInterface(remob->pCall); } - /* get rid of parameter space */ - if (remob->ParArray) { - ObParDelete(remob->ParArray); - } - /* kill Descriptor */ - DeleteDescriptor(remob->desc); - + 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); @@ -595,72 +649,60 @@ static void RemServerKill(void *self) { /* let the tasker kill me */ return; } - remserver = (RemServer *)self; - if (remserver->chan) { - RemDisconnect(remserver); + 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->user) free(remserver->user); - if (remserver->pass) free(remserver->pass); 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 *)malloc(sizeof(Remob)); + remob = (Remob *)calloc(1,sizeof(Remob)); if(!remob) { return NULL; } - /* create and initialize parameters */ - remob->ParArray = ObParCreate(2); - if (!remob->ParArray) { - free(remob); - return NULL; - } - ObParInit(remob->ParArray,INTERRUPTMODE,"interruptmode",0.0,usUser); - ObParInit(remob->ParArray,ACCESSCODE,"accesscode",(float)usUser,usMugger); - /* copy arguments */ remob->server = remserver; remob->name = strdup(name); /* initialise object descriptor */ - remob->desc = CreateDescriptor("Remob"); - if (!remob->desc) { - ObParDelete(remob->ParArray); - free(remob); - return NULL; - } + remob->desc = CreateDescriptor("RemObject"); + if (!remob->desc) goto killit; remob->desc->GetInterface = RemobGetInterface; remob->desc->SaveStatus = RemobSaveStatus; - /* initialise Drivable interface */ - remob->pDrivInt = CreateDrivableInterface(); - if (!remob->pDrivInt) { - DeleteDescriptor(remob->desc); - ObParDelete(remob->ParArray); - free(remob); - return NULL; - } - remob->pDrivInt->SetValue = RemobRun; - remob->pDrivInt->CheckLimits = RemobLimits; - remob->pDrivInt->CheckStatus = RemobStatus; - remob->pDrivInt->GetValue = RemobGetValue; - remob->pDrivInt->Halt = RemobHalt; - /* initialise callback interface */ remob->pCall = CreateCallBackInterface(); - if(!remob->pCall) { - RemobKill(remob); - return NULL; - } + if(!remob->pCall) goto killit; /* check if not yet in object list */ for (p = remserver->objList; p != NULL; p=p->next) { @@ -671,20 +713,20 @@ static Remob *RemobInit(char *name, RemServer *remserver) { remserver->objList = remob; } - if (!remserver->taskActive) { - remserver->taskActive = 1; - TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill, remserver, 1); - } + remob->markForDel = 0; /* done */ return remob; +killit: + RemobKill(remob); + return NULL; } /*-----------------------------------------------------------------------*/ -static RemServer *RemServerInit(char *name, char *host, int port, char *user, char *pass) { +static RemServer *RemServerInit(char *name, char *host, int port) { RemServer *remserver = NULL; assert(name); - remserver = malloc(sizeof(RemServer)); + remserver = calloc(1, sizeof(RemServer)); if (!remserver) { return 0; } @@ -695,90 +737,124 @@ static RemServer *RemServerInit(char *name, char *host, int port, char *user, ch free(remserver); return NULL; } - remserver->taskActive = 0; + remserver->desc->SaveStatus = RemServerSaveStatus; remserver->name = strdup(name); remserver->host = strdup(host); remserver->port = port; - remserver->user = strdup(user); - remserver->pass = strdup(pass); remserver->incomplete = 0; - + remserver->objList = NULL; + remserver->chans[0] = NULL; + remserver->chans[1] = NULL; if (!remserver->name || !remserver->host || - !remserver->port || - !remserver->pass) { + !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 user pass - Remob new remobName serverName - Remob del remobName (not yet implemented) - Remob del serverName (not yet implemented) + 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 buf[512]; + char host[128]; + char *p; int iD, iRet; - Tcl_Interp *pTcl = (Tcl_Interp *)pSics->pTcl; - + char *obj; + assert(pCon); assert(pSics); - if (argc <= 5) { - argtolower(argc,argv); - } else { - argtolower(5,argv); - } - if (argc == 7 && strcmp(argv[1], "server") == 0) { - remserver = RemServerInit(argv[2], argv[3], atoi(argv[4]), argv[5], argv[6]); + 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) { - snprintf(buf, sizeof(buf), "Failure to create remote server connection %s", argv[2]); - SCWrite(pCon, buf, eError); + 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) { - snprintf(buf, sizeof(buf),"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,buf,eError); + SCPrintf(pCon, eError, "ERROR: duplicate command %s not created",argv[2]); + RemServerKill(remserver); return 0; } return 1; - } else if (argc == 4 && strcmp(argv[1], "new") == 0) { + } else if (argc == 4 && (strcmp(argv[1], "obj") == 0 || strcmp(argv[1], "drv") == 0)) { remserver = FindCommandData(pServ->pSics, argv[3], "RemServer"); if (!remserver) { - snprintf(buf, sizeof(buf), "remote server %s not found", argv[3]); - SCWrite(pCon, buf, eError); + 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) { - snprintf(buf, sizeof(buf), "Failure to create remote driveable object %s", argv[1]); - SCWrite(pCon, buf, eError); + 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) { - snprintf(buf, sizeof(buf),"ERROR: duplicate command %s not created",argv[1]); - SCWrite(pCon,buf,eError); + 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; } - snprintf(buf, sizeof(buf),"ERROR: illegal arguments for command remob"); - SCWrite(pCon,buf,eError); + SCPrintf(pCon, eError, "ERROR: illegal arguments for command remob"); return 0; }