*** empty log message ***
This commit is contained in:
32
tecs/Makefile
Normal file
32
tecs/Makefile
Normal file
@ -0,0 +1,32 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile for the TECS Client library
|
||||
#
|
||||
# Markus Zolliker, March 2000
|
||||
#--------------------------------------------------------------------------
|
||||
OBJ= tecc.o client.o coc.o buf.o errhdl.o util.o
|
||||
|
||||
#---------- for Redhat linux
|
||||
#cc= GCC
|
||||
#cflags= -i/USR/LOCAL/INCLUDE -i. -i../ -dlinux -G -C
|
||||
|
||||
#------------ for DigitalUnix
|
||||
CC=cc
|
||||
CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c
|
||||
#------------ for DigitalUnix with Fortify
|
||||
#CFLAGS= -I/data/koenneck/include -DFORTIFY -I. -I../ -std1 -g -c
|
||||
|
||||
#------------ for CYGNUS toolchain on Win32
|
||||
#CC=gcc
|
||||
#CFLAGS= -I. -I../ -DCYGNUS -g -c
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
||||
tecsl: $(OBJ)
|
||||
- rm libtecsl.a
|
||||
ar cr libtecsl.a $(OBJ)
|
||||
ranlib libtecsl.a
|
||||
|
||||
clean:
|
||||
rm *.o
|
||||
rm *.a
|
162
tecs/buf.c
Normal file
162
tecs/buf.c
Normal file
@ -0,0 +1,162 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include "buf.h"
|
||||
|
||||
#define TWO28 268435456.0
|
||||
#define MAXINT 2147483647
|
||||
|
||||
/* static char *null="\0"; */
|
||||
|
||||
int buf_get_int(buf_type *buf)
|
||||
{ char *b;
|
||||
int *res;
|
||||
|
||||
b=buf->buf;
|
||||
if (b==NULL) return(0);
|
||||
if (b[0]!=1 || buf->size<5) {buf->buf=NULL; return(0); }
|
||||
b++;
|
||||
res=(int *)b;
|
||||
b+=4;
|
||||
buf->size-=5;
|
||||
buf->buf=b;
|
||||
return(*res);
|
||||
}
|
||||
|
||||
char *buf_get_str(buf_type *buf)
|
||||
{ char *b;
|
||||
int l;
|
||||
|
||||
b=buf->buf;
|
||||
if (b==NULL) return("");
|
||||
if (b[0]==1 || b[0]==2) return("");
|
||||
l=strlen(b);
|
||||
if (buf->size<=l) {buf->buf=NULL; return(""); }
|
||||
buf->buf+=l+1;
|
||||
buf->size-=l+1;
|
||||
return(b);
|
||||
}
|
||||
|
||||
float buf_get_float(buf_type *buf)
|
||||
{ char *b;
|
||||
float res;
|
||||
int *mant, iexp;
|
||||
|
||||
b=buf->buf;
|
||||
if (b==NULL) return(0.0);
|
||||
if (b[0]!=2 || buf->size<6) { buf->buf=NULL; return(0.0); }
|
||||
iexp=b[1];
|
||||
b+=2;
|
||||
mant=(int *)b;
|
||||
b+=4;
|
||||
buf->size-=6;
|
||||
res=(float)ldexp(*mant/TWO28, iexp);
|
||||
buf->buf=b;
|
||||
return res;
|
||||
}
|
||||
|
||||
int buf_size(buf_type *buf)
|
||||
{
|
||||
if (buf->buf==NULL) return(-1);
|
||||
return (buf->size);
|
||||
}
|
||||
|
||||
void buf_put_int(buf_type *buf, int val)
|
||||
{ char *b;
|
||||
|
||||
b=buf->buf;
|
||||
if (b==NULL) return;
|
||||
b[0]=1;
|
||||
b++;
|
||||
if (buf->size<=4) {buf->buf=NULL; return; }
|
||||
*(int *)b=val;
|
||||
b+=4;
|
||||
buf->size-=5;
|
||||
buf->buf=b;
|
||||
return;
|
||||
}
|
||||
|
||||
void buf_put_str(buf_type *buf, char *str)
|
||||
{ char *b;
|
||||
int l;
|
||||
|
||||
if (str[0]<=2 && str[0]!='\0') { buf->buf=NULL; return; };
|
||||
b=buf->buf;
|
||||
if (b==NULL) return;
|
||||
l=strlen(str);
|
||||
if (buf->size<=l) { buf->buf=NULL; return; }
|
||||
strcpy(b, str);
|
||||
buf->buf+=l+1;
|
||||
buf->size-=l+1;
|
||||
}
|
||||
|
||||
int buf_nint(float val)
|
||||
{ int res;
|
||||
|
||||
if (val<0) {
|
||||
if (val<-MAXINT) {
|
||||
return(-MAXINT);
|
||||
} else {
|
||||
return(val-0.5);
|
||||
}
|
||||
} else {
|
||||
if (val>MAXINT) {
|
||||
return(MAXINT);
|
||||
} else {
|
||||
return(val+0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void buf_put_float(buf_type *buf, float val)
|
||||
{ char *b;
|
||||
double d;
|
||||
int iexp;
|
||||
int mant;
|
||||
|
||||
b=buf->buf;
|
||||
if (b==NULL) return;
|
||||
if (buf->size<=4) {buf->buf=NULL; return; }
|
||||
d=frexp((double)val, &iexp);
|
||||
mant=buf_nint(d*TWO28);
|
||||
if (iexp>127) iexp=127;
|
||||
if (iexp<-128) iexp=-128;
|
||||
b[0]=2;
|
||||
b[1]=iexp;
|
||||
b+=2;
|
||||
*(int *)b=mant;
|
||||
b+=4;
|
||||
buf->size-=6;
|
||||
buf->buf=b;
|
||||
}
|
||||
|
||||
void buf_put_end(buf_type *buf)
|
||||
{ buf->buf=buf->start;
|
||||
buf->usize=buf->isize-buf->size;
|
||||
buf->size=buf->usize;
|
||||
}
|
||||
|
||||
void buf_put_start(buf_type *buf)
|
||||
{ buf->buf=buf->start;
|
||||
buf->size=buf->isize;
|
||||
}
|
||||
|
||||
void buf_reset(buf_type *buf)
|
||||
{ buf->buf=buf->start;
|
||||
buf->size=buf->usize;
|
||||
}
|
||||
|
||||
buf_type *buf_create(size_t size)
|
||||
{ buf_type *buf;
|
||||
|
||||
buf=malloc(sizeof(*buf));
|
||||
buf->start=malloc(size);
|
||||
buf->isize=size;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
void buf_free(buf_type *buf)
|
||||
{ free(buf->buf);
|
||||
free(buf);
|
||||
}
|
20
tecs/buf.h
Normal file
20
tecs/buf.h
Normal file
@ -0,0 +1,20 @@
|
||||
typedef struct { char *buf; char *start; int size; int usize; int isize, dummy; } buf_type;
|
||||
|
||||
/* input */
|
||||
void buf_reset(buf_type *buf);
|
||||
int buf_get_int(buf_type *buf);
|
||||
char *buf_get_str(buf_type *buf);
|
||||
float buf_get_float(buf_type *buf);
|
||||
int buf_size(buf_type *buf);
|
||||
|
||||
/* output */
|
||||
void buf_put_start(buf_type *buf);
|
||||
void buf_put_int(buf_type *buf, int val);
|
||||
void buf_put_str(buf_type *buf, char *str);
|
||||
void buf_put_float(buf_type *buf, float val);
|
||||
void buf_put_end(buf_type *buf);
|
||||
|
||||
/* common */
|
||||
buf_type *buf_create(size_t size);
|
||||
void buf_free(buf_type *buf);
|
||||
void buf_log(buf_type *buf);
|
180
tecs/client.c
Normal file
180
tecs/client.c
Normal file
@ -0,0 +1,180 @@
|
||||
#include <assert.h>
|
||||
#include "client.h"
|
||||
#include "util.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocOpen(CocConn *conn)
|
||||
{
|
||||
int i, cnt, try, port, tryConn, tmo;
|
||||
struct sockaddr_in sadr;
|
||||
char *p, *q;
|
||||
|
||||
try=2;
|
||||
tryConn=1;
|
||||
tmo=0;
|
||||
while (try>0) {
|
||||
try--;
|
||||
while (tryConn>0) {
|
||||
port=CocPORT;
|
||||
cnt=CocPORTS;
|
||||
tryConn--;
|
||||
while (cnt>0) {
|
||||
ERR_SI(conn->fd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
ERR_I(CocCreateSockAdr(&sadr, conn->host, port));
|
||||
i=connect(conn->fd, (struct sockaddr *)&sadr, sizeof(sadr));
|
||||
if (i>=0) return(0);
|
||||
if (errno!=ECONNREFUSED) { ERR_COD(errno); }
|
||||
port++; cnt--;
|
||||
}
|
||||
util_delay(tmo); tmo+=100;
|
||||
}
|
||||
if (conn->startcmd[0]=='\0' || try<=0) { ERR_COD(ECONNREFUSED); }
|
||||
p=conn->startcmd;
|
||||
q=strchr(p,' ');
|
||||
while (q!=NULL) {
|
||||
p=q+1;
|
||||
q=strchr(p,' ');
|
||||
};
|
||||
printf("start server %s\n", p);
|
||||
ERR_I(system(conn->startcmd));
|
||||
util_delay(100); tmo=200;
|
||||
tryConn=5;
|
||||
}
|
||||
ERR_COD(ECONNREFUSED);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
void CocInitClient(CocConn *conn, char *host, char *magic, int bufsize, char *startcmd)
|
||||
{ void *e;
|
||||
|
||||
if (bufsize==0) bufsize=1024;
|
||||
conn->cmdbuf=buf_create(bufsize);
|
||||
conn->resbuf=buf_create(bufsize);
|
||||
str_copy(conn->host, host);
|
||||
str_copy(conn->magic, magic);
|
||||
str_copy(conn->startcmd, startcmd);
|
||||
conn->fd=-1;
|
||||
conn->varList=NULL;
|
||||
CocVarList(&conn->varList);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocSendMagic(CocConn *conn, char *magic) {
|
||||
char *err;
|
||||
|
||||
if (magic[0]!='#') ERR_MSG("magic must start with '#'");
|
||||
buf_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */
|
||||
buf_put_str(conn->resbuf, magic);
|
||||
buf_put_end(conn->resbuf);
|
||||
if (conn->resbuf->buf==NULL) ERR_MSG("buffer full");
|
||||
ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->size, 0));
|
||||
ERR_I(CocRecv(conn->fd, conn->resbuf));
|
||||
err=buf_get_str(conn->resbuf);
|
||||
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; }
|
||||
if (buf_size(conn->resbuf)!=0) ERR_MSG("syntax error");
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocTryCmd(CocConn *conn)
|
||||
{ if (conn->fd<0) {
|
||||
ERR_I(CocOpen(conn));
|
||||
ERR_I(CocSendMagic(conn, conn->magic));
|
||||
}
|
||||
ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->size, 0));
|
||||
ERR_I(CocRecv(conn->fd, conn->resbuf));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocCmd(CocConn *conn, const char *rwList)
|
||||
{ int iret, cnt, setmode, i;
|
||||
char *err;
|
||||
const char *t, *s;
|
||||
char nam[32];
|
||||
CocVar *var;
|
||||
|
||||
buf_put_start(conn->cmdbuf);
|
||||
s=rwList;
|
||||
setmode=0;
|
||||
do {
|
||||
t=strchr(s, ',');
|
||||
if (t==NULL) t=s+strlen(s);
|
||||
if (*s=='[') {
|
||||
if (!setmode) buf_put_str(conn->cmdbuf, "[");
|
||||
s++;
|
||||
setmode=1;
|
||||
}
|
||||
i=t-s;
|
||||
assert(i<32);
|
||||
str_ncpy(nam, s, i+1);
|
||||
if (setmode) {
|
||||
if (nam[i-1]==']') { nam[i-1]='\0'; setmode=0; }
|
||||
buf_put_str(conn->cmdbuf, nam);
|
||||
ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam));
|
||||
if (!setmode) buf_put_str(conn->cmdbuf, "]");
|
||||
} else {
|
||||
var=CocFindVar(conn->varList, nam);
|
||||
if (var==NULL) ERR_MSG("variable not found");
|
||||
buf_put_str(conn->cmdbuf, nam);
|
||||
}
|
||||
s=t+1;
|
||||
} while (*t!='\0');
|
||||
|
||||
buf_put_end(conn->cmdbuf);
|
||||
if (conn->cmdbuf->buf==NULL) ERR_MSG("out buffer full");
|
||||
cnt=3;
|
||||
while (1) {
|
||||
cnt--;
|
||||
if (cnt<=0) {
|
||||
ERR_I(CocTryCmd(conn));
|
||||
break;
|
||||
}
|
||||
iret=CocTryCmd(conn);
|
||||
if (iret>=0) break;
|
||||
close(conn->fd);
|
||||
conn->fd=-1;
|
||||
if (ErrCode!=ECONNRESET && ErrCode!=EPIPE) goto OnError;
|
||||
ErrShow("try again, error was");
|
||||
}
|
||||
err=buf_get_str(conn->resbuf);
|
||||
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); goto OnError; }
|
||||
|
||||
/* read values */
|
||||
s=rwList;
|
||||
setmode=0;
|
||||
do {
|
||||
t=strchr(s, ',');
|
||||
if (t==NULL) t=s+strlen(s);
|
||||
if (*s=='[') {
|
||||
s++;
|
||||
setmode=1;
|
||||
}
|
||||
i=t-s;
|
||||
if (!setmode) {
|
||||
str_ncpy(nam, s, i+1);
|
||||
if (nam[i-1]==']') { nam[i-1]='\0'; setmode=0; }
|
||||
ERR_I(CocGetVar(conn->varList, conn->resbuf, nam));
|
||||
}
|
||||
s=t+1;
|
||||
} while (*t!='\0');
|
||||
if (buf_size(conn->resbuf)!=0) ERR_MSG("syntax error");
|
||||
return(0);
|
||||
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
void CocCloseClient(CocConn *conn) {
|
||||
close(conn->fd);
|
||||
buf_free(conn->cmdbuf);
|
||||
buf_free(conn->resbuf);
|
||||
CocFreeVarList(&conn->varList);
|
||||
}
|
16
tecs/client.h
Normal file
16
tecs/client.h
Normal file
@ -0,0 +1,16 @@
|
||||
#include "coc.h"
|
||||
|
||||
typedef struct {
|
||||
int fd, dummy;
|
||||
CocVar *varList;
|
||||
buf_type *cmdbuf; /* for sending command */
|
||||
buf_type *resbuf; /* for response */
|
||||
char host[64];
|
||||
char magic[32];
|
||||
char startcmd[64];
|
||||
} CocConn;
|
||||
|
||||
void CocInitClient(CocConn *conn, char *host, char *magic, int bufsize, char *startcmd);
|
||||
int CocSendMagic(CocConn *conn, char *magic);
|
||||
int CocCmd(CocConn *conn, const char *rwList);
|
||||
void CocCloseClient(CocConn *conn);
|
161
tecs/coc.c
Normal file
161
tecs/coc.c
Normal file
@ -0,0 +1,161 @@
|
||||
#include <assert.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) {
|
||||
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, buf_type *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");
|
||||
|
||||
buf_put_start(buf);
|
||||
ERR_SI(ret=recv(fd, buf->buf, buf->isize, 0));
|
||||
if (ret==0) { ERR_COD(ECONNRESET); }
|
||||
buf->usize=ret;
|
||||
buf_reset(buf);
|
||||
return(ret);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
void CocVarList(CocVar **varList) {
|
||||
assert(varList!=NULL);
|
||||
varListHdl=varList;
|
||||
}
|
||||
|
||||
CocVar *CocFindVar(CocVar *varList, const char *name) {
|
||||
CocVar *p;
|
||||
|
||||
p=varList;
|
||||
while (p!=NULL && 0!=strcmp(p->name,name)) p=p->next;
|
||||
return(p);
|
||||
}
|
||||
|
||||
void CocDefVar(const char *name, void *var, int type, int *flag) {
|
||||
CocVar *p;
|
||||
|
||||
assert(varListHdl!=NULL);
|
||||
p=CocFindVar(*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;
|
||||
}
|
||||
|
||||
int CocGetVar(CocVar *varList, buf_type *buf, const char *name) {
|
||||
CocVar *var;
|
||||
|
||||
var=CocFindVar(varList, name);
|
||||
if (var==NULL) ERR_MSG("undefined variable");
|
||||
if (varList==serverVarList) { /* we are the server */
|
||||
if (var->flag==&CocRD) ERR_MSG("variable is read only");
|
||||
}
|
||||
if (var->type==-1) {
|
||||
*(int *)var->var=buf_get_int(buf);
|
||||
} else if (var->type==-2) {
|
||||
*(float *)var->var=buf_get_float(buf);
|
||||
} else if (var->type>1) {
|
||||
str_ncpy((char *)var->var, buf_get_str(buf), var->type);
|
||||
} else {
|
||||
ERR_MSG("unknown type");
|
||||
}
|
||||
if (varList==serverVarList) { /* we are the server */
|
||||
if (var->flag!=NULL) (*var->flag)++;
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocPutVar(CocVar *varList, buf_type *buf, const char *name) {
|
||||
CocVar *var;
|
||||
char *c;
|
||||
|
||||
var=CocFindVar(varList, name);
|
||||
if (var==NULL) ERR_MSG("undefined variable");
|
||||
if (varList!=serverVarList) { /* we are a client */
|
||||
if (var->flag==&CocRD) ERR_MSG("variable is read only");
|
||||
}
|
||||
if (var->type==-1) {
|
||||
buf_put_int(buf, *(int *)var->var);
|
||||
} else if (var->type==-2) {
|
||||
buf_put_float(buf, *(float *)var->var);
|
||||
} else if (var->type>1) {
|
||||
c=var->var;
|
||||
if (c[0]<=2 && c[0]!=0) { ERR_MSG("illegal string"); }
|
||||
buf_put_str(buf, c);
|
||||
} else {
|
||||
ERR_MSG("unknown type");
|
||||
}
|
||||
if (varList!=serverVarList) { /* 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;
|
||||
}
|
43
tecs/coc.h
Normal file
43
tecs/coc.h
Normal file
@ -0,0 +1,43 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include "errhdl.h"
|
||||
#include "buf.h"
|
||||
#include "util.h"
|
||||
|
||||
#define CocPORT 9751
|
||||
#define CocPORTS 3
|
||||
|
||||
int CocCreateSockAdr(
|
||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port); /* Port number */
|
||||
int CocRecv(int fd, buf_type *buf);
|
||||
|
||||
typedef struct { void *next; char name[32]; void *var; int *flag; int type; } CocVar;
|
||||
|
||||
extern int CocRD;
|
||||
extern int CocWR;
|
||||
CocVar *serverVarList;
|
||||
|
||||
void CocDefVar(const char *name, void *var, int type, int *flag);
|
||||
void CocVarList(CocVar **varlist);
|
||||
void CocFreeVarList(CocVar **varList);
|
||||
CocVar *CocFindVar(CocVar *varList, const char *name);
|
||||
int CocPutVar(CocVar *varList, buf_type *buf, const char *name);
|
||||
int CocGetVar(CocVar *varList, buf_type *buf, const char *name);
|
||||
void CocDefFlag(int *flag);
|
||||
|
||||
#define CocDefInt(V,F) CocDefVar(#V,&V,-1,&F)
|
||||
#define CocDefFlt(V,F) CocDefVar(#V,&V,-2,&F)
|
||||
#define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F)
|
||||
#define CocDefStrPtr(V,S,F) CocDefVar(#V,V,S,&F)
|
86
tecs/errhdl.c
Normal file
86
tecs/errhdl.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "errhdl.h"
|
||||
|
||||
#define SLEN 64
|
||||
#define MLEN 64
|
||||
|
||||
static char *txt[SLEN];
|
||||
static int sp=0;
|
||||
|
||||
int ErrCode;
|
||||
char *ErrMessage=NULL;
|
||||
|
||||
void ErrTxt(char *text, int systemError)
|
||||
{
|
||||
if (systemError) { sp=0; ErrCode=errno; ErrMessage=strerror(errno); }
|
||||
if (sp<SLEN) {
|
||||
txt[sp++]=text;
|
||||
}
|
||||
}
|
||||
|
||||
void ErrMsg(char *msg)
|
||||
{
|
||||
ErrCode=-1;
|
||||
ErrMessage=msg; sp=0;
|
||||
}
|
||||
|
||||
void ErrCod(int code)
|
||||
{
|
||||
ErrCode=code;
|
||||
ErrMessage=strerror(code); sp=0;
|
||||
}
|
||||
|
||||
void ErrWriteGeneral(char *text, void (*outrtn)(), void *arg)
|
||||
{
|
||||
int i, l;
|
||||
char buf[256];
|
||||
|
||||
l=strlen(text)+strlen(ErrMessage)+6;
|
||||
assert(l<256);
|
||||
sprintf(buf, "--- %s: %s", text, ErrMessage);
|
||||
for (i=0;i<sp;i++) {
|
||||
if (txt[i][0]==':') {
|
||||
l+=strlen(txt[i]);
|
||||
assert(l<256);
|
||||
strcat(buf, &(txt[i][1]));
|
||||
} else {
|
||||
outrtn(arg, buf);
|
||||
l=strlen(txt[i]);
|
||||
assert(l<256);
|
||||
strcpy(buf, txt[i]);
|
||||
}
|
||||
}
|
||||
outrtn(arg, buf);
|
||||
outrtn(arg, "---");
|
||||
}
|
||||
|
||||
void ErrOutFil(void *arg, char *text) {
|
||||
fprintf((FILE *)arg, "%s\n", text);
|
||||
}
|
||||
|
||||
void ErrWrite(FILE *fil, char *text)
|
||||
{
|
||||
ErrWriteGeneral(text, ErrOutFil, fil);
|
||||
}
|
||||
|
||||
void ErrShow(char *text) {
|
||||
ErrWriteGeneral(text, ErrOutFil, stdout);
|
||||
}
|
||||
|
||||
#ifdef __VMS
|
||||
void ErrShowVms(char **text, void (*outrtn)(), void *arg) {
|
||||
char buf[256];
|
||||
int l;
|
||||
|
||||
l=*(short *)text;
|
||||
if (l>=256) l=255;
|
||||
strncpy(buf, text[1], l);
|
||||
buf[l]='\0';
|
||||
ErrWriteGeneral(buf, outrtn, arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ERR_EXIT(char *text) {
|
||||
ErrShow(text); exit(1);
|
||||
}
|
81
tecs/errhdl.h
Normal file
81
tecs/errhdl.h
Normal file
@ -0,0 +1,81 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
/* ErrHDL Error handling utilities
|
||||
-------------------------------
|
||||
Makes code more readable by hiding annoying error condition checks.
|
||||
|
||||
Macros and routines:
|
||||
|
||||
Spelling in uppercase indicates, that it the program flow
|
||||
may be modified (jump to OnError label or program exit).
|
||||
|
||||
|
||||
ERR_x
|
||||
|
||||
Usage Error condition Error message taken from
|
||||
-----------------------------------------------------------------------------------------
|
||||
ERR_SI(res=routine1(...)) res<0 errno
|
||||
ERR_SP(ptr=routine2(...)) ptr==NULL errno
|
||||
ERR_I(res=routine3(...)) res<0 stored by routine3 using errhdl mechanism
|
||||
ERR_P(ptr=routine4(...)) ptr==NULL stored by routine4 using errhdl mechanism
|
||||
|
||||
The result assignment "res=" or "ptr=" is optional.
|
||||
|
||||
Description:
|
||||
The routine routineX is called.
|
||||
If the result indicates an error, the source text is saved and the
|
||||
program continues at the OnError label.
|
||||
The error message and the source code of the calling instructions is
|
||||
saved for a later call to ErrShow or ErrExit.
|
||||
|
||||
ERR_EXIT("program_name")
|
||||
|
||||
Show error and exit program.
|
||||
|
||||
ERR_MSG("message")
|
||||
|
||||
Signals an error condition. If "message" is replaced by a variable,
|
||||
take care that it is not modified until ErrShow is called.
|
||||
|
||||
ERR_COD(cod)
|
||||
|
||||
Signals an error condition as code from errno.h
|
||||
|
||||
ErrShow("program_name")
|
||||
ErrWrite(fil, "program_name")
|
||||
|
||||
Show actual error message with traceback information to stdout
|
||||
or a file fil
|
||||
|
||||
Global Variables (read only)
|
||||
|
||||
int ErrCode
|
||||
|
||||
actual error message code
|
||||
= errno for system errors or
|
||||
= -1 for custom errors signaled by ERRMSG
|
||||
|
||||
char *ErrMessage
|
||||
|
||||
actual error message
|
||||
*/
|
||||
|
||||
#define ERR_SI(R) { if(0>(R)) { ErrTxt(#R,1); goto OnError; }; }
|
||||
#define ERR_SP(R) { if(NULL==(R)) { ErrTxt(#R,1); goto OnError; }; }
|
||||
#define ERR_I(R) { if(0>(R)) { ErrTxt(#R,0); goto OnError; }; }
|
||||
#define ERR_P(R) { if(NULL==(R)) { ErrTxt(#R,0); goto OnError; }; }
|
||||
#define ERR_MSG(R) { ErrMsg(R); goto OnError; }
|
||||
#define ERR_COD(R) { ErrCod(R); goto OnError; }
|
||||
|
||||
void ErrTxt(char *text, int systemError);
|
||||
void ErrMsg(char *msg);
|
||||
void ErrCod(int code);
|
||||
void ErrShow(char *text);
|
||||
void ErrWrite(FILE *fil, char *text);
|
||||
void ERR_EXIT(char *text);
|
||||
void ErrLog(char *text);
|
||||
|
||||
extern int ErrCode;
|
||||
extern char *ErrMessage;
|
130
tecs/tecc.c
Normal file
130
tecs/tecc.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include "errhdl.h"
|
||||
#include "client.h"
|
||||
#include "tecc.h"
|
||||
|
||||
char command[80], response[80], device[80];
|
||||
float tempX, tempP, tempC;
|
||||
|
||||
pTecsClient TeccInit(char *server) {
|
||||
CocConn *conn;
|
||||
char buf[80];
|
||||
|
||||
ERR_SP(conn=(CocConn *)malloc(sizeof(*conn)));
|
||||
#ifdef __VMS
|
||||
sprintf(buf, "@start_tecs %s", server);
|
||||
#else
|
||||
sprintf(buf, "start_tecs %s", server);
|
||||
#endif
|
||||
CocInitClient(conn, "", "#rwacs", 0, buf);
|
||||
CocDefFlt(tempX, CocRD);
|
||||
CocDefFlt(tempP, CocRD);
|
||||
CocDefFlt(tempC, CocWR);
|
||||
CocDefStr(device, CocWR);
|
||||
CocDefStr(command, CocWR);
|
||||
CocDefStr(response, CocWR);
|
||||
return((pTecsClient)conn);
|
||||
OnError: return(NULL);
|
||||
}
|
||||
|
||||
int TeccSetDev(pTecsClient conn, char *dev) {
|
||||
str_copy(device, dev);
|
||||
ERR_I(CocCmd((CocConn *)conn, "[device]"));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
char *TeccGetDev(pTecsClient conn) {
|
||||
ERR_I(CocCmd((CocConn *)conn, "device"));
|
||||
return(device);
|
||||
OnError: return(NULL);
|
||||
}
|
||||
|
||||
int TeccGet(pTecsClient conn, float *temp) {
|
||||
ERR_I(CocCmd((CocConn *)conn, "tempP"));
|
||||
*temp=tempP;
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccGet3(pTecsClient conn, float temp[3]) {
|
||||
ERR_I(CocCmd((CocConn *)conn, "tempC,tempX,tempP"));
|
||||
temp[0]=tempC;
|
||||
temp[1]=tempX;
|
||||
temp[2]=tempP;
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp) {
|
||||
tempC=temp;
|
||||
ERR_I(CocCmd((CocConn *)conn, "[tempC]"));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
|
||||
command[0]='\0';
|
||||
while (0!=strcmp(command, cmd)) {
|
||||
str_copy(command, cmd);
|
||||
strcpy(response,"<none>");
|
||||
ERR_I(CocCmd((CocConn *)conn, "[command,response]"));
|
||||
while (0==strcmp(response,"<none>") && 0==strcmp(command, cmd)) {
|
||||
util_delay(250);
|
||||
ERR_I(CocCmd((CocConn *)conn, "command,response"));
|
||||
}
|
||||
}
|
||||
str_ncpy(reply, response, replyLen);
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
void TeccClose(pTecsClient conn) {
|
||||
CocCloseClient((CocConn *)conn);
|
||||
free(conn);
|
||||
}
|
||||
|
||||
#ifdef __VMS
|
||||
|
||||
int TeccSetDevVms(pTecsClient conn, char **dev) {
|
||||
int l;
|
||||
|
||||
l=*(short *)dev;
|
||||
if (l>=sizeof(device)) l=sizeof(device)-1;
|
||||
strncpy(device, dev[1], l);
|
||||
while (l>0 && device[l-1]==' ') l--; /* trim */
|
||||
device[l]='\0';
|
||||
ERR_I(CocCmd((CocConn *)conn, "[device]"));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccGetDevVms(pTecsClient conn, char **dev) {
|
||||
int l, ld;
|
||||
|
||||
ERR_I(CocCmd((CocConn *)conn, "device"));
|
||||
ld=strlen(device);
|
||||
l=*(short *)dev;
|
||||
if (ld>=l) ld=l;
|
||||
strncpy(dev[1], device, ld);
|
||||
return(ld);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccSendVms(pTecsClient conn, char **cmd, char **reply) {
|
||||
int l, lr;
|
||||
char cbuf[80], rbuf[80];
|
||||
|
||||
l=*(short *)cmd;
|
||||
if (l>=sizeof(cbuf)) l=sizeof(cbuf)-1;
|
||||
strncpy(cbuf, cmd[1], l);
|
||||
while (l>0 && cbuf[l-1]==' ') l--; /* trim */
|
||||
cbuf[l]='\0';
|
||||
TeccSend(conn, cbuf, rbuf, sizeof(rbuf));
|
||||
lr=strlen(rbuf);
|
||||
l=*(short *)reply;
|
||||
if (lr>=l) lr=l;
|
||||
strncpy(reply[1], rbuf, lr);
|
||||
return(lr);
|
||||
OnError: return(-1);
|
||||
}
|
||||
#endif
|
39
tecs/tecc.h
Normal file
39
tecs/tecc.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
tecc.h: tecs client interface routines
|
||||
|
||||
M. Zolliker March 2000
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct { int tecc_private; } *pTecsClient;
|
||||
/* hidden structure for a tecs client
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
pTecsClient TeccInit(char *server);
|
||||
/* init tecs client (connect to server)
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
int TeccSetDev(pTecsClient conn, char *dev);
|
||||
/* set device type
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
char *TeccGetDev(pTecsClient conn);
|
||||
/* get device type
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
int TeccGet(pTecsClient conn, float *temp);
|
||||
/* set temperature
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp);
|
||||
/* get temperature
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen);
|
||||
/* send a command transparently to the controller
|
||||
replyLen is the maximal length of reply
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
void TeccClose(pTecsClient conn);
|
||||
/* close connection and free ressources
|
||||
------------------------------------------------------------------------*/
|
||||
|
182
tecs/util.c
Normal file
182
tecs/util.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "errhdl.h"
|
||||
#include "util.h"
|
||||
|
||||
/* when changing FBUF_LEN, change also the constant in the fscanf call in subroutine LscExeCmd */
|
||||
#define FBUF_LEN 132
|
||||
|
||||
char *str_split(char *str, char sep, char *list[], int *n) {
|
||||
int i;
|
||||
char *s, *e;
|
||||
|
||||
s=str;
|
||||
for (i=0; i<*n; i++) {
|
||||
list[i]=s;
|
||||
e=strchr(s, sep);
|
||||
if (e==NULL) { *n=i+1; return(NULL); }
|
||||
s=e+1;
|
||||
e--;
|
||||
while (e>str && *e==' ') e--; /* trim sequence */
|
||||
e[1]='\0';
|
||||
}
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *str_split1(char *str, char sep) {
|
||||
char *s, *e;
|
||||
|
||||
e=strchr(str, sep);
|
||||
if (e==NULL) {
|
||||
s=NULL;
|
||||
e=str+strlen(str);
|
||||
} else {
|
||||
s=e+1;
|
||||
}
|
||||
e--;
|
||||
while (e>str && *e==' ') e--; /* trim sequence */
|
||||
e[1]='\0';
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *str_ntrim(char *dest, int ldest, const char *src, int lsrc) {
|
||||
char *s, *e;
|
||||
|
||||
if (lsrc<ldest) ldest=lsrc;
|
||||
if (dest!=src) strncpy(dest, src, ldest);
|
||||
e=dest+ldest-2;
|
||||
while (e>dest && *e==' ') e--; /* trim sequence */
|
||||
e[1]='\0';
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *str_read_until(FILE *fil, char *term, char *buf, char *end) {
|
||||
char *s;
|
||||
char fmt[24];
|
||||
int i, l, siz;
|
||||
char ch;
|
||||
|
||||
siz=end-buf-1;
|
||||
if (siz<1) return(NULL);
|
||||
sprintf(fmt, "%s%d[^%s%s", "%", siz, term, "]%n%c");
|
||||
i=fscanf(fil, fmt, buf, &l, &ch);
|
||||
if (i<0) { /* eof */
|
||||
buf[0]='\0';
|
||||
return(&buf[0]);
|
||||
} else if (i==0) { /* fscanf returns 0 if first char is terminator */
|
||||
buf[0]=fgetc(fil);
|
||||
return(&buf[0]);
|
||||
} else if (i==1) { /* terminator not found -> read until eof */
|
||||
buf[l]='\0';
|
||||
return(&buf[l]);
|
||||
} else {
|
||||
buf[l]=ch;
|
||||
if (l==siz && NULL==strchr(term, ch)) return(NULL);
|
||||
return(&buf[l]);
|
||||
}
|
||||
}
|
||||
|
||||
char *str_read_arg(char *file, char *args[], int nargs) {
|
||||
FILE *fil;
|
||||
char *str, *s, *e, *p, *q;
|
||||
char ch;
|
||||
int i, l, size;
|
||||
struct stat statbuf;
|
||||
|
||||
i=stat(file, &statbuf);
|
||||
if (i<0) ERR_MSG("file not found");
|
||||
size=statbuf.st_size+4;
|
||||
if (nargs>0) size+=size/2+100; /* max size */
|
||||
while (1) {
|
||||
ERR_SP(str=malloc(size));
|
||||
e=&str[size-1];
|
||||
ERR_SP(fil=fopen(file, "r"));
|
||||
s=str;
|
||||
while (1) {
|
||||
p=str_read_until(fil, "#!", s, e);
|
||||
if (p==NULL) break;
|
||||
if (*p=='!') {
|
||||
q=str_read_until(fil, "\n", p, e);
|
||||
if (q==NULL) { p=NULL; break; }
|
||||
s=p; *s='\n'; s++;
|
||||
} else if (*p=='#') {
|
||||
ch=fgetc(fil);
|
||||
i=ch-'0';
|
||||
if (i<0 || i>=nargs) {
|
||||
s=p+1; *s=ch; s++;
|
||||
} else {
|
||||
l=strlen(args[i]);
|
||||
if (s+l>=e) { p=NULL; break; }
|
||||
strcpy(p, args[i]);
|
||||
s=p+l;
|
||||
}
|
||||
} else {
|
||||
assert(*p=='\0');
|
||||
break;
|
||||
}
|
||||
}
|
||||
ERR_SI(fclose(fil));
|
||||
if (p!=NULL) break;
|
||||
size=size*3/2; /* allocation not sufficient -> try again */
|
||||
free(str);
|
||||
}
|
||||
assert(strlen(str)<size);
|
||||
return(str);
|
||||
OnError: return(NULL);
|
||||
}
|
||||
|
||||
void str_replace_char(char *str, char ch, char rep) {
|
||||
char *s;
|
||||
|
||||
assert(ch!='\0' && ch!=rep);
|
||||
s=strchr(str, ch);
|
||||
while (s!=NULL) {
|
||||
*s=rep;
|
||||
s=strchr(s, ch);
|
||||
}
|
||||
}
|
||||
|
||||
void str_upcase(char *str) {
|
||||
while (*str!='\0') {
|
||||
*str=toupper(*str); str++;
|
||||
}
|
||||
}
|
||||
|
||||
int str_cmp(const char *str1, const char *str2) {
|
||||
int i;
|
||||
char ch1, ch2;
|
||||
ch1=tolower(*(str1++)); ch2=tolower(*(str2++));
|
||||
i=1;
|
||||
while (ch1!='\0' && ch2!='\0' && ch1==ch2) {
|
||||
ch1=tolower(*(str1++)); ch2=tolower(*(str2++)); i++;
|
||||
}
|
||||
if (ch1<ch2) {
|
||||
return(-i);
|
||||
} else if (ch1>ch2) {
|
||||
return(i);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int str_ncpy(char *dst, const char *src, int n) {
|
||||
strncpy(dst, src, n);
|
||||
if (dst[n-1]!='\0') {
|
||||
dst[n-1]='\0';
|
||||
ERR_MSG("destination string too short");
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
void util_delay(int tmo_msec) {
|
||||
struct timeval tmo;
|
||||
|
||||
tmo.tv_sec=tmo_msec / 1000;
|
||||
tmo.tv_usec=(tmo_msec % 1000)*1000+1;
|
||||
select(1,NULL,NULL,NULL,&tmo);
|
||||
}
|
65
tecs/util.h
Normal file
65
tecs/util.h
Normal file
@ -0,0 +1,65 @@
|
||||
char *str_ntrim(char *dest, int ldest, const char *src, int lsrc);
|
||||
/*
|
||||
copy characters 0 to lsrc-1 from src to dest (max ldest chars).
|
||||
*/
|
||||
|
||||
char *str_split1(char *str, char separator);
|
||||
/*
|
||||
trims text before separator in *str and returns
|
||||
a pointer to the first character after separator
|
||||
*/
|
||||
|
||||
char *str_split(char *str, char sep, char *list[], int *n);
|
||||
/*
|
||||
split string into *n strings using separator sep.
|
||||
spaces at the end of the elements are trimmed
|
||||
attention: *str is modified ('\0' placed at the end of the elements)
|
||||
|
||||
if *n separators are found, result points to string after *n-th separator
|
||||
else result is NULL
|
||||
*n contains number of elements stored in list
|
||||
*/
|
||||
|
||||
char *str_read_arg(char *file, char *args[], int nargs);
|
||||
/*
|
||||
return one string containing the contents of file *file
|
||||
the contents are treated in the following way:
|
||||
- #0,#1,...#n is replaced by the corresponding argument *args[n] (n=0..nargs-1, nargs<10)
|
||||
- at the end of each line spaces and comments separated by ! are trimmed
|
||||
*/
|
||||
|
||||
void str_replace_char(char *str, char ch, char rep);
|
||||
/*
|
||||
replace all occurences of character ch by character rep in string *str
|
||||
*/
|
||||
|
||||
void str_upcase(char *str);
|
||||
/*
|
||||
convert *str to uppercase
|
||||
*/
|
||||
|
||||
int str_cmp(const char *str1, const char *str2);
|
||||
/*
|
||||
compare *str1 with *str2
|
||||
the comparison is not case sensitive
|
||||
if result=0: strings are equal
|
||||
else
|
||||
result>0 <==> *str1>*str2
|
||||
first different character is at position abs(result)-1
|
||||
*/
|
||||
|
||||
|
||||
int str_ncpy(char *dst, const char *src, int n);
|
||||
/*
|
||||
same as strncpy, but dst has always a '\0' at end
|
||||
use str_copy if dst is a character array
|
||||
returns -1, if destination is to short, 0 otherwise
|
||||
*/
|
||||
|
||||
|
||||
#define str_copy(DST,SRC) str_ncpy(DST,SRC,sizeof(DST))
|
||||
|
||||
void util_delay(int tmo_msec);
|
||||
/*
|
||||
usleep is not available on VMS 6
|
||||
*/
|
Reference in New Issue
Block a user