*** 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