new tecs version M.Z.08.2001
This commit is contained in:
@ -3,47 +3,55 @@
|
|||||||
#
|
#
|
||||||
# Markus Zolliker, March 2000
|
# Markus Zolliker, March 2000
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
LIBR_OBJ= coc_util.o err_handling.o str_util.o str_buf.o
|
LIBR_OBJ= coc_util.o myc_err.o myc_str.o myc_buf.o myc_time.o
|
||||||
DLOG_OBJ= sys_util.o tecs_dlog.o
|
SERV_OBJ= tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o tecs_data.o $(LIBR_OBJ)
|
||||||
SERV_OBJ= tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o $(LIBR_OBJ) $(DLOG_OBJ)
|
|
||||||
CLI_OBJ= tecs_cli.o coc_client.o $(LIBR_OBJ)
|
CLI_OBJ= tecs_cli.o coc_client.o $(LIBR_OBJ)
|
||||||
TCLI_OBJ= tecs_client.o tecs_plot.o tecs_for.o sys_aunix.o sys_aunix_c.o str.o cho.o $(CLI_OBJ) $(DLOG_OBJ)
|
TCLI_OBJ= sys_aunix.o sys_aunix_c.o $(CLI_OBJ)
|
||||||
|
TECLI_OBJ= tecs_client.o tecs_plot.o tecs_for.o sys_util.o str.o $(TCLI_OBJ)
|
||||||
|
|
||||||
#------------ for DigitalUnix (add -DFORTIFY to CFLAGS for fortified version)
|
#------------ for DigitalUnix (add -DFORTIFY to CFLAGS for fortified version)
|
||||||
CC=cc
|
CC=cc
|
||||||
|
|
||||||
|
#CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup -DFORTIFY
|
||||||
CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup
|
CFLAGS= -std1 -g -warnprotos -I../ -I. -I../hardsup
|
||||||
#------------ for Linux
|
|
||||||
##CC=gcc
|
|
||||||
##CFLAGS = -fwritable-strings -DCYGNUS -DNONINTF -g -I../ -I. -I../hardsup
|
|
||||||
#------------
|
|
||||||
|
|
||||||
.f.o:
|
.f.o:
|
||||||
f77 -c -g $*.f
|
f77 -c -u -g $*.f
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CFLAGS) -c $*.c
|
$(CC) $(CFLAGS) -c $*.c
|
||||||
|
|
||||||
libtecsl.a: $(CLI_OBJ)
|
libtecsl.a: $(CLI_OBJ)
|
||||||
- rm -f libtecsl.a
|
- rm libtecsl.a
|
||||||
ar cr libtecsl.a $(CLI_OBJ)
|
ar cr libtecsl.a $(CLI_OBJ)
|
||||||
ranlib libtecsl.a
|
ranlib libtecsl.a
|
||||||
|
|
||||||
all: libtecsl.a bin/TecsServer tecs
|
all: libtecsl.a bin/TecsServer bin/TecsClient
|
||||||
|
|
||||||
tecs_plot.o: tecs_plot.f90
|
tecs_plot.o: tecs_plot.f90
|
||||||
f90 -c -g tecs_plot.f90
|
f90 -c -u -g tecs_plot.f90
|
||||||
|
|
||||||
bin/TecsServer: $(SERV_OBJ)
|
bin/TecsServer: $(SERV_OBJ)
|
||||||
- rm -f bin/TecsServer
|
- rm bin/TecsServer
|
||||||
$(CC) $(CFLAGS) -o bin/TecsServer -g $(SERV_OBJ) fortify1.c \
|
$(CC) $(CFLAGS) -o bin/TecsServer -g $(SERV_OBJ) fortify1.c \
|
||||||
-lm -L../hardsup -lhlib -lfor
|
-lm -L../hardsup -lhlib -lfor
|
||||||
|
|
||||||
tecs: $(TCLI_OBJ)
|
bin/TecsClient: $(TECLI_OBJ)
|
||||||
f77 -o tecs -g $(TCLI_OBJ) \
|
f77 -o bin/TecsClient -g $(TECLI_OBJ) \
|
||||||
-L/data/lnslib/lib -lpgplot -so_archive -lreadline -ltermcap -lX11 -lXm
|
-L/data/lnslib/lib -lpgplot -so_archive -lreadline -ltermcap -lX11 -lXm
|
||||||
|
|
||||||
|
six: six.c term.c sys_select.c $(LIBR_OBJ)
|
||||||
|
$(CC) $(CFLAGS) -o six six.c term.c sys_select.c $(LIBR_OBJ) \
|
||||||
|
-L/data/lnslib/lib -so_archive -lreadline -ltermcap -lX11 -lXm
|
||||||
|
|
||||||
|
rstart: $(LIBR_OBJ) rstart.c myc_str.o myc_err.o
|
||||||
|
$(CC) $(CFLAGS) -o rstart rstart.c myc_str.o myc_err.o
|
||||||
|
|
||||||
|
keep_running: keep_running.c
|
||||||
|
$(CC) $(CFLAGS) -o keep_running keep_running.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
- rm -f *.o
|
- rm *.o
|
||||||
- rm -f *.a
|
- rm *.a
|
||||||
- rm -f bin/TecsServer
|
- rm bin/TecsServer
|
||||||
- rm -f tecs
|
- rm bin/TecsClient
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "err_handling.h"
|
#include <signal.h>
|
||||||
|
#include "myc_err.h"
|
||||||
|
#include "coc_util.h"
|
||||||
#include "coc_client.h"
|
#include "coc_client.h"
|
||||||
#include "str_util.h"
|
#include "sys_util.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
|
||||||
/* --- non ANSI signal --- */
|
/* --- non ANSI signal --- */
|
||||||
#ifndef SIGPIPE
|
#ifndef SIGPIPE
|
||||||
#define SIGPIPE 13
|
#define SIGPIPE 13
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define COC_NETTMO 5
|
||||||
|
#define COC_RESTMO 60
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocConnect(CocConn *conn) {
|
int CocConnect(CocConn *conn) {
|
||||||
@ -67,15 +72,13 @@ int CocOpen(CocConn *conn)
|
|||||||
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) {
|
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) {
|
||||||
assert(conn!=NULL);
|
assert(conn!=NULL);
|
||||||
if (bufsize==0) bufsize=1024;
|
if (bufsize==0) bufsize=1024;
|
||||||
ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0'));
|
StrLink(&conn->cmdbuf, conn->cmdbuf_);
|
||||||
ERR_P(conn->resbuf=str_create_buf(bufsize, '\0'));
|
StrLink(&conn->resbuf, conn->resbuf_);
|
||||||
conn->port=port;
|
conn->port=port;
|
||||||
ERR_I(str_copy(conn->host, host));
|
ERR_I(str_copy(conn->host, host));
|
||||||
ERR_I(str_copy(conn->magic, magic));
|
ERR_I(str_copy(conn->magic, magic));
|
||||||
ERR_I(str_copy(conn->startcmd, startcmd));
|
ERR_I(str_copy(conn->startcmd, startcmd));
|
||||||
conn->fd=-1;
|
conn->fd=-1;
|
||||||
conn->varList=NULL;
|
|
||||||
CocVarList(&conn->varList);
|
|
||||||
ERR_I(CocOpen(conn));
|
ERR_I(CocOpen(conn));
|
||||||
ERR_I(CocSendMagic(conn, conn->magic));
|
ERR_I(CocSendMagic(conn, conn->magic));
|
||||||
return(0);
|
return(0);
|
||||||
@ -86,15 +89,17 @@ int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize,
|
|||||||
|
|
||||||
int CocSendMagic(CocConn *conn, char *magic) {
|
int CocSendMagic(CocConn *conn, char *magic) {
|
||||||
char *err;
|
char *err;
|
||||||
|
int siz, n;
|
||||||
|
|
||||||
if (magic[0]!='#') ERR_MSG("magic must start with '#'");
|
StrClear(&conn->resbuf); /* use return buffer for command in order to preserve command buffer */
|
||||||
str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */
|
ERR_I(StrPut(&conn->resbuf, "", COC_MAGIC));
|
||||||
ERR_I(str_put_str(conn->resbuf, magic));
|
ERR_I(StrPut(&conn->resbuf, magic, COC_SEP));
|
||||||
ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0));
|
ERR_I(CocSend(conn->fd, conn->resbuf.buf, conn->resbuf.wrpos));
|
||||||
ERR_I(CocRecv(conn->fd, conn->resbuf));
|
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||||
ERR_P(err=str_get_str(conn->resbuf, NULL));
|
ERR_P(err=StrGet(&conn->resbuf, NULL, COC_SEP));
|
||||||
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; }
|
if (err[0]!=COC_MAGIC) ERR_MSG("magic synch error");
|
||||||
ERR_I(str_get_end(conn->resbuf));
|
if (err[1]!='\0') { ErrMsg(err+1); ErrTxt(": (response from server)",0); goto OnError; }
|
||||||
|
ERR_I(StrGetEnd(&conn->resbuf));
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
@ -102,9 +107,10 @@ int CocSendMagic(CocConn *conn, char *magic) {
|
|||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocCheck(CocConn *conn) {
|
int CocCheck(CocConn *conn) {
|
||||||
|
|
||||||
if (conn->fd<0) return(1);
|
if (conn->fd<0) return(1);
|
||||||
ERR_SI(send(conn->fd, "quit", 5, 0));
|
ERR_I(CocSend(conn->fd, "_quit", 6));
|
||||||
ERR_I(CocRecv(conn->fd, conn->resbuf));
|
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||||
return(0);
|
return(0);
|
||||||
OnError:
|
OnError:
|
||||||
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1);
|
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1);
|
||||||
@ -114,16 +120,24 @@ int CocCheck(CocConn *conn) {
|
|||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocTryCmd(CocConn *conn) {
|
int CocTryCmd(CocConn *conn) {
|
||||||
int iret=-1;
|
int iret=-1, siz;
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
if (conn->fd<0) {
|
if (conn->fd<0) {
|
||||||
|
/*
|
||||||
ERR_I(iret=CocOpen(conn));
|
ERR_I(iret=CocOpen(conn));
|
||||||
|
*/
|
||||||
|
ERR_I(iret=CocConnect(conn));
|
||||||
|
if (iret == 1) {
|
||||||
|
CocDelay(500);
|
||||||
|
ErrTxt("connect",1); return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
iret=-1;
|
iret=-1;
|
||||||
ERR_I(CocSendMagic(conn, conn->magic));
|
ERR_I(CocSendMagic(conn, conn->magic));
|
||||||
}
|
}
|
||||||
ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0));
|
ERR_I(CocSend(conn->fd, conn->cmdbuf.buf, conn->cmdbuf.wrpos));
|
||||||
ERR_I(CocRecv(conn->fd, conn->resbuf));
|
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||||
return(0);
|
return(0);
|
||||||
OnError:
|
OnError:
|
||||||
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2);
|
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2);
|
||||||
@ -134,7 +148,6 @@ int CocTryCmd(CocConn *conn) {
|
|||||||
|
|
||||||
int CocCmdWithRetry(CocConn *conn) {
|
int CocCmdWithRetry(CocConn *conn) {
|
||||||
int cnt, iret;
|
int cnt, iret;
|
||||||
char *err;
|
|
||||||
|
|
||||||
if (conn==NULL) ERR_MSG("not connected");
|
if (conn==NULL) ERR_MSG("not connected");
|
||||||
cnt=3;
|
cnt=3;
|
||||||
@ -152,118 +165,321 @@ int CocCmdWithRetry(CocConn *conn) {
|
|||||||
ErrShort(ErrMessage);
|
ErrShort(ErrMessage);
|
||||||
ErrShort("try to reconnect");
|
ErrShort("try to reconnect");
|
||||||
}
|
}
|
||||||
ERR_P(err=str_get_str(conn->resbuf, NULL));
|
|
||||||
if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); return(-2); }
|
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocSet(CocConn *conn, const char *name, const char *value) {
|
void CocReset(CocConn *conn) {
|
||||||
int iret=-1;
|
|
||||||
|
|
||||||
assert(conn!=NULL);
|
assert(conn!=NULL);
|
||||||
str_put_start(conn->cmdbuf);
|
StrClear(&conn->cmdbuf);
|
||||||
ERR_I(str_put_str(conn->cmdbuf, "["));
|
if (conn->synch!=COC_SYN0) {
|
||||||
ERR_I(str_put_str(conn->cmdbuf, name));
|
conn->synch=COC_SYN0;
|
||||||
ERR_I(str_put_str(conn->cmdbuf, value));
|
} else {
|
||||||
ERR_I(str_put_str(conn->cmdbuf, "]"));
|
conn->synch=COC_SYN1;
|
||||||
|
}
|
||||||
ERR_I(iret=CocCmdWithRetry(conn));
|
StrPut(&conn->cmdbuf, "", conn->synch);
|
||||||
|
conn->nargs=0;
|
||||||
ERR_I(str_get_end(conn->resbuf));
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
OnError: return(iret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocGetN(CocConn *conn, const char *name, char *value, int reslen) {
|
int CocPushArg(CocConn *conn, const char *name, void *value, int type) {
|
||||||
int iret=-1;
|
StrBuf *buf;
|
||||||
|
int n;
|
||||||
|
|
||||||
assert(conn!=NULL);
|
assert(conn!=NULL);
|
||||||
str_put_start(conn->cmdbuf);
|
assert(NULL==strchr(name, ' '));
|
||||||
ERR_I(str_put_str(conn->cmdbuf, name));
|
buf=&conn->cmdbuf;
|
||||||
|
n=conn->nargs;
|
||||||
ERR_I(iret=CocCmdWithRetry(conn));
|
if (n>=sizeof(conn->args)) ERR_MSG("too many return arguments");
|
||||||
|
conn->args[n].adr=value;
|
||||||
ERR_P(str_nget_str(conn->resbuf, value, reslen));
|
conn->args[n].type=type;
|
||||||
ERR_I(str_get_end(conn->resbuf));
|
conn->args[n].cmd=buf->buf + buf->wrpos;
|
||||||
|
conn->nargs=n+1;
|
||||||
|
if (value==NULL) {
|
||||||
|
ERR_I(StrPut(buf, name, ' '));
|
||||||
|
} else {
|
||||||
|
ERR_I(StrPut(buf, name, COC_SEP));
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
OnError: return(iret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocCmd(CocConn *conn, const char *rwList)
|
int CocPutStr(CocConn *conn, const char *name, const char *value) {
|
||||||
{ int setmode, i, iret=-1;
|
StrBuf *buf;
|
||||||
const char *t, *s;
|
|
||||||
char nam[32];
|
ERR_I(CocPushArg(conn, name, NULL, 4));
|
||||||
CocVar *var;
|
ERR_I(StrPut(&conn->cmdbuf, value, COC_SEP));
|
||||||
void *adr;
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocPutFloat(CocConn *conn, const char *name, float value) {
|
||||||
|
|
||||||
|
ERR_I(CocPushArg(conn, name, NULL, COC_FLT));
|
||||||
|
ERR_I(StrPutFloat(&conn->cmdbuf, value, COC_SEP));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocPutInt(CocConn *conn, const char *name, int value) {
|
||||||
|
|
||||||
|
ERR_I(CocPushArg(conn, name, NULL, COC_INT));
|
||||||
|
ERR_I(StrPutInt(&conn->cmdbuf, value, COC_SEP));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocGetStr(CocConn *conn, const char *name, char *value, int value_len) {
|
||||||
|
|
||||||
|
return(CocPushArg(conn, name, value, value_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocGetFloat(CocConn *conn, const char *name, float *value) {
|
||||||
|
|
||||||
|
return(CocPushArg(conn, name, value, COC_FLT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocGetInt(CocConn *conn, const char *name, int *value) {
|
||||||
|
|
||||||
|
return(CocPushArg(conn, name, value, COC_INT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocDoIt(CocConn *conn, char *res, int res_len) {
|
||||||
|
StrBuf *buf;
|
||||||
|
int i, pending;
|
||||||
|
CocArg *a;
|
||||||
|
char *resp, *t, tag;
|
||||||
|
int iret=0;
|
||||||
|
|
||||||
assert(conn!=NULL);
|
assert(conn!=NULL);
|
||||||
str_put_start(conn->cmdbuf);
|
ERR_I(CocCmdWithRetry(conn));
|
||||||
s=rwList;
|
buf=&conn->resbuf;
|
||||||
setmode=0;
|
while (buf->buf[0] != conn->synch) { /* throw away unsynchronized answers */
|
||||||
do {
|
ERR_I(CocRecv(conn->fd, buf, COC_NETTMO, NULL));
|
||||||
t=strchr(s, ',');
|
}
|
||||||
if (t==NULL) t=s+strlen(s);
|
|
||||||
if (*s=='[') {
|
|
||||||
if (!setmode) ERR_I(str_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]==']') { i--; nam[i]='\0'; setmode=0; }
|
|
||||||
ERR_I(str_put_str(conn->cmdbuf, nam));
|
|
||||||
ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam, 0));
|
|
||||||
if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "]"));
|
|
||||||
} else {
|
|
||||||
var=CocFindVar(conn->varList, nam, NULL);
|
|
||||||
if (var==NULL) ERR_MSG("variable not found");
|
|
||||||
ERR_I(str_put_str(conn->cmdbuf, nam));
|
|
||||||
}
|
|
||||||
s=t+1;
|
|
||||||
} while (*t!='\0');
|
|
||||||
|
|
||||||
ERR_I(iret=CocCmdWithRetry(conn));
|
pending=conn->nargs;
|
||||||
|
*res='\0';
|
||||||
|
while (1) {
|
||||||
|
if (buf->buf[0] != conn->synch) ERR_MSG("synch error");
|
||||||
|
ERR_P(StrGet(buf, NULL, conn->synch));
|
||||||
|
i=0;
|
||||||
|
a=conn->args;
|
||||||
|
while (pending>0 && i<conn->nargs) {
|
||||||
|
if (a->type!=0) {
|
||||||
|
resp=buf->buf + buf->rdpos;
|
||||||
|
tag=*resp;
|
||||||
|
if (tag==COC_DELAYED) { /* delayed response */
|
||||||
|
resp++;
|
||||||
|
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||||
|
} else {
|
||||||
|
pending--;
|
||||||
|
if (tag==COC_ERR || tag==COC_TRM) { /* error response */
|
||||||
|
str_ncat(res, a->cmd, res_len);
|
||||||
|
resp++;
|
||||||
|
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||||
|
str_ncat(res, ": ", res_len);
|
||||||
|
iret=1;
|
||||||
|
if (tag==COC_TRM) return(1);
|
||||||
|
} else {
|
||||||
|
if (a->adr==NULL) {
|
||||||
|
t=strchr(res, COC_SEP);
|
||||||
|
str_ncat(res, a->cmd, res_len);
|
||||||
|
t=strchr(t, ' ');
|
||||||
|
assert(t!=NULL); /* truncate argument */
|
||||||
|
*t=COC_SEP;
|
||||||
|
str_ncat(res, "=", res_len);
|
||||||
|
ERR_P(StrGet(buf, NULL, COC_SEP));
|
||||||
|
} else {
|
||||||
|
str_ncat(res, a->cmd, res_len);
|
||||||
|
str_ncat(res, "=", res_len);
|
||||||
|
if (a->type==COC_INT) {
|
||||||
|
ERR_I(StrGetInt(buf, (int *)a->adr, COC_SEP));
|
||||||
|
} else if (a->type==COC_FLT) {
|
||||||
|
ERR_I(StrGetFloat(buf, (float *)a->adr, COC_SEP));
|
||||||
|
} else if (a->type>1) {
|
||||||
|
ERR_P(StrNGet(buf, (char *)a->adr, a->type, COC_SEP));
|
||||||
|
} else {
|
||||||
|
ERR_MSG("unknown type");
|
||||||
|
}
|
||||||
|
a->type=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str_ncat(res, resp, res_len);
|
||||||
|
str_ncat(res, "\n", res_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++; a++;
|
||||||
|
}
|
||||||
|
ERR_I(StrGetEnd(buf));
|
||||||
|
if (pending==0) return(iret); /* no more delayed response awaiting */
|
||||||
|
|
||||||
/* read values */
|
ERR_I(CocRecv(conn->fd, buf, COC_RESTMO, NULL));
|
||||||
s=rwList;
|
}
|
||||||
setmode=0;
|
return(iret);
|
||||||
do {
|
OnError: return(-1);
|
||||||
t=strchr(s, ',');
|
}
|
||||||
if (t==NULL) t=s+strlen(s);
|
|
||||||
if (*s=='[') {
|
static int interrupt, logFd=0;
|
||||||
s++;
|
|
||||||
setmode=1;
|
void CocIntSignal(int sig) {
|
||||||
|
char buf[4];
|
||||||
|
int siz;
|
||||||
|
|
||||||
|
if (logFd) {
|
||||||
|
interrupt=2;
|
||||||
|
buf[0]=COC_CLRLOG;
|
||||||
|
buf[1]=COC_SEP; /* send "clear log" message */
|
||||||
|
printf("\nCLRLOG\n");
|
||||||
|
CocSend(logFd, buf, 2);
|
||||||
|
} else {
|
||||||
|
printf("\ninterrupt\n");
|
||||||
|
interrupt=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocWatchLog(CocConn *conn, char *loglist) {
|
||||||
|
char cbuf[1024];
|
||||||
|
StrBuf *buf;
|
||||||
|
int fd, iret;
|
||||||
|
int i, siz, n;
|
||||||
|
|
||||||
|
sys_ctrl_init();
|
||||||
|
fd=conn->fd;
|
||||||
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutStr(conn, "loglist", loglist));
|
||||||
|
ERR_I(CocDoIt(conn, cbuf, sizeof(cbuf)));
|
||||||
|
buf=&conn->resbuf;
|
||||||
|
interrupt=0;
|
||||||
|
logFd=fd;
|
||||||
|
signal(SIGINT, CocIntSignal);
|
||||||
|
|
||||||
|
while (!interrupt) {
|
||||||
|
logFd=fd;
|
||||||
|
ERR_I(iret=CocRecv(fd, buf, 60, &logFd));
|
||||||
|
if (iret>0) {
|
||||||
|
if (buf->buf[0]==COC_CLRLOG) { /* confirmed "clear log" message */
|
||||||
|
interrupt=3;
|
||||||
|
} else { /* it's a log message */
|
||||||
|
StrReset(buf);
|
||||||
|
while (!StrEnd(buf)) {
|
||||||
|
ERR_P(StrGet(buf, cbuf, COC_SEP));
|
||||||
|
printf("%s", cbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i=t-s;
|
}
|
||||||
if (setmode) {
|
signal(SIGINT, SIG_DFL);
|
||||||
if (*(t-1)==']') setmode=0;
|
logFd=0;
|
||||||
} else {
|
if (interrupt==1) { /* send "clear log" message */
|
||||||
str_ncpy(nam, s, i+1);
|
cbuf[0]=COC_CLRLOG;
|
||||||
ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0));
|
cbuf[1]=COC_SEP; /* send "clear log" message */
|
||||||
}
|
printf("\nclrlog\n");
|
||||||
s=t+1;
|
CocSend(fd, cbuf, 2);
|
||||||
} while (*t!='\0');
|
do {
|
||||||
ERR_I(str_get_end(conn->resbuf));
|
ERR_I(CocRecv(fd, buf, 10, NULL));
|
||||||
|
} while (buf->buf[0]!=COC_CLRLOG);
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
|
OnError:
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
OnError: return(iret);
|
int CocShowLog(CocConn *conn, char *loglist, int start, int lines) {
|
||||||
|
char cbuf[1024];
|
||||||
|
StrBuf *buf;
|
||||||
|
int fd, iret;
|
||||||
|
int i, siz, n;
|
||||||
|
|
||||||
|
fd=conn->fd;
|
||||||
|
CocReset(conn);
|
||||||
|
if (start>0) {
|
||||||
|
ERR_I(CocPutInt(conn, "logstart", start));
|
||||||
|
}
|
||||||
|
ERR_I(CocPutInt(conn, "loglines", lines));
|
||||||
|
ERR_I(CocPutStr(conn, "logshow", loglist));
|
||||||
|
ERR_I(CocDoIt(conn, cbuf, sizeof(cbuf)));
|
||||||
|
buf=&conn->resbuf;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ERR_I(iret=CocRecv(fd, buf, 10, NULL));
|
||||||
|
if (iret<=0) break;
|
||||||
|
if (buf->buf[0]==COC_CLRLOG) { /* end of log message */
|
||||||
|
break;
|
||||||
|
} else { /* it's a log message */
|
||||||
|
StrReset(buf);
|
||||||
|
while (!StrEnd(buf)) {
|
||||||
|
ERR_P(StrGet(buf, cbuf, COC_SEP));
|
||||||
|
printf("%s", cbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CocCloseClient(CocConn *conn) {
|
void CocCloseClient(CocConn *conn) {
|
||||||
assert(conn!=NULL);
|
assert(conn!=NULL);
|
||||||
close(conn->fd);
|
close(conn->fd);
|
||||||
str_free_buf(conn->cmdbuf);
|
|
||||||
str_free_buf(conn->resbuf);
|
|
||||||
CocFreeVarList(&conn->varList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static char rbuf[256];
|
||||||
|
|
||||||
|
int CocSet(CocConn *conn, const char *name, const char *value) {
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
assert(conn!=NULL);
|
||||||
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutStr(conn, name, value));
|
||||||
|
ERR_I(iret=CocDoIt(conn, rbuf, sizeof(rbuf)));
|
||||||
|
if (iret) ERR_MSG(rbuf);
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocGetN(CocConn *conn, const char *name, char *value, int reslen) {
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
assert(conn!=NULL);
|
||||||
|
CocReset(conn);
|
||||||
|
ERR_I(CocGetStr(conn, name, value, reslen));
|
||||||
|
ERR_I(iret=CocDoIt(conn, rbuf, sizeof(rbuf)));
|
||||||
|
if (iret) ERR_MSG(rbuf);
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocSetGetN(CocConn *conn, const char *name, const char *cmd, char *value, int reslen) {
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
assert(conn!=NULL);
|
||||||
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutStr(conn, name, cmd));
|
||||||
|
ERR_I(CocDoIt(conn, value, reslen));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,28 @@
|
|||||||
#ifndef _COC_CLIENT_H_
|
#ifndef _COC_CLIENT_H_
|
||||||
#define _COC_CLIENT_H_
|
#define _COC_CLIENT_H_
|
||||||
|
|
||||||
|
#include "myc_buf.h"
|
||||||
#include "coc_util.h"
|
#include "coc_util.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *adr;
|
||||||
|
int type;
|
||||||
|
char *cmd;
|
||||||
|
} CocArg;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* private */
|
/* private */
|
||||||
int fd, port;
|
int fd, port;
|
||||||
CocVar *varList;
|
StrBuf cmdbuf; /* for sending command */
|
||||||
Str_Buf *cmdbuf; /* for sending command */
|
StrBuf resbuf; /* for response */
|
||||||
Str_Buf *resbuf; /* for response */
|
char cmdbuf_[COC_CMD_LEN];
|
||||||
|
char resbuf_[COC_RES_LEN];
|
||||||
|
CocArg args[16];
|
||||||
|
int nargs;
|
||||||
char host[64];
|
char host[64];
|
||||||
char magic[32];
|
char magic[32];
|
||||||
char startcmd[512];
|
char startcmd[512];
|
||||||
|
char synch;
|
||||||
} CocConn;
|
} CocConn;
|
||||||
|
|
||||||
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd);
|
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd);
|
||||||
@ -22,33 +33,47 @@ int CocSendMagic(CocConn *conn, char *magic);
|
|||||||
/* send magic word to the server for changing access rights
|
/* send magic word to the server for changing access rights
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int CocCmd(CocConn *conn, const char *rwList);
|
void CocReset(CocConn *conn);
|
||||||
/* rwList consists of a list of variables to be read or written.
|
int CocPutStr(CocConn *conn, const char *name, const char *value);
|
||||||
Variables must be separated with commas, variables to be written
|
int CocPutFloat(CocConn *conn, const char *name, float value);
|
||||||
must be enclosed in square brackets.
|
int CocPutInt(CocConn *conn, const char *name, int value);
|
||||||
|
int CocGetStr(CocConn *conn, const char *name, char *value, int value_len);
|
||||||
|
int CocGetFloat(CocConn *conn, const char *name, float *value);
|
||||||
|
int CocGetInt(CocConn *conn, const char *name, int *value);
|
||||||
|
int CocDoIt(CocConn *conn, char *error, int error_len);
|
||||||
|
|
||||||
Example (read p1 and p4, write p2 and p3):
|
|
||||||
CocCmd(&conn, "p1,[p2,p3],p4")
|
|
||||||
|
|
||||||
see COC_UTIL.H for the definiton of variables
|
|
||||||
*/
|
|
||||||
int CocCheck(CocConn *conn);
|
int CocCheck(CocConn *conn);
|
||||||
/*
|
/*
|
||||||
returns 1, if not yet open
|
returns 1, if not yet open
|
||||||
returns 0, if connection o.k.
|
returns 0, if connection o.k.
|
||||||
retruns -1 (error message), if connection died
|
returns -1 (error message), if connection died
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int CocWatchLog(CocConn *conn, char *list);
|
||||||
|
/*
|
||||||
|
Watch indefinitely for log messages
|
||||||
|
*/
|
||||||
|
|
||||||
int CocSet(CocConn *conn, const char *name, const char *value);
|
int CocSet(CocConn *conn, const char *name, const char *value);
|
||||||
/*
|
/*
|
||||||
set one variable
|
set one variable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int CocGetN(CocConn *conn, const char *name, char *value, int reslen);
|
int CocGetN(CocConn *conn, const char *name, char *value, int reslen);
|
||||||
#define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V))
|
#define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V))
|
||||||
/*
|
/*
|
||||||
read one variable. Use the macro if value is a fixed length array
|
read one variable. Use the macro if value is a fixed length array
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int CocSetGetN(CocConn *conn, const char *name, const char *cmd, char *value, int reslen);
|
||||||
|
#define CocSetGet(C,N,S,V) CocSetGetN(C,N,S,V,sizeof(V))
|
||||||
|
/*
|
||||||
|
set and get a variable. Use the macro if value is a fixed length array
|
||||||
|
*/
|
||||||
|
|
||||||
void CocCloseClient(CocConn *conn);
|
void CocCloseClient(CocConn *conn);
|
||||||
/*
|
/*
|
||||||
close the connection to the server
|
close the connection to the server
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif /* _COC_CLIENT_H_ */
|
#endif /* _COC_CLIENT_H_ */
|
||||||
|
@ -1,45 +1,35 @@
|
|||||||
/* switch off ANSI_C_SOURCE for VMS-extended fopen, even when compiling with /ANSI */
|
|
||||||
#ifdef __VMS
|
|
||||||
#ifdef __HIDE_FORBIDDEN_NAMES
|
|
||||||
#undef __HIDE_FORBIDDEN_NAMES
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#define __HIDE_FORBIDDEN_NAMES
|
|
||||||
#else
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "coc_logfile.h"
|
#include "coc_logfile.h"
|
||||||
#include "err_handling.h"
|
#include "myc_time.h"
|
||||||
#include "str_util.h"
|
#include "myc_err.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
|
||||||
static FILE *fil=NULL;
|
static FILE *fil=NULL;
|
||||||
static char lnam[256]="", filnam[256]="";
|
static char lnam[224]="", filnam[256]="";
|
||||||
static char ebuf[20000]="";
|
static char ebuf[20000]="";
|
||||||
static char *statusBuf=NULL;
|
static char *statusBuf=NULL;
|
||||||
static int statusSize;
|
static int statusSize;
|
||||||
static char *eptr=&ebuf[0];
|
static char *eptr=&ebuf[0];
|
||||||
static int lastStamp=0;
|
static int dated=0;
|
||||||
static int notDated=0;
|
|
||||||
static int logMask=0;
|
static int logMask=0;
|
||||||
static int wrtMask=0;
|
static int wrtMask=0;
|
||||||
static int newLine=1;
|
static int newLine=1;
|
||||||
static int logfileStd;
|
static int logfileStd;
|
||||||
static int dirty, writeAll;
|
static int dirty, writeAll;
|
||||||
|
static int lastline=1;
|
||||||
|
static long int lastpos=0;
|
||||||
|
static int lastStamp=0;
|
||||||
|
static int openTime;
|
||||||
|
static int openDate;
|
||||||
|
|
||||||
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */
|
void (*logfileOutRtn)(int, char *)=NULL;
|
||||||
|
|
||||||
void logfileOpen(int first) {
|
void logfileOpen(int append) {
|
||||||
struct tm *tim;
|
int year;
|
||||||
struct timeb btim;
|
|
||||||
|
|
||||||
if (logfileStd) {
|
if (logfileStd) {
|
||||||
fil=stdout;
|
fil=stdout;
|
||||||
@ -47,35 +37,35 @@ void logfileOpen(int first) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(fil==NULL);
|
assert(fil==NULL);
|
||||||
if (first) {
|
openTime = mycNow();
|
||||||
ftime(&btim);
|
openDate = mycDate(openTime); /* date in yyyymmdd decimal encoding */
|
||||||
tim=localtime(&btim.time);
|
openTime = openTime % (24*3600); /* seconds since midnight */
|
||||||
if (notDated) {
|
if (dated) {
|
||||||
if (lnam[0]=='\0') {
|
sprintf(filnam, "%s%02d-%02d.log", lnam, openDate % 10000 / 100, openDate % 100);
|
||||||
str_copy(filnam, "test.log");
|
} else {
|
||||||
} else {
|
if (lnam[0]=='\0') {
|
||||||
str_copy(filnam, lnam);
|
str_copy(filnam, "test.log");
|
||||||
str_append(filnam, ".log");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday);
|
str_copy(filnam, lnam);
|
||||||
|
str_append(filnam, ".log");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dated) {
|
||||||
|
fil=fopen(filnam, "a+");
|
||||||
|
if (fil != NULL) {
|
||||||
|
fseek(fil, 0, SEEK_SET); /* set position to start */
|
||||||
|
year=0;
|
||||||
|
fscanf(fil, "%4d", &year);
|
||||||
|
if (year != openDate / 10000) {
|
||||||
|
fclose(fil);
|
||||||
|
fil=fopen(filnam, "w+"); /* overwrite old logfile */
|
||||||
|
} else {
|
||||||
|
fseek(fil, 0, SEEK_END); /* set position to end */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(filnam[0]!='\0');
|
fil=fopen(filnam, "w+"); /* overwrite last logfile */
|
||||||
}
|
}
|
||||||
#ifdef __VMS
|
|
||||||
if (first && notDated) {
|
|
||||||
fil=fopen(filnam, "w", "SHR=UPD"); /* new version at restart */
|
|
||||||
} else {
|
|
||||||
fil=fopen(filnam, "a", "SHR=UPD");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (first && notDated) {
|
|
||||||
fil=fopen(filnam, "w"); /* overwrite at restart */
|
|
||||||
} else {
|
|
||||||
fil=fopen(filnam, "a");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (fil==NULL) {
|
if (fil==NULL) {
|
||||||
printf("Can not open %s\n", filnam);
|
printf("Can not open %s\n", filnam);
|
||||||
fil=stdout;
|
fil=stdout;
|
||||||
@ -83,10 +73,10 @@ void logfileOpen(int first) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ErrSetOutFile(fil);
|
ErrSetOutFile(fil);
|
||||||
if (first) {
|
fprintf(fil, "%04d-%02d-%02d %02d:%02d:%02d opened logfile\n"
|
||||||
fprintf(fil, "%04d-%02d-%02d opened logfile\n"
|
, openDate / 10000, openDate % 10000 / 100, openDate % 100
|
||||||
, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday);
|
, openTime / 3600, openTime / 60 % 60, openTime % 60);
|
||||||
}
|
lastStamp = openTime / 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileStatusBuffer(char *buffer, int bufsize) {
|
void logfileStatusBuffer(char *buffer, int bufsize) {
|
||||||
@ -96,22 +86,20 @@ void logfileStatusBuffer(char *buffer, int bufsize) {
|
|||||||
|
|
||||||
char *logfileInit(char *path, int nodate, int use_stdout, int write_all) {
|
char *logfileInit(char *path, int nodate, int use_stdout, int write_all) {
|
||||||
str_copy(lnam, path);
|
str_copy(lnam, path);
|
||||||
lastStamp=-2;
|
|
||||||
logfileStd=use_stdout;
|
logfileStd=use_stdout;
|
||||||
writeAll=write_all;
|
writeAll=write_all;
|
||||||
notDated=nodate;
|
dated=!nodate;
|
||||||
logfileOpen(1);
|
logfileOpen(1);
|
||||||
return(filnam);
|
return(filnam);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileOut(int mask, const char *fmt, ...)
|
void logfileOut(int mask, const char *fmt, ...)
|
||||||
{ va_list ap;
|
{ va_list ap;
|
||||||
char buf[256], *p;
|
char buf[8192], *p;
|
||||||
|
|
||||||
assert(mask>0 && mask<32);
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
if (mask & LOG_MAIN && statusBuf!=NULL) {
|
if (mask & LOG_STAT && statusBuf!=NULL) {
|
||||||
if (newLine) {
|
if (newLine) {
|
||||||
statusBuf[0]='\0';
|
statusBuf[0]='\0';
|
||||||
newLine=0;
|
newLine=0;
|
||||||
@ -119,17 +107,22 @@ void logfileOut(int mask, const char *fmt, ...)
|
|||||||
buf[statusSize]='\0';
|
buf[statusSize]='\0';
|
||||||
vsprintf(buf, fmt, ap);
|
vsprintf(buf, fmt, ap);
|
||||||
assert(buf[statusSize]=='\0'); /* check for overflow */
|
assert(buf[statusSize]=='\0'); /* check for overflow */
|
||||||
str_ncat(statusBuf, buf, statusSize);
|
if (buf[0]=='@') {
|
||||||
|
str_ncat(statusBuf, buf+1, statusSize);
|
||||||
|
} else {
|
||||||
|
str_ncat(statusBuf, buf, statusSize);
|
||||||
|
}
|
||||||
p=strchr(statusBuf, '\n');
|
p=strchr(statusBuf, '\n');
|
||||||
if (p!=NULL) {
|
if (p!=NULL) {
|
||||||
newLine=1;
|
newLine=1;
|
||||||
*p='\0';
|
*p='\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (logfileOutRtn!=NULL) {
|
||||||
|
vsprintf(buf, fmt, ap); /* does not check for overflow! */
|
||||||
|
logfileOutRtn(mask, buf);
|
||||||
|
}
|
||||||
if (writeAll) {
|
if (writeAll) {
|
||||||
#ifdef __VMS
|
|
||||||
if (fil==NULL) logfileOpen(0);
|
|
||||||
#endif
|
|
||||||
vfprintf(fil, fmt, ap);
|
vfprintf(fil, fmt, ap);
|
||||||
wrtMask=LOG_ALL;
|
wrtMask=LOG_ALL;
|
||||||
} else {
|
} else {
|
||||||
@ -139,10 +132,14 @@ void logfileOut(int mask, const char *fmt, ...)
|
|||||||
eptr=NULL;
|
eptr=NULL;
|
||||||
} else {
|
} else {
|
||||||
vsprintf(eptr, fmt, ap);
|
vsprintf(eptr, fmt, ap);
|
||||||
assert(NULL==strchr(eptr, '\1'));
|
p=strchr(eptr, '\1');
|
||||||
eptr+=strlen(eptr);
|
if (p==NULL) {
|
||||||
|
eptr+=strlen(eptr);
|
||||||
|
} else {
|
||||||
|
eptr=p; /* is in fact an error */
|
||||||
|
}
|
||||||
eptr[0]='\1'; /* put \1 as separator between blocks */
|
eptr[0]='\1'; /* put \1 as separator between blocks */
|
||||||
eptr[1]=mask;
|
eptr[1]=mask & 31;
|
||||||
eptr[2]='\0';
|
eptr[2]='\0';
|
||||||
eptr+=2;
|
eptr+=2;
|
||||||
}
|
}
|
||||||
@ -157,33 +154,35 @@ void logfileMask(int mask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void logfileStamp(char *text) {
|
void logfileStamp(char *text) {
|
||||||
struct tm *tim;
|
int time, date, stamp;
|
||||||
struct timeb btim;
|
|
||||||
int stamp;
|
|
||||||
|
|
||||||
ftime(&btim);
|
time = mycNow();
|
||||||
tim=localtime(&btim.time);
|
date = mycDate(time); /* date in yyyymmdd decimal encoding */
|
||||||
stamp=tim->tm_hour*60+tim->tm_min;
|
time = time % (24*3600); /* seconds since midnight */
|
||||||
if (stamp<lastStamp) { /* time smaller than last time -> new day -> new logfile */
|
|
||||||
|
stamp=time / 60;
|
||||||
|
if (date != openDate ) { /* day has changed -> new logfile */
|
||||||
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
||||||
|
lastpos=0;
|
||||||
|
lastline=1;
|
||||||
logfileOpen(1);
|
logfileOpen(1);
|
||||||
lastStamp=-2;
|
|
||||||
}
|
}
|
||||||
if (stamp>lastStamp+1) {
|
if (text==NULL) {
|
||||||
#ifdef __VMS
|
if (stamp>lastStamp+1) {
|
||||||
if (fil==NULL) logfileOpen(0);
|
fprintf(fil, "---\t%02d:%02d:%02d\n", stamp / 60, stamp % 60, time % 60, text);
|
||||||
#endif
|
}
|
||||||
lastStamp=stamp;
|
} else {
|
||||||
fprintf(fil, "%02d:%02d:%02d --- %s", tim->tm_hour, tim->tm_min, tim->tm_sec, text);
|
fprintf(fil, "\t%02d:%02d:%02d %s", stamp / 60, stamp % 60, time % 60, text);
|
||||||
dirty=0;
|
|
||||||
}
|
}
|
||||||
|
dirty=0;
|
||||||
|
lastStamp=stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileWrite0(int mask) {
|
void logfileWrite0(int mask) {
|
||||||
char *s, *next;
|
char *s, *next;
|
||||||
|
|
||||||
logMask=logMask | mask;
|
logMask=logMask | mask;
|
||||||
if (dirty) logfileStamp("\n"); /* there was something written since last time */
|
if (dirty) logfileStamp(NULL); /* there was something written since last time */
|
||||||
|
|
||||||
s=ebuf;
|
s=ebuf;
|
||||||
if (writeAll || *s!='\0' && wrtMask & logMask) {
|
if (writeAll || *s!='\0' && wrtMask & logMask) {
|
||||||
@ -193,10 +192,9 @@ void logfileWrite0(int mask) {
|
|||||||
next++;
|
next++;
|
||||||
if (*next & logMask) {
|
if (*next & logMask) {
|
||||||
if (*s=='@') { /* write out time */
|
if (*s=='@') { /* write out time */
|
||||||
lastStamp-=2; /* force output */
|
|
||||||
logfileStamp(s+1);
|
logfileStamp(s+1);
|
||||||
} else {
|
} else {
|
||||||
logfileStamp("\n"); /* write stamp before write something */
|
logfileStamp(NULL); /* write stamp before write something */
|
||||||
fprintf(fil, "%s", s);
|
fprintf(fil, "%s", s);
|
||||||
dirty=1;
|
dirty=1;
|
||||||
}
|
}
|
||||||
@ -211,71 +209,131 @@ void logfileWrite0(int mask) {
|
|||||||
wrtMask=0;
|
wrtMask=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg) {
|
||||||
|
FILE *sFile;
|
||||||
|
char buf[256], *res;
|
||||||
|
|
||||||
|
if (date == openDate) {
|
||||||
|
sFile=fil;
|
||||||
|
rewind(sFile);
|
||||||
|
} else {
|
||||||
|
sprintf(filnam, "%s%02d-%02d.log", lnam, date % 10000 / 100, date % 100);
|
||||||
|
sFile=fopen(filnam, "r+");
|
||||||
|
if (sFile==NULL) return;
|
||||||
|
}
|
||||||
|
res=fgets(buf, sizeof(buf), sFile);
|
||||||
|
while (res!=NULL) {
|
||||||
|
if (res[0]=='\t') {
|
||||||
|
scanLine(arg, res+1);
|
||||||
|
}
|
||||||
|
res=fgets(buf, sizeof(buf), sFile);
|
||||||
|
}
|
||||||
|
if (sFile==fil) {
|
||||||
|
fseek(fil, 0, SEEK_END);
|
||||||
|
} else {
|
||||||
|
fclose(sFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void logfileWrite(int mask) {
|
void logfileWrite(int mask) {
|
||||||
|
|
||||||
#ifdef __VMS
|
|
||||||
if (fil==NULL) logfileOpen(0);
|
|
||||||
#endif
|
|
||||||
logfileWrite0(mask);
|
logfileWrite0(mask);
|
||||||
#ifdef __VMS
|
|
||||||
if (!logfileStd) { fclose(fil); fil=NULL; }
|
|
||||||
#else
|
|
||||||
fflush(fil);
|
fflush(fil);
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileShowErr(char *text)
|
void logfileShowErr(char *text)
|
||||||
{
|
{
|
||||||
#ifdef __VMS
|
|
||||||
if (fil==NULL) logfileOpen(0);
|
|
||||||
#endif
|
|
||||||
logfileWrite0(LOG_ALL); /* write all */
|
logfileWrite0(LOG_ALL); /* write all */
|
||||||
ErrShow(text);
|
ErrShow(text);
|
||||||
#ifdef __VMS
|
|
||||||
if (!logfileStd) { fclose(fil); fil=NULL; }
|
|
||||||
#else
|
|
||||||
fflush(fil);
|
fflush(fil);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileClose()
|
void logfileClose()
|
||||||
{
|
{
|
||||||
#ifdef __VMS
|
|
||||||
if (fil==NULL) logfileOpen(0);
|
|
||||||
#endif
|
|
||||||
logfileWrite0(LOG_MAIN+LOG_INFO);
|
logfileWrite0(LOG_MAIN+LOG_INFO);
|
||||||
lastStamp=-2;
|
lastStamp=-2;
|
||||||
logfileStamp("\n");
|
logfileOut(LOG_MAIN, "closed\n");
|
||||||
|
logfileStamp(NULL);
|
||||||
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
||||||
filnam[0]='\0';
|
filnam[0]='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void logfileOutBuf(int mask, Str_Buf *buf)
|
void logfileOutBuf(int mask, StrBuf *buf)
|
||||||
{ char str[256];
|
{ char str[256];
|
||||||
int rd0, sep;
|
int rd0;
|
||||||
|
char *ret;
|
||||||
|
|
||||||
rd0=buf->rdpos;
|
rd0=buf->rdpos;
|
||||||
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|
||||||
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
|
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
|
||||||
logfileOut(mask, "<buffer corrupt>"); return;
|
logfileOut(mask, "<buffer corrupt>"); return;
|
||||||
}
|
}
|
||||||
sep=0;
|
while (!StrEnd(buf)) {
|
||||||
while (buf->rdpos < buf->wrpos) {
|
ret=StrGet(buf, str, '\0');
|
||||||
str_get_str(buf, str);
|
if (ret==NULL) {
|
||||||
if (buf->sep=='\0') {
|
ret="...";
|
||||||
if (sep) logfileOut(mask, " ");
|
buf->rdpos=buf->wrpos;
|
||||||
if (*str=='\0') {
|
}
|
||||||
logfileOut(mask, ".");
|
if (ret[0]<32 && ret[0]>0) {
|
||||||
} else {
|
logfileOut(mask, "[%d]%s;", ret[0], ret+1);
|
||||||
logfileOut(mask, "%s", str);
|
|
||||||
}
|
|
||||||
sep=1;
|
|
||||||
} else {
|
} else {
|
||||||
if (sep) logfileOut(mask, "%c", buf->sep);
|
logfileOut(mask, "%s;", ret);
|
||||||
logfileOut(mask, "%s", str);
|
|
||||||
sep=1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf->rdpos=rd0;
|
buf->rdpos=rd0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int logfileLength(void) {
|
||||||
|
char lin[256];
|
||||||
|
int l, ll;
|
||||||
|
|
||||||
|
if (logfileStd || fil==NULL) return 0;
|
||||||
|
fseek(fil, lastpos, SEEK_SET);
|
||||||
|
ll=lastpos;
|
||||||
|
l=lastline;
|
||||||
|
while (NULL!=fgets(lin, sizeof(lin), fil)) {
|
||||||
|
lastpos=ll;
|
||||||
|
ll=ftell(fil);
|
||||||
|
lastline=l;
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
return(lastline);
|
||||||
|
}
|
||||||
|
|
||||||
|
long int logfilePos(int n) {
|
||||||
|
/* set file to the start of n-th last line n, if n<0 then position to the -n-th line */
|
||||||
|
int i;
|
||||||
|
char lin[256];
|
||||||
|
|
||||||
|
if (logfileStd || fil==NULL) return 0;
|
||||||
|
if (n>0) {
|
||||||
|
n=logfileLength()-n+1;
|
||||||
|
} else {
|
||||||
|
n=-n;
|
||||||
|
}
|
||||||
|
fseek(fil, 0, SEEK_SET);
|
||||||
|
for (i=1; i<n; i++) {
|
||||||
|
if (NULL==fgets(lin, sizeof(lin), fil)) return ftell(fil);
|
||||||
|
}
|
||||||
|
return ftell(fil);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long int logfileGetLines(long int pos, int linmax, char *line, int len_line) {
|
||||||
|
int l,i;
|
||||||
|
if (logfileStd || fil==NULL) {
|
||||||
|
line[0]='\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
l=0;
|
||||||
|
fseek(fil, pos, SEEK_SET);
|
||||||
|
for (i=0; i<linmax; i++) {
|
||||||
|
if (NULL==fgets(line+l, len_line-l, fil)) {
|
||||||
|
line[l]='\0';
|
||||||
|
return ftell(fil);
|
||||||
|
}
|
||||||
|
l=strlen(line);
|
||||||
|
}
|
||||||
|
pos=ftell(fil);
|
||||||
|
fseek(fil, 0, SEEK_END);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#ifndef _COC_LOGFILE_H_
|
#ifndef _COC_LOGFILE_H_
|
||||||
#define _COC_LOGFILE_H_
|
#define _COC_LOGFILE_H_
|
||||||
|
|
||||||
#include "str_buf.h"
|
#include "myc_buf.h"
|
||||||
|
|
||||||
#define LOG_ALL 31
|
#define LOG_ALL 31
|
||||||
|
#define LOG_STAT 32
|
||||||
#define LOG_SER 8
|
#define LOG_SER 8
|
||||||
#define LOG_NET 4
|
#define LOG_NET 4
|
||||||
#define LOG_INFO 2
|
#define LOG_INFO 2
|
||||||
@ -13,10 +14,15 @@
|
|||||||
void logfileStatusBuffer(char *buffer, int bufsize);
|
void logfileStatusBuffer(char *buffer, int bufsize);
|
||||||
char *logfileInit(char *path, int nodate, int use_stdout, int write_all);
|
char *logfileInit(char *path, int nodate, int use_stdout, int write_all);
|
||||||
void logfileOut(int mask, const char *fmt, ...);
|
void logfileOut(int mask, const char *fmt, ...);
|
||||||
void logfileOutBuf(int mask, Str_Buf *buf);
|
void logfileOutBuf(int mask, StrBuf *buf);
|
||||||
void logfileShowErr(char *text);
|
void logfileShowErr(char *text);
|
||||||
void logfileMask(int mask);
|
void logfileMask(int mask);
|
||||||
|
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg);
|
||||||
void logfileWrite(int mask);
|
void logfileWrite(int mask);
|
||||||
void logfileClose(void);
|
void logfileClose(void);
|
||||||
|
long int logfilePos(int n);
|
||||||
|
long int logfileGetLines(long int pos, int linmax, char *line, int len_line);
|
||||||
|
|
||||||
|
extern void (*logfileOutRtn)(int, char *); /* custom output routine */
|
||||||
|
|
||||||
#endif /* _COC_LOGFILE_H_ */
|
#endif /* _COC_LOGFILE_H_ */
|
||||||
|
@ -1,67 +1,449 @@
|
|||||||
/* needed to define accept() and gethostbyaddr() correctly when using flag -std1
|
|
||||||
*/
|
|
||||||
#ifdef __unix__
|
|
||||||
#ifndef _XOPEN_SOURCE_EXTENDED
|
|
||||||
#define _XOPEN_SOURCE_EXTENDED
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/timeb.h>
|
#include <sys/timeb.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "myc_mem.h"
|
||||||
#include "sys_util.h"
|
#include "sys_util.h"
|
||||||
#include "err_handling.h"
|
#include "myc_err.h"
|
||||||
#include "coc_logfile.h"
|
#include "coc_logfile.h"
|
||||||
|
#include "coc_util.h"
|
||||||
#include "coc_server.h"
|
#include "coc_server.h"
|
||||||
#include "str_util.h"
|
#include "myc_str.h"
|
||||||
|
#include "myc_time.h"
|
||||||
|
|
||||||
static Str_Buf *buf, *bufo;
|
#define COC_NUL COC_SEP
|
||||||
|
|
||||||
|
typedef struct _CocVar {
|
||||||
|
struct _CocVar *next;
|
||||||
|
char name[32];
|
||||||
|
void *var;
|
||||||
|
int access;
|
||||||
|
int type;
|
||||||
|
void *strucType;
|
||||||
|
int (*hdl)(int, void *);
|
||||||
|
int pending;
|
||||||
|
} CocVar;
|
||||||
|
|
||||||
|
CocVar *serverVarList=NULL;
|
||||||
|
static CocVar **varListHandle=&serverVarList;
|
||||||
|
static CocVar *lastDef=NULL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CocVar *var;
|
||||||
|
void *base;
|
||||||
|
int mode;
|
||||||
|
} Pend;
|
||||||
|
|
||||||
|
typedef struct _CocClient {
|
||||||
|
struct _CocClient *next;
|
||||||
|
int fd;
|
||||||
|
int mode;
|
||||||
|
Pend pend[16];
|
||||||
|
int npend;
|
||||||
|
int logmask;
|
||||||
|
char synch;
|
||||||
|
void *data;
|
||||||
|
} CocClient;
|
||||||
|
|
||||||
|
void *(*setData)(void *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
static CocClientData **clData;
|
||||||
|
static int clDataSize;
|
||||||
|
*/
|
||||||
|
|
||||||
|
DeclStrBuf(buf, COC_CMD_LEN);
|
||||||
|
DeclStrBuf(bufo, COC_RES_LEN);
|
||||||
|
|
||||||
static fd_set mask, rmask;
|
static fd_set mask, rmask;
|
||||||
static int maxfd;
|
static int maxfd;
|
||||||
struct CocClient *cList, *cLastCmd=NULL;
|
CocClient *cList;
|
||||||
static int mainFd;
|
static int mainFd;
|
||||||
static int modified;
|
static int modified;
|
||||||
|
static char loglist[16];
|
||||||
|
|
||||||
int CocInitServer(int bufsize, int port) {
|
void CocVarList(void **varList) {
|
||||||
|
if (varList==NULL) {
|
||||||
|
varListHandle=(CocVar **)varList;
|
||||||
|
} else {
|
||||||
|
varListHandle=&serverVarList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocList() {
|
||||||
|
CocVar *p;
|
||||||
|
|
||||||
|
p=*varListHandle;
|
||||||
|
while (p!=NULL) {
|
||||||
|
printf("%s %d ", p->name, p->type);
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
CocVar *CocFindVar1(const char *name) {
|
||||||
|
CocVar *p;
|
||||||
|
|
||||||
|
p=*varListHandle;
|
||||||
|
while (p!=NULL && 0!=strcasecmp(p->name,name)) p=p->next;
|
||||||
|
return(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CocFindVar(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(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(nam);
|
||||||
|
if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */
|
||||||
|
p=CocFindVar(p->var, adr);
|
||||||
|
}
|
||||||
|
return(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *CocIntPtr(int *ptr) { return(ptr); }
|
||||||
|
void *CocFltPtr(float *ptr) { return(ptr); }
|
||||||
|
void *CocChrPtr(char *ptr) { return(ptr); }
|
||||||
|
|
||||||
|
void *CocDefVar(const char *name, void *var, int type, int access) {
|
||||||
|
CocVar *p;
|
||||||
|
const char *f;
|
||||||
|
void *adr;
|
||||||
|
|
||||||
|
assert(varListHandle!=NULL);
|
||||||
|
p=CocFindVar1(name);
|
||||||
|
if (p==NULL) {
|
||||||
|
NEW(p,CocVar);
|
||||||
|
p->next=*varListHandle;
|
||||||
|
*varListHandle=p;
|
||||||
|
str_copy(p->name, name);
|
||||||
|
p->type=type;
|
||||||
|
} else {
|
||||||
|
assert(p->type==type);
|
||||||
|
}
|
||||||
|
p->var=var;
|
||||||
|
p->access=access;
|
||||||
|
/* printf("define %s %d\n", name, (int)var); */
|
||||||
|
lastDef=p;
|
||||||
|
return(p);
|
||||||
|
OnError:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocHdl(int (*handler)(int, void *)) {
|
||||||
|
assert(lastDef!=NULL);
|
||||||
|
lastDef->hdl=handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, COC_RDONLY);
|
||||||
|
p->strucType=CocDefVar(tname, NULL, COC_TYPE, COC_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
char err_name[64];
|
||||||
|
|
||||||
|
int CocGetThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
|
||||||
|
void *adr;
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
if (base==NULL) {
|
||||||
|
adr=var->var;
|
||||||
|
if (adr==NULL)
|
||||||
|
ERR_MSG("NULL pointer accessed");
|
||||||
|
} else { /* dereference */
|
||||||
|
adr=(char *)base + (int)var->var;
|
||||||
|
}
|
||||||
|
/* printf("get %s %d\n", name, (int)adr); */
|
||||||
|
if (var->type==-1) {
|
||||||
|
ERR_I(StrGetInt(buf, (int *)adr, separator));
|
||||||
|
} else if (var->type==-2) {
|
||||||
|
ERR_I(StrGetFloat(buf, (float *)adr, separator));
|
||||||
|
} else if (var->type>1) {
|
||||||
|
ERR_P(StrNGet(buf, (char *)adr, var->type, separator));
|
||||||
|
} else {
|
||||||
|
ERR_MSG("unknown type");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocPutThisVar(CocVar *var, void *base, StrBuf *buf, int separator) {
|
||||||
|
void *adr;
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
if (base==NULL) {
|
||||||
|
adr=var->var;
|
||||||
|
if (adr==NULL)
|
||||||
|
ERR_MSG("NULL pointer accessed");
|
||||||
|
} else { /* dereference */
|
||||||
|
adr=(char *)base + (int)var->var;
|
||||||
|
}
|
||||||
|
/* printf("put %s %d\n", name, (int)adr); */
|
||||||
|
if (var->type==-1) {
|
||||||
|
ERR_I(StrPutInt(buf, *(int *)adr, separator));
|
||||||
|
} else if (var->type==-2) {
|
||||||
|
ERR_I(StrPutFloat(buf, *(float *)adr, separator));
|
||||||
|
} else if (var->type>1) {
|
||||||
|
ERR_I(StrPut(buf, adr, separator));
|
||||||
|
} else {
|
||||||
|
ERR_MSG("unknown type");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocGetVar(const char *name, StrBuf *buf, int separator) {
|
||||||
|
CocVar *var;
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
var=CocFindVar(name, &base);
|
||||||
|
if (var==NULL) ERR_MSG("undefined variable");
|
||||||
|
ERR_I(CocGetThisVar(var, base, buf, separator));
|
||||||
|
return(0);
|
||||||
|
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocPutVar(const char *name, StrBuf *buf, int separator) {
|
||||||
|
CocVar *var;
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
var=CocFindVar(name, &base);
|
||||||
|
if (var==NULL) ERR_MSG("undefined variable");
|
||||||
|
ERR_I(CocPutThisVar(var, base, buf, separator));
|
||||||
|
return(0);
|
||||||
|
OnError: str_copy(err_name, name); ErrTxt(err_name,0); return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocFreeVarList(void) {
|
||||||
|
CocVar *p, *v;
|
||||||
|
|
||||||
|
v=*varListHandle;
|
||||||
|
while (v!=NULL) {
|
||||||
|
p=v;
|
||||||
|
v=p->next;
|
||||||
|
p->next=NULL;
|
||||||
|
FREE(p);
|
||||||
|
}
|
||||||
|
*varListHandle=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocToClients(int mask, char *str) {
|
||||||
|
int iret;
|
||||||
|
CocClient *cl;
|
||||||
|
|
||||||
|
cl=cList->next;
|
||||||
|
while (cl!=NULL) {
|
||||||
|
if (cl->logmask & mask) {
|
||||||
|
iret=CocSend(cl->fd, str, strlen(str)+1);
|
||||||
|
if (iret<0) {
|
||||||
|
cl->logmask=0; /* disable logging for dead clients */
|
||||||
|
logfileOut(LOG_MAIN, "(%d) disconnected while logging\n", cl->fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cl=cl->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocInitServer(void *(*setDataRtn)(void *), int port) {
|
||||||
int i;
|
int i;
|
||||||
struct sockaddr_in sadr;
|
struct sockaddr_in sadr;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
if (bufsize==0) bufsize=1024;
|
setData=setDataRtn;
|
||||||
ERR_P(buf=str_create_buf(bufsize, '\0'));
|
/*
|
||||||
ERR_P(bufo=str_create_buf(bufsize,'\0'));
|
clDataSize=clientDataSize;
|
||||||
NEW(cList); /* empty header */
|
clData=clientData;
|
||||||
|
*/
|
||||||
/* first try to connect to an existing server */
|
NEW(cList,CocClient); /* empty header */
|
||||||
|
|
||||||
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
|
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
|
||||||
i = 1;
|
i = 1;
|
||||||
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
|
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
|
||||||
ERR_I(CocCreateSockAdr(&sadr, NULL, port));
|
ERR_I(CocCreateSockAdr(&sadr, NULL, port));
|
||||||
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||||
|
logfileOutRtn=CocToClients;
|
||||||
logfileOut(LOG_INFO, "created server on port %d\n", port);
|
logfileOut(LOG_INFO, "created server on port %d\n", port);
|
||||||
ERR_SI(listen(mainFd, 8));
|
ERR_SI(listen(mainFd, 8));
|
||||||
FD_ZERO(&mask);
|
FD_ZERO(&mask);
|
||||||
FD_SET(mainFd, &mask);
|
FD_SET(mainFd, &mask);
|
||||||
maxfd=mainFd+1;
|
maxfd=mainFd+1;
|
||||||
|
CocDefStr(loglist, COC_RDWR);
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CocHandleThis(CocVar *var, void *base, StrBuf *outBuf, int mode) {
|
||||||
|
int iret;
|
||||||
|
|
||||||
|
if (var->hdl!=NULL) {
|
||||||
|
iret=var->hdl(mode, base);
|
||||||
|
if (iret<0) { /* error */
|
||||||
|
ErrShow(var->name);
|
||||||
|
ERR_I(StrPut(outBuf, "", COC_ERR)); /* signal error message */
|
||||||
|
ERR_I(StrPut(outBuf, ErrMessage, COC_SEP));
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
if (iret==COC_DRD) {
|
||||||
|
ERR_I(StrPut(outBuf, "", COC_DELAYED)); /* delayed response message */
|
||||||
|
ERR_I(StrPut(outBuf, "", COC_SEP)); /* empty message */
|
||||||
|
return(COC_DRD);
|
||||||
|
}
|
||||||
|
if (iret!=0 && iret!=COC_DWR)
|
||||||
|
ERR_MSG("illegal return value from handler");
|
||||||
|
} else {
|
||||||
|
iret=0;
|
||||||
|
}
|
||||||
|
ERR_I(CocPutThisVar(var, base, outBuf, COC_NUL));
|
||||||
|
return(iret);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocPushThisHandler(CocVar *var, CocClient *cl, void *base, int mode) {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (mode==COC_DWR) {
|
||||||
|
if (var->pending) return(0);
|
||||||
|
var->pending=1;
|
||||||
|
}
|
||||||
|
n=cl->npend;
|
||||||
|
if (n>=sizeof(cl->pend)) {
|
||||||
|
ERR_MSG("too many commands")
|
||||||
|
}
|
||||||
|
cl->pend[n].var=var;
|
||||||
|
cl->pend[n].base=base;
|
||||||
|
cl->pend[n].mode=mode;
|
||||||
|
cl->npend=n+1;
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CocCallHandlers(void) {
|
||||||
|
CocClient *cl;
|
||||||
|
CocVar *var;
|
||||||
|
Pend *p;
|
||||||
|
int i, iret, mode, delayedRead;
|
||||||
|
char synch;
|
||||||
|
DeclStrBuf(bufr, COC_RES_LEN);
|
||||||
|
|
||||||
|
cl=cList->next;
|
||||||
|
while (cl!=NULL) {
|
||||||
|
|
||||||
|
delayedRead=0;
|
||||||
|
/* treat delayed write handlers first */
|
||||||
|
for (i=0; i<cl->npend; i++) {
|
||||||
|
p=&cl->pend[i];
|
||||||
|
mode=p->mode;
|
||||||
|
var=p->var;
|
||||||
|
assert(var!=NULL && var->hdl!=NULL);
|
||||||
|
if (mode==COC_DWR) {
|
||||||
|
var->pending=0;
|
||||||
|
ERR_I(var->hdl(mode, p->base));
|
||||||
|
p->mode=0;
|
||||||
|
} else {
|
||||||
|
delayedRead=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (delayedRead) {
|
||||||
|
StrClear(&bufr);
|
||||||
|
synch=cl->synch;
|
||||||
|
ERR_I(StrPut(&bufr, "", cl->synch));
|
||||||
|
for (i=0; i<cl->npend; i++) {
|
||||||
|
p=&cl->pend[i];
|
||||||
|
mode=p->mode;
|
||||||
|
var=p->var;
|
||||||
|
assert(var!=NULL && var->hdl!=NULL);
|
||||||
|
if (mode==COC_DRD) {
|
||||||
|
iret=var->hdl(mode, p->base);
|
||||||
|
if (iret<0) { /* error */
|
||||||
|
ERR_I(StrPut(&bufr, "", COC_ERR)); /* signal error message */
|
||||||
|
ERR_I(StrPut(&bufr, ErrMessage, COC_SEP));
|
||||||
|
}
|
||||||
|
ERR_I(CocPutThisVar(var, p->base, &bufr, COC_NUL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cl->synch==synch) { /* send only if no new request from client received */
|
||||||
|
assert(cl->fd!=0);
|
||||||
|
ERR_I(CocSend(cl->fd, bufr.buf, bufr.wrpos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cl->npend=0;
|
||||||
|
cl=cl->next;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
cl->npend=0;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocShowHandlers(char *buf, int buf_len) {
|
||||||
|
CocClient *cl;
|
||||||
|
Pend *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
buf[0]='\0';
|
||||||
|
cl=cList->next;
|
||||||
|
while (cl!=NULL) {
|
||||||
|
for (i=0; i<cl->npend; i++) {
|
||||||
|
p=&cl->pend[i];
|
||||||
|
if (p->mode==COC_DWR) {
|
||||||
|
assert(p->var!=NULL);
|
||||||
|
if (buf[0]!='\0') str_ncat(buf, ", ", buf_len);
|
||||||
|
str_ncat(buf, p->var->name, buf_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cl=cl->next;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int CocHandle1Request(int tmo_msec, int fd) {
|
int CocHandle1Request(int tmo_msec, int fd) {
|
||||||
struct sockaddr_in cadr;
|
struct sockaddr_in cadr;
|
||||||
struct hostent *h;
|
struct hostent *h;
|
||||||
struct timeval tmo={0,1};
|
struct timeval tmo={0,1};
|
||||||
struct CocClient *cl, *cl0;
|
CocClient *cl, *cl0;
|
||||||
int i, newfd, setmode;
|
CocVar *var;
|
||||||
size_t cadrlen;
|
int i, lmask, newfd, n, iret;
|
||||||
char *err, *varname;
|
sys_adr_len cadrlen; /* see sys_util.h */
|
||||||
|
char *err, *cmd, *arg, *varname;
|
||||||
|
void *base;
|
||||||
|
|
||||||
rmask=mask;
|
rmask=mask;
|
||||||
if (fd>0) FD_SET(fd, &rmask);
|
if (fd>0) FD_SET(fd, &rmask);
|
||||||
@ -76,14 +458,18 @@ int CocHandle1Request(int tmo_msec, int fd) {
|
|||||||
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
|
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
|
||||||
FD_SET(newfd, &mask);
|
FD_SET(newfd, &mask);
|
||||||
if (newfd>=maxfd) maxfd=newfd+1;
|
if (newfd>=maxfd) maxfd=newfd+1;
|
||||||
cl=cList;
|
NEW(cl, CocClient);
|
||||||
cl->fd=newfd;
|
cl->fd=newfd;
|
||||||
cl->mode=0;
|
cl->mode=0;
|
||||||
cl->cmd[0]='\0';
|
if (setData!=NULL) {
|
||||||
cl->res[0]='\0';
|
ERR_P(cl->data = setData(NULL)); /* create new client data object */
|
||||||
NEW(cList);
|
}
|
||||||
|
/*
|
||||||
|
ERR_SP(cList=calloc(1,sizeof(CocClient)+clDataSize));
|
||||||
|
*/
|
||||||
|
cl->next=cList->next;
|
||||||
cList->next=cl;
|
cList->next=cl;
|
||||||
h=gethostbyaddr(&cadr.sin_addr, 4, AF_INET);
|
h=gethostbyaddr((void *)&cadr.sin_addr, 4, AF_INET);
|
||||||
if (h==NULL) {
|
if (h==NULL) {
|
||||||
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
|
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
|
||||||
} else {
|
} else {
|
||||||
@ -93,8 +479,8 @@ int CocHandle1Request(int tmo_msec, int fd) {
|
|||||||
cl0=cList; cl=cl0->next;
|
cl0=cList; cl=cl0->next;
|
||||||
while (cl!=NULL) {
|
while (cl!=NULL) {
|
||||||
if (FD_ISSET(cl->fd, &rmask)) {
|
if (FD_ISSET(cl->fd, &rmask)) {
|
||||||
buf->wrpos=recv(cl->fd, buf->buf, buf->dsize, 0);
|
iret=CocRecv(cl->fd, &buf, -1, NULL);
|
||||||
if (buf->wrpos<=0) {
|
if (iret<=0) {
|
||||||
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
|
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
|
||||||
close(cl->fd);
|
close(cl->fd);
|
||||||
FD_CLR(cl->fd, &mask);
|
FD_CLR(cl->fd, &mask);
|
||||||
@ -102,76 +488,81 @@ int CocHandle1Request(int tmo_msec, int fd) {
|
|||||||
FREE(cl);
|
FREE(cl);
|
||||||
cl=cl0;
|
cl=cl0;
|
||||||
} else {
|
} else {
|
||||||
|
cl->logmask=0; /* stop output to log client */
|
||||||
str_put_start(bufo);
|
lmask=0;
|
||||||
str_get_start(buf);
|
StrReset(&buf);
|
||||||
ERR_I(str_put_str(bufo, "")); /* empty error message */
|
StrClear(&bufo);
|
||||||
setmode=0;
|
|
||||||
err=NULL;
|
err=NULL;
|
||||||
ERR_P(varname=str_get_str(buf, NULL));
|
|
||||||
logfileOut(LOG_NET, "(%d) ", cl->fd);
|
logfileOut(LOG_NET, "(%d) ", cl->fd);
|
||||||
if (varname[0]=='#') { /* access code */
|
logfileOutBuf(LOG_NET, &buf);
|
||||||
if (0==strcmp(varname,"#rdacc")) {
|
/* cl->npend=0; why that ? */
|
||||||
logfileOut(LOG_INFO, "set read mode\n");
|
logfileOut(LOG_NET, "\n");
|
||||||
cl->mode=1;
|
cl->synch=buf.buf[0];
|
||||||
} else if (0==strcmp(varname,"#rwacs")) {
|
ERR_P(StrGet(&buf, NULL, cl->synch));
|
||||||
logfileOut(LOG_INFO, "set write mode\n");
|
ERR_I(StrPut(&bufo, "", cl->synch));
|
||||||
cl->mode=2;
|
while (!StrEnd(&buf)) {
|
||||||
} else {
|
ERR_P(varname=StrGet(&buf, NULL, ' '));
|
||||||
err="bad access code";
|
if (cl->synch==COC_MAGIC) { /* access code */
|
||||||
}
|
if (0==strcmp(varname,"rdacs")) {
|
||||||
} else if (cl->mode==0) {
|
logfileOut(LOG_INFO, "set read mode\n");
|
||||||
err="no access";
|
cl->mode=1;
|
||||||
} else {
|
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
||||||
while (1) {
|
} else if (0==strcmp(varname,"rwacs")) {
|
||||||
if (varname[0]=='[') {
|
logfileOut(LOG_INFO, "set write mode\n");
|
||||||
if (cl->mode<2) { err="no write access"; break; }
|
cl->mode=2;
|
||||||
setmode=1; /* switch to set mode */
|
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
||||||
} else if (varname[0]==']') { /* switch to read mode */
|
|
||||||
setmode=0;
|
|
||||||
} else if (setmode) {
|
|
||||||
if (0==strcmp("$", varname)) { /* special case: command */
|
|
||||||
ERR_P(str_get_str(buf, cl->cmd));
|
|
||||||
cl->res[0]='\0';
|
|
||||||
} else {
|
|
||||||
i=CocGetVar(serverVarList, buf, varname, 1);
|
|
||||||
if (i<0) {
|
|
||||||
err=ErrMessage; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modified=1;
|
|
||||||
} else {
|
} else {
|
||||||
if (0==strcmp("$", varname)) { /* special case: response */
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||||
ERR_I(str_put_str(bufo, cl->res));
|
ERR_I(StrPut(&bufo, "bad access code", COC_SEP));
|
||||||
cl->res[0]='\0';
|
}
|
||||||
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||||
|
} else if (cl->mode==0) {
|
||||||
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal terminal error message */
|
||||||
|
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
||||||
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||||
|
} else {
|
||||||
|
if (cl->data!=NULL) {
|
||||||
|
setData(cl->data);
|
||||||
|
}
|
||||||
|
var=CocFindVar(varname, &base);
|
||||||
|
if (var==NULL) {
|
||||||
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||||
|
ERR_I(StrPut(&bufo, "undefined variable", COC_SEP));
|
||||||
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||||
|
} else if (buf.seen) { /* separator was there: set mode */
|
||||||
|
if (var->access > cl->mode) {
|
||||||
|
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||||
|
ERR_I(StrPut(&bufo, "no access", COC_SEP));
|
||||||
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||||
} else {
|
} else {
|
||||||
i=CocPutVar(serverVarList, bufo, varname, 0);
|
ERR_I(CocGetThisVar(var, base, &buf, COC_SEP));
|
||||||
if (i<0) {
|
if (0==strcmp(var->name,"loglist")) {
|
||||||
err=ErrMessage; break;
|
str_upcase(loglist, loglist);
|
||||||
|
if (NULL!=strchr(loglist,'A')) lmask = lmask | LOG_ALL;
|
||||||
|
if (NULL!=strchr(loglist,'S')) lmask = lmask | LOG_SER;
|
||||||
|
if (NULL!=strchr(loglist,'N')) lmask = lmask | LOG_NET;
|
||||||
|
if (NULL!=strchr(loglist,'I')) lmask = lmask | LOG_INFO;
|
||||||
|
if (NULL!=strchr(loglist,'M')) lmask = lmask | LOG_MAIN;
|
||||||
|
ERR_I(StrPut(&bufo, "", COC_NUL)); /* o.k. */
|
||||||
|
} else {
|
||||||
|
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_WR));
|
||||||
|
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
|
||||||
}
|
}
|
||||||
|
modified=1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ERR_P(StrGet(&buf, NULL, COC_NUL)); /* skip separator */
|
||||||
|
ERR_I(iret=CocHandleThis(var, base, &bufo, COC_RD));
|
||||||
|
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
|
||||||
}
|
}
|
||||||
if (buf->rdpos>=buf->wrpos) {
|
|
||||||
ERR_I(str_get_end(buf));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ERR_P(varname=str_get_str(buf, NULL));
|
|
||||||
}
|
}
|
||||||
str_get_start(buf);
|
|
||||||
logfileOutBuf(LOG_NET, buf);
|
|
||||||
str_get_start(bufo);
|
|
||||||
logfileOut(LOG_NET, " |");
|
|
||||||
logfileOutBuf(LOG_NET, bufo);
|
|
||||||
}
|
}
|
||||||
if (err==NULL) {
|
ERR_I(StrGetEnd(&buf));
|
||||||
logfileOut(LOG_NET, "\n");
|
logfileOut(LOG_NET, " ");
|
||||||
} else {
|
logfileOutBuf(LOG_NET, &bufo);
|
||||||
str_put_start(bufo); /* reset output */
|
logfileOut(LOG_NET, "\n");
|
||||||
str_put_str(bufo, err); /* put error message */
|
ERR_I(CocSend(cl->fd, bufo.buf, bufo.wrpos));
|
||||||
logfileOut(LOG_NET, " (%s)\n", err);
|
cl->logmask=lmask;
|
||||||
/* logfileMask(LOG_NET); */
|
|
||||||
}
|
|
||||||
ERR_SI(send(cl->fd, bufo->buf, bufo->wrpos, 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cl0=cl; cl=cl->next;
|
cl0=cl; cl=cl->next;
|
||||||
@ -183,54 +574,30 @@ int CocHandle1Request(int tmo_msec, int fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CocHandleRequests(int tmo_msec, int fd) {
|
int CocHandleRequests(int tmo_msec, int fd) {
|
||||||
struct timeb tim1, tim0;
|
int tdif, iret, tim0;
|
||||||
int tdif, iret;
|
|
||||||
|
|
||||||
if (modified && fd==0) { /* earlier modification */
|
if (modified && fd==0) { /* earlier modification */
|
||||||
modified=0;
|
modified=0;
|
||||||
return(2);
|
return(2);
|
||||||
}
|
}
|
||||||
ftime(&tim0);
|
tim0=mycMsecSince(0);
|
||||||
tdif=tmo_msec;
|
tdif=tmo_msec;
|
||||||
while (tdif>=0) {
|
while (tdif>=0) {
|
||||||
ERR_I(iret=CocHandle1Request(tdif, fd));
|
ERR_I(iret=CocHandle1Request(tdif, fd));
|
||||||
if (fd==0) {
|
if (fd==0) {
|
||||||
if (iret==2) return(2); /* modification of a varaible */
|
if (iret==2) return(2); /* modification of a variable */
|
||||||
} else {
|
} else {
|
||||||
if (iret==1) return(1); /* event on fd */
|
if (iret==1) return(1); /* event on fd */
|
||||||
}
|
}
|
||||||
if (iret==0) return(0); /* timeout */
|
if (iret==0) return(0); /* timeout */
|
||||||
ftime(&tim1);
|
tdif = tmo_msec - mycMsecSince(tim0);
|
||||||
tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm);
|
|
||||||
}
|
}
|
||||||
return(0); /* timeout */
|
return(0); /* timeout */
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CocClient *CocGetNextCmd() {
|
|
||||||
struct CocClient *cl;
|
|
||||||
|
|
||||||
cl=cLastCmd;
|
|
||||||
while (cl!=NULL) {
|
|
||||||
if (cl->cmd[0]!='\0') {
|
|
||||||
cLastCmd=cl->next;
|
|
||||||
return(cl);
|
|
||||||
}
|
|
||||||
cl=cl->next;
|
|
||||||
}
|
|
||||||
cl=cList->next;
|
|
||||||
while (cl!=NULL && cl!=cLastCmd) {
|
|
||||||
if (cl->cmd[0]!='\0') {
|
|
||||||
cLastCmd=cl->next;
|
|
||||||
return(cl);
|
|
||||||
}
|
|
||||||
cl=cl->next;
|
|
||||||
}
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CocCloseServer() {
|
void CocCloseServer() {
|
||||||
struct CocClient *cl, *cl0;
|
CocClient *cl, *cl0;
|
||||||
|
|
||||||
cl=cList->next;
|
cl=cList->next;
|
||||||
while (cl!=NULL) {
|
while (cl!=NULL) {
|
||||||
@ -241,6 +608,4 @@ void CocCloseServer() {
|
|||||||
}
|
}
|
||||||
FREE(cList);
|
FREE(cList);
|
||||||
close(mainFd);
|
close(mainFd);
|
||||||
str_free_buf(buf); str_free_buf(bufo);
|
|
||||||
logfileClose();
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,78 @@
|
|||||||
#ifndef _SERVER_H_
|
#ifndef _SERVER_H_
|
||||||
#define _SERVER_H_
|
#define _SERVER_H_
|
||||||
|
|
||||||
#include "coc_util.h"
|
#include "myc_buf.h"
|
||||||
|
|
||||||
struct CocClient { struct CocClient *next; int fd; int mode; char cmd[80]; char res[80]; };
|
void CocVarList(void **varlist);
|
||||||
|
/*
|
||||||
|
instal a variable list
|
||||||
|
*/
|
||||||
|
|
||||||
int CocInitServer(int bufsize, int port);
|
void CocFreeVarList(void);
|
||||||
|
/*
|
||||||
|
free variable list
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *CocFindVar(const char *name, void **adr);
|
||||||
|
/*
|
||||||
|
find a variable. returns NULL if not found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int CocPutVar(const char *name, StrBuf *buf, int separator);
|
||||||
|
/*
|
||||||
|
put a variable named <name> of variable list <varList> to the buffer <buf>
|
||||||
|
*/
|
||||||
|
|
||||||
|
int CocGetVar(const char *name, StrBuf *buf, int separator);
|
||||||
|
/*
|
||||||
|
get a variable named <name> of variable list <varList> from the buffer <buf>
|
||||||
|
*/
|
||||||
|
|
||||||
|
void CocHdl(int (*handler)(int, void *));
|
||||||
|
/*
|
||||||
|
define handler for last defined item
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *CocIntPtr(int *ptr);
|
||||||
|
void *CocFltPtr(float *ptr);
|
||||||
|
void *CocChrPtr(char *ptr);
|
||||||
|
void *CocDefVar(const char *name, void *var, int type, int access);
|
||||||
|
void CocDefVarS(const char *name, const char *tname, void *var, int type);
|
||||||
|
/*
|
||||||
|
Define variables. Call this routines not directly, but through
|
||||||
|
one of the macros below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CocDefInt(V,A) CocDefVar(#V,CocIntPtr(&V),COC_INT,A)
|
||||||
|
#define CocDefFlt(V,A) CocDefVar(#V,CocFltPtr(&V),COC_FLT,A)
|
||||||
|
#define CocDefStr(V,A) CocDefVar(#V,CocChrPtr(V),sizeof(V),A)
|
||||||
|
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,(V!=(S *)NULL,COC_PTR));
|
||||||
|
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,(&V!=(S *)NULL,COC_STRUCT));
|
||||||
|
#define CocIntFld(S,V,A) CocDefVar(#S":"#V,CocIntPtr(&((S *)NULL)->V),COC_INT,A);
|
||||||
|
#define CocFltFld(S,V,A) CocDefVar(#S":"#V,CocFltPtr(&((S *)NULL)->V),COC_FLT,A);
|
||||||
|
#define CocStrFld(S,V,A) CocDefVar(#S":"#V,CocChrPtr(((S *)NULL)->V),sizeof(((S *)NULL)->V),A);
|
||||||
|
#define CocDefCmd(V) CocDefVar("$",V,sizeof(V),0)
|
||||||
|
#define CocDefStrPtr(V,S,A) CocDefVar(#V,V,S,A)
|
||||||
|
#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS,0);
|
||||||
|
|
||||||
|
#define COC_RDONLY 3
|
||||||
|
#define COC_RDWR 2
|
||||||
|
#define COC_RDWRALL 1
|
||||||
|
|
||||||
|
#define COC_WR 1
|
||||||
|
#define COC_RD 2
|
||||||
|
#define COC_DWR 3
|
||||||
|
#define COC_DRD 4
|
||||||
|
#define COC_SHOW 5
|
||||||
|
|
||||||
|
#define COC_INT -1
|
||||||
|
#define COC_FLT -2
|
||||||
|
#define COC_PTR -3
|
||||||
|
#define COC_STRUCT -4
|
||||||
|
#define COC_TYPE -5
|
||||||
|
#define COC_ALIAS -6
|
||||||
|
|
||||||
|
int CocInitServer(void *(*setDataRtn)(void *), int port);
|
||||||
|
|
||||||
int CocHandleRequests(int tmo_msec, int fd);
|
int CocHandleRequests(int tmo_msec, int fd);
|
||||||
int CocHandle1Request(int tmo_msec, int fd);
|
int CocHandle1Request(int tmo_msec, int fd);
|
||||||
@ -30,11 +97,13 @@ int CocHandle1Request(int tmo_msec, int fd);
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct CocClient *CocGetNextCmd(void);
|
/* server handlers removed
|
||||||
/*
|
int CocPushHandler(const char *name);
|
||||||
get next client with a pending command
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int CocCallHandlers(void);
|
||||||
|
void CocShowHandlers(char *buf, int buf_len);
|
||||||
|
|
||||||
void CocCloseServer(void);
|
void CocCloseServer(void);
|
||||||
|
|
||||||
#endif /* _SERVER_H_ */
|
#endif /* _SERVER_H_ */
|
||||||
|
267
tecs/coc_util.c
267
tecs/coc_util.c
@ -1,24 +1,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <strings.h>
|
#include <sys/time.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include "myc_err.h"
|
||||||
#include "sys_util.h"
|
#include "myc_str.h"
|
||||||
#include "err_handling.h"
|
|
||||||
#include "str_util.h"
|
|
||||||
#include "coc_util.h"
|
#include "coc_util.h"
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
|
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
|
||||||
|
|
||||||
CocVar *serverVarList=NULL;
|
|
||||||
static CocVar **varListHdl=&serverVarList;
|
|
||||||
int CocRD=0;
|
|
||||||
int CocWR=0;
|
|
||||||
|
|
||||||
int CocCreateSockAdr(
|
int CocCreateSockAdr(
|
||||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||||
@ -55,202 +46,6 @@ int CocCreateSockAdr(
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
int CocRecv(int fd, Str_Buf *buf)
|
|
||||||
{
|
|
||||||
struct timeval tmo={0,1};
|
|
||||||
fd_set mask;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
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(buf->wrpos);
|
|
||||||
OnError: return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CocVarList(CocVar **varList) {
|
|
||||||
assert(varList!=NULL);
|
|
||||||
varListHdl=varList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CocList() {
|
|
||||||
CocVar *p;
|
|
||||||
|
|
||||||
p=*varListHdl;
|
|
||||||
while (p!=NULL) {
|
|
||||||
printf("%s %d ", p->name, p->type);
|
|
||||||
p=p->next;
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
CocVar *CocFindVar1(CocVar *varList, const char *name) {
|
|
||||||
CocVar *p;
|
|
||||||
|
|
||||||
p=varList;
|
|
||||||
while (p!=NULL && 0!=strcasecmp(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) {
|
|
||||||
NEW(p);
|
|
||||||
p->next=*varListHdl;
|
|
||||||
*varListHdl=p;
|
|
||||||
str_copy(p->name, name);
|
|
||||||
p->type=type;
|
|
||||||
} else {
|
|
||||||
assert(p->type==type);
|
|
||||||
}
|
|
||||||
p->var=var;
|
|
||||||
p->flag=flag;
|
|
||||||
/* printf("define %s %d\n", name, (int)var); */
|
|
||||||
return(p);
|
|
||||||
OnError:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
char err_name[64];
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
/* printf("get %s %d\n", name, (int)adr); */
|
|
||||||
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: str_copy(err_name, name); ErrTxt(err_name,0); 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) { /* check access */
|
|
||||||
if (var->flag==&CocRD) ERR_MSG("variable is read only");
|
|
||||||
}
|
|
||||||
/* printf("put %s %d\n", name, (int)adr); */
|
|
||||||
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: str_copy(err_name, name); ErrTxt(err_name,0); 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) {
|
void CocDelay(int msec) {
|
||||||
struct timeval tmo;
|
struct timeval tmo;
|
||||||
|
|
||||||
@ -258,3 +53,59 @@ void CocDelay(int msec) {
|
|||||||
tmo.tv_usec=(msec % 1000)*1000+1;
|
tmo.tv_usec=(msec % 1000)*1000+1;
|
||||||
select(1,NULL,NULL,NULL,&tmo);
|
select(1,NULL,NULL,NULL,&tmo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocSend(int fd, char *str, int size) {
|
||||||
|
int siz;
|
||||||
|
siz=htonl(size);
|
||||||
|
ERR_SI(send(fd, &siz, 4, 0));
|
||||||
|
ERR_SI(send(fd, str, size, 0));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int CocRecv(int fd, StrBuf *buf, int timeout, int *flag) {
|
||||||
|
struct timeval tmo={0,1};
|
||||||
|
fd_set mask;
|
||||||
|
int i, l;
|
||||||
|
int siz, n;
|
||||||
|
|
||||||
|
if (timeout>=0) {
|
||||||
|
tmo.tv_sec=timeout;
|
||||||
|
|
||||||
|
FD_ZERO(&mask);
|
||||||
|
FD_SET(fd, &mask);
|
||||||
|
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
|
||||||
|
if (flag!=NULL) {
|
||||||
|
*flag=0;
|
||||||
|
if (i==0) return(0);
|
||||||
|
} else {
|
||||||
|
if (i==0) { ERR_MSG("time out"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n=0;
|
||||||
|
ERR_SI(i=recv(fd, &n, 4, 0));
|
||||||
|
if (i!=4) {
|
||||||
|
ERR_COD(ECONNRESET);
|
||||||
|
}
|
||||||
|
siz=ntohl(n);
|
||||||
|
if (siz > buf->dsize)
|
||||||
|
ERR_MSG("buffer too small");
|
||||||
|
ERR_SI(l=recv(fd, buf->buf, siz, 0));
|
||||||
|
buf->wrpos=l;
|
||||||
|
while (buf->wrpos<siz) {
|
||||||
|
if (l==0) {
|
||||||
|
ERR_COD(ECONNRESET);
|
||||||
|
}
|
||||||
|
ERR_SI(l=recv(fd, buf->buf+buf->wrpos, siz, 0));
|
||||||
|
buf->wrpos+=l;
|
||||||
|
}
|
||||||
|
StrReset(buf);
|
||||||
|
return(buf->wrpos);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
#define _COC_UTIL_H_
|
#define _COC_UTIL_H_
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include "str_buf.h"
|
#include "myc_buf.h"
|
||||||
|
|
||||||
|
#define COC_CMD_LEN 256
|
||||||
|
#define COC_RES_LEN 8192
|
||||||
|
|
||||||
int CocCreateSockAdr(
|
int CocCreateSockAdr(
|
||||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||||
@ -12,76 +15,34 @@ int CocCreateSockAdr(
|
|||||||
compose internet address
|
compose internet address
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int CocRecv(int fd, Str_Buf *buf);
|
|
||||||
/*
|
|
||||||
receive data
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* private */
|
|
||||||
void *next;
|
|
||||||
char name[32];
|
|
||||||
void *var;
|
|
||||||
int *flag;
|
|
||||||
int type;
|
|
||||||
void *strucType;
|
|
||||||
} CocVar;
|
|
||||||
|
|
||||||
extern int CocRD; /* readonly variable (used as argument for CocDefXXX) */
|
|
||||||
extern int CocWR; /* read/write variable (used as argument for CocDefXXX) */
|
|
||||||
CocVar *serverVarList; /* variable list for the server process */
|
|
||||||
|
|
||||||
CocVar *CocDefVar(const char *name, void *var, int type, int *flag);
|
|
||||||
void CocDefVarS(const char *name, const char *tname, void *var, int type);
|
|
||||||
/*
|
|
||||||
Define variables. Call this routines not directly, but through
|
|
||||||
one of the macros below.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void CocVarList(CocVar **varlist);
|
|
||||||
/*
|
|
||||||
print a variable list (for debugging purposes)
|
|
||||||
*/
|
|
||||||
void CocFreeVarList(CocVar **varList);
|
|
||||||
/*
|
|
||||||
free a variable list
|
|
||||||
*/
|
|
||||||
CocVar *CocFindVar(CocVar *varList, const char *name, void **adr);
|
|
||||||
/*
|
|
||||||
find a variable. returns NULL if not found.
|
|
||||||
*/
|
|
||||||
int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure);
|
|
||||||
/*
|
|
||||||
put a variable named <name> of variable list <varList> to the buffer <buf>
|
|
||||||
if <secure>, access rights are checked
|
|
||||||
*/
|
|
||||||
int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure);
|
|
||||||
/*
|
|
||||||
get a variable named <name> of variable list <varList> from the buffer <buf>
|
|
||||||
if <secure>, access rights are checked
|
|
||||||
*/
|
|
||||||
void CocDelay(int msec);
|
void CocDelay(int msec);
|
||||||
/*
|
/*
|
||||||
system independent delay function with msec resolution
|
system independent delay function with msec resolution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int CocSend(int fd, char *buf, int size);
|
||||||
|
/*
|
||||||
|
send a message
|
||||||
|
*/
|
||||||
|
|
||||||
|
int CocRecv(int fd, StrBuf *buf, int timeout, int *flag);
|
||||||
|
/*
|
||||||
|
receive message
|
||||||
|
if flag is NULL, a timeout generates an error
|
||||||
|
else *flag is set to zero between the select and the recv command
|
||||||
|
*/
|
||||||
|
|
||||||
#define COC_INT -1
|
#define COC_INT -1
|
||||||
#define COC_FLT -2
|
#define COC_FLT -2
|
||||||
#define COC_PTR -3
|
#define COC_PTR -3
|
||||||
#define COC_STRUCT -4
|
|
||||||
#define COC_TYPE -5
|
|
||||||
#define COC_ALIAS -6
|
|
||||||
|
|
||||||
/* macros to define variables */
|
#define COC_SEP '\0'
|
||||||
#define CocDefInt(V,F) CocDefVar(#V,&V,COC_INT,&F)
|
#define COC_DELAYED '\1'
|
||||||
#define CocDefFlt(V,F) CocDefVar(#V,&V,COC_FLT,&F)
|
#define COC_ERR '\2'
|
||||||
#define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F)
|
#define COC_TRM '\3'
|
||||||
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,COC_PTR*(V!=(S *)NULL));
|
#define COC_SYN0 '\4'
|
||||||
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,COC_STRUCT*(&V!=(S *)NULL));
|
#define COC_SYN1 '\5'
|
||||||
#define CocIntFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_INT,&F);
|
#define COC_MAGIC '\6'
|
||||||
#define CocFltFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_FLT,&F);
|
#define COC_CLRLOG '\7'
|
||||||
#define CocStrFld(S,V,F) CocDefVar(#S":"#V,((S *)NULL)->V,sizeof(((S *)NULL)->V),&F);
|
|
||||||
#define CocDefCmd(V) CocDefVar("$",V,sizeof(V),&CocWR)
|
|
||||||
#define CocDefStrPtr(V,S,F) CocDefVar(#V,V,S,&F)
|
|
||||||
#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS, &CocRD);
|
|
||||||
|
|
||||||
#endif /* _COC_UTIL_H_ */
|
#endif /* _COC_UTIL_H_ */
|
||||||
|
218
tecs/myc_buf.c
Normal file
218
tecs/myc_buf.c
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sys_util.h"
|
||||||
|
#include "myc_err.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_buf.h"
|
||||||
|
|
||||||
|
char *StrNGet(StrBuf *buf, char *result, int reslen, int sep) {
|
||||||
|
char *b, *f, *e, quote;
|
||||||
|
int res, l, ll;
|
||||||
|
|
||||||
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize || buf->buf==NULL)
|
||||||
|
ERR_MSG("buffer corrupt");
|
||||||
|
b=buf->buf + buf->rdpos;
|
||||||
|
if (*b=='"' || *b=='\'') { /* take string within quotes (single or double) */
|
||||||
|
quote=*b; b++;
|
||||||
|
f=strchr(b, quote);
|
||||||
|
if (f==NULL)
|
||||||
|
ERR_MSG("missing '""'");
|
||||||
|
l=f-b;
|
||||||
|
e=strchr(f+1, sep);
|
||||||
|
if (e==NULL) {
|
||||||
|
buf->rdpos = f - buf->buf + 1 + strlen(f+1);
|
||||||
|
buf->seen=0;
|
||||||
|
} else {
|
||||||
|
buf->rdpos = e - buf->buf + 1;
|
||||||
|
buf->seen=1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f=strchr(b, sep);
|
||||||
|
if (f==NULL) {
|
||||||
|
l=strlen(b);
|
||||||
|
f=b+l;
|
||||||
|
buf->rdpos+=l;
|
||||||
|
buf->seen=0;
|
||||||
|
} else {
|
||||||
|
l=f-b;
|
||||||
|
buf->rdpos+=l+1;
|
||||||
|
buf->seen=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result==NULL) {
|
||||||
|
if (reslen==-1) { /* special case for StrGetBuf */
|
||||||
|
return(f);
|
||||||
|
}
|
||||||
|
*f='\0';
|
||||||
|
return(b);
|
||||||
|
} else {
|
||||||
|
if (l>=reslen) l=reslen-1; /* ERR_MSG("result too short"); */
|
||||||
|
strncpy(result, b, l);
|
||||||
|
result[l]='\0';
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
OnError:
|
||||||
|
buf->rdpos=buf->dsize; /* illegal value */
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrGetBuf(StrBuf *buf, StrBuf *res, int sep) {
|
||||||
|
char *b, *f;
|
||||||
|
|
||||||
|
b = buf->buf + buf->rdpos;
|
||||||
|
ERR_P(f=StrNGet(buf, NULL, -1, sep));
|
||||||
|
res->buf = b;
|
||||||
|
res->wrpos = f-b;
|
||||||
|
res->rdpos = 0;
|
||||||
|
res->dsize = f-b;
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
buf->rdpos=buf->dsize; /* illegal value */
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrGetInt(StrBuf *buf, int *res, int sep) {
|
||||||
|
char num[32];
|
||||||
|
int i, l, p;
|
||||||
|
|
||||||
|
p=buf->rdpos;
|
||||||
|
ERR_P(StrGet(buf, num, sep));
|
||||||
|
i=sscanf(num, "%d%n", res, &l);
|
||||||
|
if (i==0)
|
||||||
|
ERR_MSG("illegal number");
|
||||||
|
if (sep==StrNONE) {
|
||||||
|
buf->rdpos=p+l;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
buf->rdpos=buf->dsize; /* illegal value */
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrGetFloat(StrBuf *buf, float *res, int sep) {
|
||||||
|
char num[32];
|
||||||
|
int i, l, p;
|
||||||
|
|
||||||
|
p=buf->rdpos;
|
||||||
|
ERR_P(StrGet(buf, num, sep));
|
||||||
|
if (num[0]=='N' && num[1]=='a' && num[2]=='N') {
|
||||||
|
l=3;
|
||||||
|
*res = MYC_NAN;
|
||||||
|
} else {
|
||||||
|
i=sscanf(num, "%f%n", res, &l);
|
||||||
|
if (i==0) {
|
||||||
|
ERR_MSG("illegal number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sep==StrNONE) {
|
||||||
|
buf->rdpos=p+l;
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
buf->rdpos=buf->dsize; /* illegal value */
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrGetEnd(StrBuf *buf) {
|
||||||
|
if (buf->buf!=NULL) {
|
||||||
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize)
|
||||||
|
ERR_MSG("buffer corrupt");
|
||||||
|
if (buf->rdpos != buf->wrpos)
|
||||||
|
ERR_MSG("superflous content in buffer");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrPut(StrBuf *buf, const char *str, int sep) {
|
||||||
|
int l, pos;
|
||||||
|
char quote;
|
||||||
|
|
||||||
|
pos=buf->wrpos;
|
||||||
|
if (pos < 0 || pos >= buf->dsize || buf->buf==NULL)
|
||||||
|
ERR_MSG("buffer corrupt");
|
||||||
|
l=strlen(str);
|
||||||
|
quote='\0';
|
||||||
|
if (sep>0) {
|
||||||
|
if (strchr(str, sep)!=NULL) {
|
||||||
|
if (strchr(str, '"')!=NULL) {
|
||||||
|
quote='"'; l+=2;
|
||||||
|
}
|
||||||
|
if (strchr(str, '\'')!=NULL) {
|
||||||
|
if (quote!='\0')
|
||||||
|
ERR_MSG("str must not contain separator and both kind of quotes");
|
||||||
|
quote='\''; l+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos+l >= buf->dsize)
|
||||||
|
ERR_MSG("buffer too short");
|
||||||
|
if (quote!='\0') {
|
||||||
|
buf->buf[pos]=quote; pos++;
|
||||||
|
strcpy(buf->buf + pos, str);
|
||||||
|
buf->buf[pos]=quote; pos++;
|
||||||
|
} else {
|
||||||
|
strcpy(buf->buf + pos, str);
|
||||||
|
}
|
||||||
|
pos+=l;
|
||||||
|
if (sep!=StrNONE) {
|
||||||
|
buf->buf[pos]=sep;
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
buf->buf[pos]='\0';
|
||||||
|
}
|
||||||
|
buf->wrpos=pos;
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
buf->wrpos=-1;
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrPutInt(StrBuf *buf, int val, int sep) {
|
||||||
|
char num[32];
|
||||||
|
|
||||||
|
sprintf(num, "%d", val);
|
||||||
|
ERR_I(StrPut(buf, num, sep));
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StrPutFloat(StrBuf *buf, float val, int sep) {
|
||||||
|
char num[32];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
if (val == MYC_NAN) {
|
||||||
|
ERR_I(StrPut(buf, "NaN", sep));
|
||||||
|
} else {
|
||||||
|
sprintf(num, "%g", val);
|
||||||
|
ERR_I(StrPut(buf, num, sep));
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError:
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StrReset(StrBuf *buf) {
|
||||||
|
buf->rdpos=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StrClear(StrBuf *buf) {
|
||||||
|
buf->rdpos=0;
|
||||||
|
buf->wrpos=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StrNLink(StrBuf *buf, char *str, int length) {
|
||||||
|
int l;
|
||||||
|
buf->buf=str;
|
||||||
|
buf->rdpos=0;
|
||||||
|
l=strlen(str);
|
||||||
|
if (l<length) l=length;
|
||||||
|
buf->wrpos=l;
|
||||||
|
buf->dsize=buf->wrpos;
|
||||||
|
}
|
58
tecs/myc_buf.h
Normal file
58
tecs/myc_buf.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef _STR_BUF_H_
|
||||||
|
#define _STR_BUF_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
This module is used to write and read from character strings
|
||||||
|
It is a simplified, safe replacement for sprintf/sscanf.
|
||||||
|
|
||||||
|
DeclStrBuf(buf, size) declares and initializes a buffer of a given size.
|
||||||
|
Use this macro in the declaration part of a function.
|
||||||
|
*/
|
||||||
|
typedef struct { char *buf; int dsize, rdpos, wrpos, seen; } StrBuf;
|
||||||
|
|
||||||
|
#define DeclStrBuf(BUF,SIZ) static char STR__##BUF[SIZ]; StrBuf BUF={STR__##BUF,SIZ}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Write content to the buffer, and add separator sep, if sep!=StrNONE
|
||||||
|
*/
|
||||||
|
#define StrNONE -1
|
||||||
|
int StrPut(StrBuf *buf, const char *str, int sep);
|
||||||
|
int StrPutInt(StrBuf *buf, int val, int sep);
|
||||||
|
int StrPutFloat(StrBuf *buf, float val, int sep);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Read from the buffer until separator sep.
|
||||||
|
Use the StrGet macro if the result is a fixed size.
|
||||||
|
Special case sep=StrNONE:
|
||||||
|
- StrGet reads until the end of the buffer
|
||||||
|
- StrGetInt and StrGetFloat read until the end of a legal number
|
||||||
|
*/
|
||||||
|
char *StrNGet(StrBuf *buf, char *result, int reslen, int sep);
|
||||||
|
#define StrGet(BUF,RES,SEP) StrNGet(BUF,RES,sizeof(RES),SEP)
|
||||||
|
int StrGetInt(StrBuf *buf, int *res, int sep);
|
||||||
|
int StrGetFloat(StrBuf *buf, float *res, int sep);
|
||||||
|
#define StrEnd(BUF) ((BUF)->rdpos>=(BUF)->wrpos)
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
reset the buffer to read from the beginning
|
||||||
|
*/
|
||||||
|
void StrReset(StrBuf *buf);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Clear the buffer
|
||||||
|
*/
|
||||||
|
void StrClear(StrBuf *buf);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Verify that the end is reached
|
||||||
|
*/
|
||||||
|
int StrGetEnd(StrBuf *buf);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Link the buffer to a string. The buffer length is set to
|
||||||
|
sizeof(STR) or strlen(STR), whichever is greater
|
||||||
|
*/
|
||||||
|
#define StrLink(BUF, STR) StrNLink(BUF, STR, sizeof(STR))
|
||||||
|
void StrNLink(StrBuf *buf, char *str, int size);
|
||||||
|
|
||||||
|
#endif /* _STR_BUF_H_ */
|
144
tecs/myc_err.c
Normal file
144
tecs/myc_err.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "sys_util.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_err.h"
|
||||||
|
|
||||||
|
#define SLEN 64
|
||||||
|
#define MLEN 64
|
||||||
|
|
||||||
|
static char *txt[SLEN];
|
||||||
|
static int sp=0;
|
||||||
|
static int stack_empty=1;
|
||||||
|
|
||||||
|
int ErrCode;
|
||||||
|
char *ErrMessage=NULL;
|
||||||
|
void (*outrtn)()=NULL;
|
||||||
|
void *outarg;
|
||||||
|
|
||||||
|
void ErrTxt(char *text, int systemError)
|
||||||
|
{
|
||||||
|
if (systemError) {
|
||||||
|
sp=0; ErrCode=errno; ErrMessage=strerror(errno);
|
||||||
|
}
|
||||||
|
if (stack_empty && sp>0) {
|
||||||
|
sp=0;
|
||||||
|
stack_empty=0;
|
||||||
|
}
|
||||||
|
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 ErrOutFil(void *arg, char *text) {
|
||||||
|
fprintf((FILE *)arg, "%s\n", text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrShow(char *text)
|
||||||
|
{
|
||||||
|
int i, l;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (outrtn==NULL) {
|
||||||
|
outrtn=ErrOutFil;
|
||||||
|
outarg=stdout;
|
||||||
|
}
|
||||||
|
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(outarg, buf);
|
||||||
|
l=strlen(txt[i]);
|
||||||
|
assert(l<256);
|
||||||
|
strcpy(buf, txt[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outrtn(outarg, buf);
|
||||||
|
outrtn(outarg, "");
|
||||||
|
stack_empty=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrShort(char *msg) {
|
||||||
|
if (outrtn==NULL) {
|
||||||
|
outrtn=ErrOutFil;
|
||||||
|
outarg=stdout;
|
||||||
|
}
|
||||||
|
outrtn(outarg, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrSetOutRtn(void (*rtn)(), void *arg) {
|
||||||
|
outrtn=rtn;
|
||||||
|
outarg=arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrSetOutFile(FILE *arg) {
|
||||||
|
outrtn=ErrOutFil;
|
||||||
|
outarg=arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ERR_EXIT(char *text) {
|
||||||
|
ErrShow(text); exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FORTRAN wrappers */
|
||||||
|
|
||||||
|
#ifdef F_CHAR
|
||||||
|
/* compile only when fortran c interface stuff is defined */
|
||||||
|
|
||||||
|
#ifdef __VMS
|
||||||
|
#define err_show_ err_show
|
||||||
|
#define err_txt_ err_txt
|
||||||
|
#define err_msg_ err_msg
|
||||||
|
#define err_set_outrtn_ err_set_outrtn
|
||||||
|
#define err_short_ err_short
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void err_show_(F_CHAR(text), int text_len) {
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
STR_TO_C(buf, text);
|
||||||
|
ErrShow(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void err_txt_(F_CHAR(text), int text_len) {
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
STR_TO_C(buf, text);
|
||||||
|
ErrTxt(buf,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void err_msg_(F_CHAR(text), int text_len) {
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
STR_TO_C(buf, text);
|
||||||
|
ErrMsg(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void err_set_outrtn_(void (*rtn)(), void *arg) {
|
||||||
|
ErrSetOutRtn(rtn, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void err_short_(void) {
|
||||||
|
ErrShort(ErrMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
85
tecs/myc_err.h
Normal file
85
tecs/myc_err.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef _ERR_HANDLING_H_
|
||||||
|
#define _ERR_HANDLING_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")
|
||||||
|
|
||||||
|
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); /* write out error message with stack info */
|
||||||
|
void ErrShort(char *msg); /* write out short error message */
|
||||||
|
void ERR_EXIT(char *text);
|
||||||
|
void ErrSetOutRtn(void (*rtn)(), void *arg);
|
||||||
|
void ErrSetOutFile(FILE *file);
|
||||||
|
|
||||||
|
extern int ErrCode;
|
||||||
|
extern char *ErrMessage;
|
||||||
|
|
||||||
|
#endif /* _ERR_HANDLING_H_ */
|
30
tecs/myc_mem.h
Normal file
30
tecs/myc_mem.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _MEM_UTIL_H_
|
||||||
|
#define _MEM_UTIL_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef FORTIFY
|
||||||
|
#include "fortify.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------
|
||||||
|
these macros help for safer dynamic memory
|
||||||
|
you may change these macros if you want to log dynamic memory access
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NEW(PTR,TYP) {TYP _0_={0}; ERR_SP(PTR=malloc(sizeof(*PTR))); *PTR=_0_; }
|
||||||
|
/*
|
||||||
|
allocates and initializes an object of type TYP and make PTR point to it
|
||||||
|
TYP must be defined with an appropriate typedef declaration, and
|
||||||
|
INIT(TYP) must follow the declaration to initialize a dummy initializer
|
||||||
|
object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NEW_STR(TO,FROM) {ERR_SP(TO=malloc(strlen(FROM)+1)); strcpy(TO,FROM); }
|
||||||
|
|
||||||
|
#define MALLOC(SIZE) malloc(SIZE)
|
||||||
|
#define FREE(PTR) free(PTR)
|
||||||
|
|
||||||
|
#endif /* _MEM_UTIL_H_ */
|
252
tecs/myc_str.c
Normal file
252
tecs/myc_str.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "sys_util.h"
|
||||||
|
#include "myc_err.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_mem.h"
|
||||||
|
|
||||||
|
char *str_splitx(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_ntrim(char *dest, const char *src, int ldest, int lsrc) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (lsrc>=ldest) lsrc=ldest-1;
|
||||||
|
if (dest!=src) strncpy(dest, src, lsrc);
|
||||||
|
dest[lsrc]='\0';
|
||||||
|
i=strlen(dest)-1;
|
||||||
|
while (i>=0 && dest[i]==' ') i--; /* trim sequence */
|
||||||
|
i++;
|
||||||
|
dest[i]='\0';
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_npad(char *dest, const char *src, int ldest) {
|
||||||
|
int i, lsrc;
|
||||||
|
|
||||||
|
lsrc=strlen(src);
|
||||||
|
if (lsrc>=ldest) {
|
||||||
|
if (dest!=src) strncpy(dest, src, ldest);
|
||||||
|
lsrc=ldest;
|
||||||
|
} else {
|
||||||
|
if (dest!=src) strcpy(dest, src);
|
||||||
|
for (i=lsrc; i<ldest; i++) {
|
||||||
|
dest[i]=' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(lsrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *str_nsplit(char *dst, const char *src, char sep, int dstlen) {
|
||||||
|
char *s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s=strchr(src, sep);
|
||||||
|
if (s==NULL) {
|
||||||
|
s=NULL;
|
||||||
|
i=strlen(src);
|
||||||
|
} else {
|
||||||
|
i=s-src;
|
||||||
|
s++; /* skip separator */
|
||||||
|
}
|
||||||
|
if (i>=dstlen) {
|
||||||
|
str_copy(dst, src);
|
||||||
|
} else {
|
||||||
|
strncpy(dst, src, i);
|
||||||
|
dst[i]='\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_file(char *file) {
|
||||||
|
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;
|
||||||
|
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 {
|
||||||
|
assert(*p=='\0');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERR_SI(fclose(fil));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen) {
|
||||||
|
char *s, *p, *r;
|
||||||
|
int l, ln, lo;
|
||||||
|
|
||||||
|
p=str;
|
||||||
|
r=result;
|
||||||
|
ln=strlen(new);
|
||||||
|
lo=strlen(old);
|
||||||
|
s=strstr(p, old);
|
||||||
|
reslen--;
|
||||||
|
if (reslen<0) ERR_MSG("result buffer too short");
|
||||||
|
while (s!=NULL) {
|
||||||
|
l=s-p;
|
||||||
|
if (l>reslen) ERR_MSG("result buffer too short");
|
||||||
|
strncpy(r, p, l);
|
||||||
|
r+=l; reslen-=l;
|
||||||
|
if (ln>reslen) ERR_MSG("result buffer too short");
|
||||||
|
strncpy(r, new, reslen);
|
||||||
|
r+=ln; reslen-=ln;
|
||||||
|
p=s+lo;
|
||||||
|
s=strstr(p, old);
|
||||||
|
}
|
||||||
|
l=strlen(p);
|
||||||
|
if (l>reslen) ERR_MSG("result buffer too short");
|
||||||
|
strncpy(r, p, l);
|
||||||
|
r+=l;
|
||||||
|
*r='\0';
|
||||||
|
return(r-result);
|
||||||
|
OnError:
|
||||||
|
result[0]='\0';
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void str_nupcase(char *dst, const char *src, int dstlen) {
|
||||||
|
dstlen--; /* space for trailing nul */
|
||||||
|
while (*src!='\0' && dstlen>0) {
|
||||||
|
*dst=toupper(*src);
|
||||||
|
dst++; src++;
|
||||||
|
dstlen--;
|
||||||
|
}
|
||||||
|
*dst='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void str_nlowcase(char *dst, const char *src, int dstlen) {
|
||||||
|
dstlen--; /* space for trailing nul */
|
||||||
|
while (*src!='\0' && dstlen>0) {
|
||||||
|
*dst=tolower(*src);
|
||||||
|
dst++; src++;
|
||||||
|
dstlen--;
|
||||||
|
}
|
||||||
|
*dst='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcasecmp(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 maxdest) {
|
||||||
|
strncpy(dst, src, maxdest);
|
||||||
|
if (dst[maxdest-1]!='\0') {
|
||||||
|
dst[maxdest-1]='\0';
|
||||||
|
ERR_MSG("destination string too short");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_ncat(char *dst, const char *src, int maxdest) {
|
||||||
|
strncat(dst, src, maxdest-strlen(dst)-1);
|
||||||
|
if (dst[maxdest-1]!='\0') {
|
||||||
|
dst[maxdest-1]='\0';
|
||||||
|
ERR_MSG("destination string too short");
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
122
tecs/myc_str.h
Normal file
122
tecs/myc_str.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#ifndef _MYC_STR_H_
|
||||||
|
#define _MYC_STR_H_
|
||||||
|
|
||||||
|
#define MYC_NAN (-1.125/1024./1024./1024.)
|
||||||
|
|
||||||
|
/*
|
||||||
|
use these macros if DST is a fixed length character array
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define str_trim(DST,SRC,L) str_ntrim(DST,SRC,sizeof(DST),L)
|
||||||
|
#define str_pad(DST,SRC) str_npad(DST,SRC,sizeof(DST))
|
||||||
|
#define str_split(DST,SRC,SEP) str_nsplit(DST,SRC,SEP,sizeof(DST))
|
||||||
|
#define str_substitute(DST,SRC,OLD,NEW) str_nsubstitute(DST,SRC,OLD,NEW,sizeof(DST))
|
||||||
|
#define str_upcase(DST,SRC) str_nupcase(DST,SRC,sizeof(DST))
|
||||||
|
#define str_lowcase(DST,SRC) str_nlowcase(DST,SRC,sizeof(DST))
|
||||||
|
#define str_copy(DST,SRC) str_ncpy(DST,SRC,sizeof(DST))
|
||||||
|
#define str_append(DST,SRC) str_ncat(DST,SRC,sizeof(DST))
|
||||||
|
|
||||||
|
|
||||||
|
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_splitx(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
|
||||||
|
*/
|
||||||
|
|
||||||
|
int str_ntrim(char *dest, const char *src, int ldest, int lsrc);
|
||||||
|
/*
|
||||||
|
copy characters 0 to lsrc-1 from src to dest (max ldest chars).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int str_npad(char *dest, const char *src, int ldest);
|
||||||
|
/*
|
||||||
|
copy src to dest and fill with spaces (fortran string format)
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *str_nsplit(char *dst, const char *src, char sep, int dstlen);
|
||||||
|
/*
|
||||||
|
returns a pointer to the text after the separator sep in *src
|
||||||
|
and copies the text before the separator to *dst
|
||||||
|
when *src does not contain the separator sep
|
||||||
|
NULL is returned, and *dst is a copy of *src
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *str_read_file(char *file);
|
||||||
|
/*
|
||||||
|
return one string containing the contents of file *file
|
||||||
|
comments separated by '!' are omitted. The caller must
|
||||||
|
free the result after use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void str_replace_char(char *str, char ch, char rep);
|
||||||
|
/*
|
||||||
|
replace all occurences of character ch by character rep in string *str
|
||||||
|
*/
|
||||||
|
|
||||||
|
int str_nsubstitute(char *result, char *str, char *old, char *new, int reslen);
|
||||||
|
/*
|
||||||
|
replace every instance of old in str by new.
|
||||||
|
the result must not overlap
|
||||||
|
if the result would be longer than reslen, the result is en empty string
|
||||||
|
and the return value is -1;
|
||||||
|
else the return value is the length of the result.
|
||||||
|
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_nupcase(char *dst, const char *src, int dstlen);
|
||||||
|
/*
|
||||||
|
convert *str to uppercase
|
||||||
|
*/
|
||||||
|
|
||||||
|
void str_nlowcase(char *dst, const char *src, int dstlen);
|
||||||
|
/*
|
||||||
|
convert *str to lowercase
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __VMS_VER
|
||||||
|
#if __VMS_VER<70000000
|
||||||
|
|
||||||
|
int strcasecmp(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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <strings.h>
|
||||||
|
#endif /* __VMS_VER<70000000 */
|
||||||
|
#else
|
||||||
|
#include <strings.h>
|
||||||
|
#endif /* __VMS_VER */
|
||||||
|
|
||||||
|
int str_ncpy(char *dst, const char *src, int maxdest);
|
||||||
|
/*
|
||||||
|
copy *src to *dest, maximal maxdest characters,
|
||||||
|
it is guaranteed, that dst contains '\0'
|
||||||
|
*/
|
||||||
|
|
||||||
|
int str_ncat(char *dst, const char *src, int maxdest);
|
||||||
|
/*
|
||||||
|
append *src to *dest, maximal maxdest characters,
|
||||||
|
it is guaranteed, that dst contains '\0'
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _MYC_STR_H_ */
|
120
tecs/myc_time.c
Normal file
120
tecs/myc_time.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include "sys_util.h"
|
||||||
|
#include "myc_time.h"
|
||||||
|
|
||||||
|
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */
|
||||||
|
|
||||||
|
static time_t my_base=0;
|
||||||
|
|
||||||
|
void initBase(void) {
|
||||||
|
struct tm tim;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
tim = *localtime(&now);
|
||||||
|
tim.tm_year = MYC_TIME_BASE / 10000 - 1900;
|
||||||
|
tim.tm_mon = (MYC_TIME_BASE % 10000) / 100 - 1;
|
||||||
|
tim.tm_mday = MYC_TIME_BASE % 100;
|
||||||
|
tim.tm_hour = 12;
|
||||||
|
tim.tm_min = 0;
|
||||||
|
tim.tm_sec = 0;
|
||||||
|
/* take daylight saving time flag and gmt offset from today */
|
||||||
|
my_base=mktime(&tim) - 12*3600;
|
||||||
|
assert(tim.tm_wday == 1); /* time base must be a monday */
|
||||||
|
}
|
||||||
|
|
||||||
|
int mycNow(void) {
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
if (my_base == 0) initBase();
|
||||||
|
time(&now);
|
||||||
|
return (int)(now-my_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mycMsecSince(int since) {
|
||||||
|
struct timeb now;
|
||||||
|
int msec;
|
||||||
|
|
||||||
|
if (my_base == 0) initBase();
|
||||||
|
ftime(&now);
|
||||||
|
msec = (now.time - my_base) % (24*3600) * 1000 + now.millitm - since;
|
||||||
|
if (msec < 0) msec+=24*3600000;
|
||||||
|
return msec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mycDate(int time) {
|
||||||
|
struct tm tim;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (my_base == 0) initBase();
|
||||||
|
t = time + my_base;
|
||||||
|
tim=*localtime(&t);
|
||||||
|
return (tim.tm_year + 1900) * 10000 + (tim.tm_mon + 1) * 100 + tim.tm_mday;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mycTime(int date) {
|
||||||
|
struct tm tim;
|
||||||
|
time_t t, now;
|
||||||
|
int y, m, d;
|
||||||
|
|
||||||
|
if (my_base == 0) initBase();
|
||||||
|
time(&now);
|
||||||
|
tim=*localtime(&now);
|
||||||
|
tim.tm_hour=0;
|
||||||
|
tim.tm_min=0;
|
||||||
|
tim.tm_sec=0;
|
||||||
|
if (date != 0) {
|
||||||
|
d = date % 100;
|
||||||
|
date = date / 100;
|
||||||
|
m = date % 100;
|
||||||
|
y = date / 100;
|
||||||
|
if (y == 0) {
|
||||||
|
if (m == 0) {
|
||||||
|
if (d > tim.tm_mday) {
|
||||||
|
if (tim.tm_mon == 0) { /* jan */
|
||||||
|
tim.tm_mon=11; /* dec */
|
||||||
|
tim.tm_year--;
|
||||||
|
} else {
|
||||||
|
tim.tm_mon--; /* last month */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tim.tm_mon = m - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tim.tm_year = y - 1900;
|
||||||
|
if (m == 0) {
|
||||||
|
if (d == 0) {
|
||||||
|
tim.tm_mon = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tim.tm_mon = m - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d == 0) d = 1;
|
||||||
|
tim.tm_mday = d;
|
||||||
|
}
|
||||||
|
return (int)(mktime(&tim)-my_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fortran routines --------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef F_CHAR
|
||||||
|
/* compile only when fortran c interface stuff is defined */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __VMS
|
||||||
|
#define myc_date_ myc_date
|
||||||
|
#define myc_time_ myc_time
|
||||||
|
#define myc_now_ myc_now
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int myc_now_(void) { return mycNow(); }
|
||||||
|
int myc_date_(int *time) { return mycDate(*time); }
|
||||||
|
int myc_time_(int *date) { return mycTime(*date); }
|
||||||
|
|
||||||
|
#endif
|
42
tecs/myc_time.h
Normal file
42
tecs/myc_time.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef _MYC_TIME_H_
|
||||||
|
#define _MYC_TIME_H_
|
||||||
|
|
||||||
|
#define MYC_TIME_BASE 20010101
|
||||||
|
|
||||||
|
int mycNow(void);
|
||||||
|
/*
|
||||||
|
return seconds since a Monday specified by MYC_TIME_BASE
|
||||||
|
mycNow() % (24*3600) is always 0 at 00:00 even in daylight saving time
|
||||||
|
*/
|
||||||
|
|
||||||
|
int mycMsecSince(int since);
|
||||||
|
/*
|
||||||
|
mycMsecSince(0) return milliseconds since midnight
|
||||||
|
mycMsecSince(x) return milliseconds since x (x is time since midnight)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int mycDate(int time);
|
||||||
|
/*
|
||||||
|
return year * 10000 + month * 100 + day_of_month of a time obtained by mycNow
|
||||||
|
year > 1900
|
||||||
|
1 <= month <= 12
|
||||||
|
1 <= day_of_month <= 31
|
||||||
|
*/
|
||||||
|
|
||||||
|
int mycTime(int date);
|
||||||
|
/*
|
||||||
|
does the inverse of MycDate. Chooses the last possible date not later than today
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* the following subroutines are to be called from FORTRAN
|
||||||
|
|
||||||
|
integer function myc_now()
|
||||||
|
real function myc_date(time)
|
||||||
|
integer function myc_time(date)
|
||||||
|
|
||||||
|
integer time
|
||||||
|
real date
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* _MYC_TIME_H_ */
|
131
tecs/str.f
Normal file
131
tecs/str.f
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
!! string handling
|
||||||
|
!!
|
||||||
|
subroutine STR_TRIM(RETSTR, STR, RETLEN) !!
|
||||||
|
!!
|
||||||
|
!! if RETSTR=STR then RETSTR is not touched
|
||||||
|
!!
|
||||||
|
!! Arguments:
|
||||||
|
character*(*) STR, RETSTR !! in,out
|
||||||
|
integer RETLEN !! out
|
||||||
|
integer i
|
||||||
|
|
||||||
|
i=len(str)
|
||||||
|
if (str(1:1) .gt. ' ') then
|
||||||
|
10 if (str(i:i) .le. ' ') then
|
||||||
|
i=i-1
|
||||||
|
goto 10
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
20 if (str(i:i) .le. ' ') then
|
||||||
|
if (i .gt. 1) then
|
||||||
|
i=i-1
|
||||||
|
goto 20
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
retlen=min(len(retstr),i)
|
||||||
|
if (retstr .ne. str) then ! avoid copy to retstr if equal
|
||||||
|
retstr=str(1:i)
|
||||||
|
endif
|
||||||
|
end
|
||||||
|
|
||||||
|
!!
|
||||||
|
subroutine STR_UPCASE(RETSTR, STR) !!
|
||||||
|
!!
|
||||||
|
!! Arguments:
|
||||||
|
character STR*(*), RETSTR*(*) !! in,out
|
||||||
|
integer i, ch
|
||||||
|
|
||||||
|
retstr=str
|
||||||
|
do i=1,len(retstr)
|
||||||
|
ch=ichar(retstr(i:i))
|
||||||
|
if (ch .ge. ichar('a') .and. ch .le. ichar('z')) then
|
||||||
|
retstr(i:i)=char(ch-(ichar('a')-ichar('A')))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
end
|
||||||
|
|
||||||
|
!!
|
||||||
|
subroutine STR_LOWCASE(RETSTR, STR) !!
|
||||||
|
!!
|
||||||
|
!! Arguments:
|
||||||
|
character STR*(*), RETSTR*(*) !! in,out
|
||||||
|
integer i, ch
|
||||||
|
|
||||||
|
retstr=str
|
||||||
|
do i=1,len(retstr)
|
||||||
|
ch=ichar(retstr(i:i))
|
||||||
|
if (ch .ge. ichar('A') .and. ch .le. ichar('Z')) then
|
||||||
|
retstr(i:i)=char(ch+(ichar('a')-ichar('A')))
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
end
|
||||||
|
|
||||||
|
!!
|
||||||
|
subroutine STR_APPEND(str, length, add) !!
|
||||||
|
!!
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
character*(*) str, add !!
|
||||||
|
integer length !!
|
||||||
|
|
||||||
|
if (len(add)+length .gt. len(str)) then
|
||||||
|
if (length .lt. len(str)) then
|
||||||
|
str(length+1:)=add
|
||||||
|
length=len(str)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
str(length+1:length+len(add))=add
|
||||||
|
length=length+len(add)
|
||||||
|
endif
|
||||||
|
end
|
||||||
|
|
||||||
|
!!
|
||||||
|
integer function STR_CMP(str1, str2) !!
|
||||||
|
!!
|
||||||
|
!! if strings are equal: return 0
|
||||||
|
!! else return position of first different character
|
||||||
|
|
||||||
|
character str1*(*), str2*(*) !!
|
||||||
|
|
||||||
|
integer i
|
||||||
|
|
||||||
|
do i=0,min(len(str1),len(str2))-1
|
||||||
|
if (str1(i+1:i+1) .ne. str2(i+1:i+1)) then
|
||||||
|
str_cmp=i+1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
do i=len(str1),len(str2)-1
|
||||||
|
if (str2(i+1:i+1) .ne. ' ') then
|
||||||
|
str_cmp=i+1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
do i=len(str2),len(str1)-1
|
||||||
|
if (str1(i+1:i+1) .ne. ' ') then
|
||||||
|
str_cmp=i+1
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
str_cmp=0
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
!!
|
||||||
|
subroutine STR_FIRST_NONBLANK(STR, POS) !!
|
||||||
|
!!
|
||||||
|
!! Arguments:
|
||||||
|
character*(*) STR !! in
|
||||||
|
integer POS !! out
|
||||||
|
integer i
|
||||||
|
|
||||||
|
do i=1,len(str)
|
||||||
|
if (str(i:i) .gt. ' ') then
|
||||||
|
pos=i
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
pos=0
|
||||||
|
end
|
||||||
|
|
@ -292,7 +292,7 @@
|
|||||||
integer L !!
|
integer L !!
|
||||||
|
|
||||||
integer i
|
integer i
|
||||||
integer lnblnk
|
integer lnblnk, iargc
|
||||||
|
|
||||||
l=0
|
l=0
|
||||||
str=' '
|
str=' '
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <time.h>
|
#include <sys/time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -18,16 +18,13 @@ int usleep(time_t delay);
|
|||||||
|
|
||||||
void sys_rd_line_(char *cmd, int *retlen, char *prompt, int clen, int plen)
|
void sys_rd_line_(char *cmd, int *retlen, char *prompt, int clen, int plen)
|
||||||
{
|
{
|
||||||
char *line_read, *p;
|
char *line_read, p[64];
|
||||||
int l;
|
|
||||||
|
assert(plen < sizeof(p));
|
||||||
l = lnblnk_(prompt, clen);
|
strncpy(p,prompt,plen); p[plen] = '\0';
|
||||||
p = malloc((unsigned) l+2); if( p == NULL ) return;
|
|
||||||
strncpy(p+1,prompt,l); p[0]='\n'; p[l] = '\0';
|
|
||||||
if (last_line == NULL) { last_line =malloc(1); last_line[0] = '\0';};
|
if (last_line == NULL) { last_line =malloc(1); last_line[0] = '\0';};
|
||||||
|
|
||||||
line_read = readline(p);
|
line_read = readline(p);
|
||||||
free(p);
|
|
||||||
|
|
||||||
if (line_read)
|
if (line_read)
|
||||||
{
|
{
|
||||||
@ -156,10 +153,10 @@ int ilen1, ilen2;
|
|||||||
return(rc);
|
return(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct termios atts;
|
|
||||||
|
|
||||||
void sys_rd_tmo_(char *prompt, char *result, int *reslen, int p_len, int r_len)
|
void sys_rd_tmo_(char *prompt, char *result, int *reslen, int p_len, int r_len)
|
||||||
{
|
{
|
||||||
|
struct termios atts;
|
||||||
struct termios attr;
|
struct termios attr;
|
||||||
int ires, i, ntmo, chr;
|
int ires, i, ntmo, chr;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "str_util.h"
|
#include "myc_str.h"
|
||||||
#include "sys_util.h"
|
#include "sys_util.h"
|
||||||
|
|
||||||
#if __VMS
|
#if __VMS
|
||||||
@ -16,10 +17,17 @@ int sys_gmt_off() {
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sys_ctrl_init(void) {
|
||||||
|
static int init=1;
|
||||||
|
if (init) {
|
||||||
|
init=0;
|
||||||
|
DECC$CRTL_INIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
int sys_remove_file_(F_CHAR(file), int file_len) {
|
int sys_remove_file_(F_CHAR(file), int file_len) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -27,12 +35,4 @@ int sys_remove_file_(F_CHAR(file), int file_len) {
|
|||||||
return(unlink(buf));
|
return(unlink(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_gmt_off_() {
|
|
||||||
struct tm *timp;
|
|
||||||
time_t tim;
|
|
||||||
time(&tim);
|
|
||||||
timp=localtime(&tim);
|
|
||||||
return(timp->tm_gmtoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,33 +1,35 @@
|
|||||||
#ifndef _SYS_UTIL_H_
|
#ifndef _SYS_UTIL_H_
|
||||||
#define _SYS_UTIL_H_
|
#define _SYS_UTIL_H_
|
||||||
|
|
||||||
#ifdef FORTIFY
|
/*
|
||||||
#include "fortify.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* secure allocation stuff ----------------------------------
|
fortran interface stuff
|
||||||
change these macros if you want to log dynamic memory access
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NEW(PTR) ERR_SP(PTR=calloc(1,sizeof(*PTR)))
|
declare fortran character arguments as F_CHAR(arg)
|
||||||
#define MALLOC(SIZ) calloc(1,SIZ)
|
and at at the end for each character argument <arg> add
|
||||||
#define FREE(PTR) free(PTR)
|
int <arg>_len to the argument list
|
||||||
|
|
||||||
/* fortran interface stuff ----------------------------------
|
Use macros STR_TO_C and STR_TO_F to convert from Fortran character strings
|
||||||
|
to C character arrays and vice versa.
|
||||||
|
|
||||||
declare fortran character arguments as CHAR(arg)
|
sys_adr_len (argument of accept and gethostbyadr, system dependent)
|
||||||
and at at the end for each character argument <arg> add
|
|
||||||
int <arg>_len to the argument list
|
sys_ctrl_init() (needed in VMS only)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if defined __VMS
|
#if defined __VMS
|
||||||
|
|
||||||
|
typedef struct { short size, dummy; char *text; } SysVmsChar;
|
||||||
|
|
||||||
#define F_CHAR(VAR) SysVmsChar *VAR##_desc
|
#define F_CHAR(VAR) SysVmsChar *VAR##_desc
|
||||||
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC##_desc->text, sizeof(DST), SRC##_len=SRC##_desc->size)
|
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC##_desc->text, sizeof(DST), SRC##_len=SRC##_desc->size)
|
||||||
#define STR_TO_F(DST,SRC) str_npad(DST##_desc->text, SRC, DST##_len=DST##_desc->size)
|
#define STR_TO_F(DST,SRC) str_npad(DST##_desc->text, SRC, DST##_len=DST##_desc->size)
|
||||||
|
|
||||||
typedef struct { short size, dummy; char *text; } SysVmsChar;
|
typedef size_t sys_adr_len; /* argument of accept and gethostbyadr */
|
||||||
|
|
||||||
|
void sys_ctrl_init(void);
|
||||||
|
|
||||||
#elif defined __alpha
|
#elif defined __alpha
|
||||||
|
|
||||||
@ -35,9 +37,13 @@ typedef struct { short size, dummy; char *text; } SysVmsChar;
|
|||||||
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC, sizeof(DST), SRC##_len)
|
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC, sizeof(DST), SRC##_len)
|
||||||
#define STR_TO_F(DST,SRC) str_npad(DST, SRC, DST##_len)
|
#define STR_TO_F(DST,SRC) str_npad(DST, SRC, DST##_len)
|
||||||
|
|
||||||
|
typedef int sys_adr_len; /* argument of accept and gethostbyadr */
|
||||||
|
|
||||||
|
#define sys_ctrl_init(DUMMY)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* other machines are not yet supported */
|
/* other machines are not supported */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
2125
tecs/tecs.c
2125
tecs/tecs.c
File diff suppressed because it is too large
Load Diff
332
tecs/tecs_cli.c
332
tecs/tecs_cli.c
@ -1,98 +1,65 @@
|
|||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "myc_mem.h"
|
||||||
|
#include "myc_err.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_time.h"
|
||||||
#include "sys_util.h"
|
#include "sys_util.h"
|
||||||
#include "err_handling.h"
|
#include "coc_util.h"
|
||||||
#include "str_util.h"
|
|
||||||
#include "tecs_cli.h"
|
#include "tecs_cli.h"
|
||||||
|
#include "tecs_data.h"
|
||||||
|
|
||||||
static char device[80], command[80];
|
static char response[COC_RES_LEN];
|
||||||
static int readTemp, configuring;
|
|
||||||
static float tempX, tempP, tempC;
|
|
||||||
|
|
||||||
pTecsClient TeccInit(char *startcmd, int port) {
|
pTecsClient TeccInit(char *startcmd, int port) {
|
||||||
CocConn *conn;
|
CocConn *conn;
|
||||||
|
static char *rwCode="rwacs";
|
||||||
|
static char *rdCode="rdacs";
|
||||||
|
|
||||||
NEW(conn);
|
NEW(conn, CocConn);
|
||||||
if (startcmd[0]=='#') {
|
if (startcmd[0]=='#') {
|
||||||
ERR_I(CocInitClient(conn, startcmd+1, port, "#rwacs", 0, ""));
|
ERR_I(CocInitClient(conn, startcmd+1, port, rdCode, 0, ""));
|
||||||
} else {
|
} else {
|
||||||
ERR_I(CocInitClient(conn, "", port, "#rwacs", 0, startcmd));
|
ERR_I(CocInitClient(conn, "", port, rwCode, 0, startcmd));
|
||||||
}
|
}
|
||||||
CocDefFlt(tempC, CocRD);
|
|
||||||
CocDefFlt(tempP, CocRD);
|
|
||||||
CocDefFlt(tempX, CocRD);
|
|
||||||
CocDefStr(device, CocWR);
|
|
||||||
CocDefInt(configuring, CocRD);
|
|
||||||
CocDefInt(readTemp, CocWR);
|
|
||||||
CocDefCmd(command);
|
|
||||||
|
|
||||||
return((pTecsClient)conn);
|
return((pTecsClient)conn);
|
||||||
OnError: return(NULL);
|
OnError: return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
|
int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
|
||||||
readTemp=1;
|
int iret;
|
||||||
ERR_I(CocCmd(conn, "tempC,tempX,tempP,[readTemp],configuring"));
|
|
||||||
*tC=tempC;
|
CocReset(conn);
|
||||||
*tX=tempX;
|
ERR_I(CocGetFloat(conn, "set", tC));
|
||||||
*tP=tempP;
|
ERR_I(CocGetFloat(conn, "tempX", tX));
|
||||||
return(configuring);
|
ERR_I(CocGetFloat(conn, "tempP", tP));
|
||||||
|
ERR_I(CocPutInt(conn, "readTemp", 1));
|
||||||
|
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||||
|
if (iret) ERR_MSG(response);
|
||||||
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TeccGet(pTecsClient conn, float *temp) {
|
int TeccGet(pTecsClient conn, float *temp) {
|
||||||
readTemp=1;
|
int iret;
|
||||||
ERR_I(CocCmd(conn, "tempP,[readTemp],configuring"));
|
|
||||||
*temp=tempP;
|
|
||||||
return(configuring);
|
|
||||||
OnError: return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int TeccWait(pTecsClient conn) {
|
CocReset(conn);
|
||||||
int last, cnt;
|
ERR_I(CocGetFloat(conn, "tempP", temp));
|
||||||
|
ERR_I(CocPutInt(conn, "readTemp", 1));
|
||||||
last=0;
|
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||||
cnt=0;
|
if (iret) ERR_MSG(response);
|
||||||
do {
|
|
||||||
CocDelay(250);
|
|
||||||
ERR_I(CocCmd(conn, "configuring"));
|
|
||||||
if (configuring==last || configuring>1000) {
|
|
||||||
cnt++;
|
|
||||||
if (cnt>20) ERR_MSG("configuring timeout");
|
|
||||||
} else {
|
|
||||||
cnt=0;
|
|
||||||
last=configuring;
|
|
||||||
}
|
|
||||||
} while (configuring>0);
|
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TeccSet(pTecsClient conn, float temp) {
|
int TeccSet(pTecsClient conn, float temp) {
|
||||||
tempC=temp;
|
int iret;
|
||||||
ERR_I(CocCmd(conn, "[tempC]"));
|
|
||||||
return(0);
|
|
||||||
OnError: return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
|
CocReset(conn);
|
||||||
char *res;
|
ERR_I(CocPutFloat(conn, "set", temp));
|
||||||
int cnt;
|
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||||
|
if (iret) ERR_MSG(response);
|
||||||
str_copy(command, cmd);
|
|
||||||
ERR_I(CocCmd(conn, "[$]"));
|
|
||||||
cnt=40;
|
|
||||||
CocDelay(100);
|
|
||||||
while (cnt>0) {
|
|
||||||
ERR_I(CocCmd(conn, "$"));
|
|
||||||
if (command[0]!='\0') {
|
|
||||||
str_ncpy(reply, command, replyLen);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
CocDelay(250);
|
|
||||||
cnt--;
|
|
||||||
}
|
|
||||||
str_ncpy(reply, "<no response>", replyLen);
|
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
@ -102,7 +69,9 @@ int TeccQuitServer(pTecsClient conn) {
|
|||||||
|
|
||||||
ERR_I(iret=CocCheck(conn));
|
ERR_I(iret=CocCheck(conn));
|
||||||
if (iret==0) {
|
if (iret==0) {
|
||||||
ERR_I(CocSet(conn, "quit", "1"));
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutInt(conn, "quit", 1));
|
||||||
|
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||||
cnt=50;
|
cnt=50;
|
||||||
while (iret==0 && cnt>0) {
|
while (iret==0 && cnt>0) {
|
||||||
CocDelay(100);
|
CocDelay(100);
|
||||||
@ -110,12 +79,15 @@ int TeccQuitServer(pTecsClient conn) {
|
|||||||
cnt--;
|
cnt--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (iret==1) return(0);
|
|
||||||
ERR_MSG("Does not quit within 5 seconds");
|
ERR_MSG("Does not quit within 5 seconds");
|
||||||
OnError:
|
OnError:
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
|
||||||
|
return(CocSetGetN(conn, "send", cmd, reply, replyLen));
|
||||||
|
}
|
||||||
|
|
||||||
void TeccClose(pTecsClient conn) {
|
void TeccClose(pTecsClient conn) {
|
||||||
if (conn!=NULL) {
|
if (conn!=NULL) {
|
||||||
CocCloseClient(conn);
|
CocCloseClient(conn);
|
||||||
@ -136,48 +108,86 @@ void TeccClose(pTecsClient conn) {
|
|||||||
|
|
||||||
#ifdef __VMS
|
#ifdef __VMS
|
||||||
#define tecs_get_par_ tecs_get_par
|
#define tecs_get_par_ tecs_get_par
|
||||||
|
#define tecs_get_mult_ tecs_get_mult
|
||||||
#define tecs_set_par_ tecs_set_par
|
#define tecs_set_par_ tecs_set_par
|
||||||
#define tecs_send_ tecs_send
|
|
||||||
#define tecs_init_ tecs_init
|
#define tecs_init_ tecs_init
|
||||||
#define tecs_get3_ tecs_get3
|
#define tecs_get3_ tecs_get3
|
||||||
|
#define tecs_get_ tecs_get
|
||||||
#define tecs_set_ tecs_set
|
#define tecs_set_ tecs_set
|
||||||
#define tecs_wait_ tecs_wait
|
|
||||||
#define tecs_is_open_ tecs_is_open
|
#define tecs_is_open_ tecs_is_open
|
||||||
#define tecs_close_ tecs_close
|
#define tecs_close_ tecs_close
|
||||||
#define tecs_quit_server_ tecs_quit_server
|
#define tecs_quit_server_ tecs_quit_server
|
||||||
|
#define tecs_watch_log_ tecs_watch_log
|
||||||
|
#define tecs_get_data_ tecs_get_data
|
||||||
|
#define tecs_date_ tecs_date
|
||||||
|
#define tecs_time_ tecs_time
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static pTecsClient conn=NULL;
|
static pTecsClient conn=NULL;
|
||||||
|
|
||||||
int tecs_set_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
|
int tecs_set_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
|
||||||
char nbuf[64], pbuf[256];
|
char nbuf[64], pbuf[COC_CMD_LEN];
|
||||||
int iret=-1;
|
int iret=-1;
|
||||||
|
|
||||||
STR_TO_C(nbuf, name);
|
STR_TO_C(nbuf, name);
|
||||||
STR_TO_C(pbuf, par);
|
STR_TO_C(pbuf, par);
|
||||||
|
|
||||||
ERR_I(iret=CocSet(conn, nbuf, pbuf));
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutStr(conn, nbuf, pbuf));
|
||||||
|
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||||
|
if (*show) {
|
||||||
|
printf("%s", response);
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
OnError: return(iret);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tecs_get_par_(F_CHAR(name), F_CHAR(par), int name_len, int par_len) {
|
int tecs_get_par_(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
|
||||||
char nbuf[64], pbuf[256];
|
char *b, nbuf[64], pbuf[COC_RES_LEN];
|
||||||
int iret=-1;
|
int iret=-1;
|
||||||
|
|
||||||
STR_TO_C(nbuf, name);
|
STR_TO_C(nbuf, name);
|
||||||
ERR_I(iret=CocGet(conn, nbuf, pbuf));
|
CocReset(conn);
|
||||||
|
ERR_I(CocGetStr(conn, nbuf, pbuf, sizeof(pbuf)));
|
||||||
|
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||||
|
if (*show==2) {
|
||||||
|
b=response;
|
||||||
|
} else {
|
||||||
|
b=strchr(response,'=');
|
||||||
|
if (b==NULL) {
|
||||||
|
b=response;
|
||||||
|
} else {
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*show) {
|
||||||
|
printf("%s", b);
|
||||||
|
}
|
||||||
return(STR_TO_F(par, pbuf));
|
return(STR_TO_F(par, pbuf));
|
||||||
OnError: return(iret);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tecs_send_(F_CHAR(cmd), F_CHAR(reply), int cmd_len, int reply_len) {
|
int tecs_get_mult_(F_CHAR(names), int *time, int *nvalues, float values[], int names_len) {
|
||||||
char cbuf[80], rbuf[80];
|
char *b, nbuf[64], pbuf[COC_RES_LEN];
|
||||||
|
char *nams, nam[32];
|
||||||
|
int i;
|
||||||
|
|
||||||
STR_TO_C(cbuf, cmd);
|
STR_TO_C(nbuf, names);
|
||||||
ERR_I(TeccSend(conn, cbuf, rbuf, sizeof(rbuf)));
|
CocReset(conn);
|
||||||
return(STR_TO_F(reply, rbuf));
|
|
||||||
|
ERR_I(CocGetInt(conn, "rdTim", time));
|
||||||
|
i=0;
|
||||||
|
nams=nbuf;
|
||||||
|
while (nams!=NULL && i < *nvalues) {
|
||||||
|
nams=str_split(nam, nams, ' ');
|
||||||
|
if (nam[0]!='\0') {
|
||||||
|
ERR_I(CocGetFloat(conn, nam, values+i));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||||
|
return(0);
|
||||||
OnError: return(-1);
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,19 +201,21 @@ int tecs_init_(F_CHAR(startcmd), int *port, int startcmd_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int tecs_get_(float *temp) {
|
int tecs_get_(float *temp) {
|
||||||
return(TeccGet(conn, temp));
|
ERR_I(TeccGet(conn, temp));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tecs_get3_(float *t1, float *t2, float *t3) {
|
int tecs_get3_(float *t1, float *t2, float *t3) {
|
||||||
return(TeccGet3(conn, t1, t2, t3));
|
ERR_I(TeccGet3(conn, t1, t2, t3));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tecs_set_(float *temp) {
|
int tecs_set_(float *temp) {
|
||||||
return(TeccSet(conn, *temp));
|
ERR_I(TeccSet(conn, *temp));
|
||||||
}
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
int tecs_wait_(void) {
|
|
||||||
return(TeccWait(conn));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tecs_is_open_() {
|
int tecs_is_open_() {
|
||||||
@ -216,7 +228,141 @@ void tecs_close_(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int tecs_quit_server_(void) {
|
int tecs_quit_server_(void) {
|
||||||
return(TeccQuitServer(conn));
|
ERR_I(TeccQuitServer(conn));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tecs_watch_log_(F_CHAR(list), int list_len) {
|
||||||
|
char buf[16];
|
||||||
|
STR_TO_C(buf, list);
|
||||||
|
ERR_I(CocWatchLog(conn, buf));
|
||||||
|
return(0);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *encode=DATA_CODE;
|
||||||
|
|
||||||
|
int DataDecode(float *data, int dataSize, char *coded, int *retSize) {
|
||||||
|
int i, p, gap, dig1, dig2;
|
||||||
|
float minD, range;
|
||||||
|
char ch, *q;
|
||||||
|
static int decode[256];
|
||||||
|
static int init=1;
|
||||||
|
|
||||||
|
if (coded[0] == '\0') {
|
||||||
|
*retSize=0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (init) {
|
||||||
|
init=0;
|
||||||
|
for (i=0; i<256; i++) {
|
||||||
|
decode[i]=-1;
|
||||||
|
}
|
||||||
|
i=0;
|
||||||
|
while (encode[i]!=0) {
|
||||||
|
decode[encode[i]]=i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p=0;
|
||||||
|
ERR_SI(sscanf(coded, "%d %e %e %n", retSize, &minD, &range, &p)-3);
|
||||||
|
if (*retSize < dataSize) dataSize = *retSize;
|
||||||
|
i=0;
|
||||||
|
while (i < dataSize) {
|
||||||
|
ch=coded[p++];
|
||||||
|
dig1=decode[ch];
|
||||||
|
if (dig1 < 0) { /* code is no 64-digit */
|
||||||
|
if (ch=='\0' || ch==',') break;
|
||||||
|
if (ch=='/') { data[i++] = DATA_UNDEF; }
|
||||||
|
} else {
|
||||||
|
ch=coded[p++];
|
||||||
|
dig2=decode[ch];
|
||||||
|
while (dig2<0) {
|
||||||
|
if (ch=='\0' || ch==',') break;
|
||||||
|
ch=coded[p++];
|
||||||
|
dig2=decode[ch];
|
||||||
|
}
|
||||||
|
if (ch=='\0' || ch==',') break;
|
||||||
|
data[i++] = (dig1 + dig2 * 64) / 4095.0 * range + minD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i < dataSize) {
|
||||||
|
data[i++] = DATA_UNDEF;
|
||||||
|
}
|
||||||
|
if (ch=='\0') {
|
||||||
|
return p-1;
|
||||||
|
} else if (ch!=',') {
|
||||||
|
q=strchr(coded+p, ',');
|
||||||
|
if (q==NULL) return strlen(coded);
|
||||||
|
return q-coded+1;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
OnError:
|
||||||
|
*retSize=0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int tecs_get_data_(F_CHAR(names), int *startTime, int *endTime, int *step, float data[], int *maxLen, int *width
|
||||||
|
, int retLen[], int names_len) {
|
||||||
|
char nam[64];
|
||||||
|
char str[128];
|
||||||
|
char res[COC_RES_LEN];
|
||||||
|
char *cod;
|
||||||
|
int i, l, iret, retSize;
|
||||||
|
|
||||||
|
if (*endTime - *startTime > *step * (*maxLen-1)) {
|
||||||
|
printf("maxLen too small\n");
|
||||||
|
}
|
||||||
|
STR_TO_C(nam, names);
|
||||||
|
if (*step <= 0) {
|
||||||
|
*step = 60;
|
||||||
|
}
|
||||||
|
sprintf(str, "%d %d %d %s", *startTime, *endTime, *step, nam);
|
||||||
|
|
||||||
|
CocReset(conn);
|
||||||
|
ERR_I(CocPutStr(conn, "pltdata", str));
|
||||||
|
ERR_I(CocGetStr(conn, "pltdata", res, sizeof(res)));
|
||||||
|
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||||
|
if (iret) ERR_MSG(response);
|
||||||
|
cod=res;
|
||||||
|
for (i=0; i < *width; i++) {
|
||||||
|
ERR_I(l=DataDecode(data + i * *maxLen, *maxLen, cod, retLen+i));
|
||||||
|
cod+=l;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
OnError:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
float tecs_date_(time_t *time) {
|
||||||
|
struct tm tim;
|
||||||
|
|
||||||
|
tim=*localtime(time);
|
||||||
|
return(tim.tm_mday+(tim.tm_mon+1)*0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t tecs_time_(float *date) {
|
||||||
|
struct tm tim;
|
||||||
|
time_t t, now;
|
||||||
|
int m;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
tim=*localtime(&now);
|
||||||
|
tim.tm_hour=0;
|
||||||
|
tim.tm_min=0;
|
||||||
|
tim.tm_sec=0;
|
||||||
|
tim.tm_mday=(int)*date;
|
||||||
|
m=(int)(*date*100+0.1) % 100;
|
||||||
|
if (m > 0) tim.tm_mon=m-1;
|
||||||
|
t=mktime(&tim);
|
||||||
|
if (t > now) {
|
||||||
|
tim.tm_year--;
|
||||||
|
t=mktime(&tim);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,9 +20,6 @@ int TeccGet(pTecsClient conn, float *temp);
|
|||||||
int TeccSet(pTecsClient conn, float temp);
|
int TeccSet(pTecsClient conn, float temp);
|
||||||
/* set temperature */
|
/* set temperature */
|
||||||
|
|
||||||
int TeccWait(pTecsClient conn);
|
|
||||||
/* wait until the controller is configured */
|
|
||||||
|
|
||||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen);
|
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen);
|
||||||
/* send a command transparently to the controller
|
/* send a command transparently to the controller
|
||||||
replyLen is the maximal length of reply */
|
replyLen is the maximal length of reply */
|
||||||
|
@ -1,26 +1,33 @@
|
|||||||
program tecs_client
|
program tecs_client
|
||||||
|
|
||||||
real*4 temp(4)
|
real temp
|
||||||
character device*32, init*80, line*80, cmd*16, par*80, response*80
|
character device*32, init*80, line*80, cmd*16, par*80, response*1024
|
||||||
integer i,j,k,iret,l
|
integer i,j,k,iret,l
|
||||||
character file*128, cmdpar*128
|
character cmdpar*128
|
||||||
|
character prompt*32/'tecs>'/
|
||||||
|
integer promptlen/6/
|
||||||
logical oneCommand
|
logical oneCommand
|
||||||
|
character logarg*4/'25'/
|
||||||
|
character defcmd*8/'status'/
|
||||||
|
|
||||||
! functions
|
! functions
|
||||||
integer tecs_get_par, tecs_quit_server, tecs_send, tecs_set_par
|
integer tecs_get_par, tecs_quit_server, tecs_set_par, tecs_watch_log
|
||||||
|
integer tecs_get, show_log
|
||||||
|
|
||||||
call sys_getenv('TECS_INIT', init)
|
call sys_getenv('TECS_INIT', init)
|
||||||
|
|
||||||
call sys_get_cmdpar(line, l)
|
call sys_get_cmdpar(line, l)
|
||||||
if (l .ne. 0) then
|
if (l .ne. 0) then
|
||||||
if (line .eq. 'off' .or. line .eq. 'OFF') init=' '
|
|
||||||
oneCommand=.true.
|
oneCommand=.true.
|
||||||
else
|
else
|
||||||
oneCommand=.false.
|
oneCommand=.false.
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if (init .eq. ' ') then
|
if (oneCommand .and. line(1:1) .eq. '#') then
|
||||||
call tecs_open(0, ' ', iret)
|
call tecs_open(0, line, iret)
|
||||||
|
oneCommand=.false.
|
||||||
|
else if (init .eq. ' ') then
|
||||||
|
call tecs_open(0, line, iret)
|
||||||
else
|
else
|
||||||
call tecs_open(1, init, iret)
|
call tecs_open(1, init, iret)
|
||||||
endif
|
endif
|
||||||
@ -38,7 +45,8 @@
|
|||||||
print *,'device <device> set cryo device'
|
print *,'device <device> set cryo device'
|
||||||
print *,'<parameter> show parameter'
|
print *,'<parameter> show parameter'
|
||||||
print *,'<parameter> <value> set parameter'
|
print *,'<parameter> <value> set parameter'
|
||||||
print *,'plot temperature and power chart'
|
print *,'plot <var> chart for temperature and <var>'
|
||||||
|
1 ,' var = P (default), He, Aux'
|
||||||
print *,'log <n> show last n lines of logfile'
|
print *,'log <n> show last n lines of logfile'
|
||||||
print *,'kill close TecsServer and exit'
|
print *,'kill close TecsServer and exit'
|
||||||
print *,'exit,quit exit, but do not close TecsServer'
|
print *,'exit,quit exit, but do not close TecsServer'
|
||||||
@ -47,7 +55,7 @@
|
|||||||
|
|
||||||
l=0
|
l=0
|
||||||
1 if (oneCommand) goto 99
|
1 if (oneCommand) goto 99
|
||||||
call sys_rd_line(line, l, 'tecs> ')
|
call sys_rd_line(line, l, prompt(1:promptlen))
|
||||||
if (l .lt. 0) goto 99
|
if (l .lt. 0) goto 99
|
||||||
11 l=l+1
|
11 l=l+1
|
||||||
line(l:l)=' '
|
line(l:l)=' '
|
||||||
@ -61,44 +69,54 @@
|
|||||||
cmd(k:k)=char(ichar(cmd(k:k))+32)
|
cmd(k:k)=char(ichar(cmd(k:k))+32)
|
||||||
endif
|
endif
|
||||||
elseif (k .gt. 0) then ! end of command
|
elseif (k .gt. 0) then ! end of command
|
||||||
goto 2
|
par=' '
|
||||||
|
do i=j,l
|
||||||
|
if (line(i:i) .gt. ' ') then
|
||||||
|
par=line(i:l)
|
||||||
|
goto 3 ! command with parameter
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
goto 2 ! parameterless command
|
||||||
endif
|
endif
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
if (k .eq. 0) then ! empty line
|
if (k .ne. 0) then
|
||||||
call tecs_get_t(6, temp, iret)
|
print *,'command too long'
|
||||||
if (iret .ne. 0) goto 1
|
|
||||||
iret=tecs_get_par('device', device)
|
|
||||||
if (iret .lt. 0) goto 19
|
|
||||||
print '(x,3(a,f8.3),2a)','tempX=', temp(3),', tempP=',temp(2)
|
|
||||||
1 ,', set=',temp(1), ', device=',device
|
|
||||||
goto 1
|
goto 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
print *,'command too long'
|
! empty command
|
||||||
goto 1
|
|
||||||
|
|
||||||
2 par=' '
|
|
||||||
do i=j,l
|
|
||||||
if (line(i:i) .gt. ' ') then
|
|
||||||
par=line(i:l)
|
|
||||||
goto 3
|
|
||||||
endif
|
|
||||||
enddo
|
|
||||||
|
|
||||||
! simple query
|
12 cmd=defcmd
|
||||||
|
|
||||||
if (cmd .eq. 'kill' .or. cmd .eq. 'off') then
|
2 continue ! parameterless command
|
||||||
|
|
||||||
|
defcmd='status'
|
||||||
|
|
||||||
|
if (cmd(1:1) .eq. '#') then
|
||||||
|
call tecs_close
|
||||||
|
call tecs_open(0, cmd, iret)
|
||||||
|
if (iret .lt. 0) goto 91
|
||||||
|
prompt='tecs/'//cmd(2:)
|
||||||
|
promptlen=1
|
||||||
|
do i=1,len(prompt)-2
|
||||||
|
if (prompt(i:i) .ne. ' ') promptlen=i
|
||||||
|
enddo
|
||||||
|
promptlen=promptlen+1
|
||||||
|
prompt(promptlen:promptlen)='>'
|
||||||
|
promptlen=promptlen+1
|
||||||
|
else if (cmd .eq. 'kill') then
|
||||||
iret=tecs_quit_server()
|
iret=tecs_quit_server()
|
||||||
elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then
|
elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then
|
||||||
goto 99
|
goto 99
|
||||||
elseif (cmd .eq. 'on') then
|
elseif (cmd .eq. 'status') then
|
||||||
|
iret=tecs_get_par('status', response, 1)
|
||||||
|
if (iret .lt. 0) goto 19
|
||||||
|
elseif (cmd .eq. 'on' .or. cmd .eq. 'off') then
|
||||||
l=0
|
l=0
|
||||||
goto 11
|
goto 11
|
||||||
elseif (cmd .eq. 'plot') then
|
elseif (cmd .eq. 'plot') then
|
||||||
iret=tecs_get_par('dlogfile', file)
|
call tecs_plot('Tm Ts Tr P', 1)
|
||||||
if (iret .lt. 0) goto 19
|
|
||||||
call tecs_plot(file)
|
|
||||||
elseif (cmd .eq. 'help') then
|
elseif (cmd .eq. 'help') then
|
||||||
print *
|
print *
|
||||||
print *,'Writeable parameters:'
|
print *,'Writeable parameters:'
|
||||||
@ -116,9 +134,9 @@
|
|||||||
print *
|
print *
|
||||||
print *,'Read only parameters:'
|
print *,'Read only parameters:'
|
||||||
print *
|
print *
|
||||||
print *,'tX heat exchanger temperature'
|
print *,'Tm main temperature'
|
||||||
print *,'tS sample temperature'
|
print *,'Ts sample temperature'
|
||||||
print *,'tempH set-point on regulation'
|
print *,'setH set-point on regulation'
|
||||||
print *,'tLimit temperature limit'
|
print *,'tLimit temperature limit'
|
||||||
print *,'htr heater current percentage'
|
print *,'htr heater current percentage'
|
||||||
print *,'resist heater resistance'
|
print *,'resist heater resistance'
|
||||||
@ -126,10 +144,7 @@
|
|||||||
print *,'remoteMode 1: local, 2: remote '
|
print *,'remoteMode 1: local, 2: remote '
|
||||||
1 ,'(switch on with device command)'
|
1 ,'(switch on with device command)'
|
||||||
print *
|
print *
|
||||||
print *,'t1 regulation temperature (hi-T sensor)'
|
print *,'Ta,Tb,Tc,Td values of channels A,B,C,D'
|
||||||
print *,'t2 regulation temperature (low-T sensor)'
|
|
||||||
print *,'t3 sample temperature (hi-T sensor)'
|
|
||||||
print *,'t4 sample temperature (low-T sensor)'
|
|
||||||
print *
|
print *
|
||||||
print *,'Temperature devices:'
|
print *,'Temperature devices:'
|
||||||
print *
|
print *
|
||||||
@ -139,33 +154,43 @@
|
|||||||
print *,'ccr4k (4K closed cycle), hef4c (TriCS 4circle cryo)'
|
print *,'ccr4k (4K closed cycle), hef4c (TriCS 4circle cryo)'
|
||||||
print *,'sup4t (supra.magnet 4T)'
|
print *,'sup4t (supra.magnet 4T)'
|
||||||
print *,'rdr11, rdr12 (LTF dilution 1 & 2, 20kOhm)'
|
print *,'rdr11, rdr12 (LTF dilution 1 & 2, 20kOhm)'
|
||||||
1 ,', rdrn11_2, rdr12_2 (2kOhm)'
|
|
||||||
print *
|
print *
|
||||||
elseif (cmd .eq. 'log') then
|
elseif (cmd .eq. 'log') then
|
||||||
iret=tecs_get_par('logfile', file)
|
if (line(1:l) .eq. ' ') then
|
||||||
|
print '(x,a)'
|
||||||
|
1 ,char(27)//'[A'//char(13)//char(27)//'[K'//char(27)//'[2A'
|
||||||
|
endif
|
||||||
|
if (show_log(logarg) .le. 0) then
|
||||||
|
logarg='25'
|
||||||
|
print *,'-------- end of logfile --------'
|
||||||
|
goto 12
|
||||||
|
endif
|
||||||
|
defcmd='log'
|
||||||
|
logarg=' '
|
||||||
|
elseif (cmd .eq. 'watch') then
|
||||||
|
iret=tecs_watch_log('M')
|
||||||
if (iret .lt. 0) goto 19
|
if (iret .lt. 0) goto 19
|
||||||
call show_log(50, file)
|
|
||||||
else
|
else
|
||||||
iret=tecs_get_par(cmd, response)
|
iret=tecs_get_par(cmd, response, 2)
|
||||||
if (iret .lt. 0) goto 19
|
if (iret .lt. 0) goto 19
|
||||||
print '(7x,3a)',cmd(1:k),'=',response
|
|
||||||
endif
|
endif
|
||||||
goto 1
|
goto 1
|
||||||
|
|
||||||
3 if (cmd .eq. 'send') then
|
3 continue ! command with parameter
|
||||||
iret=tecs_send(par, response)
|
|
||||||
|
if (cmd .eq. 'log') then
|
||||||
|
if (show_log(par) .gt. 0) then
|
||||||
|
defcmd='log'
|
||||||
|
endif
|
||||||
|
logarg=' '
|
||||||
|
elseif (cmd .eq. 'plot') then
|
||||||
|
call tecs_plot('Tm Ts Tr '//par, 1)
|
||||||
|
elseif (cmd .eq. 'watch') then
|
||||||
|
iret=tecs_watch_log(par)
|
||||||
if (iret .lt. 0) goto 19
|
if (iret .lt. 0) goto 19
|
||||||
print '(7x,2a)','response: ',response
|
|
||||||
elseif (cmd .eq. 'log') then
|
|
||||||
i=50
|
|
||||||
read(par, *, err=31) i
|
|
||||||
31 iret=tecs_get_par('logfile', file)
|
|
||||||
if (iret .lt. 0) goto 19
|
|
||||||
call show_log(i, file)
|
|
||||||
else
|
else
|
||||||
iret=tecs_set_par(cmd, par)
|
iret=tecs_set_par(cmd, par, 2)
|
||||||
if (iret .lt. 0) goto 19
|
if (iret .lt. 0) goto 19
|
||||||
print '(7x,3a)',cmd(1:k),':=',par
|
|
||||||
endif
|
endif
|
||||||
goto 1
|
goto 1
|
||||||
|
|
||||||
@ -182,27 +207,21 @@
|
|||||||
99 end
|
99 end
|
||||||
|
|
||||||
|
|
||||||
subroutine show_log(lines, file)
|
integer function show_log(lines)
|
||||||
|
|
||||||
integer lines
|
character*(*) lines
|
||||||
|
|
||||||
integer i,l
|
integer i,l
|
||||||
character str*132, file*(*)
|
character str*8192
|
||||||
|
|
||||||
print *
|
! functions
|
||||||
print *
|
integer tecs_get_par, tecs_set_par
|
||||||
open(1, name=file, status='old', readonly, shared, err=39)
|
|
||||||
i=0
|
if (lines .ne. ' ') then
|
||||||
31 read(1,'(a)',end=32)
|
l=tecs_set_par('logstart', lines, 0)
|
||||||
i=i+1
|
print *,'line: ',lines
|
||||||
goto 31
|
print *
|
||||||
32 rewind(1)
|
endif
|
||||||
do i=1,i-lines
|
|
||||||
read(1,*,end=39)
|
show_log=tecs_get_par('logline', str, 1)
|
||||||
enddo
|
|
||||||
33 read(1,'(q,a)',end=39) l,str
|
|
||||||
print *,str(1:min(len(str),max(1,l)))
|
|
||||||
goto 33
|
|
||||||
39 continue
|
|
||||||
close(1)
|
|
||||||
end
|
end
|
||||||
|
585
tecs/tecs_data.c
Normal file
585
tecs/tecs_data.c
Normal file
@ -0,0 +1,585 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "myc_mem.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_err.h"
|
||||||
|
#include "myc_time.h"
|
||||||
|
#include "coc_logfile.h"
|
||||||
|
#include "tecs_data.h"
|
||||||
|
|
||||||
|
#define RUN_SIZE 1024
|
||||||
|
#define SET_LEN 1024
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int tmin, tmax, tlim;
|
||||||
|
float dmin, dmax;
|
||||||
|
int reset;
|
||||||
|
} Summary;
|
||||||
|
|
||||||
|
typedef struct _Run {
|
||||||
|
struct _Run *next;
|
||||||
|
int size, step;
|
||||||
|
int startTime, endTime;
|
||||||
|
float data[RUN_SIZE];
|
||||||
|
} Run;
|
||||||
|
|
||||||
|
typedef struct _Set {
|
||||||
|
DataSet set;
|
||||||
|
struct _Set *next;
|
||||||
|
int nRuns;
|
||||||
|
int step, lifetime;
|
||||||
|
int start, end;
|
||||||
|
float *var;
|
||||||
|
Run *runs;
|
||||||
|
Summary sum;
|
||||||
|
} Set;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Set *head;
|
||||||
|
} Base;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Base *base;
|
||||||
|
int tim, from, to;
|
||||||
|
int stdStep;
|
||||||
|
} ScanData;
|
||||||
|
|
||||||
|
static Base database;
|
||||||
|
|
||||||
|
void InsSum(Summary *sum, int t, float d) {
|
||||||
|
if (sum->tmin == 0) {
|
||||||
|
sum->tmin = t;
|
||||||
|
sum->tmax = t;
|
||||||
|
sum->dmin = d;
|
||||||
|
sum->dmax = d;
|
||||||
|
} else {
|
||||||
|
if (d <= sum->dmin) {
|
||||||
|
sum->dmin = d;
|
||||||
|
sum->tmin = t;
|
||||||
|
} else if (d >= sum->dmax) {
|
||||||
|
sum->dmax = d;
|
||||||
|
sum->tmax = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetSum(Summary *sum) {
|
||||||
|
sum->reset = 1;
|
||||||
|
sum->tmin = 0;
|
||||||
|
sum->dmin = DATA_UNDEF;
|
||||||
|
sum->dmax = DATA_UNDEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PutSum(Summary *sum, float *data) {
|
||||||
|
if (sum->tmin == 0) {
|
||||||
|
data[1] = sum->dmin;
|
||||||
|
data[0] = sum->dmax;
|
||||||
|
} else if (sum->tmin > sum->tmax) {
|
||||||
|
data[1] = sum->dmin;
|
||||||
|
data[0] = sum->dmax;
|
||||||
|
sum->dmin = sum->dmax;
|
||||||
|
} else if (sum->tmin < sum->tmax) {
|
||||||
|
data[1] = sum->dmax;
|
||||||
|
data[0] = sum->dmin;
|
||||||
|
sum->dmax = sum->dmin;
|
||||||
|
} else {
|
||||||
|
data[1] = sum->dmin;
|
||||||
|
data[0] = sum->dmax;
|
||||||
|
}
|
||||||
|
sum->tmin = 0;
|
||||||
|
if (sum->reset) {
|
||||||
|
sum->dmin = DATA_UNDEF;
|
||||||
|
sum->dmax = DATA_UNDEF;
|
||||||
|
sum->reset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set *FindSet(Base *base, char *name) {
|
||||||
|
Set *s;
|
||||||
|
int total;
|
||||||
|
|
||||||
|
total=0;
|
||||||
|
s = base->head;
|
||||||
|
while (s!=NULL && 0!=strcmp(name, s->set.name)) {
|
||||||
|
s = s->next;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set *CreateSet(Base *base, char *name, float *var, int step, int lifetime, int start) {
|
||||||
|
Set *s;
|
||||||
|
char *nam;
|
||||||
|
|
||||||
|
s = FindSet(base, name);
|
||||||
|
if (s != NULL) ERR_MSG("dataset exists");
|
||||||
|
NEW(s, Set);
|
||||||
|
s->next = base->head;
|
||||||
|
base->head = s;
|
||||||
|
NEW_STR(nam, name);
|
||||||
|
s->set.name = nam;
|
||||||
|
s->runs = NULL;
|
||||||
|
s->nRuns = 0;
|
||||||
|
s->lifetime = lifetime;
|
||||||
|
s->start = start;
|
||||||
|
s->step = step;
|
||||||
|
s->var = var;
|
||||||
|
ResetSum(&s->sum);
|
||||||
|
return s;
|
||||||
|
OnError:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSet *DataFindSet(DataBase *dBase, char *name) {
|
||||||
|
Base *base;
|
||||||
|
if (dBase==NULL) {
|
||||||
|
base=&database;
|
||||||
|
} else {
|
||||||
|
base=(Base *)dBase;
|
||||||
|
}
|
||||||
|
return (DataSet *) FindSet(base, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start) {
|
||||||
|
Base *base;
|
||||||
|
if (dBase==NULL) {
|
||||||
|
base=&database;
|
||||||
|
} else {
|
||||||
|
base=(Base *)dBase;
|
||||||
|
}
|
||||||
|
return (DataSet *) CreateSet(base, name, var, step, lifetime, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataSetStep(DataSet *set, int step) {
|
||||||
|
Set *s;
|
||||||
|
|
||||||
|
ERR_P(set);
|
||||||
|
ERR_I(step-1); /* step > 0 */
|
||||||
|
s = (Set *)set;
|
||||||
|
s->step = step;
|
||||||
|
return 0;
|
||||||
|
OnError: return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataSetLifetime(DataSet *set, int lifetime) {
|
||||||
|
Set *s;
|
||||||
|
|
||||||
|
ERR_P(set);
|
||||||
|
s = (Set *)set;
|
||||||
|
s->lifetime = lifetime;
|
||||||
|
return 0;
|
||||||
|
OnError: return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Run *InsertRun(Set *s, int time) {
|
||||||
|
Run *r, *next, *last;
|
||||||
|
|
||||||
|
NEW(r, Run);
|
||||||
|
r->next = s->runs;
|
||||||
|
s->runs = r;
|
||||||
|
r->step = s->step;
|
||||||
|
s->nRuns++;
|
||||||
|
if (s->nRuns * s->step > s->lifetime) {
|
||||||
|
next=r->next;
|
||||||
|
last=r;
|
||||||
|
while (next!=NULL && next->endTime > time - s->lifetime) {
|
||||||
|
last = next;
|
||||||
|
next = last->next;
|
||||||
|
}
|
||||||
|
while (next!=NULL) {
|
||||||
|
last->next = next->next;
|
||||||
|
FREE(next);
|
||||||
|
s->nRuns--;
|
||||||
|
next = last->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
OnError:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Put(Set *set, int time, float value) {
|
||||||
|
Run *r;
|
||||||
|
int t, try = 1;
|
||||||
|
int size;
|
||||||
|
float last;
|
||||||
|
|
||||||
|
ERR_P(set);
|
||||||
|
if (value == DATA_UNDEF) return 0;
|
||||||
|
r = set->runs;
|
||||||
|
if (r == NULL || r->step != set->step || r->size+3 > RUN_SIZE) {
|
||||||
|
ERR_P(r = InsertRun(set, time));
|
||||||
|
r->startTime = time;
|
||||||
|
r->endTime = time - r->step;
|
||||||
|
size = 0;
|
||||||
|
t = 1;
|
||||||
|
} else {
|
||||||
|
size = r->size;
|
||||||
|
t = (time - r->endTime) / r->step;
|
||||||
|
last = r->data[size-1];
|
||||||
|
}
|
||||||
|
if (t<0) {
|
||||||
|
if (t<-1) {
|
||||||
|
logfileOut(LOG_MAIN, "%s %d <? %d\n", set->set.name, time, r->endTime);
|
||||||
|
ERR_MSG("back in time not possible");
|
||||||
|
}
|
||||||
|
t=0;
|
||||||
|
}
|
||||||
|
if (t == 0) {
|
||||||
|
InsSum(&set->sum, time, value);
|
||||||
|
} else {
|
||||||
|
if (size % 2) {
|
||||||
|
PutSum(&set->sum, r->data+size-1); size++;
|
||||||
|
r->endTime += r->step;
|
||||||
|
t--;
|
||||||
|
}
|
||||||
|
if (t > 2) {
|
||||||
|
r->data[size]=t-1; size++;
|
||||||
|
r->data[size]=DATA_UNDEF; size++;
|
||||||
|
set->sum.reset = 1;
|
||||||
|
r->endTime += r->step * (t-1);
|
||||||
|
t=1;
|
||||||
|
}
|
||||||
|
InsSum(&set->sum, time, value);
|
||||||
|
if (t % 2) {
|
||||||
|
r->data[size]=value; size++; /* put a provisory value */
|
||||||
|
r->endTime += r->step;
|
||||||
|
} else {
|
||||||
|
PutSum(&set->sum, r->data+size); size+=2;
|
||||||
|
r->endTime += r->step * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r->size = size;
|
||||||
|
return 0;
|
||||||
|
OnError:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataPut(DataSet *set, int time, float value) {
|
||||||
|
return Put((Set *)set, time, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataPutAll(DataBase *base, int time) {
|
||||||
|
Set *s;
|
||||||
|
|
||||||
|
if (base == NULL) {
|
||||||
|
s=database.head;
|
||||||
|
} else {
|
||||||
|
s=((Base *)base)->head;
|
||||||
|
}
|
||||||
|
while (s!=NULL) {
|
||||||
|
if (s->var!=NULL) {
|
||||||
|
ERR_I(Put(s, time, *s->var));
|
||||||
|
}
|
||||||
|
s=s->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
OnError:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Start(Set *s) {
|
||||||
|
Run *r;
|
||||||
|
int t1, t2;
|
||||||
|
|
||||||
|
r = s->runs;
|
||||||
|
t1 = s->start;
|
||||||
|
if (r != NULL) {
|
||||||
|
t2 = r->endTime - s->lifetime;
|
||||||
|
if (t1 < t2) {
|
||||||
|
while (r != NULL) {
|
||||||
|
t1 = r->startTime;
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
if (t1 > t2) {
|
||||||
|
t1 = t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FreeBase(Base *base) {
|
||||||
|
Set *s, *sFree;
|
||||||
|
Run *r, *rFree;
|
||||||
|
|
||||||
|
s = base->head;
|
||||||
|
while (s != NULL) {
|
||||||
|
r = s->runs;
|
||||||
|
while (r != NULL) {
|
||||||
|
rFree = r;
|
||||||
|
r = r->next;
|
||||||
|
FREE(rFree);
|
||||||
|
}
|
||||||
|
sFree=s;
|
||||||
|
s = s->next;
|
||||||
|
FREE(sFree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetSet(Set *s, int startTime, int endTime, int size, float *data) {
|
||||||
|
Run *r;
|
||||||
|
int t, tlim, tmin;
|
||||||
|
float d;
|
||||||
|
int i, idx;
|
||||||
|
Summary sum;
|
||||||
|
|
||||||
|
if (size<=0 || size%2 != 0) ERR_MSG("size must be even and positive");
|
||||||
|
ERR_P(s);
|
||||||
|
ERR_P(data);
|
||||||
|
|
||||||
|
r = s->runs;
|
||||||
|
|
||||||
|
ResetSum(&sum);
|
||||||
|
idx = size - 2;
|
||||||
|
tlim = (endTime - startTime) * idx / size + startTime;
|
||||||
|
|
||||||
|
while (r != NULL) {
|
||||||
|
if (startTime > r->endTime) break;
|
||||||
|
if (endTime >= r->startTime) {
|
||||||
|
t = r->endTime;
|
||||||
|
d = 0;
|
||||||
|
for (i = r->size - 1; i>=0; i--, t-=r->step) {
|
||||||
|
d = r->data[i];
|
||||||
|
if (d == DATA_UNDEF) {
|
||||||
|
i--;
|
||||||
|
t -= (int)(r->data[i] + 0.5) * r->step;
|
||||||
|
sum.reset = 1;
|
||||||
|
} else {
|
||||||
|
if (t < startTime) break;
|
||||||
|
if (t < endTime) {
|
||||||
|
while (t < tlim) {
|
||||||
|
PutSum(&sum, data+idx); idx-=2;
|
||||||
|
tlim = (endTime - startTime) * idx / size + startTime;
|
||||||
|
}
|
||||||
|
InsSum(&sum, t, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = r->next;
|
||||||
|
}
|
||||||
|
sum.reset = 1;
|
||||||
|
while (idx >= 0) {
|
||||||
|
PutSum(&sum, data+idx); idx-=2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
OnError:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scan(void *sData, char *line) {
|
||||||
|
Set *set;
|
||||||
|
Run *run;
|
||||||
|
Base *base;
|
||||||
|
char str[64], nam[64];
|
||||||
|
int l, iret, hh, mm, ss;
|
||||||
|
float num;
|
||||||
|
int tim, tshift, t0;
|
||||||
|
|
||||||
|
base=((ScanData *)sData)->base;
|
||||||
|
tim=((ScanData *)sData)->tim;
|
||||||
|
|
||||||
|
/* read time */
|
||||||
|
l=0; iret=sscanf(line, "%d:%d:%d%n", &hh, &mm, &ss, &l); line+=l;
|
||||||
|
if (iret!=3) return;
|
||||||
|
tim+=hh*3600+mm*60+ss;
|
||||||
|
if (tim < ((ScanData *)sData)->from || tim > ((ScanData *)sData)->to) return;
|
||||||
|
|
||||||
|
set=NULL;
|
||||||
|
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
|
||||||
|
while (iret==1) {
|
||||||
|
if (str[0] >= 'A') {
|
||||||
|
str_copy(nam, str);
|
||||||
|
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
|
||||||
|
if (iret==1) {
|
||||||
|
iret=sscanf(str, "%f", &num);
|
||||||
|
if (iret==1) {
|
||||||
|
tshift = 0;
|
||||||
|
if (0 != strcmp(nam, "_")) {
|
||||||
|
set=FindSet(base, nam);
|
||||||
|
if (set!=NULL) tshift = 1;
|
||||||
|
}
|
||||||
|
if (set!=NULL && tim < set->end) {
|
||||||
|
if (tshift) {
|
||||||
|
t0 = tim - ((ScanData *)sData)->stdStep*2;
|
||||||
|
run = set->runs;
|
||||||
|
if (run != NULL && run->endTime >= t0) {
|
||||||
|
t0 = run->endTime;
|
||||||
|
}
|
||||||
|
t0 += set->step;
|
||||||
|
if (t0 > tim) t0 = tim;
|
||||||
|
Put(set, t0, num);
|
||||||
|
} else {
|
||||||
|
Put(set, tim, num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l=0; iret=sscanf(line, "%64s%n", str, &l); line+=l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load(Base *base, int from, int to, int stdStep) {
|
||||||
|
Set *set;
|
||||||
|
ScanData scanData;
|
||||||
|
int t, date;
|
||||||
|
|
||||||
|
scanData.base = base;
|
||||||
|
scanData.stdStep = stdStep;
|
||||||
|
scanData.from = from;
|
||||||
|
scanData.to = to;
|
||||||
|
|
||||||
|
/* round down "from" and "to" to 00:00 local time */
|
||||||
|
from = from - (from % (24*3600));
|
||||||
|
to = to - (to % (24*3600));
|
||||||
|
|
||||||
|
for (t=from; t<=to; t+=24*3600) {
|
||||||
|
scanData.tim=t;
|
||||||
|
logfileScan(mycDate(t), Scan, &scanData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *encode=DATA_CODE;
|
||||||
|
|
||||||
|
int DataEncode(float *data, int dataSize, char *coded, int codedLen) {
|
||||||
|
int i, n, p, gap;
|
||||||
|
float minD, maxD, range;
|
||||||
|
|
||||||
|
if (dataSize >= (codedLen-26)/2) ERR_MSG("codedLen too small");
|
||||||
|
minD=DATA_UNDEF;
|
||||||
|
maxD=DATA_UNDEF;
|
||||||
|
for (i=0; i<dataSize; i++) {
|
||||||
|
if (data[i]!=DATA_UNDEF) {
|
||||||
|
if (maxD==DATA_UNDEF) {
|
||||||
|
maxD=data[i]; minD=data[i];
|
||||||
|
} else {
|
||||||
|
if (data[i] > maxD) maxD=data[i];
|
||||||
|
if (data[i] < minD) minD=data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
range = maxD - minD;
|
||||||
|
if (range == 0) range=1;
|
||||||
|
ERR_SI(p=sprintf(coded, "%d %5g %5g ", dataSize, minD, range));
|
||||||
|
gap=0;
|
||||||
|
for (i=0; i<dataSize; i++) {
|
||||||
|
if ( data[i] == DATA_UNDEF ) {
|
||||||
|
coded[p++]='/';
|
||||||
|
} else {
|
||||||
|
n=( (data[i] - minD) * 4095 ) / range + 0.5;
|
||||||
|
assert(n>=0 && n <4096);
|
||||||
|
coded[p++]=encode[n % 64];
|
||||||
|
coded[p++]=encode[n / 64];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
coded[p++]=',';
|
||||||
|
coded[p]='\0';
|
||||||
|
assert(p < codedLen);
|
||||||
|
return p;
|
||||||
|
OnError:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataGetCoded(char *names, int startTime, int endTime, int step, int stdStep, char *coded, int codedLen) {
|
||||||
|
Base base;
|
||||||
|
Set *set, *s;
|
||||||
|
int stp, minStep, period, s1;
|
||||||
|
char *nams, nam[32];
|
||||||
|
int p, l, n, i, j, siz1, siz2, halfsiz, start;
|
||||||
|
float data[SET_LEN];
|
||||||
|
|
||||||
|
base.head = NULL;
|
||||||
|
period = endTime - startTime;
|
||||||
|
n=0; nams = names;
|
||||||
|
while (nams != NULL) {
|
||||||
|
nams = str_split(nam, nams, ' ');
|
||||||
|
if (nam[0] != '\0') n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
stp=step;
|
||||||
|
if (stp<stdStep) stp=stdStep;
|
||||||
|
nams=names;
|
||||||
|
while (nams!=NULL) {
|
||||||
|
nams=str_split(nam, nams, ' ');
|
||||||
|
if (nam[0]!='\0') {
|
||||||
|
set=FindSet(&database, nam);
|
||||||
|
if (set != NULL) {
|
||||||
|
start = Start(set);
|
||||||
|
} else {
|
||||||
|
start = endTime;
|
||||||
|
}
|
||||||
|
if (set == NULL || start > startTime) {
|
||||||
|
set=CreateSet(&base, nam, NULL, stp, period, startTime);
|
||||||
|
set->end = start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (base.head != NULL) {
|
||||||
|
Load(&base, startTime, endTime, stdStep);
|
||||||
|
}
|
||||||
|
p=0;
|
||||||
|
nams=names;
|
||||||
|
coded[0]='\0';
|
||||||
|
while (nams!=NULL) {
|
||||||
|
nams=str_split(nam, nams, ' ');
|
||||||
|
if (nam[0]!='\0') {
|
||||||
|
s = FindSet(&database, nam);
|
||||||
|
set = FindSet(&base, nam);
|
||||||
|
s1 = startTime;
|
||||||
|
if (s == NULL) {
|
||||||
|
if (set == NULL) {
|
||||||
|
s1 = 0;
|
||||||
|
} else {
|
||||||
|
s = set;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
minStep = s->step;
|
||||||
|
if (set != NULL) {
|
||||||
|
s1 = Start(s);
|
||||||
|
if (s1 >= endTime) {
|
||||||
|
s = set;
|
||||||
|
s1 = startTime;
|
||||||
|
} else if (s1 < startTime || s1 <= Start(set)) {
|
||||||
|
s1 = startTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s1 == 0) {
|
||||||
|
data[0]=DATA_UNDEF;
|
||||||
|
ERR_I(l=DataEncode(data, 1, coded+p, codedLen-p));
|
||||||
|
} else {
|
||||||
|
minStep = s->step;
|
||||||
|
stp = step;
|
||||||
|
halfsiz = period / (2 * stp) + 1;
|
||||||
|
if (startTime + minStep * halfsiz * 2 > endTime) {
|
||||||
|
if (stp < minStep) stp = minStep;
|
||||||
|
halfsiz = period / (2 * stp) + 1;
|
||||||
|
if (halfsiz * 2 > SET_LEN) halfsiz = SET_LEN / 2;
|
||||||
|
if (halfsiz * 4 + 32 * n > codedLen) {
|
||||||
|
halfsiz = ((codedLen - p) / n - 32) / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
siz1 = (s1 - startTime) * halfsiz / period * 2;
|
||||||
|
siz2 = halfsiz * 2 - siz1;
|
||||||
|
s1 = startTime + (siz1 * period + halfsiz) / halfsiz / 2;
|
||||||
|
if (siz1 > 0) {
|
||||||
|
ERR_I(GetSet(set, startTime, s1, siz1, data));
|
||||||
|
}
|
||||||
|
if (siz2 > 0) {
|
||||||
|
ERR_I(GetSet(s, s1, endTime, siz2, data+siz1));
|
||||||
|
}
|
||||||
|
ERR_I(l=DataEncode(data, siz1+siz2, coded+p, codedLen-p));
|
||||||
|
}
|
||||||
|
p+=l;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeBase(&base);
|
||||||
|
return (0);
|
||||||
|
OnError:
|
||||||
|
return(-1);
|
||||||
|
}
|
47
tecs/tecs_data.h
Normal file
47
tecs/tecs_data.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef TECS_DATA_H_
|
||||||
|
#define TECS_DATA_H_
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
} DataSet;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *private;
|
||||||
|
} DataBase;
|
||||||
|
|
||||||
|
DataSet *DataCreateSet(DataBase *dBase, char *name, float *var, int step, int lifetime, int start);
|
||||||
|
/*
|
||||||
|
create a new dataset
|
||||||
|
if the dataset already exists, or memory allocation failed, NULL is returned
|
||||||
|
set <dBase> to NULL to use the common database
|
||||||
|
*/
|
||||||
|
|
||||||
|
DataSet *DataFindSet(DataBase *dBase, char *name);
|
||||||
|
/*
|
||||||
|
find a previously created dataset.
|
||||||
|
returns NULL if dataset not found
|
||||||
|
set <dBase> to NULL to use the common database
|
||||||
|
*/
|
||||||
|
|
||||||
|
int DataSetStep(DataSet *set, int step);
|
||||||
|
int DataSetLifetime(DataSet *set, int lifetime);
|
||||||
|
int DataPut(DataSet *set, int time, float value);
|
||||||
|
/*
|
||||||
|
put one value to dataset
|
||||||
|
*/
|
||||||
|
|
||||||
|
int DataPutAll(DataBase *dBase, int time);
|
||||||
|
/*
|
||||||
|
put all variables in a set to their dataset
|
||||||
|
*/
|
||||||
|
|
||||||
|
int DataDecode(float *data, int dataSize, char *coded, int *retLen);
|
||||||
|
int DataGetCoded(char *names, int startTime, int endTime, int step, int stdStep, char *coded, int codedLen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
define DATA_UNDEF as a binary and decimal well defined, hopefully rarely used number
|
||||||
|
*/
|
||||||
|
#define DATA_UNDEF MYC_NAN
|
||||||
|
#define DATA_CODE "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
#endif /* TECS_DATA_H_ */
|
@ -9,7 +9,7 @@ c M. Zolliker, March 2000
|
|||||||
c Updates:
|
c Updates:
|
||||||
c V01A 21-Mar-2000 DM. Integrate into TASMAD
|
c V01A 21-Mar-2000 DM. Integrate into TASMAD
|
||||||
c 05-Apr-2000 M.Z. modifed error handling/changed arguments in TeccGet3
|
c 05-Apr-2000 M.Z. modifed error handling/changed arguments in TeccGet3
|
||||||
c 01-May-2000 M.Z. renamed source, TECS_OPEN is now in a separate, system dependend file
|
c 01-May-2000 M.Z. renamed source, TECS_OPEN is now in a separate, system dependent file
|
||||||
c V01C 11-May-2000 DM. Split into modules.
|
c V01C 11-May-2000 DM. Split into modules.
|
||||||
c V01D 12-May-2000 M.Z. Changed error handling, no longer automatic call to TECS_OPEN
|
c V01D 12-May-2000 M.Z. Changed error handling, no longer automatic call to TECS_OPEN
|
||||||
c------------------------------------------------------------------------------
|
c------------------------------------------------------------------------------
|
||||||
@ -102,11 +102,18 @@ c extract the port number from the start command
|
|||||||
i=index(init, '-p ')
|
i=index(init, '-p ')
|
||||||
if (i .eq. 0) i=index(init, '-P ')
|
if (i .eq. 0) i=index(init, '-P ')
|
||||||
if (i .ne. 0) then
|
if (i .ne. 0) then
|
||||||
read(init,*,iostat=ios) port
|
read(init(min(len(init),i+3):),*,iostat=ios) port
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if (port .eq. 0) port=9753
|
if (port .eq. 0) port=9753
|
||||||
iret=tecs_init(init, port)
|
|
||||||
|
if (init(1:1) .eq. '#') then
|
||||||
|
i=index(init, '-')-1
|
||||||
|
if (i .le. 0) i=len(init)
|
||||||
|
else
|
||||||
|
i=len(init)
|
||||||
|
endif
|
||||||
|
iret=tecs_init(init(1:i), port)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -131,7 +138,7 @@ c if INIT exists, read it to get the port number and the start command
|
|||||||
end
|
end
|
||||||
|
|
||||||
SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !!
|
SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !!
|
||||||
!! ============================================
|
!! =========================================
|
||||||
!!
|
!!
|
||||||
!! Get temperatures and wait if TECS is configuring
|
!! Get temperatures and wait if TECS is configuring
|
||||||
!!
|
!!
|
||||||
@ -152,18 +159,18 @@ c------------------------------------------------------------------------------
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
if (iret .gt. 0) then
|
if (iret .gt. 0) then
|
||||||
write(iolun, *) 'configuring temperature controller ...'
|
! write(iolun, *) 'configuring temperature controller ...'
|
||||||
iret=tecs_wait()
|
! iret=tecs_wait()
|
||||||
if (iret .lt. 0) then
|
! if (iret .lt. 0) then
|
||||||
call err_txt('tecs_wait'//char(10)//'tecs_get_t')
|
! call err_txt('tecs_wait'//char(10)//'tecs_get_t')
|
||||||
return
|
! return
|
||||||
endif
|
! endif
|
||||||
write(iolun, *) '... done'
|
! write(iolun, *) '... done'
|
||||||
iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
|
! iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
|
||||||
if (iret .lt. 0) then
|
! if (iret .lt. 0) then
|
||||||
call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
|
! call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
|
||||||
return
|
! return
|
||||||
endif
|
! endif
|
||||||
endif
|
endif
|
||||||
temp(4)=0.0 ! no auxilliary sensor
|
temp(4)=0.0 ! no auxilliary sensor
|
||||||
end
|
end
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "err_handling.h"
|
#include "myc_err.h"
|
||||||
#include "coc_logfile.h"
|
#include "coc_logfile.h"
|
||||||
#include "coc_util.h"
|
#include "coc_server.h"
|
||||||
#include "tecs_lsc.h"
|
#include "tecs_lsc.h"
|
||||||
#include "str_util.h"
|
#include "myc_str.h"
|
||||||
|
|
||||||
#define MAX_PAR 16
|
#define MAX_PAR 16
|
||||||
#define MAX_ARG 9
|
#define MAX_ARG 9
|
||||||
@ -46,15 +46,14 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
char *blank, *colon, *qu, *res;
|
char *blank, *colon, *qu, *res;
|
||||||
const char *p, *this, *next, *cmd_ptr, *retreq;
|
const char *p, *this, *next, *cmd_ptr, *retreq;
|
||||||
const char *list[nLIST];
|
const char *list[nLIST];
|
||||||
char seg[SER_BUF_LEN], buf[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN];
|
char seg[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN];
|
||||||
char cmd[SER_BUF_LEN];
|
char cmd[SER_BUF_LEN];
|
||||||
char varname[32];
|
char varname[32];
|
||||||
Str_Buf sbuf;
|
DeclStrBuf(sbuf, SER_BUF_LEN);
|
||||||
int nres, i, j, response;
|
int nres, i, j, response;
|
||||||
|
|
||||||
nres=0;
|
nres=0;
|
||||||
response=0;
|
response=0;
|
||||||
str_link_buf(&sbuf, buf, sizeof(buf), STR_NOSEPARATOR);
|
|
||||||
this=cmds;
|
this=cmds;
|
||||||
while (this!=NULL) {
|
while (this!=NULL) {
|
||||||
next=str_split(cmd, this, ';');
|
next=str_split(cmd, this, ';');
|
||||||
@ -67,13 +66,13 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
}
|
}
|
||||||
cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */
|
cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */
|
||||||
p=str_split(seg, cmd, '[');
|
p=str_split(seg, cmd, '[');
|
||||||
ERR_I(str_put_str(&sbuf, seg));
|
ERR_I(StrPut(&sbuf, seg, StrNONE));
|
||||||
while (p!=NULL) { /* substitute variables */
|
while (p!=NULL) { /* substitute variables */
|
||||||
p=str_split(varname, p, ']');
|
p=str_split(varname, p, ']');
|
||||||
if (p==NULL) ERR_MSG("missing ']'");
|
if (p==NULL) ERR_MSG("missing ']'");
|
||||||
ERR_I(CocPutVar(serverVarList, &sbuf, varname, 0));
|
ERR_I(CocPutVar(varname, &sbuf, StrNONE));
|
||||||
p=str_split(seg, p, '[');
|
p=str_split(seg, p, '[');
|
||||||
ERR_I(str_put_str(&sbuf, seg));
|
ERR_I(StrPut(&sbuf, seg, StrNONE));
|
||||||
}
|
}
|
||||||
ERR_I(str_copy(cmd, cmd_ptr));
|
ERR_I(str_copy(cmd, cmd_ptr));
|
||||||
colon=strchr(cmd_ptr, ':');
|
colon=strchr(cmd_ptr, ':');
|
||||||
@ -86,16 +85,15 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
}
|
}
|
||||||
list[nres]=colon+1; nres++; assert(nres<=nLIST); /* pointer to parameters */
|
list[nres]=colon+1; nres++; assert(nres<=nLIST); /* pointer to parameters */
|
||||||
list[nres]=cmd_ptr; nres++; assert(nres<=nLIST); /* pointer to command */
|
list[nres]=cmd_ptr; nres++; assert(nres<=nLIST); /* pointer to command */
|
||||||
ERR_I(str_put_str(&sbuf, ";"));
|
ERR_I(StrPut(&sbuf, ";", StrNONE));
|
||||||
cmd[blank-cmd_ptr]='?'; /* build query */
|
cmd[blank-cmd_ptr]='?'; /* build query */
|
||||||
if (colon==blank) colon++;
|
if (colon==blank) colon++;
|
||||||
cmd[colon-cmd_ptr]='\0';
|
cmd[colon-cmd_ptr]='\0';
|
||||||
ERR_I(str_put_str(&sbuf, cmd)); /* put query */
|
ERR_I(StrPut(&sbuf, cmd, ';')); /* put query */
|
||||||
ERR_I(str_put_str(&sbuf, ";"));
|
|
||||||
response=1;
|
response=1;
|
||||||
} else {
|
} else {
|
||||||
qu=strchr(cmd, '?');
|
qu=strchr(cmd, '?');
|
||||||
ERR_I(str_put_str(&sbuf, ";"));
|
ERR_I(StrPut(&sbuf, ";", StrNONE));
|
||||||
if (qu!=NULL) { /* command is a query */
|
if (qu!=NULL) { /* command is a query */
|
||||||
response=1;
|
response=1;
|
||||||
if (retreq==NULL) {
|
if (retreq==NULL) {
|
||||||
@ -110,11 +108,11 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!response) {
|
if (!response) {
|
||||||
ERR_I(str_put_str(&sbuf, "busy?"));
|
ERR_I(StrPut(&sbuf, "busy?",'\0'));
|
||||||
} else {
|
} else {
|
||||||
buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */
|
sbuf.buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */
|
||||||
}
|
}
|
||||||
ERR_P(res=SerCmd(ser, buf));
|
ERR_P(res=SerCmd(ser, sbuf.buf));
|
||||||
if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout");
|
if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout");
|
||||||
/*
|
/*
|
||||||
list[0..nres-1] contains a now:
|
list[0..nres-1] contains a now:
|
||||||
@ -158,18 +156,19 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (retreq!=NULL) { /* query */
|
if (retreq!=NULL) { /* query */
|
||||||
str_link_buf(&sbuf, result, 0, ',');
|
StrLink(&sbuf, result);
|
||||||
str_split(par, retreq+1, ';');
|
str_split(par, retreq+1, ';');
|
||||||
p=par;
|
p=par;
|
||||||
while (p!=NULL) {
|
while (p!=NULL) {
|
||||||
p=str_split(varname, p, ',');
|
p=str_split(varname, p, ',');
|
||||||
if (varname[0]!='\0') {
|
if (varname[0]!='\0') {
|
||||||
if (p==NULL) { /* last element: get rest of line */
|
if (p==NULL) { /* last element: get rest of line */
|
||||||
sbuf.sep='\0';
|
ERR_I(CocGetVar(varname, &sbuf, '\0'));
|
||||||
|
} else {
|
||||||
|
ERR_I(CocGetVar(varname, &sbuf, ','));
|
||||||
}
|
}
|
||||||
ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0));
|
|
||||||
} else {
|
} else {
|
||||||
ERR_P(str_get_str(&sbuf, NULL));
|
ERR_P(StrGet(&sbuf, varname, ','));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,3 +176,33 @@ char *LscCmd(SerChannel *ser, const char *cmds) {
|
|||||||
return(res);
|
return(res);
|
||||||
OnError: return(NULL);
|
OnError: return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *LscReadStat(int stat) {
|
||||||
|
if (stat &128) return("units overrange");
|
||||||
|
if (stat & 64) return("units zero");
|
||||||
|
if (stat & 32) return("temp overrange");
|
||||||
|
if (stat & 16) return("temp underrange");
|
||||||
|
if (stat & 2) return("old reading");
|
||||||
|
if (stat & 1) return("invalid reading");
|
||||||
|
return ("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char
|
||||||
|
*heaterStatus[7]={
|
||||||
|
"",
|
||||||
|
"heater supply over V",
|
||||||
|
"heater supply under V",
|
||||||
|
"heater output DAC error",
|
||||||
|
"heater Ilimit DAC error",
|
||||||
|
"open heater load",
|
||||||
|
"heater load < 10 Ohm",
|
||||||
|
};
|
||||||
|
|
||||||
|
char *LscHtrStat(int stat) {
|
||||||
|
if (stat<0 || stat>sizeof(heaterStatus)) {
|
||||||
|
return("unknown heater status");
|
||||||
|
} else {
|
||||||
|
return(heaterStatus[stat]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@ char *LscCmd(SerChannel *ser, const char *cmds);
|
|||||||
name="CTI5"
|
name="CTI5"
|
||||||
head="R10410 ,3,+330.000E+0,2"
|
head="R10410 ,3,+330.000E+0,2"
|
||||||
|
|
||||||
All used variables have to be declared with CocDef... (see coc_util.h)
|
All used variables have to be declared with CocDef... (see coc_server.h)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int LscEqPar(char *par, char *res);
|
int LscEqPar(char *par, char *res);
|
||||||
@ -49,4 +49,8 @@ int LscEqPar(char *par, char *res);
|
|||||||
if any parameter in par is omitted, it is not compared
|
if any parameter in par is omitted, it is not compared
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
char *LscReadStat(int stat);
|
||||||
|
|
||||||
|
char *LscHtrStat(int stat);
|
||||||
|
|
||||||
#endif /* _TECS_LSC_H_ */
|
#endif /* _TECS_LSC_H_ */
|
||||||
|
@ -1,36 +1,55 @@
|
|||||||
subroutine tecs_plot(file)
|
subroutine tecs_plot(pars, naux)
|
||||||
|
|
||||||
character(len=*) file
|
character(len=*) pars ! parameters to plot
|
||||||
|
integer naux ! number of auxiliary, non-T parameters
|
||||||
|
|
||||||
integer, parameter :: dmax=500, nset=3, nmenu=10, chartfreq=2
|
integer, parameter :: dmax=1000, nmax=5, nmenu=11, chartfreq=1
|
||||||
real, parameter :: winmin=60., undef=-65535.0
|
integer, parameter :: minRange=60, maxRange=7*24*3600
|
||||||
|
integer, parameter :: oneDay = 24*3600
|
||||||
|
real, parameter :: winmin=60., undef=-1.125/1024./1024./1024.
|
||||||
|
|
||||||
real*4 x1,x2,xmin,xmax,ymin(2),ymax(2),window
|
real*4 x1,x2,xmin,xmax,ymin(2),ymax(2),window
|
||||||
real*4 xd(dmax),yd(dmax,nset)
|
real*4 xd(dmax, nmax),yd(dmax,nmax), yy0(nmax), yy1(nmax)
|
||||||
real*4 ylast1,ylast2,y1,y2
|
real*4 ylast1,ylast2,y1,y2
|
||||||
real*4 ex,ey,fx,fy,hmenu,wmenu,ymenu,ticks
|
real*4 ex,ey,fx,fy,row,ticks,tim0,tim1
|
||||||
real*4 xbox(8), ybox(8)
|
integer l,j,i,n,t,leng,i1,i2,rl,startday,thisday
|
||||||
integer l,j,i,t0,t1,ntot,i1,i2,rl,n,startday,thisday
|
integer nset
|
||||||
integer first,last,tbase,lastj
|
integer first,last,step,tbase,lastj
|
||||||
integer color(3)/2,4,3/
|
integer color(nmax)
|
||||||
|
integer retLen(nmax)
|
||||||
character key*1
|
character key*1
|
||||||
character text(nmenu)*12/ &
|
character text(nmenu)*12/ &
|
||||||
'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','file','quit'/
|
'live off','sel. zoom','zoom in','zoom out','show all','n days','n hours','n min','date','file','quit'/
|
||||||
character keys*(nmenu)/'LZ+-XDHMFQ'/
|
character keys*(nmenu)/'LZ+-XDHMTFQ'/
|
||||||
character weekdays(7)*3/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
|
character weekdays(7)*4/'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
|
||||||
character buf*8, device*8, line*40, filnam*128
|
character buf*8, device*8, name*40, filnam*128, numb*16
|
||||||
|
character(len=16) parnam(nmax)
|
||||||
external tplot_close
|
external tplot_close
|
||||||
|
logical gap, done
|
||||||
logical live, xwin, zoom, right, saveit
|
logical live, xwin, zoom, right, saveit
|
||||||
integer iret, numb, lund
|
integer iret, lund, numl, mon, day
|
||||||
|
|
||||||
integer dlog_open_r, dlog_get, dlog_close_r
|
! functions
|
||||||
|
integer sys_gmt_off, myc_now, myc_time, myc_date, tecs_get_data, tecs_get_mult
|
||||||
|
|
||||||
data window/1800./
|
data window/0./
|
||||||
|
|
||||||
|
if (window==0) window=1800.
|
||||||
saveit=.false.
|
saveit=.false.
|
||||||
zoom=.false.
|
zoom=.false.
|
||||||
right=.true.
|
right=.true.
|
||||||
call pgopen(" ")
|
call pgopen(" ")
|
||||||
|
|
||||||
|
call pgscr(0, 1.0, 1.0, 1.0)
|
||||||
|
call pgscr(1, 0.0, 0.0, 0.0)
|
||||||
|
call pgscr(2, 1.0, 0.0, 0.0)
|
||||||
|
call pgscr(3, 0.0, 1.0, 0.0)
|
||||||
|
call pgscr(4, 0.0, 0.0, 1.0)
|
||||||
|
call pgscr(5, 0.0, 1.0, 1.0)
|
||||||
|
call pgscr(6, 1.0, 0.0, 1.0)
|
||||||
|
call pgscr(7, 1.0, 1.0, 0.0)
|
||||||
|
call pgscr(8, 1.0, 0.5, 0.0)
|
||||||
|
|
||||||
call pgqinf('TYPE', device, l)
|
call pgqinf('TYPE', device, l)
|
||||||
if (device=='NULL') then
|
if (device=='NULL') then
|
||||||
print *,'No PGPLOT-Device defined'
|
print *,'No PGPLOT-Device defined'
|
||||||
@ -38,72 +57,104 @@ subroutine tecs_plot(file)
|
|||||||
endif
|
endif
|
||||||
live=device(1:1)/='X' ! live switched off by default on X-Windows
|
live=device(1:1)/='X' ! live switched off by default on X-Windows
|
||||||
|
|
||||||
|
nset=1
|
||||||
|
l=1
|
||||||
|
i=1
|
||||||
|
do while (i <= nmax)
|
||||||
|
do while (l < len(pars) .and. pars(l:l) <= ' ')
|
||||||
|
l=l+1
|
||||||
|
enddo
|
||||||
|
if (pars(l:l) > ' ') then
|
||||||
|
j=l
|
||||||
|
do while (l < len(pars) .and. pars(l:l) > ' ')
|
||||||
|
l=l+1
|
||||||
|
enddo
|
||||||
|
parnam(i)=pars(j:l)
|
||||||
|
nset=i
|
||||||
|
if (l == len(pars)) i=nmax
|
||||||
|
else
|
||||||
|
i=nmax
|
||||||
|
endif
|
||||||
|
i=i+1
|
||||||
|
enddo
|
||||||
|
|
||||||
call pgask(.false.)
|
call pgask(.false.)
|
||||||
l=0
|
l=0
|
||||||
iret=dlog_open_r(file, first, last, tbase)
|
|
||||||
if (iret<0) then
|
|
||||||
call err_txt('dlog_open_r')
|
|
||||||
goto 99
|
|
||||||
endif
|
|
||||||
xmax=0
|
|
||||||
x1=0
|
x1=0
|
||||||
|
step=0
|
||||||
|
|
||||||
1 if (right .or. window==0 .or. live) then
|
1 iret=tecs_get_mult(pars, t, nset, yy0)
|
||||||
ntot=dlog_get(dmax, nset, tbase, -window*1.1, 0.0, undef, xd, yd)
|
if (iret < 0) goto 99
|
||||||
if (ntot<=0) then
|
if (window == 0) then
|
||||||
if (ntot<0) then
|
last=t
|
||||||
call err_txt('dlog_get')
|
step=maxRange/dmax
|
||||||
goto 99
|
window=maxRange
|
||||||
endif
|
first=t-min(dmax*step-1,maxRange-step)
|
||||||
x2=last-tbase
|
else if (right .or. live) then
|
||||||
else
|
step=window/(dmax-1)+0.99
|
||||||
x2=maxval(xd(1:ntot))
|
last=t
|
||||||
endif
|
first=t-min(dmax*step-1,nint(window)-step)
|
||||||
if (live) then
|
|
||||||
if (x1 .eq. 0) then
|
|
||||||
x1=max(x2-window,xd(1))
|
|
||||||
else
|
|
||||||
window=x2-x1
|
|
||||||
endif
|
|
||||||
x2=max(x1+window,x2+min(window*0.2,max(window*0.01,300.)))
|
|
||||||
elseif (window==0) then
|
|
||||||
x1=minval(xd(1:ntot))
|
|
||||||
window=x2-x1
|
|
||||||
else
|
|
||||||
x1=x2-window
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
if (.not. zoom) then
|
if (.not. zoom) then
|
||||||
x2=(x1+x2+window)/2
|
x2=(x1+x2+window)/2
|
||||||
x1=x2-window
|
x1=x2-window
|
||||||
endif
|
endif
|
||||||
ntot=dlog_get(dmax, nset, tbase, x1-window*0.1, x2+window*0.1, undef, xd, yd)
|
if (x1 .gt. x2-minRange) x1=x2-minRange
|
||||||
endif
|
step=(x2-x1)/(dmax-1)+0.99
|
||||||
if (ntot<0) then
|
last=nint(x2)+tbase
|
||||||
call err_txt('dlog_get')
|
first=nint(x1)+tbase
|
||||||
goto 99
|
endif
|
||||||
endif
|
if (step == 0) step=1
|
||||||
if (saveit) goto 9
|
|
||||||
if (ntot>0) then
|
iret=tecs_get_data(pars, first, last, step, yd, dmax, nmax, retLen)
|
||||||
xmin=minval(xd(1:ntot))
|
if (iret < 0) goto 99
|
||||||
xmax=maxval(xd(1:ntot))
|
! do i=1,nmax
|
||||||
|
! if (retLen(i) > 0) nset=i
|
||||||
|
! enddo
|
||||||
|
! if (nset == 0) then
|
||||||
|
! retLen(1)=0
|
||||||
|
! nset=1
|
||||||
|
! endif
|
||||||
|
color(1)=2
|
||||||
|
color(2)=4
|
||||||
|
color(3)=3
|
||||||
|
color(4)=5
|
||||||
|
color(5)=8
|
||||||
|
if (naux > 0) color(nset)=8
|
||||||
|
|
||||||
|
tbase=first-mod(first,7*oneDay);
|
||||||
|
x2 = last - tbase;
|
||||||
|
if (right .or. live) then
|
||||||
|
x1=x2-window
|
||||||
else
|
else
|
||||||
xmin=x1
|
x1 = first - tbase;
|
||||||
xmax=x2
|
endif
|
||||||
|
tim0=t-tbase
|
||||||
|
do j=1,nset
|
||||||
|
leng=retLen(j)
|
||||||
|
do i=1,leng
|
||||||
|
xd(i,j)=(float(i-1)*(last-tbase)+float(leng-i)*(first-tbase))/(leng-1)
|
||||||
|
enddo
|
||||||
|
if (live .and. leng>0) then
|
||||||
|
xd(leng,j)=tim0
|
||||||
|
yd(leng,j)=yy0(j)
|
||||||
|
endif
|
||||||
|
enddo
|
||||||
|
if (saveit) goto 9
|
||||||
|
if (live) then
|
||||||
|
x2=max(tim0,x2)+min(1800., window*0.5)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call pgsvp(0.07,0.93,0.1,0.9) ! define window size
|
if (window>50*3600) then
|
||||||
|
ticks=8*3600
|
||||||
if (xmax<=xmin) then
|
elseif (window>25*3600) then
|
||||||
xmax=xmin+1
|
ticks=4*3600
|
||||||
! l=0
|
else
|
||||||
! print *,'no points found'
|
ticks=0.0 ! automatic
|
||||||
! print *
|
|
||||||
! goto 9
|
|
||||||
endif
|
endif
|
||||||
call pgsch(1.0)
|
|
||||||
i1=1
|
i1=1
|
||||||
i2=2
|
i2=nset-naux
|
||||||
do rl=1,2
|
do rl=1,2
|
||||||
if (zoom) then
|
if (zoom) then
|
||||||
ymin(1)=y1
|
ymin(1)=y1
|
||||||
@ -114,13 +165,13 @@ subroutine tecs_plot(file)
|
|||||||
ylast1=ymin(rl)
|
ylast1=ymin(rl)
|
||||||
ylast2=ymax(rl)
|
ylast2=ymax(rl)
|
||||||
do i=i1,i2
|
do i=i1,i2
|
||||||
do j=1,ntot
|
do j=1,retLen(i)
|
||||||
if (xd(j) >= x1 .and. xd(j) <= x2 .and. yd(j,i)/=undef) then
|
if (yd(j,i)/=undef) then
|
||||||
ymin(rl)=min(ymin(rl),yd(j,i))
|
ymin(rl)=min(ymin(rl),yd(j,i))
|
||||||
ymax(rl)=max(ymax(rl),yd(j,i))
|
ymax(rl)=max(ymax(rl),yd(j,i))
|
||||||
endif
|
endif
|
||||||
enddo
|
enddo
|
||||||
do j=max(1,ntot-4),ntot
|
do j=max(1,retLen(i)-4),retLen(i)
|
||||||
if (yd(j, i)/=undef) then
|
if (yd(j, i)/=undef) then
|
||||||
ylast1=min(ylast1,yd(j, i))
|
ylast1=min(ylast1,yd(j, i))
|
||||||
ylast2=max(ylast2,yd(j, i))
|
ylast2=max(ylast2,yd(j, i))
|
||||||
@ -130,169 +181,190 @@ subroutine tecs_plot(file)
|
|||||||
|
|
||||||
ey=(ymax(rl)-ymin(rl))
|
ey=(ymax(rl)-ymin(rl))
|
||||||
fy=abs(ymax(rl))
|
fy=abs(ymax(rl))
|
||||||
if (rl==1) then
|
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.01)
|
||||||
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.25)
|
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
|
||||||
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
|
|
||||||
else
|
|
||||||
ymax(rl)=ymax(rl)+max(fy*0.1,ey*0.01)
|
|
||||||
ymin(rl)=ymin(rl)-max(fy,ey*4)
|
|
||||||
endif
|
|
||||||
if (live) then
|
if (live) then
|
||||||
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
|
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
|
||||||
ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
|
ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if (ymax(rl) .lt. ymin(rl)) then
|
if (ymax(rl) < ymin(rl)) then
|
||||||
ymax(rl)=1
|
ymax(rl)=1.0
|
||||||
ymin(rl)=0
|
|
||||||
elseif (ymax(rl) .eq. ymin(rl)) then
|
|
||||||
ymax(rl)=ymin(rl)+1.0
|
|
||||||
ymin(rl)=0
|
ymin(rl)=0
|
||||||
|
elseif (ymax(rl) == ymin(rl)) then
|
||||||
|
ymax(rl)=ymin(rl)*1.00001+1.0
|
||||||
|
ymin(rl)=-1.0e-3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
zoom=.false.
|
zoom=.false.
|
||||||
|
|
||||||
call pgswin(x1,x2,ymin(rl),ymax(rl))
|
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||||
call pgscr(0, 1.0, 1.0, 1.0)
|
|
||||||
call pgscr(1, 0.0, 0.0, 0.0)
|
|
||||||
call pgscr(2, 1.0, 0.0, 0.0)
|
|
||||||
call pgscr(3, 0.0, 0.7, 0.0)
|
|
||||||
call pgscr(4, 0.0, 0.0, 1.0)
|
|
||||||
|
|
||||||
do i=i1,i2
|
do i=i2,i1,-1
|
||||||
call pgsci(color(i))
|
call pgsci(color(i))
|
||||||
n=0
|
|
||||||
lastj=1
|
lastj=1
|
||||||
do j=1,ntot
|
do j=1,retLen(i)
|
||||||
if (yd(j,i)==undef) then
|
if (yd(j,i)==undef) then
|
||||||
if (j>lastj) call pgline(j-lastj, xd(lastj), yd(lastj,i))
|
if (j>lastj) then
|
||||||
|
call pgline(j-lastj, xd(lastj,i), yd(lastj,i))
|
||||||
|
endif
|
||||||
lastj=j+1
|
lastj=j+1
|
||||||
endif
|
endif
|
||||||
enddo
|
enddo
|
||||||
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i))
|
if (retLen(i) > lastj) call pgline(retLen(i)+1-lastj, xd(lastj,i), yd(lastj,i))
|
||||||
enddo
|
enddo
|
||||||
i1=3
|
call pgsci(1)
|
||||||
i2=3
|
if (rl == 1) then
|
||||||
|
call pgsch(1.0)
|
||||||
|
call pgtbox('ZHXYBINST', ticks, 0, 'BCINMST', 0.0, 0)
|
||||||
|
call pgtbox('C', 0.0, 0, ' ', 0.0, 0)
|
||||||
|
ey=0.0
|
||||||
|
do i=i1,i2
|
||||||
|
name=parnam(i)
|
||||||
|
if (name=="Tm") then
|
||||||
|
name="Main Sensor"
|
||||||
|
elseif (name=="Ts") then
|
||||||
|
name="Sample Sensor"
|
||||||
|
elseif (name=="Tr") then
|
||||||
|
name="SetPoint"
|
||||||
|
endif
|
||||||
|
call pglen(5, trim(name), fx, fy)
|
||||||
|
call pgsci(color(i))
|
||||||
|
call pgmtxt ('L', 2.5, ey, 0.0, trim(name))
|
||||||
|
ey=ey+fy+0.04
|
||||||
|
enddo
|
||||||
|
call pgsci(1)
|
||||||
|
call pgmtxt ('L', 2.5, ey, 0.0, 'T [K]')
|
||||||
|
else if (naux > 0) then
|
||||||
|
call pgsch(0.7)
|
||||||
|
call pgtbox('ZCIST', ticks, 0, 'BCVINMST', 0.0, 0)
|
||||||
|
call pgtbox('B', 0.0, 0, ' ', 0.0, 0)
|
||||||
|
call pgsci(color(nset))
|
||||||
|
call pgsch(1.0)
|
||||||
|
if (parnam(nset) == 'P' .or. parnam(nset) == 'p') then
|
||||||
|
call pgmtxt ('L', 2.5, 0.5, 0.5, 'Power [W]')
|
||||||
|
else
|
||||||
|
call pgmtxt ('L', 2.5, 0.5, 0.5, parnam(nset))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
i1=nset-naux+1
|
||||||
|
i2=nset
|
||||||
enddo
|
enddo
|
||||||
rl=2
|
|
||||||
call pgsci(1)
|
call pgsch(0.8)
|
||||||
! call pgtbox(' ', 0.0, 0, 'CIMST', 0.0, 0)
|
|
||||||
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.20
|
|
||||||
call pgsch(0.7)
|
|
||||||
call pgaxis('N', x1, ey, x1, ymax(rl), ey, ymax(rl), 0, 0, 0.5, 0.0, 0.0, -1.0, 0.0)
|
|
||||||
rl=1
|
rl=1
|
||||||
call pgswin(x1,x2,ymin(rl),ymax(rl))
|
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||||
ey=ymax(rl)-(ymax(rl)-ymin(rl))*0.21
|
|
||||||
call pgsch(1.0)
|
|
||||||
call pgaxis('N', x1, ymin(rl), x1, ey, ymin(rl), ey, 0, 0, 0.5, 0.0, 0.5, -1.0, 0.0)
|
|
||||||
if (window>50*3600) then
|
|
||||||
ticks=8*3600
|
|
||||||
elseif (window>25*3600) then
|
|
||||||
ticks=4*3600
|
|
||||||
else
|
|
||||||
ticks=0.0 ! automatic
|
|
||||||
endif
|
|
||||||
call pgtbox('ZHXYBCINST', ticks, 0, 'CIMST', 0.0, 0)
|
|
||||||
call pgmtxt ('L', 2.5, 0.4, 0.5, 'T [K]')
|
|
||||||
call pgsci(color(1))
|
|
||||||
call pgmtxt ('L', 2.5, 0.2, 0.5, 'Main Sensor')
|
|
||||||
call pgsci(color(2))
|
|
||||||
call pgmtxt ('L', 2.5, 0.6, 0.5, 'Sample Sensor')
|
|
||||||
call pgsci(color(3))
|
|
||||||
call pgmtxt ('L', 2.5, 0.9, 0.5, 'Power [W]')
|
|
||||||
call pgsci(1)
|
call pgsci(1)
|
||||||
call pgsclp(0)
|
call pgsclp(0)
|
||||||
hmenu=(ymax(rl)-ymin(rl))/15.
|
|
||||||
ymenu=ymax(rl)+hmenu*0.5
|
|
||||||
wmenu=(x2-x1)/(nmenu+2)
|
|
||||||
if (live) then
|
if (live) then
|
||||||
text(1)='live off'
|
text(1)='live off'
|
||||||
else
|
else
|
||||||
text(1)='live on'
|
text(1)='live on'
|
||||||
endif
|
endif
|
||||||
call pgsch(0.7)
|
ex=0.0
|
||||||
do i=1,nmenu
|
do i=1,nmenu
|
||||||
xbox(1)=x1+(i-0.7)*wmenu
|
call pglen(5, trim(text(i)), fx, fy)
|
||||||
ybox(1)=ymenu+hmenu
|
call pgmtxt('T', 3.0, ex, 0.0, '|'//keys(i:i))
|
||||||
xbox(2)=xbox(1)
|
call pgmtxt('T', 2.5, ex, 0.0, '|')
|
||||||
ybox(2)=ymenu+hmenu*0.5
|
call pgmtxt('T', 2.0, ex, 0.0, '|'//text(i))
|
||||||
xbox(3)=x1+(i-0.95)*wmenu
|
ex=ex+fx+0.01
|
||||||
ybox(3)=ybox(2)
|
|
||||||
xbox(4)=xbox(3)
|
|
||||||
ybox(4)=ybox(1)
|
|
||||||
xbox(5)=xbox(1)
|
|
||||||
ybox(5)=ybox(1)
|
|
||||||
call pgline(5, xbox, ybox)
|
|
||||||
call pgptxt(x1+(i-0.9)*wmenu, ymenu+0.65*hmenu, 0.0, 0.0, keys(i:i))
|
|
||||||
call pgptxt(x1+(i-0.9)*wmenu, ymenu+0.15*hmenu, 0.0, 0.0, text(i))
|
|
||||||
enddo
|
enddo
|
||||||
call pgmtxt('T', 3.5, 1.0, 1.0, 'any digit to enter n')
|
call pgmtxt('T', 3.0, ex, 0.0, '|')
|
||||||
call pgmtxt('T', 2.0, 0.9, 1.0, 'n=')
|
call pgmtxt('T', 2.5, ex, 0.0, '|')
|
||||||
thisday=(x1+x2)/2/(24*3600)
|
call pgmtxt('T', 2.0, ex, 0.0, '|')
|
||||||
ey=ymin(rl)-hmenu*1.5
|
call pgmtxt('T', 3.0, 0.8, 0.0, 'any digit to enter n')
|
||||||
i=max(0,int((x1+12*3600)/(24*3600)))
|
call pgmtxt('T', 2.0, 0.8, 0.0, 'n=')
|
||||||
|
|
||||||
|
done=.false.
|
||||||
|
row=(ymax(rl)-ymin(rl))/30.
|
||||||
|
ey=ymin(rl)-row*3.5
|
||||||
|
i=max(0,int((x1+oneDay/2)/oneDay))
|
||||||
|
|
||||||
do
|
do
|
||||||
ex=(i+0.5)*24*3600
|
ex=(i+0.5)*oneDay
|
||||||
if (ex>x2) EXIT
|
if (ex > x2) EXIT
|
||||||
thisday=0
|
done=.true.
|
||||||
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1))
|
write(buf,'(i8.8)') myc_date(nint(ex)+tbase)
|
||||||
|
call pgptxt(ex, ey, 0.0, 0.5, weekdays(mod(i,7)+1)//buf(7:8)//'.'//buf(5:6))
|
||||||
ex=ex-12*3600
|
ex=ex-12*3600
|
||||||
if (ex .gt. x1) then
|
if (ex > x1) then
|
||||||
call pgmove(ex, ey)
|
call pgmove(ex, ey)
|
||||||
call pgdraw(ex, ey+hmenu/2)
|
call pgdraw(ex, ey+row)
|
||||||
endif
|
endif
|
||||||
ex=ex+24*3600
|
ex=ex+oneDay
|
||||||
if (ex .lt. x2) then
|
if (ex < x2) then
|
||||||
call pgmove(ex, ey)
|
call pgmove(ex, ey)
|
||||||
call pgdraw(ex, ey+hmenu/2)
|
call pgdraw(ex, ey+row)
|
||||||
endif
|
endif
|
||||||
i=i+1
|
i=i+1
|
||||||
enddo
|
enddo
|
||||||
if (thisday>0) then
|
if (.not. done) then
|
||||||
call pgptxt((x1+x2)/2, ey, 0.0, 0.5, weekdays(mod(thisday,7)+1))
|
n=nint(x2)/oneDay*oneDay;
|
||||||
|
i=nint(x1)-n
|
||||||
|
j=nint(x2)-n
|
||||||
|
if (i < 0) then
|
||||||
|
if (-i > j) then
|
||||||
|
ex=0.0
|
||||||
|
i=nint(x1)+tbase
|
||||||
|
else
|
||||||
|
ex=1.0
|
||||||
|
i=nint(x2)+tbase
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
ex=0.5
|
||||||
|
i=nint(x2)+tbase
|
||||||
|
endif
|
||||||
|
thisday=mod(i/oneDay,7)+1
|
||||||
|
write(buf,'(i8.8)') myc_date(i)
|
||||||
|
! call pgptxt((x1+x2)/2, ey, 0.0, ex, weekdays(mod(thisday,7)+1)//buf(7:8)//'.'//buf(5:6))
|
||||||
|
call pgmtxt('B', 3.5, ex, ex, weekdays(thisday)//buf(7:8)//'.'//buf(5:6))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call pgsclp(1)
|
call pgsclp(1)
|
||||||
|
|
||||||
call get_key(key, 0, 0) ! purge buffer
|
call get_key(key, 0, 0) ! purge buffer
|
||||||
|
|
||||||
numb=0
|
numl=0
|
||||||
|
numb=' '
|
||||||
7 if (live) then
|
7 if (live) then
|
||||||
if (device(1:1)=='X') then
|
if (device(1:1)=='X') then
|
||||||
call pgmtxt('T', 1.0, 1.0, 1.0, 'LIVE MODE (click on text window before pressing any further key)')
|
call pgmtxt('T', 0.5, 0.0, 0.0, 'LIVE MODE (click on text window before pressing any further key)')
|
||||||
endif
|
endif
|
||||||
call get_key(key, 0, chartfreq)
|
call get_key(key, 0, chartfreq)
|
||||||
do while (key .eq. char(0)) ! no key pressed
|
|
||||||
ntot=dlog_get(dmax, nset, tbase, xmax-0.5, 1e10, undef, xd, yd)
|
do while (key == char(0)) ! no key pressed
|
||||||
if (ntot<0) then
|
iret=tecs_get_mult(pars, t, nset, yy1)
|
||||||
call err_txt('dlog_open_r 2')
|
if (iret<0) goto 99
|
||||||
goto 99
|
tim1=t-tbase
|
||||||
|
if (tim1 > x2) then
|
||||||
|
call pgpage
|
||||||
|
window=x2-x1
|
||||||
|
goto 1
|
||||||
endif
|
endif
|
||||||
if (ntot .gt. 1) then
|
if (tim1 > tim0) then
|
||||||
i1=1
|
i1=1
|
||||||
i2=2
|
i2=nset-naux
|
||||||
do rl=1,2
|
do rl=1,2
|
||||||
call pgswin(x1,x2,ymin(rl),ymax(rl))
|
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||||
do i=i1,i2
|
do i=i2,i1,-1
|
||||||
call pgsci(color(i))
|
if (yy0(i) .ne. undef .and. yy1(i) .ne. undef) then
|
||||||
n=0
|
if (yy1(i) < ymin(rl) .or. yy1(i) > ymax(rl)) then
|
||||||
lastj=1
|
|
||||||
do j=1,ntot
|
|
||||||
if (yd(j,i)==undef) then
|
|
||||||
if (j>lastj) call pgline(j-lastj, xd(lastj), yd(lastj,i))
|
|
||||||
lastj=j+1
|
|
||||||
elseif (xd(j)>x2 .or. yd(j,i)<ymin(rl) .or. yd(j,i)>ymax(rl)) then
|
|
||||||
call pgpage
|
call pgpage
|
||||||
window=x2-x1
|
window=x2-x1
|
||||||
goto 1
|
goto 1
|
||||||
endif
|
endif
|
||||||
enddo
|
call pgsci(color(i))
|
||||||
if (ntot .gt. lastj) call pgline(ntot+1-lastj, xd(lastj), yd(lastj,i))
|
call pgmove(tim0, yy0(i))
|
||||||
|
call pgdraw(tim1, yy1(i))
|
||||||
|
endif
|
||||||
|
yy0(i)=yy1(i)
|
||||||
enddo
|
enddo
|
||||||
i1=3
|
i1=nset-naux+1
|
||||||
i2=3
|
i2=nset
|
||||||
enddo
|
enddo
|
||||||
xmax=max(xmax,xd(ntot))
|
tim0=tim1
|
||||||
|
|
||||||
endif
|
endif
|
||||||
call get_key(key, 0, chartfreq)
|
call get_key(key, 0, chartfreq)
|
||||||
enddo
|
enddo
|
||||||
@ -301,16 +373,11 @@ subroutine tecs_plot(file)
|
|||||||
call must_purge
|
call must_purge
|
||||||
endif
|
endif
|
||||||
rl=1
|
rl=1
|
||||||
call pgswin(x1,x2,ymin(rl),ymax(rl))
|
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||||
|
|
||||||
8 if (key>='a') key=char(ichar(key)-32)
|
8 if (key>='a') key=char(ichar(key)-32)
|
||||||
if (ey>ymenu) then
|
|
||||||
i=max(0,min(nmenu,int((ex-x1)/wmenu+1)))
|
|
||||||
key=keys(i:i)
|
|
||||||
ex=(x1+x2)/2
|
|
||||||
endif
|
|
||||||
if (key=='-') then
|
if (key=='-') then
|
||||||
window=min(window*2, 8*24*3600.)
|
window=min(window*2, 8.0*oneDay)
|
||||||
elseif (key=='X') then
|
elseif (key=='X') then
|
||||||
window=0
|
window=0
|
||||||
live=.false.
|
live=.false.
|
||||||
@ -319,10 +386,10 @@ subroutine tecs_plot(file)
|
|||||||
elseif (key=='Z') then
|
elseif (key=='Z') then
|
||||||
call pgsci(1)
|
call pgsci(1)
|
||||||
if (live) then
|
if (live) then
|
||||||
call pgmtxt('T', 1.0, 0.0, 0.0, 'click on two opposite corners of a selection rectangle')
|
call pgmtxt('T', 0.5, 0.0, 0.0, 'click on two opposite corners of a selection rectangle')
|
||||||
call pgcurs(ex, ey, key)
|
call pgcurs(ex, ey, key)
|
||||||
else
|
else
|
||||||
call pgmtxt('T', 1.0, 0.3, 0.0, 'click on second corner of selection rectangle')
|
call pgmtxt('T', 0.5, 0.0, 0.0, 'click on second corner of selection rectangle')
|
||||||
endif
|
endif
|
||||||
call pgsci(5)
|
call pgsci(5)
|
||||||
xmin=x1
|
xmin=x1
|
||||||
@ -349,16 +416,13 @@ subroutine tecs_plot(file)
|
|||||||
zoom=.true.
|
zoom=.true.
|
||||||
live=.false.
|
live=.false.
|
||||||
right=.false.
|
right=.false.
|
||||||
elseif (key .ge. '0' .and. key .le. '9') then
|
elseif (key >= '0' .and. key <= '9' .or. key == '.') then ! number
|
||||||
numb=numb*10+(ichar(key)-ichar('0'))
|
if (numl .lt. len(numb)) then
|
||||||
if (numb>0) then
|
numl=numl+1
|
||||||
write(buf, '(i8)') numb
|
numb(numl:numl)=key
|
||||||
l=1
|
|
||||||
do while (buf(l:l)==' ')
|
|
||||||
l=l+1
|
|
||||||
enddo
|
|
||||||
call pgsci(1)
|
call pgsci(1)
|
||||||
call pgmtxt('T', 2.0, 0.9, 0.0, buf(l:))
|
call pgsch(0.8)
|
||||||
|
call pgmtxt('T', 2.0, 0.825, 0.0, numb(1:numl))
|
||||||
endif
|
endif
|
||||||
if (device(1:1)=='X' .and. .not. live) then
|
if (device(1:1)=='X' .and. .not. live) then
|
||||||
call pgcurs(ex, ey, key)
|
call pgcurs(ex, ey, key)
|
||||||
@ -368,35 +432,59 @@ subroutine tecs_plot(file)
|
|||||||
endif
|
endif
|
||||||
if (key/=char(0)) goto 8
|
if (key/=char(0)) goto 8
|
||||||
goto 7
|
goto 7
|
||||||
elseif (key .eq. 'D') then
|
elseif (key == 'D') then
|
||||||
window=min(7*24*3600,24*3600*max(1,numb))
|
ex=1
|
||||||
|
read(numb, *, iostat=i) ex
|
||||||
|
window=min(maxRange,max(minRange, nint(oneDay*ex)))
|
||||||
right=.true.
|
right=.true.
|
||||||
x1=0
|
x1=0
|
||||||
elseif (key .eq. 'H') then
|
elseif (key == 'H') then
|
||||||
window=min(7*24*3600,3600*max(1,numb))
|
ex=1
|
||||||
|
read(numb, *, iostat=i) ex
|
||||||
|
window=min(maxRange,max(minRange, nint(3600*ex)))
|
||||||
right=.true.
|
right=.true.
|
||||||
x1=0
|
x1=0
|
||||||
elseif (key .eq. 'M') then
|
elseif (key == 'M') then
|
||||||
window=min(7*24*3600,60*max(1,numb))
|
ex=1
|
||||||
|
read(numb, *, iostat=i) ex
|
||||||
|
window=min(maxRange,max(minRange, nint(60*ex)))
|
||||||
right=.true.
|
right=.true.
|
||||||
x1=0
|
x1=0
|
||||||
elseif (key .eq. 'L') then
|
elseif (key == 'T' .or. numl>0 .and. (key==char(13) .or. key==char(10))) then
|
||||||
|
j=index(numb,'.')
|
||||||
|
day=0
|
||||||
|
if (j > 1 .and. j < numl) then
|
||||||
|
read(numb(1:j-1), *, iostat=i) day
|
||||||
|
mon=0
|
||||||
|
read(numb(j+1:numl), *, iostat=i) mon
|
||||||
|
tbase = myc_time(day+mon*100);
|
||||||
|
else
|
||||||
|
read(numb, *, iostat=i) day
|
||||||
|
tbase = myc_time(day);
|
||||||
|
endif
|
||||||
|
x1=0
|
||||||
|
x2=oneDay
|
||||||
|
window=x2
|
||||||
|
live=.false.
|
||||||
|
right=.false.
|
||||||
|
elseif (key == 'L') then
|
||||||
live=.not. live
|
live=.not. live
|
||||||
if (live) then
|
if (live) then
|
||||||
right=.true.
|
right=.true.
|
||||||
x2=xmax
|
|
||||||
endif
|
endif
|
||||||
elseif (key .eq. 'F') then
|
elseif (key == 'F') then
|
||||||
saveit=.true.
|
saveit=.true.
|
||||||
elseif (key=='Q' .or. key==char(13)) then
|
elseif (key=='Q' .or. key==char(13) .or. key==char(10)) then
|
||||||
goto 9
|
goto 9
|
||||||
|
elseif (key == 'R') then
|
||||||
elseif (live) then
|
elseif (live) then
|
||||||
goto 7
|
goto 7
|
||||||
endif
|
endif
|
||||||
numb=0
|
numl=0
|
||||||
|
numb=' '
|
||||||
call pgpage
|
call pgpage
|
||||||
goto 1
|
goto 1
|
||||||
99 call tecs_write_error(6)
|
99 call tecs_write_msg(6)
|
||||||
9 continue
|
9 continue
|
||||||
call tplot_close
|
call tplot_close
|
||||||
call get_key(key, 0, 0) ! purge type-ahead-buffer
|
call get_key(key, 0, 0) ! purge type-ahead-buffer
|
||||||
@ -406,19 +494,35 @@ subroutine tecs_plot(file)
|
|||||||
print '(x,a,$)', 'Filename: '
|
print '(x,a,$)', 'Filename: '
|
||||||
read(*,'(a)') filnam
|
read(*,'(a)') filnam
|
||||||
open(lund, file=filnam, status='unknown', carriagecontrol='list')
|
open(lund, file=filnam, status='unknown', carriagecontrol='list')
|
||||||
write(lund, *) ' time [h]',char(9),' T1 [K]',char(9),' T2 [K]',char(9),'power [W]'
|
|
||||||
do i=1,ntot
|
gap=.false.
|
||||||
write(line, '(4(f9.4,a))') xd(i)/3600., (char(9), max(-999.,min(9999.,yd(i,j))), j=1,3)
|
do j=1,nset
|
||||||
do j=1,3
|
if (j == 1) then
|
||||||
|
write(lund, *) ' time [h]',char(9),' Tm [K]'
|
||||||
|
elseif (j == 2) then
|
||||||
|
write(lund,*)
|
||||||
|
write(lund, *) ' time [h]',char(9),' Ts [K]'
|
||||||
|
else
|
||||||
|
write(lund,*)
|
||||||
|
write(lund, *) ' time [h]',char(9), ' ',trim(parnam(j))
|
||||||
|
endif
|
||||||
|
|
||||||
|
do i=1,retLen(j)
|
||||||
if (yd(i,j)==undef) then
|
if (yd(i,j)==undef) then
|
||||||
line(10*j+1:10*j+9)=' '
|
if (gap) then
|
||||||
|
write(lund, '(f9.4,2a)') xd(i,j)/3600., char(9), ' '
|
||||||
|
gap=.false.
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
write(lund, '(f9.4,a,f9.4)') xd(i,j)/3600., char(9), max(-999.,min(9999.,yd(i,j)))
|
||||||
|
gap=.true.
|
||||||
endif
|
endif
|
||||||
enddo
|
enddo
|
||||||
write(lund, *) line(1:39)
|
|
||||||
enddo
|
enddo
|
||||||
close(lund)
|
close(lund)
|
||||||
print *, ntot+1, ' lines written to ',filnam(1:48)
|
print *, retLen(1)+1, ' lines written to ',filnam(1:48)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
end subroutine
|
end subroutine
|
||||||
|
|
||||||
subroutine get_key(key, tmo1, tmo2)
|
subroutine get_key(key, tmo1, tmo2)
|
||||||
@ -439,7 +543,20 @@ entry must_purge
|
|||||||
purge=.true.
|
purge=.true.
|
||||||
end subroutine
|
end subroutine
|
||||||
|
|
||||||
|
subroutine set_win(rl, x1, x2, y1, y2)
|
||||||
|
integer rl
|
||||||
|
real x1, x2, y1, y2
|
||||||
|
|
||||||
|
if (rl == 1) then
|
||||||
|
call pgsvp(0.07,0.93,0.3,0.9)
|
||||||
|
else
|
||||||
|
call pgsvp(0.07,0.93,0.01,0.20)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call pgswin(x1,x2,y1,y2)
|
||||||
|
end subroutine
|
||||||
|
|
||||||
subroutine tplot_close
|
subroutine tplot_close
|
||||||
call pgclos
|
call pgclos
|
||||||
call dlog_close_r
|
! call dlog_close_r
|
||||||
end subroutine
|
end subroutine
|
||||||
|
@ -1,27 +1,37 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/timeb.h>
|
#include <assert.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include "rs232c_def.h"
|
#include "rs232c_def.h"
|
||||||
#include "asynsrv_def.h"
|
#include "asynsrv_def.h"
|
||||||
#include "sinq_prototypes.h"
|
#include "sinq_prototypes.h"
|
||||||
#include "sys_util.h"
|
#include "sys_util.h"
|
||||||
#include "err_handling.h"
|
#include "myc_err.h"
|
||||||
#include "tecs_serial.h"
|
#include "tecs_serial.h"
|
||||||
#include "coc_logfile.h"
|
#include "coc_logfile.h"
|
||||||
#include "str_util.h"
|
#include "coc_util.h"
|
||||||
|
#include "myc_str.h"
|
||||||
|
#include "myc_mem.h"
|
||||||
|
|
||||||
#define A_CHK(R) if (1!=(R)) { SerA_error(); ErrTxt(#R,0); goto OnError; }
|
#define ASYNSRV_TYPE 1
|
||||||
|
#define TERMSRV_TYPE 2
|
||||||
|
#define EOT '\r'
|
||||||
|
|
||||||
int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */
|
typedef struct {
|
||||||
|
int type; /* = ASYNSRV_TYPE */
|
||||||
void (*idleHandler)(int,int);
|
|
||||||
|
|
||||||
struct SerChan {
|
|
||||||
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
|
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
|
||||||
struct RS__MsgStruct to_host;
|
struct RS__MsgStruct to_host;
|
||||||
struct RS__RespStruct from_host;
|
struct RS__RespStruct from_host;
|
||||||
char cmd[SER_BUF_LEN];
|
} AsynSrvChan;
|
||||||
};
|
|
||||||
|
typedef struct {
|
||||||
|
int type; /* = TERMSRV_TYPE */
|
||||||
|
char res[SER_BUF_LEN];
|
||||||
|
int fd, tmo;
|
||||||
|
int (*idleHdl)(int,int);
|
||||||
|
} TermSrvChan;
|
||||||
|
|
||||||
void SerA_error(void) {
|
void SerA_error(void) {
|
||||||
char *a_txt;
|
char *a_txt;
|
||||||
@ -31,43 +41,182 @@ void SerA_error(void) {
|
|||||||
ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
|
ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)) {
|
int SerWait(int tmo_msec, int fd) {
|
||||||
struct SerChan *ser;
|
struct timeval tmo;
|
||||||
char hbuf[64], cport[16];
|
fd_set mask;
|
||||||
char *p, *c;
|
int i;
|
||||||
int port, chan, iRet;
|
|
||||||
|
FD_ZERO(&mask);
|
||||||
|
FD_SET(fd, &mask);
|
||||||
|
tmo.tv_sec=tmo_msec / 1000;
|
||||||
|
tmo.tv_usec=(tmo_msec % 1000) % 1000 +1;
|
||||||
|
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
|
||||||
|
if (i==0) return(0); /* timeout */
|
||||||
|
return(1);
|
||||||
|
OnError: return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
idleHandler=idleHdl;
|
SerChannel *SerOpen(const char *hostPort, int msecTmo, int (*idleHdl)(int,int)) {
|
||||||
NEW(ser);
|
AsynSrvChan *aser;
|
||||||
str_copy(hbuf, host);
|
TermSrvChan *tser;
|
||||||
p=str_split(ser->asyn_info.host, hbuf, ':');
|
char hbuf[64], cport[16], host[32];
|
||||||
port=4000;
|
char *p, *c;
|
||||||
chan=0;
|
struct sockaddr_in sadr;
|
||||||
if (p!=NULL) {
|
int iret;
|
||||||
c=str_split(cport, p, '/');
|
time_t t1, t2;
|
||||||
if (c!=NULL) chan=atoi(c);
|
static int ecnt;
|
||||||
port=atoi(cport);
|
|
||||||
}
|
time(&t1);
|
||||||
ser->asyn_info.port=port;
|
str_copy(hbuf, hostPort);
|
||||||
ser->asyn_info.chan=chan;
|
p=str_split(host, hbuf, ':');
|
||||||
A_CHK(AsynSrv_Open(&ser->asyn_info));
|
assert(p!=NULL);
|
||||||
|
c=str_split(cport, p, '/');
|
||||||
if (msecTmo==0) msecTmo=5000;
|
if (msecTmo==0) msecTmo=5000;
|
||||||
A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL));
|
if (c!=NULL) {
|
||||||
logfileOut(LOG_MAIN, "connection to %s:%d/%d opened\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan);
|
NEW(aser, AsynSrvChan); aser->type=ASYNSRV_TYPE;
|
||||||
return((SerChannel *)ser);
|
str_copy(aser->asyn_info.host, host);
|
||||||
|
aser->asyn_info.port=atoi(cport);
|
||||||
|
aser->asyn_info.chan=atoi(c);
|
||||||
|
|
||||||
|
iret=AsynSrv_Open(&aser->asyn_info);
|
||||||
|
if (iret==1) {
|
||||||
|
iret=AsynSrv_Config(&aser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL);
|
||||||
|
}
|
||||||
|
if (iret!=1) {
|
||||||
|
SerA_error();
|
||||||
|
goto OnError;
|
||||||
|
}
|
||||||
|
time(&t2);
|
||||||
|
ecnt=0;
|
||||||
|
logfileOut(LOG_MAIN, "connection to %s:%d/%d opened (%d sec)\n",
|
||||||
|
aser->asyn_info.host, aser->asyn_info.port, aser->asyn_info.chan,
|
||||||
|
t2-t1);
|
||||||
|
return((SerChannel *)aser);
|
||||||
|
} else {
|
||||||
|
NEW(tser, TermSrvChan); tser->type=TERMSRV_TYPE;
|
||||||
|
tser->tmo=msecTmo;
|
||||||
|
if (idleHdl==NULL) {
|
||||||
|
tser->idleHdl=SerWait;
|
||||||
|
} else {
|
||||||
|
tser->idleHdl=idleHdl;
|
||||||
|
}
|
||||||
|
ERR_I(CocCreateSockAdr(&sadr, host, atoi(p)));
|
||||||
|
ERR_SI(tser->fd=socket(AF_INET, SOCK_STREAM, 0));
|
||||||
|
/* do we need this really as a client ?
|
||||||
|
i = 1;
|
||||||
|
ERR_SI(setsockopt(conn->fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int)));
|
||||||
|
*/ /* allow quick port reuse */
|
||||||
|
ERR_SI(connect(tser->fd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||||
|
time(&t2);
|
||||||
|
ecnt=0;
|
||||||
|
logfileOut(LOG_MAIN, "connected to %s (%d sec)\n", hostPort, t2-t1);
|
||||||
|
return ((SerChannel *)tser);
|
||||||
|
}
|
||||||
|
OnError:
|
||||||
|
time(&t2);
|
||||||
|
if (ecnt<4) {
|
||||||
|
logfileOut(LOG_MAIN, "failed after %d sec\n", t2-t1);
|
||||||
|
ecnt++;
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerClose(SerChannel *serch) {
|
||||||
|
AsynSrvChan *aser;
|
||||||
|
TermSrvChan *tser;
|
||||||
|
|
||||||
|
if (serch->type==ASYNSRV_TYPE) {
|
||||||
|
aser=(AsynSrvChan *)serch;
|
||||||
|
AsynSrv_Close(&aser->asyn_info, 0);
|
||||||
|
} else if (serch->type==TERMSRV_TYPE) {
|
||||||
|
tser=(TermSrvChan *)serch;
|
||||||
|
close(tser->fd);
|
||||||
|
}
|
||||||
|
serch->type=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerChannel *SerCheck(SerChannel *serch) {
|
||||||
|
if (serch==NULL || serch->type==0) {
|
||||||
|
return(NULL);
|
||||||
|
} else {
|
||||||
|
return(serch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SerCmd(SerChannel *serch, char *cmnd) {
|
||||||
|
int l, n;
|
||||||
|
AsynSrvChan *aser;
|
||||||
|
TermSrvChan *tser;
|
||||||
|
char *result, *pos, *trm;
|
||||||
|
int iret, incomplete;
|
||||||
|
|
||||||
|
l=strlen(cmnd);
|
||||||
|
if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
|
||||||
|
cmnd[l]=EOT; l++;
|
||||||
|
cmnd[l]='\0';
|
||||||
|
|
||||||
|
logfileOut(LOG_SER, ">%s\n", cmnd);
|
||||||
|
if (serch->type==ASYNSRV_TYPE) {
|
||||||
|
aser=(AsynSrvChan *)serch;
|
||||||
|
iret=AsynSrv_SendCmnds(&aser->asyn_info, &aser->to_host, &aser->from_host, cmnd, NULL);
|
||||||
|
if (iret!=1) {
|
||||||
|
SerA_error();
|
||||||
|
SerClose(serch);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
result=AsynSrv_GetReply(&aser->asyn_info, &aser->from_host, NULL);
|
||||||
|
if (result==NULL) ERR_MSG("empty result");
|
||||||
|
} else if (serch->type==TERMSRV_TYPE) {
|
||||||
|
tser=(TermSrvChan *)serch;
|
||||||
|
iret=send(tser->fd, cmnd, l, 0);
|
||||||
|
if (iret<0) {
|
||||||
|
ErrMsg("disconnected");
|
||||||
|
SerClose(serch);
|
||||||
|
goto OnError;
|
||||||
|
}
|
||||||
|
n=sizeof(tser->res);
|
||||||
|
pos=tser->res;
|
||||||
|
result=NULL;
|
||||||
|
incomplete=1;
|
||||||
|
while (incomplete) {
|
||||||
|
/* Wait for an event on tser->fd or a timeout tmo */
|
||||||
|
iret=tser->idleHdl(tser->tmo, tser->fd);
|
||||||
|
if (iret==0) {
|
||||||
|
if (result==NULL) ERR_MSG("time out");
|
||||||
|
ERR_MSG("missing terminator");
|
||||||
|
}
|
||||||
|
ERR_SI(l=recv(tser->fd, pos, n, 0));
|
||||||
|
if (l==0) {
|
||||||
|
ErrMsg("disconnected");
|
||||||
|
SerClose(serch);
|
||||||
|
goto OnError;
|
||||||
|
}
|
||||||
|
n -= l;
|
||||||
|
if (n==0) ERR_MSG("answer too long");
|
||||||
|
while (l>0) {
|
||||||
|
if (*pos>' ') {
|
||||||
|
if (result==NULL) result=pos; /* skip trailing white space */
|
||||||
|
} else if (*pos<' ') { /* all control characters are treated as terminators */
|
||||||
|
if (result!=NULL) {
|
||||||
|
*pos='\0';
|
||||||
|
incomplete=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos++; l--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serch->type=0;
|
||||||
|
ERR_MSG("invalid channel");
|
||||||
|
}
|
||||||
|
logfileOut(LOG_SER, "<%s\n", result);
|
||||||
|
|
||||||
|
return(result);
|
||||||
OnError:
|
OnError:
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SerClose(SerChannel *serch) {
|
/* obsolete ?
|
||||||
struct SerChan *ser;
|
|
||||||
|
|
||||||
ser=(struct SerChan *)serch;
|
|
||||||
A_CHK(AsynSrv_Close(&ser->asyn_info, 0));
|
|
||||||
return(0);
|
|
||||||
OnError: return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *SerCmdC(SerChannel *serch, const char *cmnd) {
|
char *SerCmdC(SerChannel *serch, const char *cmnd) {
|
||||||
char cmd[SER_BUF_LEN];
|
char cmd[SER_BUF_LEN];
|
||||||
int l;
|
int l;
|
||||||
@ -78,33 +227,5 @@ char *SerCmdC(SerChannel *serch, const char *cmnd) {
|
|||||||
return(SerCmd(serch, cmd));
|
return(SerCmd(serch, cmd));
|
||||||
OnError: return(NULL);
|
OnError: return(NULL);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
char *SerCmd(SerChannel *serch, char *cmnd) {
|
|
||||||
int l;
|
|
||||||
struct SerChan *ser;
|
|
||||||
char *result;
|
|
||||||
struct timeb tim0, tim1;
|
|
||||||
int tdif;
|
|
||||||
|
|
||||||
l=strlen(cmnd);
|
|
||||||
if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
|
|
||||||
|
|
||||||
ser=(struct SerChan *)serch;
|
|
||||||
logfileOut(LOG_SER, ">%s\n", cmnd);
|
|
||||||
cmnd[l]=ser->asyn_info.eot[1];
|
|
||||||
cmnd[l+1]='\0';
|
|
||||||
ftime(&tim0);
|
|
||||||
A_CHK(AsynSrv_SendCmnds(&ser->asyn_info, &ser->to_host, &ser->from_host, cmnd, NULL));
|
|
||||||
result=AsynSrv_GetReply(&ser->asyn_info, &ser->from_host, NULL);
|
|
||||||
ftime(&tim1);
|
|
||||||
tdif=(tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm;
|
|
||||||
if (result==NULL) ERR_MSG("empty result");
|
|
||||||
/* if (idleHandler!=NULL) idleHandler(50,0); */
|
|
||||||
logfileOut(LOG_SER, "<%s\n", result);
|
|
||||||
if (tdif>1000) {
|
|
||||||
logfileOut(LOG_SER, "%d msec:\n >%s\n", tdif, cmnd);
|
|
||||||
logfileOut(LOG_SER, " <%s\n", result);
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
OnError: return(NULL);
|
|
||||||
}
|
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
|
|
||||||
#define SER_BUF_LEN 320
|
#define SER_BUF_LEN 320
|
||||||
|
|
||||||
typedef struct { int private; } SerChannel;
|
typedef struct {
|
||||||
|
/* private */
|
||||||
|
int type;
|
||||||
|
} SerChannel;
|
||||||
|
|
||||||
SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int));
|
SerChannel *SerOpen(const char *host, int msecTmo, int (*idleHdl)(int,int));
|
||||||
char *SerCmdC(SerChannel *ser, const char *cmnd);
|
|
||||||
char *SerCmd(SerChannel *ser, char *cmnd);
|
char *SerCmd(SerChannel *ser, char *cmnd);
|
||||||
int SerClose(SerChannel *ser);
|
SerChannel *SerCheck(SerChannel *ser);
|
||||||
|
void SerClose(SerChannel *ser);
|
||||||
|
|
||||||
|
/* char *SerCmdC(SerChannel *ser, const char *cmnd); */
|
||||||
|
|
||||||
#endif /* _SERUTIL_H_ */
|
#endif /* _SERUTIL_H_ */
|
||||||
|
Reference in New Issue
Block a user