#include #include #include #include #include #include #include #include "errhdl.h" #include "str_util.h" #include "coc.h" /*-------------------------------------------------------------------------*/ /* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */ CocVar *serverVarList=NULL; static CocVar **varListHdl=&serverVarList; int CocRD=0; int CocWR=0; int CocCreateSockAdr( struct sockaddr_in *sockaddrPtr, /* Socket address */ const char *host, /* Host. NULL implies INADDR_ANY */ int port) /* Port number */ { struct hostent *hostent; /* Host database entry */ struct in_addr addr; /* For 64/32 bit madness */ (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); sockaddrPtr->sin_family = AF_INET; sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); if (host == NULL || host[0]=='\0') { addr.s_addr = INADDR_ANY; } else { hostent = gethostbyname(host); if (hostent != NULL) { memcpy((char *) &addr, (char *) hostent->h_addr_list[0], (size_t) hostent->h_length); } else { addr.s_addr = inet_addr(host); if (addr.s_addr == (unsigned long)-1) { return -1; /* error */ } } } /* * There is a rumor that this assignment may require care on * some 64 bit machines. */ sockaddrPtr->sin_addr.s_addr = addr.s_addr; return 0; } /*-------------------------------------------------------------------------*/ int CocRecv(int fd, Str_Buf *buf) { struct timeval tmo={0,1}; fd_set mask; int i, ret; tmo.tv_sec=5; /* timeout 5 sec. */ FD_ZERO(&mask); FD_SET(fd, &mask); ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo)); if (i==0) ERR_MSG("time out"); ERR_SI(buf->wrpos=recv(fd, buf->buf, buf->dsize, 0)); if (buf->wrpos==0) { ERR_COD(ECONNRESET); } str_get_start(buf); return(ret); OnError: return(-1); } void CocVarList(CocVar **varList) { assert(varList!=NULL); varListHdl=varList; } void CocList() { CocVar *p; p=*varListHdl; while (p!=NULL) { printf("%s %d\n", p->name, p->type); p=p->next; } } CocVar *CocFindVar1(CocVar *varList, const char *name) { CocVar *p; p=varList; while (p!=NULL && 0!=strcmp(p->name,name)) p=p->next; return(p); } CocVar *CocFindVar(CocVar *varList, const char *name, void **adr) { CocVar *p, *t; const char *f; void *base; char nam[32]; f=str_split(nam, name, '.'); if (f==NULL) { f=str_split(nam, name, '-'); if (f!=NULL) { if (f[0]!='>') { f=NULL; } else { f++; } } } if (f!=NULL) { if (adr!=NULL) *adr=NULL; p=CocFindVar1(varList, nam); if (p==NULL) { return(NULL); } t=p->strucType; if (t==NULL) { return(NULL); } str_copy(nam, t->name); str_append(nam, ":"); str_append(nam, f); if (adr!=NULL) { base=p->var; if (p->type==COC_PTR) base=*(void **)base; *adr=base; } } else if (adr!=NULL) { *adr=NULL; } p=CocFindVar1(varList, nam); if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */ p=CocFindVar(varList, p->var, adr); } return(p); } CocVar *CocDefVar(const char *name, void *var, int type, int *flag) { CocVar *p; const char *f; void *adr; assert(varListHdl!=NULL); p=CocFindVar1(*varListHdl, name); if (p==NULL) { p=malloc(sizeof(*p)); p->next=*varListHdl; *varListHdl=p; str_copy(p->name, name); } p->var=var; p->type=type; p->flag=flag; return(p); } void CocDefVarS(const char *name, const char *tname, void *var, int type) { CocVar *p, *t; assert(type==COC_PTR || type==COC_STRUCT); p=CocDefVar(name, var, type, &CocRD); p->strucType=CocDefVar(tname, NULL, COC_TYPE, &CocRD); } int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { CocVar *var; void *adr; var=CocFindVar(varList, name, &adr); if (var==NULL) ERR_MSG("undefined variable"); if (adr==NULL) { adr=var->var; } else { adr=(char *)adr + (int)var->var; } if (secure) { /* we are the server */ if (var->flag==&CocRD) ERR_MSG("variable is read only"); } if (var->type==-1) { ERR_I(str_get_int(buf, (int *)adr)); } else if (var->type==-2) { ERR_I(str_get_float(buf, (float *)adr)); } else if (var->type>1) { ERR_P(str_nget_str(buf, (char *)adr, var->type)); } else { ERR_MSG("unknown type"); } if (secure) { /* we are the server */ (*var->flag)++; } return(0); OnError: return(-1); } int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { CocVar *var; void *adr; char *c; var=CocFindVar(varList, name, &adr); if (var==NULL) ERR_MSG("undefined variable"); if (adr==NULL) { adr=var->var; } else { adr=(char *)adr + (int)var->var; } if (secure) { /* we are the client */ if (var->flag==&CocRD) ERR_MSG("variable is read only"); } if (var->type==-1) { ERR_I(str_put_int(buf, *(int *)adr)); } else if (var->type==-2) { ERR_I(str_put_float(buf, *(float *)adr)); } else if (var->type>1) { ERR_I(str_put_str(buf, adr)); } else { ERR_MSG("unknown type"); } if (secure) { /* we are a client */ if (var->flag!=NULL) (*var->flag)++; } return(0); OnError: return(-1); } void CocFreeVarList(CocVar **varList) { CocVar *p, *v; if (varList==NULL) varList=&serverVarList; v=*varList; while (v!=NULL) { p=v; v=p->next; p->next=NULL; free(p); } *varList=NULL; } void CocDelay(int msec) { struct timeval tmo; tmo.tv_sec=msec / 1000; tmo.tv_usec=(msec % 1000)*1000+1; select(1,NULL,NULL,NULL,&tmo); }