PSI sics-cvs-psi_pre-ansto
This commit is contained in:
521
tecs/coc_client.c
Normal file
521
tecs/coc_client.c
Normal file
@@ -0,0 +1,521 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include "myc_err.h"
|
||||
#include "coc_util.h"
|
||||
#include "coc_client.h"
|
||||
#include "myc_str.h"
|
||||
|
||||
/* --- non ANSI signal --- */
|
||||
#ifndef SIGPIPE
|
||||
#define SIGPIPE 13
|
||||
#endif
|
||||
|
||||
#define COC_NETTMO 5
|
||||
#define COC_RESTMO 60
|
||||
|
||||
#define ARG_CHAR 1
|
||||
#define ARG_INT 2
|
||||
#define ARG_FLT 3
|
||||
#define ARG_ARR 4
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocConnect(CocConn *conn) { /* connect, but do not start */
|
||||
int i;
|
||||
struct sockaddr_in sadr;
|
||||
|
||||
ERR_I(CocCreateSockAdr(&sadr, conn->host, conn->port));
|
||||
ERR_SI(conn->fd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
i = 1;
|
||||
ERR_SI(setsockopt(conn->fd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
|
||||
i=connect(conn->fd, (struct sockaddr *)&sadr, sizeof(sadr));
|
||||
if (i<0) {
|
||||
if (errno==ECONNREFUSED) return(1);
|
||||
ERR_COD(errno);
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocOpen(CocConn *conn) { /* connect and start, if not succsessful */
|
||||
int i, try, tmo;
|
||||
|
||||
ERR_I(i=CocConnect(conn));
|
||||
if (i==0) return(0);
|
||||
/* connection refused */
|
||||
if (conn->startcmd[0]=='\0') {
|
||||
CocDelay(500);
|
||||
ErrTxt("connect",1); return(1);
|
||||
}
|
||||
|
||||
printf("Starting TecsServer ...\n\n%s\n", conn->startcmd);
|
||||
ERR_I(system(conn->startcmd));
|
||||
|
||||
try=15;
|
||||
tmo=100; /* wait total ca. 10 sec. for max. 15 tries */
|
||||
while (try>0) {
|
||||
try--;
|
||||
CocDelay(tmo); tmo=tmo*5/4;
|
||||
ERR_I(i=CocConnect(conn));
|
||||
if (i==0) {
|
||||
printf("\n... connected to TecsServer\n");
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
ERR_MSG("can not start TECS, too many retries");
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) {
|
||||
int iret;
|
||||
assert(conn!=NULL);
|
||||
if (bufsize==0) bufsize=1024;
|
||||
StrLink(&conn->cmdbuf, conn->cmdbuf_);
|
||||
StrLink(&conn->resbuf, conn->resbuf_);
|
||||
conn->port=port;
|
||||
ERR_I(str_copy(conn->host, host));
|
||||
ERR_I(str_copy(conn->magic, magic));
|
||||
ERR_I(str_copy(conn->startcmd, startcmd));
|
||||
conn->fd=-1;
|
||||
ERR_I(iret=CocOpen(conn));
|
||||
if (iret==0) {
|
||||
iret=CocSendMagic(conn, conn->magic);
|
||||
if (iret<0) {
|
||||
CocCloseClient(conn);
|
||||
iret=1;
|
||||
}
|
||||
}
|
||||
return(iret);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocSendMagic(CocConn *conn, char *magic) {
|
||||
char *err;
|
||||
int siz, n;
|
||||
|
||||
StrClear(&conn->resbuf); /* use return buffer for command in order to preserve command buffer */
|
||||
ERR_I(StrPut(&conn->resbuf, "", COC_MAGIC));
|
||||
ERR_I(StrPut(&conn->resbuf, magic, COC_SEP));
|
||||
ERR_I(CocSend(conn->fd, conn->resbuf.buf, conn->resbuf.wrpos));
|
||||
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||
ERR_P(err=StrGet(&conn->resbuf, NULL, COC_SEP));
|
||||
if (err[0]!=COC_MAGIC) ERR_MSG("magic synch error");
|
||||
if (err[1]!='\0') { ErrMsg(err+1); ErrTxt(": (response from server)",0); goto OnError; }
|
||||
ERR_I(StrGetEnd(&conn->resbuf));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocCheck(CocConn *conn) {
|
||||
|
||||
if (conn->fd<0) return(1);
|
||||
ERR_I(CocSend(conn->fd, "_quit", 6));
|
||||
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||
return(0);
|
||||
OnError:
|
||||
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(1);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocTryCmd(CocConn *conn) {
|
||||
int iret=-1, siz;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (conn->fd<0) {
|
||||
ERR_I(iret=CocConnect(conn)); /* was CocOpen earlier */
|
||||
if (iret == 1) {
|
||||
CocDelay(500);
|
||||
ErrTxt("connect",1); return (-1);
|
||||
}
|
||||
|
||||
iret=-1;
|
||||
ERR_I(CocSendMagic(conn, conn->magic));
|
||||
}
|
||||
ERR_I(CocSend(conn->fd, conn->cmdbuf.buf, conn->cmdbuf.wrpos));
|
||||
ERR_I(CocRecv(conn->fd, &conn->resbuf, COC_NETTMO, NULL));
|
||||
return(0);
|
||||
OnError:
|
||||
if (ErrCode==ECONNRESET || ErrCode==EPIPE) return(-2);
|
||||
return(iret);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocCmdWithRetry(CocConn *conn) {
|
||||
int cnt, iret;
|
||||
|
||||
if (conn==NULL) ERR_MSG("not connected");
|
||||
cnt=3;
|
||||
while (1) {
|
||||
cnt--;
|
||||
if (cnt<=0) {
|
||||
ERR_I(CocTryCmd(conn));
|
||||
break;
|
||||
}
|
||||
iret=CocTryCmd(conn);
|
||||
if (iret>=0) break;
|
||||
close(conn->fd);
|
||||
conn->fd=-1;
|
||||
if (iret==-1) goto OnError; /* severe error */
|
||||
ErrShort(ErrMessage);
|
||||
ErrShort("try to reconnect");
|
||||
}
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
void CocReset(CocConn *conn) {
|
||||
assert(conn!=NULL);
|
||||
StrClear(&conn->cmdbuf);
|
||||
if (conn->synch!=COC_SYN0) {
|
||||
conn->synch=COC_SYN0;
|
||||
} else {
|
||||
conn->synch=COC_SYN1;
|
||||
}
|
||||
StrPut(&conn->cmdbuf, "", conn->synch);
|
||||
conn->nargs=0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocPushArg(CocConn *conn, const char *name, void *value, int type, int size) {
|
||||
StrBuf *buf;
|
||||
int n;
|
||||
|
||||
assert(conn!=NULL);
|
||||
assert(NULL==strchr(name, ' '));
|
||||
buf=&conn->cmdbuf;
|
||||
n=conn->nargs;
|
||||
if (n>=sizeof(conn->args)) ERR_MSG("too many return arguments");
|
||||
conn->args[n].adr=value;
|
||||
conn->args[n].type=type;
|
||||
conn->args[n].size=size;
|
||||
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);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocPutStr(CocConn *conn, const char *name, const char *value) {
|
||||
StrBuf *buf;
|
||||
|
||||
ERR_I(CocPushArg(conn, name, NULL, ARG_CHAR, 0));
|
||||
ERR_I(StrPut(&conn->cmdbuf, value, COC_SEP));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocPutFloat(CocConn *conn, const char *name, float value) {
|
||||
|
||||
ERR_I(CocPushArg(conn, name, NULL, ARG_FLT, 0));
|
||||
ERR_I(StrPutFloat(&conn->cmdbuf, value, COC_SEP));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocPutArray(CocConn *conn, const char *name, float *value, int value_size) {
|
||||
|
||||
ERR_I(CocPushArg(conn, name, NULL, ARG_ARR, 0));
|
||||
ERR_I(StrPutArray(&conn->cmdbuf, value, value_size));
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocPutInt(CocConn *conn, const char *name, int value) {
|
||||
|
||||
ERR_I(CocPushArg(conn, name, NULL, ARG_INT, 0));
|
||||
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, ARG_CHAR, value_len));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocGetFloat(CocConn *conn, const char *name, float *value) {
|
||||
|
||||
return(CocPushArg(conn, name, value, ARG_FLT, 0));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocGetInt(CocConn *conn, const char *name, int *value) {
|
||||
|
||||
return(CocPushArg(conn, name, value, ARG_INT, 0));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
int CocGetArray(CocConn *conn, const char *name, float *value, int value_size) {
|
||||
|
||||
return(CocPushArg(conn, name, value, ARG_ARR, value_size));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
ERR_I(CocCmdWithRetry(conn));
|
||||
buf=&conn->resbuf;
|
||||
while (buf->buf[0] != conn->synch) { /* throw away unsynchronized answers */
|
||||
ERR_I(CocRecv(conn->fd, buf, COC_NETTMO, NULL));
|
||||
}
|
||||
|
||||
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==ARG_INT) {
|
||||
ERR_I(StrGetInt(buf, (int *)a->adr, COC_SEP));
|
||||
} else if (a->type==ARG_FLT) {
|
||||
ERR_I(StrGetFloat(buf, (float *)a->adr, COC_SEP));
|
||||
} else if (a->type==ARG_ARR) {
|
||||
ERR_I(StrGetArray(buf, (float *)a->adr, a->size));
|
||||
resp="<array>";
|
||||
} else if (a->type==ARG_CHAR) {
|
||||
ERR_P(StrNGet(buf, (char *)a->adr, a->size, COC_SEP));
|
||||
} else {
|
||||
ERR_MSG("unknown type");
|
||||
}
|
||||
a->type=0; /* done */
|
||||
}
|
||||
}
|
||||
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 */
|
||||
|
||||
ERR_I(CocRecv(conn->fd, buf, COC_RESTMO, NULL));
|
||||
}
|
||||
return(iret);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
static int interrupt, logFd=0;
|
||||
|
||||
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;
|
||||
static int init=1;
|
||||
|
||||
#if __VMS
|
||||
if (init) {
|
||||
init=0;
|
||||
DECC$CRTL_INIT();
|
||||
}
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
signal(SIGINT, SIG_DFL);
|
||||
logFd=0;
|
||||
if (interrupt==1) { /* send "clear log" message */
|
||||
cbuf[0]=COC_CLRLOG;
|
||||
cbuf[1]=COC_SEP; /* send "clear log" message */
|
||||
printf("\nclrlog\n");
|
||||
CocSend(fd, cbuf, 2);
|
||||
do {
|
||||
ERR_I(CocRecv(fd, buf, 10, NULL));
|
||||
} while (buf->buf[0]!=COC_CLRLOG);
|
||||
}
|
||||
return(0);
|
||||
OnError:
|
||||
signal(SIGINT, SIG_DFL);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(conn!=NULL);
|
||||
close(conn->fd);
|
||||
conn->fd=-1;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
82
tecs/coc_client.h
Normal file
82
tecs/coc_client.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef _COC_CLIENT_H_
|
||||
#define _COC_CLIENT_H_
|
||||
|
||||
#include "myc_buf.h"
|
||||
#include "coc_util.h"
|
||||
|
||||
typedef struct {
|
||||
void *adr;
|
||||
int type, size;
|
||||
char *cmd;
|
||||
} CocArg;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
/* private */
|
||||
int port;
|
||||
StrBuf cmdbuf; /* for sending command */
|
||||
StrBuf resbuf; /* for response */
|
||||
char cmdbuf_[COC_CMD_LEN];
|
||||
char resbuf_[COC_RES_LEN];
|
||||
CocArg args[16];
|
||||
int nargs;
|
||||
char host[64];
|
||||
char magic[32];
|
||||
char startcmd[512];
|
||||
char synch;
|
||||
} CocConn;
|
||||
|
||||
int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd);
|
||||
/* initialize a connection to the server process
|
||||
*/
|
||||
|
||||
int CocSendMagic(CocConn *conn, char *magic);
|
||||
/* send magic word to the server for changing access rights
|
||||
*/
|
||||
|
||||
void CocReset(CocConn *conn);
|
||||
int CocPutStr(CocConn *conn, const char *name, const char *value);
|
||||
int CocPutFloat(CocConn *conn, const char *name, float value);
|
||||
int CocPutInt(CocConn *conn, const char *name, int value);
|
||||
int CocPutArray(CocConn *conn, const char *name, float *value, int value_size);
|
||||
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 CocGetArray(CocConn *conn, const char *name, float *value, int value_size);
|
||||
int CocDoIt(CocConn *conn, char *error, int error_len);
|
||||
|
||||
int CocCheck(CocConn *conn);
|
||||
/*
|
||||
returns 1, if not yet open
|
||||
returns 0, if connection o.k.
|
||||
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);
|
||||
/*
|
||||
set one variable
|
||||
*/
|
||||
|
||||
int CocGetN(CocConn *conn, const char *name, char *value, int reslen);
|
||||
#define CocGet(C,N,V) CocGetN(C,N,V,sizeof(V))
|
||||
/*
|
||||
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);
|
||||
/*
|
||||
close the connection to the server
|
||||
*/
|
||||
|
||||
#endif /* _COC_CLIENT_H_ */
|
||||
350
tecs/coc_logfile.c
Normal file
350
tecs/coc_logfile.c
Normal file
@@ -0,0 +1,350 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include "coc_logfile.h"
|
||||
#include "myc_time.h"
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
|
||||
static FILE *fil=NULL;
|
||||
static char lnam[224]="";
|
||||
static char filnam[256]="";
|
||||
static char ebuf[20000]="";
|
||||
static char *statusBuf=NULL;
|
||||
static int statusSize;
|
||||
static char *eptr=&ebuf[0];
|
||||
static int dated=0;
|
||||
static int logMask=0;
|
||||
static int wrtMask=0;
|
||||
static int newLine=1;
|
||||
static int logfileStd;
|
||||
static int dirty, writeAll;
|
||||
static int lastline=1;
|
||||
static long int lastpos=0;
|
||||
static int lastStamp=0;
|
||||
static int openTime;
|
||||
static int openDate;
|
||||
|
||||
void (*logfileOutRtn)(int, char *)=NULL;
|
||||
|
||||
void logfileOpen(int append) {
|
||||
int year;
|
||||
|
||||
if (logfileStd) {
|
||||
fil=stdout;
|
||||
str_copy(filnam, "<stdout>");
|
||||
return;
|
||||
}
|
||||
assert(fil==NULL);
|
||||
openTime = mycNow();
|
||||
openDate = mycDate(openTime); /* date in yyyymmdd decimal encoding */
|
||||
openTime = openTime % (24*3600); /* seconds since midnight */
|
||||
if (dated) {
|
||||
sprintf(filnam, "%s%02d-%02d.log", lnam, openDate % 10000 / 100, openDate % 100);
|
||||
} else {
|
||||
if (lnam[0]=='\0') {
|
||||
str_copy(filnam, "test.log");
|
||||
} else {
|
||||
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 {
|
||||
fil=fopen(filnam, "w+"); /* overwrite last logfile */
|
||||
}
|
||||
if (fil==NULL) {
|
||||
printf("Can not open %s\n", filnam);
|
||||
fil=stdout;
|
||||
str_copy(filnam, "<stdout>");
|
||||
return;
|
||||
}
|
||||
ErrSetOutFile(fil);
|
||||
fprintf(fil, "%04d-%02d-%02d %02d:%02d:%02d opened logfile\n"
|
||||
, openDate / 10000, openDate % 10000 / 100, openDate % 100
|
||||
, openTime / 3600, openTime / 60 % 60, openTime % 60);
|
||||
lastStamp = openTime / 60;
|
||||
}
|
||||
|
||||
void logfileStatusBuffer(char *buffer, int bufsize) {
|
||||
statusBuf=buffer;
|
||||
statusSize=bufsize-1;
|
||||
}
|
||||
|
||||
char *logfileInit(char *path, int nodate, int use_stdout, int write_all) {
|
||||
str_copy(lnam, path);
|
||||
logfileStd=use_stdout;
|
||||
writeAll=write_all;
|
||||
dated=!nodate;
|
||||
logfileOpen(1);
|
||||
return(filnam);
|
||||
}
|
||||
|
||||
void logfileStamp(char *text) {
|
||||
int time, date, stamp;
|
||||
|
||||
time = mycNow();
|
||||
date = mycDate(time); /* date in yyyymmdd decimal encoding */
|
||||
time = time % (24*3600); /* seconds since midnight */
|
||||
|
||||
stamp=time / 60;
|
||||
if (date != openDate ) { /* day has changed -> new logfile */
|
||||
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
||||
lastpos=0;
|
||||
lastline=1;
|
||||
logfileOpen(1);
|
||||
}
|
||||
if (text==NULL) {
|
||||
if (stamp>lastStamp+1) {
|
||||
fprintf(fil, "---\t%02d:%02d:%02d\n", stamp / 60, stamp % 60, time % 60, text);
|
||||
}
|
||||
} else {
|
||||
fprintf(fil, "\t%02d:%02d:%02d%s", stamp / 60, stamp % 60, time % 60, text);
|
||||
}
|
||||
dirty=0;
|
||||
lastStamp=stamp;
|
||||
}
|
||||
|
||||
void logfileOut(int mask, const char *fmt, ...)
|
||||
{ va_list ap;
|
||||
char buf[8192], *p;
|
||||
int l;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
if (mask & LOG_STAT && statusBuf!=NULL) {
|
||||
if (newLine) {
|
||||
statusBuf[0]='\0';
|
||||
newLine=0;
|
||||
}
|
||||
buf[statusSize]='\0';
|
||||
vsprintf(buf, fmt, ap);
|
||||
assert(buf[statusSize]=='\0'); /* check for overflow */
|
||||
if (buf[0]=='@') {
|
||||
if (buf[1]==' ') {
|
||||
str_ncat(statusBuf, buf+2, statusSize);
|
||||
} else {
|
||||
str_ncat(statusBuf, buf+1, statusSize);
|
||||
}
|
||||
} else {
|
||||
str_ncat(statusBuf, buf, statusSize);
|
||||
}
|
||||
p=strchr(statusBuf, '\n');
|
||||
if (p!=NULL) {
|
||||
newLine=1;
|
||||
*p='\0';
|
||||
}
|
||||
}
|
||||
if (logfileOutRtn!=NULL) {
|
||||
vsprintf(buf, fmt, ap); /* does not check for overflow! */
|
||||
logfileOutRtn(mask, buf);
|
||||
}
|
||||
if (writeAll) {
|
||||
vfprintf(fil, fmt, ap);
|
||||
wrtMask=LOG_ALL;
|
||||
} else if ((mask | LOG_NET) != LOG_NET) { /* do not store LOG_NET info */
|
||||
if (eptr!=NULL) {
|
||||
if (eptr-ebuf > sizeof(ebuf)-512) {
|
||||
sprintf(eptr, "... buffer full ... \1\1");
|
||||
eptr=NULL;
|
||||
} else {
|
||||
vsprintf(eptr, fmt, ap);
|
||||
p=strchr(eptr, '\1');
|
||||
if (p==NULL) {
|
||||
l=strlen(eptr);
|
||||
if (l>256) {
|
||||
sprintf(buf, "unusual long output %.32s... (%d chars)\n", eptr, l);
|
||||
logfileStamp(buf);
|
||||
}
|
||||
eptr+=l;
|
||||
} else {
|
||||
eptr=p; /* is in fact an error */
|
||||
}
|
||||
eptr[0]='\1'; /* put \1 as separator between blocks */
|
||||
eptr[1]=mask & 31;
|
||||
eptr[2]='\0';
|
||||
eptr+=2;
|
||||
}
|
||||
}
|
||||
wrtMask=wrtMask | mask;
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void logfileMask(int mask) {
|
||||
logMask=logMask | mask;
|
||||
}
|
||||
|
||||
void logfileWrite0(int mask) {
|
||||
char *s, *next;
|
||||
|
||||
logMask=logMask | mask;
|
||||
if (dirty) logfileStamp(NULL); /* there was something written since last time */
|
||||
|
||||
s=ebuf;
|
||||
if (writeAll || *s!='\0' && wrtMask & logMask) {
|
||||
next=strchr(s, '\1');
|
||||
while (next!=NULL) {
|
||||
*next='\0';
|
||||
next++;
|
||||
if (*next & logMask) {
|
||||
if (*s=='@') { /* write out time */
|
||||
logfileStamp(s+1);
|
||||
} else {
|
||||
logfileStamp(NULL); /* write stamp before write something */
|
||||
fprintf(fil, "%s", s);
|
||||
dirty=1;
|
||||
}
|
||||
}
|
||||
s=next+1;
|
||||
next=strchr(s, '\1');
|
||||
}
|
||||
}
|
||||
ebuf[0]='\0';
|
||||
eptr=&ebuf[0];
|
||||
logMask=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(buf, "%s%02d-%02d.log", lnam, date % 10000 / 100, date % 100);
|
||||
sFile=fopen(buf, "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) {
|
||||
logfileWrite0(mask);
|
||||
fflush(fil);
|
||||
}
|
||||
|
||||
void logfileShowErr(char *text)
|
||||
{
|
||||
logfileWrite0(LOG_ALL); /* write all */
|
||||
ErrShow(text);
|
||||
fflush(fil);
|
||||
}
|
||||
|
||||
void logfileClose()
|
||||
{
|
||||
logfileWrite0(LOG_MAIN+LOG_INFO);
|
||||
lastStamp=-2;
|
||||
logfileOut(LOG_MAIN, "closed\n");
|
||||
logfileStamp(NULL);
|
||||
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
||||
filnam[0]='\0';
|
||||
}
|
||||
|
||||
void logfileOutBuf(int mask, StrBuf *buf)
|
||||
{ char str[256];
|
||||
int rd0;
|
||||
char *ret;
|
||||
|
||||
rd0=buf->rdpos;
|
||||
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|
||||
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
|
||||
logfileOut(mask, "<buffer corrupt>"); return;
|
||||
}
|
||||
while (!StrEnd(buf)) {
|
||||
ret=StrGet(buf, str, '\0');
|
||||
if (ret==NULL) {
|
||||
ret="...";
|
||||
buf->rdpos=buf->wrpos;
|
||||
}
|
||||
if (ret[0]<32 && ret[0]>0) {
|
||||
logfileOut(mask, "[%d]%s;", ret[0], ret+1);
|
||||
} else {
|
||||
logfileOut(mask, "%s;", ret);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
28
tecs/coc_logfile.h
Normal file
28
tecs/coc_logfile.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _COC_LOGFILE_H_
|
||||
#define _COC_LOGFILE_H_
|
||||
|
||||
#include "myc_buf.h"
|
||||
|
||||
#define LOG_ALL 31
|
||||
#define LOG_STAT 32
|
||||
#define LOG_SER 8
|
||||
#define LOG_NET 4
|
||||
#define LOG_INFO 2
|
||||
#define LOG_MAIN 1
|
||||
#define logfileStatusBuf(B) logfileStatusBuffer(B,sizeof(B))
|
||||
|
||||
void logfileStatusBuffer(char *buffer, int bufsize);
|
||||
char *logfileInit(char *path, int nodate, int use_stdout, int write_all);
|
||||
void logfileOut(int mask, const char *fmt, ...);
|
||||
void logfileOutBuf(int mask, StrBuf *buf);
|
||||
void logfileShowErr(char *text);
|
||||
void logfileMask(int mask);
|
||||
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg);
|
||||
void logfileWrite(int mask);
|
||||
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_ */
|
||||
661
tecs/coc_server.c
Normal file
661
tecs/coc_server.c
Normal file
@@ -0,0 +1,661 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "myc_mem.h"
|
||||
#include "myc_err.h"
|
||||
#include "coc_logfile.h"
|
||||
#include "coc_util.h"
|
||||
#include "coc_server.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_time.h"
|
||||
|
||||
#define COC_NUL COC_SEP
|
||||
|
||||
typedef struct _CocVar {
|
||||
struct _CocVar *next;
|
||||
char name[32];
|
||||
void *var;
|
||||
int access;
|
||||
int type;
|
||||
int size;
|
||||
void *strucType;
|
||||
int (*hdl)(int, void *, int);
|
||||
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 int maxfd;
|
||||
CocClient *cList;
|
||||
static int mainFd;
|
||||
static int modified;
|
||||
static char loglist[16];
|
||||
|
||||
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 size, 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;
|
||||
p->size=size;
|
||||
} 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 *, int)) {
|
||||
assert(lastDef!=NULL);
|
||||
lastDef->hdl=handler;
|
||||
}
|
||||
|
||||
int *CocSizePtr(void) {
|
||||
assert(lastDef!=NULL && lastDef->type==COC_ARRAY);
|
||||
return &lastDef->size;
|
||||
}
|
||||
|
||||
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, 0, COC_RDONLY);
|
||||
p->strucType=CocDefVar(tname, NULL, COC_TYPE, 0, 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==COC_CHAR) {
|
||||
ERR_P(StrNGet(buf, (char *)adr, var->size, separator));
|
||||
} else if (var->type==COC_INT) {
|
||||
ERR_I(StrGetInt(buf, (int *)adr, separator));
|
||||
} else if (var->type==COC_FLT) {
|
||||
ERR_I(StrGetFloat(buf, (float *)adr, separator));
|
||||
} else if (var->type==COC_ARRAY) {
|
||||
ERR_I(StrGetArray(buf, (float *)adr, var->size));
|
||||
} 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==COC_CHAR) {
|
||||
ERR_I(StrPut(buf, adr, separator));
|
||||
} else if (var->type==COC_INT) {
|
||||
ERR_I(StrPutInt(buf, *(int *)adr, separator));
|
||||
} else if (var->type==COC_FLT) {
|
||||
ERR_I(StrPutFloat(buf, *(float *)adr, separator));
|
||||
} else if (var->type==COC_ARRAY) {
|
||||
ERR_I(StrPutArray(buf, (float *)adr, var->size));
|
||||
} 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;
|
||||
}
|
||||
|
||||
char *CocReadVars(char *str, char stop){
|
||||
int i, l;
|
||||
char *eql, *cr, buf[80];
|
||||
StrBuf sbuf;
|
||||
|
||||
/* interprete variables until stop character appeares */
|
||||
i=sscanf(str, "%79s%n", buf, &l);
|
||||
while (i>0 && buf[0]!=stop) {
|
||||
if (buf[0]=='!') {
|
||||
cr=strchr(str, '\n');
|
||||
if (cr==NULL) return strchr(str, '\0');
|
||||
str=cr+1;
|
||||
} else {
|
||||
eql=strchr(buf,'=');
|
||||
if (eql==NULL) ERR_MSG("syntax error");
|
||||
*eql='\0';
|
||||
if (eql[1] == '\'' || eql[1]== '"') {
|
||||
eql=strchr(str, '=');
|
||||
StrNLink(&sbuf, eql+1, 80);
|
||||
ERR_I(CocGetVar(buf, &sbuf, StrNONE));
|
||||
str = sbuf.buf + sbuf.rdpos;
|
||||
} else {
|
||||
str+=l;
|
||||
StrLink(&sbuf, eql+1);
|
||||
ERR_I(CocGetVar(buf, &sbuf, ' '));
|
||||
}
|
||||
}
|
||||
i=sscanf(str, "%79s%n", buf, &l);
|
||||
}
|
||||
return str;
|
||||
OnError: return 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;
|
||||
struct sockaddr_in sadr;
|
||||
char *err;
|
||||
|
||||
setData=setDataRtn;
|
||||
/*
|
||||
clDataSize=clientDataSize;
|
||||
clData=clientData;
|
||||
*/
|
||||
NEW(cList,CocClient); /* empty header */
|
||||
|
||||
ERR_SI(mainFd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
i = 1;
|
||||
ERR_SI(setsockopt(mainFd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(int))); /* allow quick port reuse */
|
||||
ERR_I(CocCreateSockAdr(&sadr, NULL, port));
|
||||
ERR_SI(bind(mainFd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||
logfileOutRtn=CocToClients;
|
||||
logfileOut(LOG_INFO, "created server on port %d\n", port);
|
||||
ERR_SI(listen(mainFd, 8));
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(mainFd, &mask);
|
||||
maxfd=mainFd+1;
|
||||
CocDefStr(loglist, COC_RDWR);
|
||||
return(0);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocHandleThis(CocVar *var, void *base, StrBuf *outBuf, int mode, int fd) {
|
||||
int iret;
|
||||
|
||||
if (var->hdl!=NULL) {
|
||||
iret=var->hdl(mode, base, fd);
|
||||
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, cl->fd));
|
||||
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, cl->fd);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef __VMS
|
||||
typedef size_t socklen_type;
|
||||
#else
|
||||
typedef int socklen_type;
|
||||
#endif
|
||||
|
||||
int CocHandle1Request(int tmo_msec, int fd) {
|
||||
struct sockaddr_in cadr;
|
||||
struct hostent *h;
|
||||
struct timeval tmo={0,1};
|
||||
CocClient *cl, *cl0;
|
||||
CocVar *var;
|
||||
int i, lmask, newfd, n, iret;
|
||||
socklen_type cadrlen;
|
||||
char *err, *cmd, *arg, *varname;
|
||||
void *base;
|
||||
|
||||
rmask=mask;
|
||||
if (fd>0) FD_SET(fd, &rmask);
|
||||
tmo.tv_sec=tmo_msec / 1000;
|
||||
tmo.tv_usec=(tmo_msec % 1000)*1000+1;
|
||||
if (fd>=maxfd) maxfd=fd+1;
|
||||
ERR_SI(i=select(maxfd,&rmask,NULL,NULL,&tmo));
|
||||
if (fd>0 && FD_ISSET(fd, &rmask)) return(1); /* event on fd */
|
||||
if (i==0) return(0); /* timeout */
|
||||
|
||||
if (FD_ISSET(mainFd, &rmask)) {
|
||||
cadrlen=sizeof(cadr);
|
||||
ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen));
|
||||
FD_SET(newfd, &mask);
|
||||
if (newfd>=maxfd) maxfd=newfd+1;
|
||||
NEW(cl, CocClient);
|
||||
cl->fd=newfd;
|
||||
cl->mode=0;
|
||||
if (setData!=NULL) {
|
||||
ERR_P(cl->data = setData(NULL)); /* create new client data object */
|
||||
}
|
||||
/*
|
||||
ERR_SP(cList=calloc(1,sizeof(CocClient)+clDataSize));
|
||||
*/
|
||||
cl->next=cList->next;
|
||||
cList->next=cl;
|
||||
h=gethostbyaddr((void *)&cadr.sin_addr, 4, AF_INET);
|
||||
if (h==NULL) {
|
||||
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, "local");
|
||||
} else {
|
||||
logfileOut(LOG_INFO, "(%d) open from %s\n", newfd, h->h_name);
|
||||
}
|
||||
} else {
|
||||
cl0=cList; cl=cl0->next;
|
||||
while (cl!=NULL) {
|
||||
if (FD_ISSET(cl->fd, &rmask)) {
|
||||
iret=CocRecv(cl->fd, &buf, -1, NULL);
|
||||
if (iret<=0) {
|
||||
logfileOut(LOG_INFO, "(%d) disconnected\n",cl->fd);
|
||||
close(cl->fd);
|
||||
FD_CLR(cl->fd, &mask);
|
||||
cl0->next=cl->next;
|
||||
FREE(cl);
|
||||
cl=cl0;
|
||||
} else {
|
||||
cl->logmask=0; /* stop output to log client */
|
||||
lmask=0;
|
||||
StrReset(&buf);
|
||||
StrClear(&bufo);
|
||||
err=NULL;
|
||||
logfileOut(LOG_NET, "(%d) ", cl->fd);
|
||||
logfileOutBuf(LOG_NET, &buf);
|
||||
/* cl->npend=0; why that ? */
|
||||
logfileOut(LOG_NET, "\n");
|
||||
cl->synch=buf.buf[0];
|
||||
ERR_P(StrGet(&buf, NULL, cl->synch));
|
||||
ERR_I(StrPut(&bufo, "", cl->synch));
|
||||
while (!StrEnd(&buf)) {
|
||||
ERR_P(varname=StrGet(&buf, NULL, ' '));
|
||||
if (cl->synch==COC_MAGIC) { /* access code */
|
||||
if (0==strcmp(varname,"rdacs")) {
|
||||
logfileOut(LOG_INFO, "set read mode\n");
|
||||
cl->mode=1;
|
||||
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
||||
} else if (0==strcmp(varname,"rwacs")) {
|
||||
logfileOut(LOG_INFO, "set write mode\n");
|
||||
cl->mode=2;
|
||||
ERR_I(StrPut(&bufo, "", COC_SEP)); /* empty message */
|
||||
} else {
|
||||
ERR_I(StrPut(&bufo, "", COC_ERR)); /* signal error message */
|
||||
ERR_I(StrPut(&bufo, "bad access code", COC_SEP));
|
||||
}
|
||||
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 {
|
||||
ERR_I(CocGetThisVar(var, base, &buf, COC_SEP));
|
||||
if (0==strcmp(var->name,"loglist")) {
|
||||
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, cl->fd));
|
||||
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, cl->fd));
|
||||
if (iret) ERR_I(CocPushThisHandler(var, cl, base, iret));
|
||||
}
|
||||
}
|
||||
}
|
||||
ERR_I(StrGetEnd(&buf));
|
||||
logfileOut(LOG_NET, " ");
|
||||
logfileOutBuf(LOG_NET, &bufo);
|
||||
logfileOut(LOG_NET, "\n");
|
||||
ERR_I(CocSend(cl->fd, bufo.buf, bufo.wrpos));
|
||||
cl->logmask=lmask;
|
||||
}
|
||||
}
|
||||
cl0=cl; cl=cl->next;
|
||||
}
|
||||
}
|
||||
if (modified) return(2);
|
||||
return(3);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int CocHandleRequests(int tmo_msec, int fd) {
|
||||
int tdif, iret, tim0;
|
||||
|
||||
if (modified && fd==0) { /* earlier modification */
|
||||
modified=0;
|
||||
return(2);
|
||||
}
|
||||
tim0=mycMsecSince(0);
|
||||
tdif=tmo_msec;
|
||||
while (tdif>=0) {
|
||||
ERR_I(iret=CocHandle1Request(tdif, fd));
|
||||
if (fd==0) {
|
||||
if (iret==2) return(2); /* modification of a variable */
|
||||
} else {
|
||||
if (iret==1) return(1); /* event on fd */
|
||||
}
|
||||
if (iret==0) return(0); /* timeout */
|
||||
tdif = tmo_msec - mycMsecSince(tim0);
|
||||
}
|
||||
return(0); /* timeout */
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
void CocCloseServer() {
|
||||
CocClient *cl, *cl0;
|
||||
|
||||
cl=cList->next;
|
||||
while (cl!=NULL) {
|
||||
close(cl->fd);
|
||||
cl0=cl;
|
||||
cl=cl->next;
|
||||
FREE(cl0);
|
||||
}
|
||||
FREE(cList);
|
||||
close(mainFd);
|
||||
}
|
||||
123
tecs/coc_server.h
Normal file
123
tecs/coc_server.h
Normal file
@@ -0,0 +1,123 @@
|
||||
#ifndef _SERVER_H_
|
||||
#define _SERVER_H_
|
||||
|
||||
#include "myc_buf.h"
|
||||
|
||||
void CocVarList(void **varlist);
|
||||
/*
|
||||
instal a variable list
|
||||
*/
|
||||
|
||||
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>
|
||||
*/
|
||||
|
||||
char *CocReadVars(char *str, char stop);
|
||||
/*
|
||||
read variables from the string str until a word starts with the stop character
|
||||
the string has the form [ whitespace var=value ] whitespace stop-character
|
||||
any text between an exclamation character and the next line break is treated as comment
|
||||
*/
|
||||
|
||||
void CocHdl(int (*handler)(int, void *, int));
|
||||
/*
|
||||
define handler for last defined item
|
||||
*/
|
||||
|
||||
int *CocSizePtr(void);
|
||||
/*
|
||||
get size pointer from last defined item (only valid when an array)
|
||||
*/
|
||||
|
||||
void *CocIntPtr(int *ptr);
|
||||
void *CocFltPtr(float *ptr);
|
||||
void *CocChrPtr(char *ptr);
|
||||
void *CocDefVar(const char *name, void *var, int type, int size, 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,0,A)
|
||||
#define CocDefFlt(V,A) CocDefVar(#V,CocFltPtr(&V),COC_FLT,0,A)
|
||||
#define CocDefStr(V,A) CocDefVar(#V,CocChrPtr(V),COC_CHAR,sizeof(V),A)
|
||||
#define CocDefArr(V,A) CocDefVar(#V,CocFltPtr(V),COC_ARRAY,sizeof(V)/sizeof(float),A)
|
||||
#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,(V!=(S *)NULL,0,COC_PTR));
|
||||
#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,(&V!=(S *)NULL,0,COC_STRUCT));
|
||||
#define CocIntFld(S,V,A) CocDefVar(#S":"#V,CocIntPtr(&((S *)NULL)->V),COC_INT,0,A);
|
||||
#define CocFltFld(S,V,A) CocDefVar(#S":"#V,CocFltPtr(&((S *)NULL)->V),COC_FLT,0,A);
|
||||
#define CocStrFld(S,V,A) CocDefVar(#S":"#V,CocChrPtr(((S *)NULL)->V),COC_CHAR,sizeof(((S *)NULL)->V),A);
|
||||
#define CocArrFld(S,V,A) CocDefVar(#S":"#V,CocFltPtr(((S *)NULL)->V),COC_FLT,sizeof(((S *)NULL)->V)/sizeof(float),A);
|
||||
#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS,0,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_CHAR 1
|
||||
#define COC_INT 2
|
||||
#define COC_FLT 3
|
||||
#define COC_ARRAY 4
|
||||
#define COC_PTR 5
|
||||
#define COC_STRUCT 6
|
||||
#define COC_TYPE 7
|
||||
#define COC_ALIAS 8
|
||||
|
||||
int CocInitServer(void *(*setDataRtn)(void *), int port);
|
||||
|
||||
int CocHandleRequests(int tmo_msec, int fd);
|
||||
int CocHandle1Request(int tmo_msec, int fd);
|
||||
/*
|
||||
handle hetwork requests.
|
||||
|
||||
return value: <0: error
|
||||
=0: timeout
|
||||
=1: event on fd
|
||||
=2: variable was changed
|
||||
=3: other network request treated
|
||||
|
||||
CocHandle1Request handles only one network request
|
||||
|
||||
For CocHandleRequests:
|
||||
|
||||
if fd=0: returns when a network request has changed a variable,
|
||||
or when timeout has expired (result is 0 or 2)
|
||||
|
||||
if fd>0: returns when an read event is pending on fd
|
||||
or when timeout has expired (result is 0 or 1)
|
||||
|
||||
*/
|
||||
|
||||
/* server handlers removed
|
||||
int CocPushHandler(const char *name);
|
||||
*/
|
||||
|
||||
int CocCallHandlers(void);
|
||||
void CocShowHandlers(char *buf, int buf_len);
|
||||
|
||||
void CocCloseServer(void);
|
||||
|
||||
#endif /* _SERVER_H_ */
|
||||
112
tecs/coc_util.c
Normal file
112
tecs/coc_util.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include "coc_util.h"
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
|
||||
|
||||
int CocCreateSockAdr(
|
||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port) /* Port number */
|
||||
{
|
||||
struct hostent *hostent; /* Host database entry */
|
||||
struct in_addr addr; /* For 64/32 bit madness */
|
||||
|
||||
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
|
||||
sockaddrPtr->sin_family = AF_INET;
|
||||
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
|
||||
if (host == NULL || host[0]=='\0') {
|
||||
addr.s_addr = INADDR_ANY;
|
||||
} else {
|
||||
hostent = gethostbyname(host);
|
||||
if (hostent != NULL) {
|
||||
memcpy((char *) &addr,
|
||||
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
|
||||
} else {
|
||||
addr.s_addr = inet_addr(host);
|
||||
if (addr.s_addr == (unsigned long)-1) {
|
||||
return -1; /* error */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* There is a rumor that this assignment may require care on
|
||||
* some 64 bit machines.
|
||||
*/
|
||||
|
||||
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
void CocDelay(int msec) {
|
||||
struct timeval tmo;
|
||||
|
||||
tmo.tv_sec=msec / 1000;
|
||||
tmo.tv_usec=(msec % 1000)*1000+1;
|
||||
select(1,NULL,NULL,NULL,&tmo);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
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(ECONNREFUSED);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
44
tecs/coc_util.h
Normal file
44
tecs/coc_util.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef _COC_UTIL_H_
|
||||
#define _COC_UTIL_H_
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include "myc_buf.h"
|
||||
|
||||
#define COC_CMD_LEN 256
|
||||
#define COC_RES_LEN 16384
|
||||
|
||||
int CocCreateSockAdr(
|
||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port); /* Port number */
|
||||
/*
|
||||
compose internet address
|
||||
*/
|
||||
|
||||
void CocDelay(int msec);
|
||||
/*
|
||||
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_SEP '\0'
|
||||
#define COC_DELAYED '\1'
|
||||
#define COC_ERR '\2'
|
||||
#define COC_TRM '\3'
|
||||
#define COC_SYN0 '\4'
|
||||
#define COC_SYN1 '\5'
|
||||
#define COC_MAGIC '\6'
|
||||
#define COC_CLRLOG '\7'
|
||||
|
||||
#endif /* _COC_UTIL_H_ */
|
||||
4
tecs/fortify1.c
Normal file
4
tecs/fortify1.c
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "fortify.c"
|
||||
#ifndef FORTIFY
|
||||
void null(void){}
|
||||
#endif
|
||||
87
tecs/instr_hosts.c
Normal file
87
tecs/instr_hosts.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "myc_str.h"
|
||||
#include "myc_fortran.h"
|
||||
|
||||
typedef struct { char *instr; char *host; int port; char *user; int cod; } Instrument;
|
||||
static Instrument list[]={
|
||||
{ "DMC", "lnsa05.psi.ch", 9753, "DMC" , 1},
|
||||
{ "TOPSI", "pc4120.psi.ch", 9753, "TOPSI" , 1},
|
||||
{ "SANS", "lnsa10.psi.ch", 9753, "SANS" , 1},
|
||||
{ "HRPT", "lnsa11.psi.ch", 9753, "HRPT" , 1},
|
||||
{ "TRICS", "lnsa18.psi.ch", 9753, "TRICS" , 1},
|
||||
{ "AMOR", "lnsa14.psi.ch", 9753, "AMOR" , 1},
|
||||
{ "FOCUS", "lnsa16.psi.ch", 9753, "FOCUS" , 1},
|
||||
{ "TASP", "lnsa12.psi.ch", 9753, "TASP", 1},
|
||||
{ "TASP0", "lnsa09.psi.ch", 9753, NULL , 0},
|
||||
{ "RITA", "rita2.psi.ch", 9753, NULL , 0},
|
||||
{ "PREP", "lnsa01.psi.ch", 9753, NULL , 0},
|
||||
{ "AREA", "lnsa01.psi.ch", 9751, NULL , 0},
|
||||
{ "TEST", "lnsa15.psi.ch", 9753, "lnslib", 2}
|
||||
};
|
||||
|
||||
int InstrHost(char *input, char *instr, char *host, char *user, char *pcod
|
||||
, int instr_len, int host_len, int user_len, int pcod_len) {
|
||||
char buf[256];
|
||||
int i, j;
|
||||
struct tm tim;
|
||||
time_t t;
|
||||
|
||||
j=-1;
|
||||
str_upcase(buf, input);
|
||||
for (i = 0; i < sizeof(list) / sizeof(list[0]); i++) {
|
||||
if (0==strcmp(buf, list[i].instr)) {
|
||||
j=i;
|
||||
}
|
||||
}
|
||||
if (j<0) {
|
||||
str_lowcase(buf, input);
|
||||
for (i = 0; i < sizeof(list) / sizeof(list[0]); i++) {
|
||||
if (list[i].host==strstr(list[i].host, buf)) {
|
||||
if (j>=0) return 0;
|
||||
j=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j<0) return 0;
|
||||
str_ncpy(instr,list[j].instr, instr_len);
|
||||
str_ncpy(host, list[j].host, host_len);
|
||||
if (list[j].user != NULL) {
|
||||
str_ncpy(user, list[j].user, user_len);
|
||||
if (list[j].cod == 1) {
|
||||
str_ncpy(pcod, instr, pcod_len);
|
||||
str_ncat(pcod, "LNS", pcod_len);
|
||||
} else if (list[j].cod == 2) {
|
||||
time(&t);
|
||||
tim=*localtime(&t);
|
||||
sprintf(pcod, "%02dlns%d", tim.tm_year % 100, tim.tm_mon/6+1);
|
||||
} else {
|
||||
str_ncpy(pcod, " ", pcod_len);
|
||||
}
|
||||
}
|
||||
return list[j].port;
|
||||
}
|
||||
|
||||
|
||||
#ifdef F_CHAR
|
||||
/* compile only when fortran c interface stuff is defined */
|
||||
|
||||
int F_FUN(instr_host)(F_CHAR(input), F_CHAR(instr), F_CHAR(host), F_CHAR(user), F_CHAR(pcod)
|
||||
, int input_len, int instr_len, int host_len, int user_len, int pcod_len) {
|
||||
char buf[256], in[256], ho[256], us[256], pc[256];
|
||||
int iRet;
|
||||
|
||||
STR_TO_C(buf, input);
|
||||
iRet=InstrHost(buf, in, ho, us, pc, sizeof(in), sizeof(ho), sizeof(us), sizeof(pc));
|
||||
if (iRet>0) {
|
||||
STR_TO_F(instr, in);
|
||||
STR_TO_F(host, ho);
|
||||
STR_TO_F(user, us);
|
||||
STR_TO_F(pcod, pc);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
|
||||
#endif
|
||||
11
tecs/instr_hosts.h
Normal file
11
tecs/instr_hosts.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef _MYC_STR_H_
|
||||
#define _MYC_STR_H_
|
||||
|
||||
int InstrHost(char *input, char *instr, char *host, char *user, char *pcod
|
||||
, int instr_len, int host_len, int user_len, int pcod_len);
|
||||
|
||||
/* input may be a host of instrument name
|
||||
output is: instrument name, host name, user name and pcod (the code needed to enter...)
|
||||
*/
|
||||
|
||||
#endif /* _MYC_STR_H_ */
|
||||
49
tecs/keep_running.c
Normal file
49
tecs/keep_running.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define MAX_CNT 10
|
||||
#define MIN_PERIOD 3600
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int cnt, dif;
|
||||
time_t tim1, tim2;
|
||||
pid_t pid;
|
||||
int status, i;
|
||||
|
||||
if (argc<2) return 0;
|
||||
cnt = MAX_CNT;
|
||||
while (cnt > 0) {
|
||||
time(&tim1);
|
||||
pid=vfork();
|
||||
if (pid == 0) {
|
||||
execvp(argv[1], argv+1);
|
||||
perror("execvp");
|
||||
exit(1);
|
||||
}
|
||||
waitpid(pid, &status, 0);
|
||||
if (status==512) { /* kill */
|
||||
return 0;
|
||||
}
|
||||
if (status==256) { /* restart */
|
||||
cnt = MAX_CNT;
|
||||
}
|
||||
time(&tim2);
|
||||
dif = (int) difftime(tim2, tim1);
|
||||
cnt += dif / MIN_PERIOD;
|
||||
if (cnt > MAX_CNT) cnt = MAX_CNT;
|
||||
cnt--;
|
||||
if (dif < MIN_PERIOD) {
|
||||
printf("Status=%d. Died after %d sec", status, dif);
|
||||
} else {
|
||||
printf("Status=%d. Died after %f hours", status, dif/3600.);
|
||||
}
|
||||
if (cnt > 0) {
|
||||
printf(" - %d tries left - retry ...\n", cnt);
|
||||
}
|
||||
}
|
||||
printf(" - too many restarts\n");
|
||||
return -1;
|
||||
}
|
||||
65
tecs/make_gen
Normal file
65
tecs/make_gen
Normal file
@@ -0,0 +1,65 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile (sytem independent part) for the TECS Client library and TecsServer
|
||||
# included in a machine-specific makefile
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
LIBR_OBJ =coc_util.o myc_err.o myc_str.o myc_buf.o myc_time.o
|
||||
SERV_OBJ =tecs.o coc_server.o tecs_lsc.o tecs_serial.o coc_logfile.o \
|
||||
tecs_data.o $(LIBR_OBJ)
|
||||
CLI_OBJ =tecs_cli.o coc_client.o $(LIBR_OBJ)
|
||||
TCLI_OBJ =sys_getenv.o sys_env.o myc_tmp.o sys_cmdpar.o \
|
||||
sys_date.o sys_wait.o sys_lun.o sys_rdline.o \
|
||||
sys_get_key.o sys_unix.o sys_open$(SYS_OPEN).o \
|
||||
$(CLI_OBJ)
|
||||
TECLI_OBJ =tecs_client.o tecs_plot.o str.o instr_hosts.o \
|
||||
$(TCLI_OBJ)
|
||||
|
||||
#.f.o:
|
||||
# $(FC) $(FFLAGS) -c $F
|
||||
#
|
||||
#.c.o:
|
||||
# $(CC) $(CFLAGS) -c $C
|
||||
|
||||
libtecsl.a: $(CLI_OBJ)
|
||||
rm -f $@
|
||||
$(AR) $(ARFLAGS) $@ $Q
|
||||
ranlib $@
|
||||
|
||||
all: libtecsl.a TecsServer TecsClient keep_running six
|
||||
|
||||
test: tecs_cli.c
|
||||
echo $(VPATH) $C
|
||||
|
||||
TecsServer: $(SERV_OBJ) $(HARDSUPLIB)
|
||||
$(CC) $(CFLAGS) -o $@ $Q -lm $(FORTIFYOBJ)
|
||||
|
||||
TecsClient: $(TECLI_OBJ)
|
||||
$(FC) -o $@ $Q $(PGLIB) $(RDLIB) $(FORTIFYOBJ)
|
||||
|
||||
# -- for tascom --
|
||||
libtecs.so: tecs_c.c $(CLI_OBJ)
|
||||
$(CC) $(CFLAGS) -shared -o $@ $Q $(FORTIFYOBJ)
|
||||
|
||||
# -- needs special include
|
||||
tecs_serial.o: tecs_serial.c
|
||||
$(CC) $(CFLAGS) -I$(SICS)/hardsup -c $Q
|
||||
|
||||
keep_running: keep_running.c
|
||||
$(CC) $(CFLAGS) -o $@ $Q $(FORTIFYOBJ)
|
||||
|
||||
six: six.c term.o sys_select.o libtecsl.a
|
||||
$(CC) $(CFLAGS) -o $@ $Q $(FORTIFYOBJ)
|
||||
|
||||
#rstart: rstart.c myc_str.o myc_err.o instr_hosts.o
|
||||
# $(CC) $(CFLAGS) -o $@ $Q $(FORTIFYOBJ)
|
||||
#
|
||||
#serverd: serverd.c myc_str.o myc_err.o coc_util.o myc_buf.o
|
||||
# $(CC) $(CFLAGS) -o $@ $Q $(FORTIFYOBJ)
|
||||
#
|
||||
#starts: starts.c myc_str.o myc_err.o coc_util.o myc_buf.o
|
||||
# $(CC) $(CFLAGS) -o $@ $Q $(FORTIFYOBJ)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a six keep_running TecsServer TecsClient
|
||||
37
tecs/make_opt
Normal file
37
tecs/make_opt
Normal file
@@ -0,0 +1,37 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile options for the TECS Client library and TecsServer
|
||||
# for Redhat linux on llc3 or llc4
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
SINQ=/afs/psi.ch/project/sinq/linux
|
||||
SICS=..
|
||||
|
||||
# -- GNU make
|
||||
# -- all prerequisites:
|
||||
Q=$^
|
||||
# -- Fortran source:
|
||||
F=$<
|
||||
# -- C source
|
||||
C=$<
|
||||
|
||||
CC = gcc
|
||||
FC = g77
|
||||
CFLAGS = -DLINUX -g
|
||||
FFLAGS = -u -fvxt -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# FORTIFYOBJ = fortify.o
|
||||
|
||||
# -- system dependent routines
|
||||
SYS_FILE =sys_linux
|
||||
|
||||
# -- PGPLOT library
|
||||
PGLIB =$(SINQ)/pgplot/libpgplot.a -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=$(SICS)/hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
27
tecs/make_opt_alpha
Normal file
27
tecs/make_opt_alpha
Normal file
@@ -0,0 +1,27 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile options for the TECS Client library and TecsServer
|
||||
# for Redhat linux on llc3 or llc4
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
SINQ=/afs/psi.ch/project/sinq/linux
|
||||
SICS=..
|
||||
|
||||
CC = cc
|
||||
FC = f77
|
||||
CFLAGS = -std1 -g -warnprotos
|
||||
FFLAGS = -u -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# -- system dependent routines
|
||||
SYS_FILE =sys_aunix
|
||||
|
||||
# -- PGPLOT library
|
||||
PGLIB =$(PGPLOT_DIR)/libpgplot.a -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=$(SICS)/hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
27
tecs/make_opt_llc
Normal file
27
tecs/make_opt_llc
Normal file
@@ -0,0 +1,27 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile options for the TECS Client library and TecsServer
|
||||
# for Redhat linux on llc3 or llc4
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
SINQ=/afs/psi.ch/project/sinq/linux
|
||||
SICS=..
|
||||
|
||||
CC = gcc
|
||||
FC = g77
|
||||
CFLAGS = -DLINUX -g
|
||||
FFLAGS = -u -fvxt -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# -- system dependent routines
|
||||
SYS_FILE =sys_linux
|
||||
|
||||
# -- PGPLOT library
|
||||
PGLIB =$(SINQ)/pgplot/libpgplot.a -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=$(SICS)/hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
3
tecs/makefile
Normal file
3
tecs/makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
#include makefile_alpha
|
||||
include makefile_linux
|
||||
|
||||
44
tecs/makefile_alpha
Normal file
44
tecs/makefile_alpha
Normal file
@@ -0,0 +1,44 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile for the TECS Client library and TecsServer
|
||||
# machine-dependent part for Tru64 Unix
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
# the following lines only for fortified version
|
||||
#DFORTIFY=-DFORTIFY -I$(SRC)..
|
||||
#FORTIFYOBJ=../strdup.o ../fortify.o
|
||||
#==========================================================================
|
||||
|
||||
|
||||
SICS=src/..
|
||||
|
||||
CC = cc
|
||||
FC = f77
|
||||
CFLAGS = -std1 -g -warnprotos $(DFORITFY)
|
||||
FFLAGS = -u -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# -- system dependent routines
|
||||
SYS_OPEN = _alpha
|
||||
|
||||
# -- PGPLOT library
|
||||
PGLIB =$(PGPLOT_DIR)/libpgplot.a -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=../hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
|
||||
# -- the following macros are used as a replacement for some automatic variables
|
||||
# due to different make versions.
|
||||
# This is for Tru64 standard make.
|
||||
#
|
||||
# list of prerequisites including paths for VPATH
|
||||
Q=$>
|
||||
|
||||
# Fortran/C source file name
|
||||
F=$*.f
|
||||
C=$*.c
|
||||
|
||||
include make_gen
|
||||
45
tecs/makefile_linux
Normal file
45
tecs/makefile_linux
Normal file
@@ -0,0 +1,45 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Makefile options for the TECS Client library and TecsServer
|
||||
# machine-dependent part for Redhat Linux with AFS at PSI
|
||||
#
|
||||
# Markus Zolliker, March 2003
|
||||
#--------------------------------------------------------------------------
|
||||
# the following lines only for fortified version
|
||||
DFORTIFY=-DFORTIFY -I$(SRC)..
|
||||
FORTIFYOBJ=../strdup.o ../fortify.o
|
||||
#==========================================================================
|
||||
|
||||
SICST=..
|
||||
SICS=$(SRC)..
|
||||
|
||||
CC = gcc
|
||||
FC = g77
|
||||
CFLAGS = -DLINUX -g $(DFORTIFY)
|
||||
FFLAGS = -u -fvxt -g
|
||||
ARFLAGS = cr
|
||||
|
||||
# -- system dependent routines
|
||||
|
||||
# -- PGPLOT library
|
||||
#PGPLOT =/afs/psi.ch/project/sinq/linux/pgplot/
|
||||
PGPLOT =/afs/psi.ch/user/z/zolliker/pgplot/
|
||||
PGLIB =$(PGPLOT)/libpgplot.a -L/usr/X11R6/lib -lX11
|
||||
|
||||
# -- library for ASYNSRV
|
||||
HARDSUPLIB=$(SICST)/hardsup/libhlib.a
|
||||
|
||||
# -- readline library
|
||||
RDLIB =-lreadline -ltermcap
|
||||
|
||||
# -- the following macros are used as a replacement for some automatic variables
|
||||
# due to different make versions.
|
||||
# This is for GNU make.
|
||||
#
|
||||
# list of prerequisites including paths for VPATH
|
||||
Q=$^
|
||||
|
||||
# Fortran/C source file name
|
||||
F=$<
|
||||
C=$<
|
||||
|
||||
include $(SRC)make_gen
|
||||
312
tecs/myc_buf.c
Normal file
312
tecs/myc_buf.c
Normal file
@@ -0,0 +1,312 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdlib.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;
|
||||
if (sep == StrNONE) {
|
||||
buf->rdpos=f - buf->buf + 1;
|
||||
buf->seen = 0;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
#define TWO_23 8388608
|
||||
#define EXP_OFFS 128
|
||||
|
||||
void flt_to_char4(double f, char buf[4]) {
|
||||
double m;
|
||||
int e, res, ir;
|
||||
|
||||
m=frexp(f, &e);
|
||||
e=e+EXP_OFFS;
|
||||
if (e<0 || m==0) {
|
||||
res=0; m=0;
|
||||
} else {
|
||||
if (e>255) {
|
||||
res=255*TWO_23+(TWO_23-1); /* max. representable number */
|
||||
} else {
|
||||
res=e*TWO_23+(int)(0.5+(fabs(m*2)-1.0)*TWO_23);
|
||||
}
|
||||
}
|
||||
buf[0]=res % 256; res=res/256;
|
||||
buf[1]=res % 256; res=res/256;
|
||||
buf[2]=res % 256; res=res/256;
|
||||
if (m<0) {
|
||||
buf[3]=res-128;
|
||||
} else {
|
||||
buf[3]=res;
|
||||
}
|
||||
}
|
||||
|
||||
double flt_from_char4(char buf[4]) {
|
||||
int s, i, b0, b1, b2, b3;
|
||||
|
||||
b0=buf[0]; if (b0<0) b0+=256;
|
||||
b1=buf[1]; if (b1<0) b1+=256;
|
||||
b2=buf[2]; if (b2<0) b2+=256;
|
||||
b3=buf[3]; if (b3<0) b3+=256;
|
||||
if (b3>=128) {
|
||||
i=(b3-128)*(256*65536)+b2*65536+b1*256+b0;
|
||||
if (i==0) return 0.0;
|
||||
return -ldexp((i % TWO_23)*1.0/(TWO_23)*0.5+0.5, i/TWO_23-EXP_OFFS);
|
||||
} else {
|
||||
i=b3*(256*65536)+b2*65536+b1*256+b0;
|
||||
if (i==0) return 0.0;
|
||||
return ldexp((i % TWO_23)*1.0/(TWO_23)*0.5+0.5, i/TWO_23-EXP_OFFS);
|
||||
}
|
||||
}
|
||||
|
||||
int StrPutArray(StrBuf *buf, float val[], int size) {
|
||||
int i, pos;
|
||||
char *b;
|
||||
|
||||
pos=buf->wrpos;
|
||||
if (pos < 0 || pos >= buf->dsize || buf->buf==NULL)
|
||||
ERR_MSG("buffer corrupt");
|
||||
if (pos+4*size >= buf->dsize)
|
||||
ERR_MSG("buffer too short");
|
||||
b=buf->buf+pos;
|
||||
flt_to_char4((float)size, b);
|
||||
b+=4;
|
||||
for (i=0; i<size; i++) {
|
||||
flt_to_char4(val[i], b);
|
||||
b+=4;
|
||||
}
|
||||
buf->wrpos=b - buf->buf;
|
||||
return(0);
|
||||
OnError:
|
||||
buf->wrpos=-1;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int StrGetArray(StrBuf *buf, float val[], int maxsize) {
|
||||
int size, i;
|
||||
char *b;
|
||||
double gg;
|
||||
|
||||
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize || buf->buf==NULL)
|
||||
ERR_MSG("buffer corrupt");
|
||||
b=buf->buf + buf->rdpos;
|
||||
size=flt_from_char4(b); b+=4;
|
||||
buf->rdpos+=4*(size+1);
|
||||
if (maxsize<size) size=maxsize;
|
||||
for (i=0; i<size; i++) {
|
||||
gg=flt_from_char4(b); b+=4;
|
||||
val[i]=gg;
|
||||
}
|
||||
return size;
|
||||
OnError:
|
||||
buf->rdpos=buf->dsize; /* illegal value */
|
||||
return(-1);
|
||||
}
|
||||
60
tecs/myc_buf.h
Normal file
60
tecs/myc_buf.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#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);
|
||||
int StrPutArray(StrBuf *buf, float val[], int size);
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
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 or until the end of a quoted string
|
||||
- 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);
|
||||
int StrGetArray(StrBuf *buf, float val[], int maxsize);
|
||||
#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_ */
|
||||
136
tecs/myc_err.c
Normal file
136
tecs/myc_err.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "myc_fortran.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)(void *, char *)=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 *, char *), 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 */
|
||||
|
||||
void F_FUN(err_show)(F_CHAR(text), int text_len) {
|
||||
char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrShow(buf);
|
||||
}
|
||||
|
||||
void F_FUN(err_txt)(F_CHAR(text), int text_len) {
|
||||
char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrTxt(buf,0);
|
||||
}
|
||||
|
||||
void F_FUN(err_msg)(F_CHAR(text), int text_len) {
|
||||
static char buf[256];
|
||||
|
||||
STR_TO_C(buf, text);
|
||||
ErrMsg(buf);
|
||||
}
|
||||
|
||||
void F_FUN(err_set_outrtn)(void (*rtn)(void *, char*), void *arg) {
|
||||
ErrSetOutRtn(rtn, arg);
|
||||
}
|
||||
|
||||
void F_FUN(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 *,char *), void *arg);
|
||||
void ErrSetOutFile(FILE *file);
|
||||
|
||||
extern int ErrCode;
|
||||
extern char *ErrMessage;
|
||||
|
||||
#endif /* _ERR_HANDLING_H_ */
|
||||
56
tecs/myc_fortran.h
Executable file
56
tecs/myc_fortran.h
Executable file
@@ -0,0 +1,56 @@
|
||||
#ifndef _SYS_UTIL_H_
|
||||
#define _SYS_UTIL_H_
|
||||
|
||||
/*
|
||||
|
||||
fortran interface stuff
|
||||
|
||||
declare fortran character arguments as F_CHAR(arg)
|
||||
and at at the end for each character argument <arg> add
|
||||
int <arg>_len to the argument list
|
||||
|
||||
Use macros STR_TO_C and STR_TO_F to convert from Fortran character strings
|
||||
to C character arrays and vice versa.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#if defined __VMS
|
||||
|
||||
typedef struct { short size, dummy; char *text; } SysVmsChar;
|
||||
|
||||
#define F_CHAR(VAR) SysVmsChar *VAR
|
||||
#define F_DCHAR(VAR,LEN) static char VAR##_str[LEN]; SysVmsChar VAR##_desc={LEN,270,&VAR##_str[0]}; SysVmsChar *VAR=&VAR##_desc
|
||||
#define F_CLEN(VAR)
|
||||
#define F_ALEN(VAR)
|
||||
#define F_LEN(VAR) VAR->size
|
||||
#define STR_TO_C(DST,SRC) str_ntrim(DST, SRC->text, sizeof(DST), SRC->size)
|
||||
#define STR_TO_F(DST,SRC) str_npad(DST->text, SRC, DST->size)
|
||||
#define F_FUN(A) A
|
||||
|
||||
|
||||
#elif defined __alpha || defined __unix || defined __GNUC__
|
||||
|
||||
#define F_CHAR(VAR) char *VAR
|
||||
#define F_DCHAR(VAR,LEN) char VAR[LEN]; int VAR##_len=LEN
|
||||
#define F_CLEN(VAR) ,int VAR##_len
|
||||
#define F_ALEN(VAR) ,VAR##_len
|
||||
#define F_LEN(VAR) VAR##_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)
|
||||
|
||||
#ifdef __alpha
|
||||
#define F_FUN(A) A##_
|
||||
#elif defined __GNUC__
|
||||
#define F_FUN(A) A##__
|
||||
#else
|
||||
#define F_FUN(A) A##__
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#error "other machines are not supported"
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_UTIL_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); PTR=NULL; }
|
||||
|
||||
#endif /* _MEM_UTIL_H_ */
|
||||
251
tecs/myc_str.c
Normal file
251
tecs/myc_str.c
Normal file
@@ -0,0 +1,251 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.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 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;
|
||||
int i, 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((int)*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((int)*src);
|
||||
dst++; src++;
|
||||
dstlen--;
|
||||
}
|
||||
*dst='\0';
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
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_ */
|
||||
124
tecs/myc_time.c
Normal file
124
tecs/myc_time.c
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#if __VMS
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
#include "myc_fortran.h"
|
||||
#include "myc_time.h"
|
||||
|
||||
|
||||
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) {
|
||||
#if __VMS
|
||||
struct timeb now;
|
||||
#else
|
||||
struct timeval now;
|
||||
#endif
|
||||
int msec;
|
||||
|
||||
if (my_base == 0) initBase();
|
||||
#if __VMS
|
||||
ftime(&now);
|
||||
msec = (now.time - my_base) % (24*3600) * 1000 + now.millitm - since;
|
||||
#else
|
||||
gettimeofday(&now, NULL);
|
||||
msec = (now.tv_sec - my_base) % (24*3600) * 1000 + now.tv_usec/1000 - since;
|
||||
#endif
|
||||
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 */
|
||||
|
||||
int F_FUN(myc_now)(void) { return mycNow(); }
|
||||
int F_FUN(myc_date)(int *time) { return mycDate(*time); }
|
||||
int F_FUN(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_ */
|
||||
96
tecs/myc_tmp.c
Normal file
96
tecs/myc_tmp.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "myc_fortran.h"
|
||||
#include "myc_mem.h"
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
|
||||
int MycTmpName(char *result, const char *name, int reslen) {
|
||||
char tmp[128];
|
||||
char *u;
|
||||
|
||||
if (strlen(name)+64 > sizeof(tmp))
|
||||
ERR_MSG("destination string too short"); /* do not accept too long names */
|
||||
u=getenv("USER");
|
||||
if (u==NULL)
|
||||
ERR_MSG("USER undefined");
|
||||
sprintf(tmp, "/tmp/%s_%s.%d", name, u, getpid());
|
||||
ERR_I(str_ncpy(result, tmp, reslen));
|
||||
return 0;
|
||||
OnError:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MycCleanTmp(void) {
|
||||
time_t tim;
|
||||
static time_t last=0;
|
||||
char file[128], line[1024], fullid[16];
|
||||
char *sess=NULL, *files=NULL;
|
||||
char *list, *id, *nxt, *nextline;
|
||||
int i;
|
||||
|
||||
time(&tim);
|
||||
if (tim < last+3600) return 0; /* do not clean up before an hour after last time */
|
||||
last=tim;
|
||||
file[0]='\0';
|
||||
ERR_I(MycTmpName(file, ".cleanup", sizeof(file)));
|
||||
unlink(file);
|
||||
/* make a list of used session and process id's */
|
||||
sprintf(line, "ps -U $USER -o pid,sess > %s", file);
|
||||
system(line);
|
||||
ERR_P(sess=str_read_file(file));
|
||||
unlink(file);
|
||||
for (i=0; i<2; i++) {
|
||||
if (i==0) {
|
||||
sprintf(line,
|
||||
"find /tmp/. ! -name . -prune -name \".*_$USER.*\" > %s", file);
|
||||
} else {
|
||||
sprintf(line,
|
||||
"find /tmp/. ! -name . -prune -name \"*_$USER.*\" -mtime +7 > %s", file);
|
||||
}
|
||||
system(line);
|
||||
ERR_P(files=str_read_file(file));
|
||||
unlink(file);
|
||||
str_replace_char(sess, '\n', ' ');
|
||||
list=files;
|
||||
while (*list != '\0') {
|
||||
nextline=str_split1(list, '\n');
|
||||
id=NULL;
|
||||
nxt=list;
|
||||
while (nxt != NULL) { /* find last dot */
|
||||
id=nxt+1;
|
||||
nxt=strchr(nxt+1, '.');
|
||||
}
|
||||
if (id!=NULL) { /* file contains a dot */
|
||||
sprintf(fullid, " %.12s ", id);
|
||||
if (strstr(sess, fullid)==NULL) {
|
||||
unlink(list);
|
||||
}
|
||||
}
|
||||
list=nextline;
|
||||
}
|
||||
FREE(files); files=NULL;
|
||||
}
|
||||
FREE(sess); sess=NULL;
|
||||
return 0;
|
||||
OnError:
|
||||
if (file[0] != '\0') unlink(file);
|
||||
if (sess!=NULL) FREE(sess);
|
||||
if (files!=NULL) FREE(files);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void F_FUN(sys_temp_name) ( F_CHAR(name), F_CHAR(path) F_CLEN(name) F_CLEN(path)) {
|
||||
char nam[128];
|
||||
char pat[1024];
|
||||
|
||||
STR_TO_C(nam, name);
|
||||
MycTmpName(pat, nam, sizeof(pat));
|
||||
STR_TO_F(path, pat);
|
||||
}
|
||||
|
||||
void F_FUN(sys_clean_tmp) (void) {
|
||||
MycCleanTmp();
|
||||
}
|
||||
9
tecs/myc_tmp.h
Normal file
9
tecs/myc_tmp.h
Normal file
@@ -0,0 +1,9 @@
|
||||
int MycTmpName(char *result, const char *name, int reslen);
|
||||
/* generate a temporary filename containing 'name'.
|
||||
* the filename is stored in 'result' with less than 'reslen' characters.
|
||||
*/
|
||||
|
||||
int MycCleanTmp(void);
|
||||
/* deletes temporary files from closed sessions. files not beginning with a
|
||||
* dot will be kept at least for 7 days (if the system does not delete then)
|
||||
*/
|
||||
52
tecs/rstart.c
Normal file
52
tecs/rstart.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include "myc_str.h"
|
||||
#include "instr_hosts.h"
|
||||
|
||||
int rexec(char **host, int port, char *user, char *passwd, char *command, int *err_file_desc);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int port, i, j, l, fd;
|
||||
char inst[32], cmd[256], host[256], user[64], pcod[64];
|
||||
char *hostp;
|
||||
struct tm tim;
|
||||
time_t t;
|
||||
|
||||
struct servent s;
|
||||
|
||||
s=*getservbyname("exec", "tcp");
|
||||
i=0;
|
||||
if (argc < 3) {
|
||||
printf("not enough arguments\n");
|
||||
return 0;
|
||||
}
|
||||
i=InstrHost(argv[1], inst, host, user, pcod, sizeof(inst), sizeof(host), sizeof(user), sizeof(pcod));
|
||||
if (i==0) {
|
||||
printf("unknown host/instrument\n");
|
||||
return -1;
|
||||
}
|
||||
str_copy(cmd, "");
|
||||
for (i=2; i<argc; i++) {
|
||||
if (0==strcmp(argv[i], "sics")) {
|
||||
str_append(cmd, "bin/startsics\n");
|
||||
} else if (0==strcmp(argv[i], "tecs")) {
|
||||
if (i<argc) i++; /* skip argument */
|
||||
str_append(cmd, "bin/startecs\n");
|
||||
} else {
|
||||
printf("unknown server %s\n", argv[i]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("login to %s\n", host);
|
||||
hostp=host;
|
||||
fd=rexec(&hostp, s.s_port, user, pcod, cmd, &i);
|
||||
if (fd<0) {
|
||||
perror("rexec"); return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
220
tecs/six.c
Normal file
220
tecs/six.c
Normal file
@@ -0,0 +1,220 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "coc_util.h"
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include "term.h"
|
||||
|
||||
int CocCreateSockAdr(
|
||||
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||
const char *host, /* Host. NULL implies INADDR_ANY */
|
||||
int port) /* Port number */
|
||||
{
|
||||
struct hostent *hostent; /* Host database entry */
|
||||
struct in_addr addr; /* For 64/32 bit madness */
|
||||
|
||||
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
|
||||
sockaddrPtr->sin_family = AF_INET;
|
||||
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
|
||||
if (host == NULL || host[0]=='\0') {
|
||||
addr.s_addr = INADDR_ANY;
|
||||
} else {
|
||||
hostent = gethostbyname(host);
|
||||
if (hostent != NULL) {
|
||||
memcpy((char *) &addr,
|
||||
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
|
||||
} else {
|
||||
addr.s_addr = inet_addr(host);
|
||||
if (addr.s_addr == (unsigned long)-1) {
|
||||
return -1; /* error */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* There is a rumor that this assignment may require care on
|
||||
* some 64 bit machines.
|
||||
*/
|
||||
|
||||
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readWrite(int fd, int skip) {
|
||||
char msg[128];
|
||||
int l, i, go, iret, ires, n;
|
||||
/*
|
||||
* read from fd and write to stdout until a key pressed,
|
||||
* a timeout occured (1 or 5 sec.), or a <go ahead> message
|
||||
* received.
|
||||
* skip=0: timeout 1 sec (normal behaviour)
|
||||
* skip>0: timeout 5 sec.
|
||||
* skip>1: swallow text
|
||||
* skip=1,2: return 0 if SICS not found in message text
|
||||
* skip=3: return 0 if not acknowledged
|
||||
*/
|
||||
n=0;
|
||||
go=0;
|
||||
ires=0;
|
||||
iret=term_wait_fd(fd, skip?5000:1000);
|
||||
while (iret==1) {
|
||||
ERR_SI(l=recv(fd, msg, sizeof(msg)-1, 0));
|
||||
/* if (l==0) return(0); */
|
||||
msg[l]='\0';
|
||||
if (skip==3) {
|
||||
if (NULL!=strstr(msg, "Acknowledged")) ires=1;
|
||||
} else if (skip==1 || skip==2) {
|
||||
if (NULL!=strstr(msg, "SICS")) ires=1;
|
||||
}
|
||||
for (i=0; i<l-1; i++) {
|
||||
if (msg[i]==-1 && msg[i+1]==-7) { /* go ahead */
|
||||
go=1;
|
||||
msg[i]='<'; msg[i+1]='>';
|
||||
} else {
|
||||
go=0;
|
||||
}
|
||||
}
|
||||
if (skip<2 || skip==2 && ires==0) {
|
||||
fputs(msg, stdout);
|
||||
} else {
|
||||
n+=strlen(msg);
|
||||
}
|
||||
if (go) break;
|
||||
iret=term_wait_fd(fd, skip?5000:1000);
|
||||
}
|
||||
if (n==0 && ires==1) return 1;
|
||||
return ires*n;
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int iret, pos;
|
||||
fd_set mask;
|
||||
int fd, l, i, j, port, skip;
|
||||
char buf[128], lbuf[16], ibuf[64];
|
||||
char *rights, *instr, *sim="", *us, *ps;
|
||||
|
||||
struct sockaddr_in sadr;
|
||||
|
||||
port=1301;
|
||||
skip=2;
|
||||
j=0;
|
||||
for (i=1; i<argc; i++) {
|
||||
if (0==strcmp(argv[i], "-s")) {
|
||||
port=1303; sim="-sim";
|
||||
} else if (0==strcmp(argv[i], "-w")) {
|
||||
skip=1;
|
||||
} else {
|
||||
if (strlen(argv[i])>=32) {
|
||||
printf("argument too long\n");
|
||||
} else {
|
||||
if (j==0) {
|
||||
us=argv[i];
|
||||
j=1;
|
||||
} else if (j==1) {
|
||||
ps=argv[i];
|
||||
j=2;
|
||||
} else {
|
||||
printf("too many arguments\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j==1) {
|
||||
printf("missing password\n");
|
||||
return(0);
|
||||
}
|
||||
instr=getenv("Instrument");
|
||||
if (instr==NULL || instr[0]=='\0') {
|
||||
printf("Instrument is undefined\n");
|
||||
return(0);
|
||||
}
|
||||
ERR_I(CocCreateSockAdr(&sadr, "0", port));
|
||||
ERR_SI(fd=socket(AF_INET, SOCK_STREAM, 0));
|
||||
term_reg_socket(fd);
|
||||
ERR_SI(connect(fd, (struct sockaddr *)&sadr, sizeof(sadr)));
|
||||
strcpy(buf, "sicslogin Spy 007\r\n");
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,skip));
|
||||
if (!i) {
|
||||
printf("rejected\n");
|
||||
return 0;
|
||||
}
|
||||
if (skip==2) printf("reading welcome message ...\n");
|
||||
if (j==0) {
|
||||
rights=getenv("six_rights");
|
||||
if (rights!=NULL && 0==strcmp(rights, instr)) {
|
||||
us="lnsmanager";
|
||||
ps="lnsSICSlns";
|
||||
} else {
|
||||
sprintf(ibuf, "%suser", instr);
|
||||
str_lowcase(ibuf, ibuf);
|
||||
us=ibuf;
|
||||
ps="03lns1";
|
||||
}
|
||||
}
|
||||
sprintf(buf, "config Rights %s %s\r\n", us, ps);
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,3));
|
||||
if (!i) {
|
||||
us="Spy";
|
||||
}
|
||||
printf("\rlogged in to SICS as %s on %s%s\n", us, instr, sim);
|
||||
/*
|
||||
if (*sim!='\0') {
|
||||
strcpy(buf, "sync\r\n");
|
||||
ERR_SI(send(fd, buf, strlen(buf), 0));
|
||||
ERR_I(i=readWrite(fd,1));
|
||||
}
|
||||
*/
|
||||
iret=1;
|
||||
buf[0]='\0';
|
||||
pos=0;
|
||||
str_lowcase(instr,instr);
|
||||
sprintf(ibuf, "six[%s%s] ", instr, sim);
|
||||
while (1) {
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(fd, &mask);
|
||||
iret=term_get_line(buf, sizeof(buf)-2, &pos, ibuf, &mask);
|
||||
if (iret==STDIN_FILENO) { /* input line terminated */
|
||||
str_lowcase(lbuf, buf);
|
||||
if (0==strcmp(lbuf,"quit")) break;
|
||||
if (0==strcmp(lbuf,"exit")) break;
|
||||
if (0==strcmp(lbuf,"stop")) {
|
||||
strcpy(buf, "INT1712 3");
|
||||
} else if (0==strcmp(buf, "")) {
|
||||
strcpy(buf, "status");
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
skip=0;
|
||||
if (0==strcmp(lbuf,"sync")) skip=1;
|
||||
l=strlen(buf);
|
||||
/*
|
||||
printf("sent> %s[%d chars]\n", buf, l);
|
||||
*/
|
||||
buf[l]=13;
|
||||
buf[l+1]=10;
|
||||
ERR_SI(send(fd, buf, l+2, 0));
|
||||
ERR_I(i=readWrite(fd,skip));
|
||||
buf[0]='\0';
|
||||
pos=0;
|
||||
} else if (iret<0) { /* ?? */
|
||||
printf("\nwhat?\n"); exit(1);
|
||||
} else { /* socket iret ready to read */
|
||||
assert(fd==iret);
|
||||
ERR_I(readWrite(fd,0));
|
||||
}
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
return(0);
|
||||
OnError:
|
||||
ErrShow("end");
|
||||
return(0);
|
||||
}
|
||||
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
|
||||
|
||||
23
tecs/sys_cmdpar.f
Executable file
23
tecs/sys_cmdpar.f
Executable file
@@ -0,0 +1,23 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_GET_CMDPAR(STR, L) !!
|
||||
!! ---------------------------------
|
||||
!!
|
||||
character*(*) STR !!
|
||||
integer L !!
|
||||
|
||||
integer i,iargc
|
||||
|
||||
l=0
|
||||
str=' '
|
||||
do i=1,iargc()
|
||||
if (l .lt. len(str)) then
|
||||
call getarg(i, str(l+1:))
|
||||
call str_trim(str, str, l)
|
||||
l=l+1
|
||||
endif
|
||||
enddo
|
||||
if (l .gt. 0) then
|
||||
if (str(1:l) .eq. ' ') l=0
|
||||
endif
|
||||
end
|
||||
18
tecs/sys_date.f
Executable file
18
tecs/sys_date.f
Executable file
@@ -0,0 +1,18 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_DATE(YEAR, MONTH, DAY) !!
|
||||
!! -------------------------------------
|
||||
!!
|
||||
!! get actual date
|
||||
!!
|
||||
integer YEAR, MONTH, DAY !! 4-Digits year, month and day
|
||||
|
||||
integer tarray(9)
|
||||
external time
|
||||
integer time
|
||||
|
||||
call ltime(time(), tarray)
|
||||
day=tarray(4)
|
||||
month=tarray(5)+1 ! tarray(5): months since january (0-11)!
|
||||
year=tarray(6)+1900 ! tarray(6): years since 1900, no y2k problem
|
||||
end
|
||||
179
tecs/sys_env.c
Executable file
179
tecs/sys_env.c
Executable file
@@ -0,0 +1,179 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <utmp.h>
|
||||
#include "myc_tmp.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_fortran.h"
|
||||
|
||||
#define ENAM_LEN 128
|
||||
#define EVAL_LEN 1024
|
||||
|
||||
int lnblnk_(const char *str, int len);
|
||||
#ifdef __alpha
|
||||
int setenv(char *p1, char *p2, int ow);
|
||||
#endif
|
||||
|
||||
typedef struct _EnvList { struct _EnvList *next; char *name; char *value; } EnvList;
|
||||
static EnvList *envlist;
|
||||
static char tmpfil[128];
|
||||
static char senv_id[16];
|
||||
static char *empty="";
|
||||
static int loaded=0;
|
||||
static int dirty=0;
|
||||
|
||||
EnvList *sys_findenv(char *name) {
|
||||
EnvList *p;
|
||||
for (p=envlist; p!=NULL; p=p->next) {
|
||||
if (0==strcmp(name, p->name)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int F_FUN(sys_loadenv)(void) {
|
||||
FILE *fil;
|
||||
char buf[ENAM_LEN+EVAL_LEN+10];
|
||||
char old[EVAL_LEN], userid[32];
|
||||
char *nam, *val, *pold, *u, *ret, *v;
|
||||
int l;
|
||||
EnvList *p;
|
||||
|
||||
if (!loaded) {
|
||||
loaded=-1; /* assume failure */
|
||||
/* u=cuserid(userid); */
|
||||
u=getenv("USER");
|
||||
if (u==NULL) {
|
||||
strcpy(userid, "Anonymous");
|
||||
} else {
|
||||
strncpy(userid, u, sizeof(userid));
|
||||
}
|
||||
val=getenv("senv_id");
|
||||
if (val==NULL) {
|
||||
sprintf(senv_id, "%d", getppid());
|
||||
} else {
|
||||
strcpy(senv_id, val);
|
||||
}
|
||||
sprintf(tmpfil, "/tmp/.senv_%s.%s", userid, senv_id);
|
||||
fil=fopen(tmpfil, "r");
|
||||
if (fil==NULL) {
|
||||
loaded=1;
|
||||
return 1;
|
||||
}
|
||||
while (1) {
|
||||
|
||||
ret=fgets(buf, sizeof(buf), fil);
|
||||
if (!ret || buf[0]=='#') break;
|
||||
l=strlen(buf);
|
||||
if (l<10 || buf[l-1]!='\n') return -1;
|
||||
buf[l-1]='\0';
|
||||
buf[6]='\0';
|
||||
if (0!=strcmp(buf, "setenv")) return -1;
|
||||
nam=buf+7;
|
||||
val=strchr(nam, ' ');
|
||||
if (val==NULL) return -1;
|
||||
*val='\0'; val++;
|
||||
if (*val=='"') {
|
||||
if (buf[l-2]!='"') return -1;
|
||||
buf[l-2]='\0';
|
||||
val++;
|
||||
}
|
||||
|
||||
ret=fgets(old, sizeof(old), fil);
|
||||
if (!ret) break;
|
||||
l=strlen(old);
|
||||
if (l==0 || old[0]!='#' || old[l-1]!='\n') return -1;
|
||||
old[l-1]='\0';
|
||||
pold=old+1;
|
||||
|
||||
v=getenv(nam);
|
||||
if (v==NULL) v=empty;
|
||||
if (0==strcmp(v,pold)) { /* take value from file only if env. variable not changed in the meantime */
|
||||
p = malloc(sizeof(*p)); if (p == NULL) goto senv;
|
||||
if (NULL==(p->name = strdup(nam))) goto senv;
|
||||
if (NULL==(p->value = strdup(v))) goto senv;
|
||||
p->next = envlist;
|
||||
envlist=p;
|
||||
senv:
|
||||
setenv(nam, val, 1);
|
||||
}
|
||||
}
|
||||
if (0>fclose(fil)) return -1;
|
||||
loaded=1;
|
||||
}
|
||||
return loaded;
|
||||
}
|
||||
|
||||
int F_FUN(sys_setenv)(char *enam, char *eval, int snam, int sval) {
|
||||
int lnam, lval;
|
||||
char *v, nam[ENAM_LEN], val[EVAL_LEN];
|
||||
EnvList *p=NULL;
|
||||
|
||||
lnam = lnblnk_(enam,snam);
|
||||
if (lnam>=sizeof(nam)) lnam=sizeof(nam)-1;
|
||||
strncpy(nam,enam,lnam); nam[lnam] = '\0';
|
||||
|
||||
lval = lnblnk_(eval,sval);
|
||||
if (lval>=sizeof(val)) lval=sizeof(val)-1;
|
||||
strncpy(val,eval,lval); val[lval] = '\0';
|
||||
|
||||
if (loaded>0) {
|
||||
v=getenv(nam);
|
||||
if (v == NULL) v=empty;
|
||||
if (!dirty) {
|
||||
dirty = 0 != strcmp(val,v);
|
||||
}
|
||||
p=sys_findenv(nam);
|
||||
if (p==NULL) {
|
||||
p = malloc(sizeof(*p)); if (p == NULL) goto senv;
|
||||
if (NULL==(p->name = strdup(nam))) goto senv;
|
||||
if (NULL==(p->value = strdup(v))) goto senv;
|
||||
p->next = envlist;
|
||||
envlist=p;
|
||||
}
|
||||
}
|
||||
senv:
|
||||
return setenv(nam, val, 1);
|
||||
}
|
||||
|
||||
int F_FUN(sys_saveenv)(void) {
|
||||
FILE *fil;
|
||||
char *v;
|
||||
EnvList *p;
|
||||
|
||||
if (F_FUN(sys_loadenv)()<0 || !dirty) return loaded;
|
||||
|
||||
fil=fopen(tmpfil, "w");
|
||||
if (fil==NULL) return -1;
|
||||
|
||||
for (p=envlist; p!=NULL; p=p->next) {
|
||||
v=getenv(p->name);
|
||||
if (0!=strcmp(v, p->value)) {
|
||||
if (0>fputs("setenv ", fil)) return -1;
|
||||
if (0>fputs(p->name, fil)) return -1;
|
||||
if (0>fputs(" \"", fil)) return -1;
|
||||
if (0>fputs(v, fil)) return -1;
|
||||
if (0>fputs("\"\n#", fil)) return -1;
|
||||
if (0>fputs(p->value, fil)) return -1;
|
||||
if (0>fputs("\n", fil)) return -1;
|
||||
}
|
||||
}
|
||||
if (0>fputs("#\nif ($$ == ", fil)) return -1;
|
||||
if (0>fputs(senv_id, fil)) return -1;
|
||||
if (0>fputs(") then\n /bin/rm ", fil)) return -1;
|
||||
if (0>fputs(tmpfil, fil)) return -1;
|
||||
/*
|
||||
if (0>fputs("\n echo \"#\" > ", fil)) return -1;
|
||||
if (0>fputs(tmpfil, fil)) return -1;
|
||||
*/
|
||||
if (0>fputs("\nendif\n", fil)) return -1;
|
||||
if (0>fclose(fil)) return -1;
|
||||
dirty=0;
|
||||
return 0;
|
||||
}
|
||||
52
tecs/sys_get_key.f
Normal file
52
tecs/sys_get_key.f
Normal file
@@ -0,0 +1,52 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_GET_KEY(KEY, TMO) !!
|
||||
!!
|
||||
!! read for keyboard with timeout, without echo
|
||||
!!
|
||||
character KEY*1 !!
|
||||
integer TMO !! timeout in seconds (<100)
|
||||
|
||||
character esc*1, csi*1, ss3*1
|
||||
|
||||
esc=char(27)
|
||||
csi=char(155)
|
||||
ss3=char(143)
|
||||
|
||||
call sys_get_raw_key(key, tmo)
|
||||
1 if (key .eq. esc) then
|
||||
call sys_get_raw_key(key, tmo)
|
||||
if (key .eq. 'O') then
|
||||
key=ss3
|
||||
goto 1
|
||||
elseif (key .eq. '[') then
|
||||
key=csi
|
||||
goto 1
|
||||
endif
|
||||
elseif (key .eq. csi) then
|
||||
call sys_get_raw_key(key, tmo)
|
||||
do while (key .ge. '0' .and. key .le. '9')
|
||||
call sys_get_raw_key(key, tmo)
|
||||
enddo
|
||||
key=' '
|
||||
elseif (key .eq. ss3) then
|
||||
call sys_get_raw_key(key, tmo)
|
||||
if (key .eq. 'm') then
|
||||
key='-'
|
||||
elseif (key .eq. 'l') then
|
||||
key='+'
|
||||
elseif (key .eq. 'n') then
|
||||
key='.'
|
||||
elseif (key .eq. 'M') then
|
||||
key=char(13)
|
||||
elseif (key .eq. 'S') then
|
||||
key='*'
|
||||
elseif (key .eq. 'R') then
|
||||
key='/'
|
||||
elseif (key .eq. 'Q') then
|
||||
key='='
|
||||
else
|
||||
key=' '
|
||||
endif
|
||||
endif
|
||||
end
|
||||
75
tecs/sys_getenv.f
Executable file
75
tecs/sys_getenv.f
Executable file
@@ -0,0 +1,75 @@
|
||||
!!------------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_GETENV(NAME, VALUE) !!
|
||||
!! ==================================
|
||||
!!
|
||||
!! Get environment variable NAME
|
||||
!! try all uppercase also
|
||||
|
||||
implicit none
|
||||
!! Arguments:
|
||||
character*(*) NAME !! logical name
|
||||
character*(*) VALUE !! result
|
||||
|
||||
integer l
|
||||
character nam*128
|
||||
|
||||
call sys_loadenv
|
||||
call str_trim(nam, name, l)
|
||||
call getenv(nam(1:l), value)
|
||||
if (value .ne. ' ') RETURN
|
||||
if (nam(1:1) .ge. 'a') then
|
||||
call str_upcase(nam(1:l), nam(1:l))
|
||||
else
|
||||
call str_lowcase(nam(1:l), nam(1:l))
|
||||
endif
|
||||
call getenv(nam(1:l), value)
|
||||
end
|
||||
|
||||
!!------------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_GETENV_IDX(NAME, VALUE, IDX) !!
|
||||
!! ===========================================
|
||||
!!
|
||||
!! Get environment variable NAME, only list element IDX (start with 0)
|
||||
!! (separated by comma)
|
||||
|
||||
implicit none
|
||||
!! Arguments:
|
||||
character*(*) NAME !! logical name
|
||||
character*(*) VALUE !! result
|
||||
integer IDX !! index
|
||||
|
||||
integer l,pos,j,i
|
||||
character nam*128, list*1024
|
||||
|
||||
call str_trim(nam, name, l)
|
||||
call getenv(nam(1:l), list)
|
||||
if (list .eq. ' ') then
|
||||
if (nam(1:1) .ge. 'a') then
|
||||
call str_upcase(nam(1:l), nam(1:l))
|
||||
else
|
||||
call str_lowcase(nam(1:l), nam(1:l))
|
||||
endif
|
||||
call getenv(nam(1:l), list)
|
||||
endif
|
||||
pos=0
|
||||
do i=1,idx
|
||||
j=index(list(pos+1:), ',')
|
||||
if (j .eq. 0) then
|
||||
value=' '
|
||||
RETURN
|
||||
endif
|
||||
pos=pos+j
|
||||
enddo
|
||||
j=index(list(pos+1:), ',')
|
||||
if (j .eq. 1) then
|
||||
value=' '
|
||||
RETURN
|
||||
endif
|
||||
if (j .le. 0) then
|
||||
value=list(pos+1:)
|
||||
else
|
||||
value=list(pos+1:pos+j-1)
|
||||
endif
|
||||
end
|
||||
43
tecs/sys_lun.f
Executable file
43
tecs/sys_lun.f
Executable file
@@ -0,0 +1,43 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_GET_LUN(LUN) !!
|
||||
!!
|
||||
!! allocate logical unit number
|
||||
!!
|
||||
integer LUN !! out
|
||||
|
||||
logical*1 act(50:100)/51*.false./
|
||||
common /sys_lun/act
|
||||
|
||||
integer l
|
||||
|
||||
l=50
|
||||
do while (l .lt. 99 .and. act(l))
|
||||
l=l+1
|
||||
enddo
|
||||
if (l .eq. 100) stop 'SYS_GET_LUN: no more luns available'
|
||||
lun=l
|
||||
act(l)=.true.
|
||||
end
|
||||
|
||||
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_FREE_LUN(LUN) !!
|
||||
!!
|
||||
!! deallocate logical unit number
|
||||
!!
|
||||
integer LUN !! in
|
||||
|
||||
logical*1 act(50:100)/51*.false./
|
||||
common /sys_lun/act
|
||||
|
||||
if (lun .lt. 50 .or. lun .gt. 99) then
|
||||
stop 'SYS_FREE_LUN: illegal lun'
|
||||
endif
|
||||
if (act(lun)) then
|
||||
act(lun)=.false.
|
||||
else
|
||||
stop 'SYS_FREE_LUN: lun already free'
|
||||
endif
|
||||
end
|
||||
55
tecs/sys_open.f
Executable file
55
tecs/sys_open.f
Executable file
@@ -0,0 +1,55 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_OPEN(LUN, FILE, ACCESS, IOSTAT) !!
|
||||
!! ==============================================
|
||||
!!
|
||||
!! ACCESS='r': open file for read
|
||||
!! ACCESS='w': open or create file for write (on vms: new version, on unix: overwrite)
|
||||
!! ACCESS='wo': overwrite existing file (do not make a new version)
|
||||
!! ACCESS='wn': keep old file (on unix systems, a tilde '~' is appended to the name)
|
||||
!! ACCESS='a': open or create file for append
|
||||
|
||||
integer LUN !! (in) logical unit number
|
||||
character FILE*(*) !! (in) filename
|
||||
character ACCESS*(*) !! (in) access mode
|
||||
integer IOSTAT !! (out) status
|
||||
|
||||
character acc*2
|
||||
character amnt*128
|
||||
integer i,j,l,ios
|
||||
real s
|
||||
|
||||
call str_upcase(acc, access)
|
||||
|
||||
if (acc .eq. 'R') then
|
||||
open(lun, name=file, iostat=iostat, status='old')
|
||||
if (iostat .eq. 0) RETURN ! success
|
||||
l=0
|
||||
i=1
|
||||
do while (i .ne. 0)
|
||||
l=l+i
|
||||
i=index(file(l+1:),'/')
|
||||
enddo
|
||||
if (l .eq. 1) RETURN ! no directory given
|
||||
open(lun, name=file(1:l-1), iostat=ios, status='old')
|
||||
if (ios .eq. 0) then
|
||||
close(lun)
|
||||
RETURN ! directory exists -> already mounted
|
||||
endif
|
||||
call sys_getenv('dat_automount', amnt)
|
||||
if (amnt .eq. ' ') RETURN
|
||||
call sys_cmd(amnt) !try to mount
|
||||
open(lun, name=file, iostat=iostat, status='old')
|
||||
else if (acc .eq. 'W' .or. acc .eq. 'WO') then
|
||||
open(lun, name=file, iostat=iostat, status='unknown')
|
||||
else if (acc .eq. 'WN') then
|
||||
! rename to be done
|
||||
open(lun, name=file, iostat=iostat, status='unknown')
|
||||
else if (acc .eq. 'A') then
|
||||
open(lun, name=file, iostat=iostat, status='unknown'
|
||||
1, access='append')
|
||||
else
|
||||
print *,'unknown access mode: ',acc
|
||||
stop 'error in SYS_OPEN'
|
||||
endif
|
||||
end
|
||||
54
tecs/sys_open_alpha.f
Executable file
54
tecs/sys_open_alpha.f
Executable file
@@ -0,0 +1,54 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_OPEN(LUN, FILE, ACCESS, IOSTAT) !!
|
||||
!! ==============================================
|
||||
!!
|
||||
!! ACCESS='r': open file for read
|
||||
!! ACCESS='w': open or create file for write (on vms: new version, on unix: overwrite)
|
||||
!! ACCESS='wo': overwrite existing file (do not make a new version)
|
||||
!! ACCESS='wn': keep old file (on unix systems, a tilde '~' is appended to the name)
|
||||
!! ACCESS='a': open or create file for append
|
||||
|
||||
integer LUN !! (in) logical unit number
|
||||
character FILE*(*) !! (in) filename
|
||||
character ACCESS*(*) !! (in) access mode
|
||||
integer IOSTAT !! (out) status
|
||||
|
||||
character acc*2
|
||||
character amnt*128
|
||||
integer i,j,l,ios
|
||||
|
||||
call str_upcase(acc, access)
|
||||
|
||||
if (acc .eq. 'R') then
|
||||
open(lun, name=file, iostat=iostat, status='old', readonly)
|
||||
if (iostat .eq. 0) RETURN
|
||||
l=0
|
||||
i=1
|
||||
do while (i .ne. 0)
|
||||
l=l+i
|
||||
i=index(file(l+1:),'/')
|
||||
enddo
|
||||
if (l .eq. 1) RETURN ! no directory given
|
||||
open(lun, name=file(1:l-1), iostat=ios, status='old')
|
||||
if (ios .eq. 0) then
|
||||
close(lun)
|
||||
RETURN ! directory exists -> already mounted
|
||||
endif
|
||||
call sys_getenv('dat_automount', amnt)
|
||||
if (amnt .eq. ' ') RETURN
|
||||
call sys_cmd(amnt) !try to mount
|
||||
open(lun, name=file, iostat=iostat, status='old', readonly)
|
||||
else if (acc .eq. 'W' .or. acc .eq. 'WO') then
|
||||
open(lun, name=file, iostat=iostat, status='unknown')
|
||||
else if (acc .eq. 'WN') then
|
||||
! rename to be done
|
||||
open(lun, name=file, iostat=iostat, status='unknown')
|
||||
else if (acc .eq. 'A') then
|
||||
open(lun, name=file, iostat=iostat, status='unknown'
|
||||
1, access='append')
|
||||
else
|
||||
print *,'unknown access mode: ',acc
|
||||
stop 'error in SYS_OPEN'
|
||||
endif
|
||||
end
|
||||
37
tecs/sys_rdline.c
Executable file
37
tecs/sys_rdline.c
Executable file
@@ -0,0 +1,37 @@
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "myc_str.h"
|
||||
#include "myc_fortran.h"
|
||||
|
||||
static char *last_line = NULL;
|
||||
|
||||
char *readline (char *prompt);
|
||||
void add_history(const char *line);
|
||||
|
||||
void F_FUN(sys_rd_line)(F_CHAR(cmd), int *retlen, F_CHAR(prompt) F_CLEN(cmd) F_CLEN(prompt))
|
||||
{
|
||||
char *line_read;
|
||||
char p0[64], p[64];
|
||||
|
||||
STR_TO_C(p0, prompt);
|
||||
str_copy(p, "\n");
|
||||
str_append(p, p0);
|
||||
if (last_line == NULL) { last_line =malloc(1); last_line[0] = '\0';};
|
||||
|
||||
line_read = readline(p);
|
||||
|
||||
if (line_read)
|
||||
{
|
||||
if (*line_read && strcmp(last_line, line_read)!=0)
|
||||
add_history (line_read);
|
||||
free (last_line);
|
||||
STR_TO_F(cmd, line_read);
|
||||
*retlen=strlen(line_read);
|
||||
last_line = line_read;
|
||||
if (*retlen>F_LEN(cmd)) *retlen=F_LEN(cmd);
|
||||
} else {
|
||||
*retlen=-1;
|
||||
}
|
||||
}
|
||||
91
tecs/sys_select.c
Normal file
91
tecs/sys_select.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static int lastFd=-1;
|
||||
static struct termios atts;
|
||||
|
||||
void sys_keys_on(void) {
|
||||
int iret;
|
||||
|
||||
struct termios attr;
|
||||
iret=tcgetattr(STDIN_FILENO,&attr);
|
||||
atts=attr; /* save term. attr. */
|
||||
if (iret!=0) { perror("***\n");}
|
||||
attr.c_lflag &= ~(ICANON) & ~(ECHO); /* canonical mode off, echo off */
|
||||
attr.c_cc[VMIN]=0;
|
||||
attr.c_cc[VTIME]=1; /* 0.1 sec */
|
||||
iret= tcsetattr(STDIN_FILENO,TCSANOW,&attr);
|
||||
if (iret!=0) {perror("***\n");}
|
||||
}
|
||||
|
||||
void sys_keys_off(void) {
|
||||
int iret;
|
||||
|
||||
iret=tcsetattr(STDIN_FILENO,TCSANOW,&atts); /* restore term. attributes */
|
||||
if (iret!=0) {perror("***\n");};
|
||||
}
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, char *key) {
|
||||
int chan, fd, iret, fd1, m, chr;
|
||||
struct timeval tmo, tmo0={0,0};
|
||||
fd_set rmask;
|
||||
static int init=1;
|
||||
|
||||
if (init) {
|
||||
sys_keys_on();
|
||||
init=0;
|
||||
}
|
||||
rmask=*mask;
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, &tmo0);
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
fd1=STDIN_FILENO;
|
||||
chr=fgetc(stdin);
|
||||
if (chr==EOF && iret==0) {
|
||||
rmask=*mask;
|
||||
FD_SET(STDIN_FILENO, &rmask);
|
||||
if (msecTmo>=0) {
|
||||
if (msecTmo>100) { /* reduce 100 ms for the 1 tenth second in fgetc */
|
||||
msecTmo=msecTmo-100;
|
||||
} else {
|
||||
msecTmo=1;
|
||||
}
|
||||
tmo.tv_sec=msecTmo / 1000;
|
||||
tmo.tv_usec=(msecTmo%1000)*1000;
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, &tmo);
|
||||
} else {
|
||||
iret=select(FD_SETSIZE, &rmask, NULL, NULL, NULL);
|
||||
}
|
||||
if (iret<0) {
|
||||
FD_ZERO(&rmask);
|
||||
perror("error in select");
|
||||
}
|
||||
if (FD_ISSET(STDIN_FILENO, &rmask)) {
|
||||
chr=fgetc(stdin);
|
||||
}
|
||||
FD_CLR(STDIN_FILENO, &rmask);
|
||||
}
|
||||
if (chr==EOF) {
|
||||
chr=0;
|
||||
fd1=-1;
|
||||
for (fd=1; fd<FD_SETSIZE; fd++) {
|
||||
if (FD_ISSET(fd, &rmask)) {
|
||||
if (fd1<0) {
|
||||
fd1=fd; /* first fd */
|
||||
} else if (fd>lastFd) {
|
||||
fd1=fd; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*mask=rmask;
|
||||
*key=chr;
|
||||
/*
|
||||
sys_keys_off();
|
||||
*/
|
||||
return(fd1);
|
||||
}
|
||||
14
tecs/sys_select.h
Normal file
14
tecs/sys_select.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef SYS_SELECT_H_
|
||||
#define SYS_SELECT_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
int sys_select_or_key(fd_set *mask, int msecTmo, char *key);
|
||||
|
||||
/* wait for read event on sockets included in mask or from keyboard or a timeout
|
||||
result is negative for timeout,
|
||||
STDIN_FILENO for a key pressed,
|
||||
else socket number
|
||||
*/
|
||||
|
||||
#endif /* SYS_SELECT_H_ */
|
||||
133
tecs/sys_unix.c
Executable file
133
tecs/sys_unix.c
Executable file
@@ -0,0 +1,133 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <utmp.h>
|
||||
#include "myc_tmp.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_fortran.h"
|
||||
|
||||
void F_FUN(usleep)(int *usec) { usleep(*usec); }
|
||||
int F_FUN(getppid)(void) { return getppid(); }
|
||||
int lnblnk_(const char *str, int len);
|
||||
|
||||
void F_FUN(sys_check_system)(F_CHAR(code) F_CLEN(code)) {
|
||||
#if defined __alpha
|
||||
STR_TO_F(code, "TRU64");
|
||||
#elif defined __GNUC__
|
||||
STR_TO_F(code, "GNU");
|
||||
#else
|
||||
"sys_check_system: unsupported machine"
|
||||
#endif
|
||||
}
|
||||
|
||||
void F_FUN(sys_realpath)(F_CHAR(rpath), int *reslen,
|
||||
F_CHAR(path) F_CLEN(rpath) F_CLEN(path)) {
|
||||
char p[PATH_MAX], rp[PATH_MAX], *pt;
|
||||
|
||||
STR_TO_C(p, path);
|
||||
pt=realpath(p, rp);
|
||||
if (pt==NULL) str_copy(rp, p);
|
||||
*reslen=strlen(rp);
|
||||
STR_TO_F(rpath, rp);
|
||||
}
|
||||
|
||||
void F_FUN(sys_cmd)(char *command, int clen) {
|
||||
int rc, l;
|
||||
char *p;
|
||||
|
||||
l = lnblnk_(command, clen);
|
||||
p = malloc((unsigned) l+1); if( p == NULL ) return;
|
||||
strncpy(p,command,l); p[l] = '\0';
|
||||
rc = system(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static struct termios atts;
|
||||
|
||||
void F_FUN(sys_rd_tmo)(char *prompt, char *result, int *reslen, int p_len, int r_len) {
|
||||
struct termios attr;
|
||||
int ires, i, ntmo, chr;
|
||||
|
||||
ires=tcgetattr(STDIN_FILENO,&attr);
|
||||
atts=attr; /* save term. attr. */
|
||||
if (ires!=0) {
|
||||
perror("error in terinq/tcgetattr ");
|
||||
(*reslen)=0;
|
||||
*result='\0';
|
||||
return;
|
||||
}
|
||||
attr.c_lflag &= ~(ICANON) & ~(ECHO); /* canonical mode off, echo off */
|
||||
attr.c_cc[VMIN]=0;
|
||||
ires= tcsetattr(STDIN_FILENO,TCSANOW,&attr);
|
||||
if (ires!=0) {perror("error in terinq/tcsetattr ");}
|
||||
|
||||
do { chr=fgetc(stdin); } while (chr!=EOF);
|
||||
|
||||
for (i=0; i<p_len; i++)
|
||||
{ fputc(prompt[i], stderr);
|
||||
};
|
||||
|
||||
ires=fflush(stdin);
|
||||
ires=fflush(stderr);
|
||||
|
||||
*reslen=0;
|
||||
if (prompt[0]=='\0') { ntmo=10; }
|
||||
else { ntmo=200; }; /* wait 2 sec. for the first char */
|
||||
while (*reslen<r_len)
|
||||
{ chr=fgetc(stdin);
|
||||
if (chr==EOF)
|
||||
{ while ((chr==EOF) & (ntmo>0))
|
||||
{ usleep(10000); /* wait 10 ms */
|
||||
chr=fgetc(stdin);
|
||||
ntmo--;
|
||||
};
|
||||
if (chr==EOF) break;
|
||||
if (chr==10) {ntmo=10;} else {ntmo=100;}; /* wait 0.1 sec after LF, 1 sec else */
|
||||
};
|
||||
result[(*reslen)++]=(char)chr;
|
||||
if (chr==24) {(*reslen)=0;}; /* ctrl-X purges buffer */
|
||||
};
|
||||
if (result[(*reslen)-1]==10) {(*reslen)--;}; /* strip trailing LF */
|
||||
|
||||
ires=tcsetattr(STDIN_FILENO,TCSANOW,&atts); /* restore term. attributes */
|
||||
clearerr(stdin);
|
||||
if (ires!=0) {
|
||||
perror("error in terinq/tcsetattr ");
|
||||
}
|
||||
}
|
||||
|
||||
void F_FUN(sys_get_raw_key)(char *key, int *tmo, int k_len)
|
||||
{
|
||||
struct termios attr;
|
||||
int ires, ntmo, chr;
|
||||
|
||||
ires=tcgetattr(STDIN_FILENO,&attr);
|
||||
atts=attr; /* save term. attr. */
|
||||
if (ires!=0) {perror("***\n");}
|
||||
attr.c_lflag &= ~(ICANON) & ~(ECHO); /* canonical mode off, echo off */
|
||||
attr.c_cc[VMIN]=0;
|
||||
ires= tcsetattr(STDIN_FILENO,TCSANOW,&attr);
|
||||
if (ires!=0) {perror("***\n");}
|
||||
|
||||
ntmo=*tmo*100;
|
||||
chr=fgetc(stdin);
|
||||
if (chr==EOF) {
|
||||
while ((chr==EOF) & (ntmo>0)) {
|
||||
usleep(10000); /* wait 10 ms */
|
||||
chr=fgetc(stdin);
|
||||
ntmo--;
|
||||
}
|
||||
}
|
||||
if (chr==EOF) chr=0;
|
||||
|
||||
*key=chr;
|
||||
|
||||
ires=tcsetattr(STDIN_FILENO,TCSANOW,&atts); /* restore term. attributes */
|
||||
if (ires!=0) {perror("***\n");};
|
||||
}
|
||||
|
||||
20
tecs/sys_wait.f
Executable file
20
tecs/sys_wait.f
Executable file
@@ -0,0 +1,20 @@
|
||||
!!-----------------------------------------------------------------------------
|
||||
!!
|
||||
subroutine SYS_WAIT(SECONDS) !!
|
||||
!! ============================
|
||||
!! wait for SECONDS
|
||||
real SECONDS !! resolution should be better than 0.1 sec.
|
||||
|
||||
real tim, del
|
||||
|
||||
tim=secnds(0.0)
|
||||
1 del=seconds-secnds(tim)
|
||||
if (del .ge. 0.999) then
|
||||
call sleep(int(del))
|
||||
goto 1
|
||||
endif
|
||||
if (del .gt. 0) then
|
||||
call usleep(int(del*1E6))
|
||||
goto 1
|
||||
endif
|
||||
end
|
||||
4
tecs/tecs.bld
Normal file
4
tecs/tecs.bld
Normal file
@@ -0,0 +1,4 @@
|
||||
f90 -c -g tecs_plot.f90
|
||||
f77 -o tecs -g tecs_client.f tecs_for.f sys_aunix_c.c \
|
||||
tecs_plot.o sys_aunix.f -L. -ltecsl -L/data/lnslib/lib -lpgplot \
|
||||
-so_archive -lreadline -ltermcap -lX11 -lXm
|
||||
2553
tecs/tecs.c
Normal file
2553
tecs/tecs.c
Normal file
File diff suppressed because it is too large
Load Diff
3
tecs/tecs.tcl
Normal file
3
tecs/tecs.tcl
Normal file
@@ -0,0 +1,3 @@
|
||||
catch {evfactory del temperature} msg
|
||||
evfactory new temperature tecs
|
||||
SicsAlias temperature tt
|
||||
82
tecs/tecs_c.c
Normal file
82
tecs/tecs_c.c
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_time.h"
|
||||
#include "myc_mem.h"
|
||||
#include "tecs_cli.h"
|
||||
#include "tecs_c.h"
|
||||
|
||||
static pTecsClient conn=NULL;
|
||||
static char response[COC_RES_LEN];
|
||||
static char *rwCode="rwacs";
|
||||
static char *rdCode="rdacs";
|
||||
|
||||
char *TecsCmd(char *cmd) {
|
||||
char nbuf[64], *p, pbuf[4];
|
||||
int iret=-1, l;
|
||||
|
||||
p=strchr(cmd, ' ');
|
||||
if (p==NULL) {
|
||||
str_copy(nbuf, cmd);
|
||||
} else {
|
||||
l=p-cmd;
|
||||
if (l>=sizeof(nbuf)) l=sizeof(nbuf)-1;
|
||||
strncpy(nbuf, cmd, l+1);
|
||||
nbuf[l]='\0';
|
||||
while (*p>'\0' && *p<=' ') p++;
|
||||
if (*p=='\0') p=NULL;
|
||||
}
|
||||
if (p==NULL) {
|
||||
CocReset(conn);
|
||||
ERR_I(CocGetStr(conn, nbuf, pbuf, sizeof(pbuf)));
|
||||
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||
} else {
|
||||
CocReset(conn);
|
||||
ERR_I(CocPutStr(conn, nbuf, p));
|
||||
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||
}
|
||||
return response;
|
||||
OnError: return ErrMessage;
|
||||
}
|
||||
|
||||
char *TecsGet3(float *tset, float *texch, float *tsamp) {
|
||||
ERR_I(TeccGet3(conn, tset, texch, tsamp));
|
||||
return NULL;
|
||||
OnError: return ErrMessage;
|
||||
}
|
||||
|
||||
char *TecsSet(float temp) {
|
||||
ERR_I(TeccSet(conn, temp));
|
||||
return NULL;
|
||||
OnError: return ErrMessage;
|
||||
}
|
||||
|
||||
char *TecsInit(char *host, int port) {
|
||||
int iret;
|
||||
if (conn!=NULL) TeccClose(conn);
|
||||
NEW(conn, CocConn);
|
||||
if (host==NULL || *host=='\0') {
|
||||
ERR_I(iret=CocInitClient(conn, "", port, rwCode, 0, ""));
|
||||
} else {
|
||||
ERR_I(iret=CocInitClient(conn, host, port, rdCode, 0, ""));
|
||||
}
|
||||
if (iret==1) ErrShort("TECS_INIT: can not connect to TecsServer");
|
||||
return NULL;
|
||||
OnError:
|
||||
FREE(conn);
|
||||
return ErrMessage;
|
||||
}
|
||||
|
||||
int TecsIsOpen(void) {
|
||||
return(conn!=NULL);
|
||||
}
|
||||
|
||||
void TecsClose(void) {
|
||||
if (conn!=NULL) {
|
||||
TeccClose(conn);
|
||||
conn=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
8
tecs/tecs_c.h
Normal file
8
tecs/tecs_c.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/* prototypes for TASCOM */
|
||||
|
||||
char *TecsCmd(char *cmd);
|
||||
char *TecsGet3(float *tset, float *texch, float *tsamp);
|
||||
char *TecsSet(float temp);
|
||||
char *TecsInit(char *host, int port);
|
||||
int TecsIsOpen(void);
|
||||
void TecsClose(void);
|
||||
374
tecs/tecs_cli.c
Normal file
374
tecs/tecs_cli.c
Normal file
@@ -0,0 +1,374 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "myc_mem.h"
|
||||
#include "myc_err.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_time.h"
|
||||
#include "myc_fortran.h"
|
||||
#include "coc_util.h"
|
||||
#include "tecs_cli.h"
|
||||
#include "tecs_data.h"
|
||||
|
||||
int gethostname(char *name, int namelen);
|
||||
|
||||
static char response[COC_RES_LEN];
|
||||
static char *rwCode="rwacs";
|
||||
static char *rdCode="rdacs";
|
||||
|
||||
pTecsClient TeccInit(char *startcmd, int port) {
|
||||
CocConn *conn=NULL;
|
||||
char *code, host[64];
|
||||
int iret;
|
||||
|
||||
NEW(conn, CocConn);
|
||||
code=rwCode;
|
||||
if (startcmd[0]=='#') {
|
||||
gethostname(host, sizeof(host));
|
||||
if (0!=strcmp(startcmd+1, host)) code=rdCode;
|
||||
ERR_I(iret=CocInitClient(conn, startcmd+1, port, code, 0, ""));
|
||||
} else {
|
||||
ERR_I(iret=CocInitClient(conn, "", port, code, 0, startcmd));
|
||||
}
|
||||
if (iret==1) ErrShort("TECS_INIT: can not connect to TecsServer");
|
||||
return((pTecsClient)conn);
|
||||
OnError:
|
||||
if (conn!=NULL) FREE(conn);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
pTecsClient TeccStart(char *startcmd, char *host, int port) {
|
||||
CocConn *conn;
|
||||
char *code, *cmd, thishost[64];
|
||||
int iret;
|
||||
|
||||
NEW(conn, CocConn);
|
||||
code=rwCode;
|
||||
cmd=startcmd;
|
||||
if (host[0]!='\0') {
|
||||
gethostname(thishost, sizeof(thishost));
|
||||
if (0!=strcmp(thishost, host)) {
|
||||
code=rdCode;
|
||||
cmd="";
|
||||
}
|
||||
}
|
||||
ERR_I(iret=CocInitClient(conn, host, port, code, 0, cmd));
|
||||
if (iret==1) ErrShort("TECS_INIT: can not connect to TecsServer");
|
||||
return((pTecsClient)conn);
|
||||
OnError: return(NULL);
|
||||
}
|
||||
|
||||
int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) {
|
||||
int iret;
|
||||
|
||||
CocReset(conn);
|
||||
ERR_I(CocGetFloat(conn, "set", tC));
|
||||
ERR_I(CocGetFloat(conn, "tempX", tX));
|
||||
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);
|
||||
}
|
||||
|
||||
int TeccGet(pTecsClient conn, float *temp) {
|
||||
int iret;
|
||||
|
||||
CocReset(conn);
|
||||
ERR_I(CocGetFloat(conn, "tempP", temp));
|
||||
ERR_I(CocPutInt(conn, "readTemp", 1));
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
if (iret) ERR_MSG(response);
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccGetX(pTecsClient conn, float *tC, float *tP, float *tDif) {
|
||||
int iret;
|
||||
float tx;
|
||||
|
||||
CocReset(conn);
|
||||
CocReset(conn);
|
||||
ERR_I(CocGetFloat(conn, "set", tC));
|
||||
ERR_I(CocGetFloat(conn, "tx", &tx));
|
||||
ERR_I(CocGetFloat(conn, "tempP", tP));
|
||||
ERR_I(CocPutInt(conn, "readTemp", 1));
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
*tDif = *tC - tx;
|
||||
if (iret) ERR_MSG(response);
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp) {
|
||||
int iret;
|
||||
|
||||
CocReset(conn);
|
||||
ERR_I(CocPutFloat(conn, "set", temp));
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
if (iret) ERR_MSG(response);
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int TeccQuitServer(pTecsClient conn, int kill) {
|
||||
int iret, cnt;
|
||||
|
||||
ERR_I(iret=CocCheck(conn));
|
||||
if (iret>0) return iret;
|
||||
CocReset(conn);
|
||||
ERR_I(CocPutInt(conn, "quit", 1+kill));
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
if (iret) ERR_MSG(response);
|
||||
cnt=50;
|
||||
while (iret==0 && cnt>0) {
|
||||
CocDelay(100);
|
||||
ERR_I(iret=CocCheck(conn));
|
||||
cnt--;
|
||||
}
|
||||
if (iret==0) ERR_MSG("Does not quit within 5 seconds");
|
||||
return 0;
|
||||
OnError:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) {
|
||||
return(CocSetGetN(conn, "send", cmd, reply, replyLen));
|
||||
}
|
||||
|
||||
void TeccClose(pTecsClient conn) {
|
||||
if (conn!=NULL) {
|
||||
CocCloseClient(conn);
|
||||
FREE(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/* fortran wrappers --------------------------------------------------
|
||||
|
||||
reduced functionality:
|
||||
connection is static, so only one connection at a time may be opened
|
||||
|
||||
*/
|
||||
|
||||
#ifdef F_CHAR
|
||||
/* compile only when fortran c interface stuff is defined */
|
||||
|
||||
|
||||
static pTecsClient conn=NULL;
|
||||
|
||||
int F_FUN(tecs_set_par)(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
|
||||
char nbuf[64], pbuf[COC_CMD_LEN];
|
||||
int iret=-1;
|
||||
|
||||
STR_TO_C(nbuf, name);
|
||||
STR_TO_C(pbuf, par);
|
||||
|
||||
CocReset(conn);
|
||||
ERR_I(CocPutStr(conn, nbuf, pbuf));
|
||||
ERR_I(CocDoIt(conn, response, sizeof(response)));
|
||||
if (*show) {
|
||||
printf("%s", response);
|
||||
}
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_get_par)(F_CHAR(name), F_CHAR(par), int *show, int name_len, int par_len) {
|
||||
char *b, nbuf[64], pbuf[COC_RES_LEN];
|
||||
int iret=-1;
|
||||
|
||||
STR_TO_C(nbuf, name);
|
||||
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));
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_get_mult)(F_CHAR(names), int *time, int *nvalues, float values[], int names_len) {
|
||||
char *b, nbuf[64], pbuf[COC_RES_LEN];
|
||||
char *nams, nam[32];
|
||||
int i;
|
||||
|
||||
STR_TO_C(nbuf, names);
|
||||
CocReset(conn);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_init)(F_CHAR(startcmd), int *port, int startcmd_len) {
|
||||
char sbuf[132];
|
||||
|
||||
STR_TO_C(sbuf, startcmd);
|
||||
ERR_P(conn=TeccInit(sbuf, *port));
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_start)(F_CHAR(startcmd), F_CHAR(host), int *port, int startcmd_len, int host_len) {
|
||||
char sbuf[132], hbuf[64];
|
||||
|
||||
STR_TO_C(sbuf, startcmd);
|
||||
STR_TO_C(hbuf, host);
|
||||
ERR_P(conn=TeccStart(sbuf, hbuf, *port));
|
||||
if (conn->fd<0) return 1;
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_rights)(int write) {
|
||||
if (write) {
|
||||
ERR_I(CocSendMagic(conn, rwCode));
|
||||
} else {
|
||||
ERR_I(CocSendMagic(conn, rdCode));
|
||||
}
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_get)(float *temp) {
|
||||
ERR_I(TeccGet(conn, temp));
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_get3)(float *t1, float *t2, float *t3) {
|
||||
ERR_I(TeccGet3(conn, t1, t2, t3));
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_set)(float *temp) {
|
||||
ERR_I(TeccSet(conn, *temp));
|
||||
return 0;
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_is_open)(void) {
|
||||
return(conn!=NULL);
|
||||
}
|
||||
|
||||
void F_FUN(tecs_close)(void) {
|
||||
TeccClose(conn);
|
||||
conn=NULL;
|
||||
}
|
||||
|
||||
int F_FUN(tecs_quit_server)(int *kill) {
|
||||
int iret;
|
||||
|
||||
ERR_I(iret=TeccQuitServer(conn, *kill));
|
||||
return(iret);
|
||||
OnError: return(-1);
|
||||
}
|
||||
|
||||
int F_FUN(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);
|
||||
}
|
||||
|
||||
int F_FUN(tecs_get_data)(F_CHAR(names), int *startTime, int *endTime, int *step, int *tbase
|
||||
, float xdata[], float ydata[], int *maxLen, int *width
|
||||
, int retLen[], int names_len) {
|
||||
char nam[64];
|
||||
char str[128];
|
||||
float offset, fact, *py, data[8192];
|
||||
int i, j, k, l, iret;
|
||||
|
||||
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, "grapar", str));
|
||||
ERR_I(CocGetArray(conn, "gradata", data, sizeof(data)/sizeof(float)));
|
||||
ERR_I(iret=CocDoIt(conn, response, sizeof(response)));
|
||||
if (iret) ERR_MSG(response);
|
||||
py=data;
|
||||
for (i=0; i < *width; i++) {
|
||||
l=*py; py++;
|
||||
if (l>0) {
|
||||
fact = (float)(*endTime - *startTime) / l;
|
||||
}
|
||||
offset = *startTime - *tbase;
|
||||
k = i * *maxLen;
|
||||
for (j=0; j<l; j++) {
|
||||
if (py[j] != DATA_GAP) {
|
||||
ydata[k] = py[j];
|
||||
xdata[k] = offset + j * fact;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
py+=l;
|
||||
retLen[i] = k - i * *maxLen;
|
||||
}
|
||||
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
|
||||
65
tecs/tecs_cli.h
Normal file
65
tecs/tecs_cli.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef _TECS_CLI_H_
|
||||
#define _TECS_CLI_H_
|
||||
|
||||
#include "coc_client.h"
|
||||
/*
|
||||
tecs_cli.h: tecs client interface routines
|
||||
|
||||
M. Zolliker March 2000
|
||||
*/
|
||||
|
||||
typedef CocConn *pTecsClient;
|
||||
|
||||
|
||||
pTecsClient TeccInit(char *server, int port);
|
||||
/* init tecs client (connect to server) */
|
||||
|
||||
int TeccGet(pTecsClient conn, float *temp);
|
||||
/* get temperature */
|
||||
|
||||
int TeccGetX(pTecsClient conn, float *tC, float *tP, float *tDif);
|
||||
/* get controlled temperature */
|
||||
|
||||
int TeccGet3(pTecsClient conn, float *tSet, float *tExch, float *tSamp);
|
||||
/* get temperatures */
|
||||
|
||||
int TeccSet(pTecsClient conn, float temp);
|
||||
/* set temperature */
|
||||
|
||||
int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen);
|
||||
/* send a command transparently to the controller
|
||||
replyLen is the maximal length of reply */
|
||||
|
||||
void TeccClose(pTecsClient conn);
|
||||
/* close connection and free ressources */
|
||||
|
||||
int TeccQuitServer(pTecsClient conn, int kill);
|
||||
/* quit the server process, kill = 0: restart if possible */
|
||||
|
||||
/* Fortran interface:
|
||||
|
||||
integer function TECS_INIT(STARTCMD, PORT) - open server connection
|
||||
logical function TECS_IS_OPEN () - check if tecs is open
|
||||
integer function TECS_GET3(SET_T, REG_T, SAM_T) - read 3 temperatures
|
||||
integer function TECS_WAIT() - wait for end of configuration
|
||||
integer function TECS_SET (TEMP) - set temperature target
|
||||
integer function TECS_GET (TEMP) - get sample temperature
|
||||
integer function TECS_QUIT_SERVER () - force server to quit
|
||||
integer function TECS_GET_PAR (NAME, PAR) - get parameter
|
||||
integer function TECS_SET_PAR (NAME, PAR) - set parameter
|
||||
integer function TECS_SEND (CMND, REPLY) - send command to LakeShore
|
||||
subroutine TECS_CLOSE - close connection to tecs
|
||||
|
||||
character*(*) STARTCMD - command to start server (no restart if empty)
|
||||
integer PORT - port number
|
||||
real SET_T,REG_T,SAM_T - set-temperature, regulation temperature, sample temperature
|
||||
real TEMP - temperature
|
||||
character*(*) NAME - parameter name
|
||||
character*(*) PAR - parameter value
|
||||
character*(*) CMND - raw command
|
||||
character*(*) REPLY - reply to command
|
||||
|
||||
integer return values are error codes (negative means error, like in most C system routines)
|
||||
*/
|
||||
|
||||
#endif /* _TECS_CLI_H_ */
|
||||
364
tecs/tecs_client.f
Normal file
364
tecs/tecs_client.f
Normal file
@@ -0,0 +1,364 @@
|
||||
program tecs_client
|
||||
|
||||
character device*32, start*80, line*80, cmd*16, par*80, response*1024
|
||||
character inst*64, host*64, user*1, pcod*1
|
||||
integer i,j,k,iret,l,port
|
||||
integer maxfiles
|
||||
real wait
|
||||
parameter (maxfiles=10)
|
||||
integer nfiles/0/, mfiles/0/, idx, luns(0:maxfiles-1)
|
||||
character cmdpar*128
|
||||
character prompt*32/'tecs>'/
|
||||
integer promptlen/6/
|
||||
logical oneCommand
|
||||
character logarg*4/'25'/
|
||||
character defcmd*8/'status'/
|
||||
|
||||
! functions
|
||||
integer tecs_get_par, tecs_quit_server, tecs_set_par, tecs_watch_log
|
||||
integer tecs_get, tecs_rights, show_log, instr_host, tecs_start
|
||||
|
||||
call sys_loadenv
|
||||
call sys_getenv('CHOOSER_GDEV', line)
|
||||
if (line .ne. ' ') then
|
||||
call sys_setenv('PGPLOT_DEV', '/'//line)
|
||||
endif
|
||||
|
||||
call sys_get_cmdpar(line, l)
|
||||
|
||||
if (l .ne. 0) then
|
||||
if (line(1:l) .eq. 'off' .or. line(1:l) .eq. 'OFF') then
|
||||
iret=tecs_start(' ', ' ', 9753)
|
||||
if (iret .lt. 0) goto 91
|
||||
iret=tecs_quit_server(0)
|
||||
if (iret .lt. 0) goto 91
|
||||
goto 99
|
||||
endif
|
||||
oneCommand=.true.
|
||||
port=instr_host(line, inst, host, user, pcod)
|
||||
else
|
||||
oneCommand=.false.
|
||||
port=0
|
||||
endif
|
||||
|
||||
call sys_getenv('TECS_START', start)
|
||||
if (port .gt. 0) then
|
||||
if (port .eq. 1) port=9753
|
||||
call str_trim(start, start, k)
|
||||
call str_trim(inst, inst, i)
|
||||
if (start .ne. ' ') then
|
||||
start=start(1:k)//' '//inst(1:i)
|
||||
endif
|
||||
iret=tecs_start(start, host, port)
|
||||
oneCommand=.false.
|
||||
prompt='tecs/'//inst(1:i)//'> '
|
||||
promptlen=i+7
|
||||
else
|
||||
iret=tecs_start(start, ' ', 9753)
|
||||
endif
|
||||
if (iret .ne. 0) goto 90
|
||||
|
||||
if (oneCommand) goto 11
|
||||
|
||||
print *
|
||||
print *,'Tecs Client'
|
||||
print *,'-----------'
|
||||
print *
|
||||
print *,'set <temp> set temperature'
|
||||
print *,'send <command> direct command to LSC340'
|
||||
print *,'device <device> set cryo device'
|
||||
print *,'<parameter> show parameter'
|
||||
print *,'<parameter> <value> set parameter'
|
||||
print *
|
||||
print *,'<empty line> show summary'
|
||||
print *,'plot <var> chart for temperature and <var>'
|
||||
1 ,' var = P (default), He, Aux'
|
||||
print *,'log <n> show last n lines of logfile'
|
||||
print *,'remote set to remote mode'
|
||||
print *,'reset reset alarms'
|
||||
print *,'kill shut down TecsServer'
|
||||
print *,'restart restart TecsServer'
|
||||
print *,'exit,quit exit tecs client'
|
||||
print *,'help show list of parameters and cryo devices'
|
||||
print *
|
||||
|
||||
l=0
|
||||
1 if (oneCommand) goto 99
|
||||
if (nfiles .gt. 0) then
|
||||
read(luns(idx), '(q,a)', err=22,end=22) l, line
|
||||
print '(x,2a)', prompt(1:promptlen),line(1:max(1,l))
|
||||
else
|
||||
call sys_rd_line(line, l, prompt(1:promptlen))
|
||||
if (l .lt. 0) goto 99
|
||||
endif
|
||||
if (line(1:1) .eq. '@') then
|
||||
nfiles=nfiles+1
|
||||
idx=mod(nfiles, maxfiles)
|
||||
if (nfiles .gt. mfiles+maxfiles) then ! close files which are too much nested
|
||||
close(luns(idx))
|
||||
mfiles=nfiles-maxfiles
|
||||
else
|
||||
call sys_get_lun(luns(idx))
|
||||
endif
|
||||
call sys_open(luns(idx), line(2:), 'R', i)
|
||||
if (i .ne. 0) then
|
||||
print *,'error opening ',line(2:)
|
||||
close(luns(idx))
|
||||
call sys_free_lun(luns(idx))
|
||||
nfiles=nfiles-1
|
||||
idx=mod(nfiles, maxfiles)
|
||||
endif
|
||||
goto 1
|
||||
endif
|
||||
11 l=l+1
|
||||
line(l:l)=' '
|
||||
cmd=' '
|
||||
k=0
|
||||
do j=1,l
|
||||
if (k .gt. 0 .and. line(j:j) .eq. '=') line(j:j)=' '
|
||||
if (line(j:j) .gt. ' ') then
|
||||
k=k+1
|
||||
cmd(k:k)=line(j:j)
|
||||
if (cmd(k:k) .ge. 'A' .and. cmd(k:k) .le. 'Z') then ! set to lowercase
|
||||
cmd(k:k)=char(ichar(cmd(k:k))+32)
|
||||
endif
|
||||
elseif (k .gt. 0) then ! end of command
|
||||
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
|
||||
enddo
|
||||
|
||||
if (k .ne. 0) then
|
||||
print *,'command too long'
|
||||
goto 1
|
||||
endif
|
||||
|
||||
! empty command
|
||||
|
||||
12 cmd=defcmd
|
||||
|
||||
2 continue ! parameterless command
|
||||
|
||||
defcmd='status'
|
||||
|
||||
if (cmd .eq. 'kill') then
|
||||
iret=tecs_quit_server(1)
|
||||
if (iret .lt. 0) goto 19
|
||||
if (iret .gt. 0) then
|
||||
print *,'tecs server is not running'
|
||||
endif
|
||||
else if (cmd .eq. 'restart') then
|
||||
iret=tecs_quit_server(0)
|
||||
if (iret .lt. 0) goto 19
|
||||
if (iret .gt. 0) then
|
||||
print *,'tecs server is not running'
|
||||
endif
|
||||
else if (cmd .eq. 'remote') then
|
||||
iret=tecs_set_par('remoteMode', '2', 2)
|
||||
if (iret .lt. 0) goto 19
|
||||
else if (cmd .eq. 'reset') then
|
||||
iret=tecs_set_par('relay', '0', 2)
|
||||
if (iret .lt. 0) goto 19
|
||||
elseif (cmd .eq. 'rwacs') then
|
||||
iret=tecs_rights(1)
|
||||
if (iret .lt. 0) goto 19
|
||||
elseif (cmd .eq. 'exit' .or. cmd .eq. 'quit') then
|
||||
goto 99
|
||||
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
|
||||
goto 11
|
||||
elseif (cmd .eq. 'plot') then
|
||||
call tecs_plot(' ')
|
||||
elseif (cmd .eq. 'help') then
|
||||
print *
|
||||
print *,'Writeable parameters:'
|
||||
print *
|
||||
print *,'set temperature set-point'
|
||||
print *,'device temperature device'
|
||||
print *,'controlMode control on: 0: heat exchanger, '
|
||||
1 ,'1: sample, 2: second loop'
|
||||
print *,'maxPower heater max. power'
|
||||
print *,'ramp ramp in K/min. (0: no ramp)'
|
||||
print *,'prop PID gain'
|
||||
print *,'int PID integration time: 1000/int sec'
|
||||
print *,'deriv PID derivation term'
|
||||
print *,'maxShift maximum (set-tempH) for controlMode=2'
|
||||
print *,'int2 integration time (sec) for controlMode=2'
|
||||
! print *,'remoteMode 1: local, 2: remote'
|
||||
print *
|
||||
print *,'Read only parameters:'
|
||||
print *
|
||||
print *,'Tm main temperature'
|
||||
print *,'Ts sample temperature'
|
||||
print *,'Tr set-point on regulation'
|
||||
print *,'tLimit temperature limit'
|
||||
print *,'helium helium level'
|
||||
print *,'htr heater current percentage'
|
||||
print *,'resist heater resistance'
|
||||
print *,'logfile name of the logfile'
|
||||
print *
|
||||
print *,'Ta,Tb,Tc,Td values of channels A,B,C,D'
|
||||
print *
|
||||
print *,'devhelp list available temperature devices'
|
||||
print *
|
||||
elseif (cmd .eq. 'log') then
|
||||
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
|
||||
else
|
||||
iret=tecs_get_par(cmd, response, 2)
|
||||
if (iret .lt. 0) goto 19
|
||||
if (oneCommand .and. response .eq. ' ') goto 92
|
||||
endif
|
||||
goto 1
|
||||
|
||||
3 continue ! command with parameter
|
||||
|
||||
defcmd='status'
|
||||
|
||||
if (cmd .eq. 'log') then
|
||||
if (show_log(par) .gt. 0) then
|
||||
defcmd='log'
|
||||
endif
|
||||
logarg=' '
|
||||
elseif (cmd .eq. 'plot') then
|
||||
call str_lowcase(par, par)
|
||||
call str_upcase(par(1:1), par(1:1))
|
||||
call tecs_plot(par)
|
||||
elseif (cmd .eq. 'watch') then
|
||||
iret=tecs_watch_log(par)
|
||||
if (iret .lt. 0) goto 19
|
||||
elseif (cmd .eq. 'wait') then
|
||||
read(par, *, err=17,end=17) wait
|
||||
call sys_wait(wait*60.0)
|
||||
17 continue
|
||||
else
|
||||
iret=tecs_set_par(cmd, par, 2)
|
||||
if (iret .lt. 0) goto 19
|
||||
if (oneCommand .and. par .eq. ' ') goto 92
|
||||
endif
|
||||
goto 1
|
||||
|
||||
19 if (iret .eq. -2) then
|
||||
call tecs_write_msg(6)
|
||||
if (oneCommand) goto 90
|
||||
else
|
||||
call tecs_write_error(6)
|
||||
endif
|
||||
goto 1
|
||||
|
||||
22 continue ! end of file
|
||||
close(luns(idx))
|
||||
call sys_free_lun(luns(idx))
|
||||
nfiles=nfiles-1
|
||||
if (nfiles .lt. mfiles) then
|
||||
print *,'too many files nested'
|
||||
mfiles=0
|
||||
nfiles=0
|
||||
endif
|
||||
idx=mod(nfiles,maxfiles)
|
||||
goto 1
|
||||
|
||||
90 call tecs_write_error(6)
|
||||
92 call exit(40) ! Abort
|
||||
|
||||
91 if (iret .lt. 0) then
|
||||
call tecs_write_error(6)
|
||||
endif
|
||||
99 end
|
||||
|
||||
|
||||
integer function show_log(lines)
|
||||
|
||||
character*(*) lines
|
||||
|
||||
integer i,l
|
||||
character str*8192
|
||||
|
||||
! functions
|
||||
integer tecs_get_par, tecs_set_par
|
||||
|
||||
if (lines .ne. ' ') then
|
||||
l=tecs_set_par('logstart', lines, 0)
|
||||
print *,'line: ',lines
|
||||
print *
|
||||
endif
|
||||
|
||||
show_log=tecs_get_par('logline', str, 1)
|
||||
end
|
||||
|
||||
|
||||
subroutine TECS_WRITE_ERROR(IOLUN) !!
|
||||
!! ==================================
|
||||
!!
|
||||
!! write out error message of last error and stack info
|
||||
!!
|
||||
implicit none
|
||||
|
||||
integer IOLUN !! logical unit for output
|
||||
|
||||
external tecs_err_routine
|
||||
|
||||
call err_set_outrtn(tecs_err_routine, iolun)
|
||||
call err_show('Error in TECS')
|
||||
end
|
||||
|
||||
|
||||
subroutine TECS_WRITE_MSG(IOLUN) !!
|
||||
!! ================================
|
||||
!!
|
||||
!! write out error message of last error without stack info
|
||||
!!
|
||||
implicit none
|
||||
|
||||
integer IOLUN !! logical unit for output
|
||||
|
||||
external tecs_err_routine
|
||||
|
||||
call err_set_outrtn(tecs_err_routine, iolun)
|
||||
call err_short
|
||||
end
|
||||
|
||||
|
||||
SUBROUTINE TECS_ERR_ROUTINE (LUN, TEXT)
|
||||
! =======================================
|
||||
!
|
||||
! routine called from C
|
||||
!
|
||||
implicit none
|
||||
c--------------------------------------------------------------
|
||||
c Define the dummy arguments
|
||||
byte text(128)
|
||||
integer lun
|
||||
c--------------------------------------------------------------
|
||||
integer i, j
|
||||
c--------------------------------------------------------------
|
||||
do i=1,128
|
||||
if (text(i) .eq. 0) then
|
||||
write(lun, '(x,128a1)') (text(j), j=1,i-1)
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
! no terminating ASCII NUL found
|
||||
write(lun, *) 'error in TECS_ERR_ROUTINE: illegal error text'
|
||||
end
|
||||
558
tecs/tecs_data.c
Normal file
558
tecs/tecs_data.c
Normal file
@@ -0,0 +1,558 @@
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <strings.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!=strcasecmp(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 if (t == 2) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
int DataGetMult(char *names, int startTime, int endTime, int step, int stdStep, float *data, int data_len) {
|
||||
Base base;
|
||||
Set *set, *s;
|
||||
int stp, minStep, period, s1;
|
||||
char *nams, nam[32];
|
||||
int p, l, n, i, j, siz1, siz2, halfsiz, start;
|
||||
|
||||
base.head = NULL;
|
||||
period = endTime - startTime;
|
||||
if (period<=0) period=1;
|
||||
n=0; nams = names;
|
||||
while (nams != NULL) { /* count names */
|
||||
nams = str_split(nam, nams, ' ');
|
||||
if (nam[0] != '\0') n++;
|
||||
}
|
||||
|
||||
stp=step;
|
||||
if (stp<stdStep) stp=stdStep;
|
||||
nams=names;
|
||||
while (nams!=NULL) { /* create sets for data not in memory */
|
||||
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);
|
||||
if (set != NULL) set->end = start;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (base.head != NULL) { /* load if needed */
|
||||
Load(&base, startTime, endTime, stdStep);
|
||||
}
|
||||
p=0;
|
||||
nams=names;
|
||||
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) { /* empty array */
|
||||
data[p++]=0;
|
||||
} 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 + n > data_len) { /* check if enough space */
|
||||
halfsiz = ((data_len - p) / n - 1) / 2;
|
||||
}
|
||||
}
|
||||
siz1 = (s1 - startTime) * halfsiz / period * 2;
|
||||
siz2 = halfsiz * 2 - siz1;
|
||||
s1 = startTime + (siz1 * period + halfsiz) / halfsiz / 2;
|
||||
p++;
|
||||
if (siz1 > 0) {
|
||||
halfsiz = (s1 - startTime) / set->step / 2;
|
||||
if (halfsiz * 2 < siz1 && halfsiz > 0) {
|
||||
ERR_I(GetSet(set, startTime, s1, halfsiz*2, data+p));
|
||||
j = siz1 - 1;
|
||||
for (i = halfsiz * 2-1; i >= 0; i--) { /* expand data */
|
||||
while (j > siz1 / 2 * i / halfsiz) {
|
||||
data[p+j]=DATA_GAP; j--;
|
||||
}
|
||||
data[p+j]=data[p+i]; j--;
|
||||
}
|
||||
} else {
|
||||
ERR_I(GetSet(set, startTime, s1, siz1, data+p));
|
||||
}
|
||||
l=siz1;
|
||||
} else {
|
||||
l=0;
|
||||
}
|
||||
if (siz2 > 0) {
|
||||
ERR_I(GetSet(s, s1, endTime, siz2, data+p+siz1));
|
||||
l+=siz2;
|
||||
}
|
||||
data[p-1]=l;
|
||||
p+=l;
|
||||
}
|
||||
n--;
|
||||
}
|
||||
}
|
||||
FreeBase(&base);
|
||||
return p;
|
||||
OnError:
|
||||
return -1;
|
||||
}
|
||||
49
tecs/tecs_data.h
Normal file
49
tecs/tecs_data.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#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 DataGetMult(char *names, int startTime, int endTime, int step, int stdStep, float *data, int data_len);
|
||||
/*
|
||||
get multiple datasets
|
||||
*/
|
||||
|
||||
/*
|
||||
define DATA_UNDEF as a binary and decimal well defined, hopefully rarely used number
|
||||
*/
|
||||
#define DATA_UNDEF MYC_NAN
|
||||
#define DATA_GAP (MYC_NAN*2)
|
||||
|
||||
#endif /* TECS_DATA_H_ */
|
||||
14
tecs/tecs_dlog.inc
Normal file
14
tecs/tecs_dlog.inc
Normal file
@@ -0,0 +1,14 @@
|
||||
integer version, recs, mdat, recl
|
||||
parameter (version=106, recs=1024, mdat=4, recl=mdat*recs)
|
||||
integer step,size,dirlen
|
||||
parameter (step=5, size=8*24*3600/step, dirlen=size/recs+1)
|
||||
real undef
|
||||
parameter (undef=-65535.0)
|
||||
|
||||
integer lunw, lunr, wrec, rrec
|
||||
integer vers, stim, etim
|
||||
logical update
|
||||
real wdat(mdat,0:recs-1), rdat(mdat,0:recs-1)
|
||||
integer wdir(0:dirlen-1), rdir(0:dirlen-1)
|
||||
common/tecs_dlog_inc/ lunw, lunr, wrec, rrec
|
||||
1, vers, stim, etim, update, wdat, rdat, wdir, rdir
|
||||
231
tecs/tecs_for.f
Normal file
231
tecs/tecs_for.f
Normal file
@@ -0,0 +1,231 @@
|
||||
SUBROUTINE TECS_FOR ! File TAS_SRC:[TECS]TECS_FOR.FOR
|
||||
c ===================
|
||||
c
|
||||
cdec$ ident 'V01D'
|
||||
c------------------------------------------------------------------------------
|
||||
c Fortran-Interface to the TECS Client
|
||||
c
|
||||
c M. Zolliker, March 2000
|
||||
c Updates:
|
||||
c V01A 21-Mar-2000 DM. Integrate into TASMAD
|
||||
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 dependent file
|
||||
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------------------------------------------------------------------------------
|
||||
c
|
||||
c For a description of the public interface:
|
||||
c on VMS: search tecs_for.for "!'''!" (''' may be omitted)
|
||||
c on Unix: grep !"!" tecs_for.for
|
||||
c
|
||||
c Public routines in this Module:
|
||||
c
|
||||
c subroutine TECS_OPEN (LUN, INIT, IRET) - open connection to tecs, if not yet open
|
||||
c subroutine TECS_GET_T (IOLUN, TEMP, IRET) - read the temperature, wait if tecs is configuring
|
||||
c subroutine TECS_WRITE_ERROR (IOLUN) - write out last occured error in TECS_x routines
|
||||
c
|
||||
c For internal use only:
|
||||
c
|
||||
c subroutine TECS_FOR - dummy entry point to get module name
|
||||
c in library to match the file name.
|
||||
c subroutine TECS_ERR_ROUTINE (LUN, TEXT) - (for internal use only)
|
||||
c
|
||||
!!------------------------------------------------------------------------------
|
||||
!! C Routines with Fortran interface (see TECS_CLI.C):
|
||||
!!
|
||||
!! integer function TECS_SET (TEMP) - set temperature target
|
||||
!! integer function TECS_GET (TEMP) - get sample temperature
|
||||
!! integer function TECS_QUIT_SERVER () - force server to quit
|
||||
!! integer function TECS_GET_PAR (NAME, PAR) - get parameter
|
||||
!! integer function TECS_SET_PAR (NAME, PAR) - set parameter
|
||||
!! integer function TECS_SEND (CMND, REPLY) - send command to LakeShore
|
||||
!! subroutine TECS_CLOSE - close connection to tecs
|
||||
!!
|
||||
!! real TEMP
|
||||
!! character*(*) NAME, PAR, CMND, REPLY
|
||||
!!
|
||||
!! integer return values are error codes (negative means error, like in most C system routines)
|
||||
!!
|
||||
!
|
||||
! C routines only for internal use in TECS_FOR.FOR:
|
||||
!
|
||||
! integer function TECS_INIT(STARTCMD, PORT) - open server connection
|
||||
! logical function TECS_IS_OPEN () - check if tecs is open
|
||||
! integer function TECS_GET3(SET_T, REG_T, SAM_T) - read 3 temperatures
|
||||
! integer function TECS_WAIT() - wait for end of configuration
|
||||
!
|
||||
! character*(*) STARTCMD
|
||||
! integer PORT
|
||||
! real SET_T,REG_T,SAM_T
|
||||
c------------------------------------------------------------------------------
|
||||
implicit none
|
||||
stop 'TECS_FOR: do not call module header'
|
||||
end
|
||||
!!------------------------------------------------------------------------------
|
||||
!! Fortran routines in this file:
|
||||
!!
|
||||
SUBROUTINE TECS_OPEN(LUN, INIT, IRET) !!
|
||||
!! =====================================
|
||||
!!
|
||||
!! Open connection to the Tecs Server, if not yet done.
|
||||
!! (a) LUN==0: INIT is the start command which should contain "-p <portnumber>"
|
||||
!! (b) LUN/=0: INIT is the file specification where to read port number and start command
|
||||
!!
|
||||
c------------------------------------------------------------------------------
|
||||
implicit none
|
||||
|
||||
c--------------------------------------------------------------
|
||||
c Define the dummy arguments
|
||||
integer LUN !! logical number for reading init file
|
||||
character*(*) INIT !! file specification or start command
|
||||
integer IRET !! iret<0 means error
|
||||
c--------------------------------------------------------------
|
||||
integer ios, port, i
|
||||
character*128 startcmd
|
||||
|
||||
! functions:
|
||||
integer tecs_init
|
||||
logical tecs_is_open
|
||||
c--------------------------------------------------------------
|
||||
|
||||
if (tecs_is_open()) then
|
||||
iret=1 ! already open
|
||||
return
|
||||
endif
|
||||
|
||||
port=0
|
||||
|
||||
if (lun .eq. 0) then
|
||||
|
||||
c extract the port number from the start command
|
||||
|
||||
i=index(init, '-p ')
|
||||
if (i .eq. 0) i=index(init, '-P ')
|
||||
if (i .ne. 0) then
|
||||
read(init(min(len(init),i+3):),*,iostat=ios) port
|
||||
endif
|
||||
|
||||
if (port .eq. 0) port=9753
|
||||
|
||||
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
|
||||
|
||||
c if INIT exists, read it to get the port number and the start command
|
||||
|
||||
startcmd=' '
|
||||
|
||||
call sys_open(lun, init, 'R', ios)
|
||||
if (ios .eq. 0) read (lun, *, iostat=ios) port
|
||||
if (ios .eq. 0) read (lun, *, iostat=ios) ! skip options line
|
||||
if (ios .eq. 0) read (lun, '(a)', iostat=ios) startcmd
|
||||
close(lun)
|
||||
if (ios .ne. 0) then
|
||||
iret=-2
|
||||
call err_msg('TECS_OPEN: init file not found')
|
||||
return
|
||||
endif
|
||||
if (port .eq. 0) port=9753
|
||||
iret=tecs_init(startcmd, port)
|
||||
|
||||
endif
|
||||
end
|
||||
|
||||
SUBROUTINE TECS_GET_T (IOLUN, TEMP, IRET) !!
|
||||
!! =========================================
|
||||
!!
|
||||
!! Get temperatures and wait if TECS is configuring
|
||||
!!
|
||||
implicit none
|
||||
|
||||
c Define the dummy arguments
|
||||
|
||||
integer IOLUN !! unit to write informational messages
|
||||
real*4 TEMP(4) !! TASMAD temperature array: set-temp, regulation, sample, aux-temp
|
||||
integer IRET !! IRET=0: o.k., IRET<0: error
|
||||
c------------------------------------------------------------------------------
|
||||
integer tecs_get3, tecs_wait
|
||||
external tecs_get3, tecs_wait
|
||||
c------------------------------------------------------------------------------
|
||||
iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
|
||||
if (iret .lt. 0) then
|
||||
call err_txt('tecs_get_3'//char(10)//'tecs_get_t')
|
||||
return
|
||||
endif
|
||||
if (iret .gt. 0) then
|
||||
! write(iolun, *) 'configuring temperature controller ...'
|
||||
! iret=tecs_wait()
|
||||
! if (iret .lt. 0) then
|
||||
! call err_txt('tecs_wait'//char(10)//'tecs_get_t')
|
||||
! return
|
||||
! endif
|
||||
! write(iolun, *) '... done'
|
||||
! iret=tecs_get3(temp(1), temp(3), temp(2)) ! temp(2) and temp(3) are exchanged in MSHOWT
|
||||
! if (iret .lt. 0) then
|
||||
! call err_txt('tecs_get3(2)'//char(10)//'tecs_get_t')
|
||||
! return
|
||||
! endif
|
||||
endif
|
||||
temp(4)=0.0 ! no auxilliary sensor
|
||||
end
|
||||
|
||||
subroutine TECS_WRITE_ERROR(IOLUN) !!
|
||||
!! ==================================
|
||||
!!
|
||||
!! write out error message of last error and stack info
|
||||
!!
|
||||
implicit none
|
||||
|
||||
integer IOLUN !! logical unit for output
|
||||
|
||||
external tecs_err_routine
|
||||
|
||||
call err_set_outrtn(tecs_err_routine, iolun)
|
||||
call err_show('Error in TECS')
|
||||
end
|
||||
|
||||
|
||||
subroutine TECS_WRITE_MSG(IOLUN) !!
|
||||
!! ================================
|
||||
!!
|
||||
!! write out error message of last error without stack info
|
||||
!!
|
||||
implicit none
|
||||
|
||||
integer IOLUN !! logical unit for output
|
||||
|
||||
external tecs_err_routine
|
||||
|
||||
call err_set_outrtn(tecs_err_routine, iolun)
|
||||
call err_short
|
||||
end
|
||||
|
||||
|
||||
SUBROUTINE TECS_ERR_ROUTINE (LUN, TEXT)
|
||||
! =======================================
|
||||
!
|
||||
! routine called from C
|
||||
!
|
||||
implicit none
|
||||
c--------------------------------------------------------------
|
||||
c Define the dummy arguments
|
||||
byte text(128)
|
||||
integer lun
|
||||
c--------------------------------------------------------------
|
||||
integer i, j
|
||||
c--------------------------------------------------------------
|
||||
do i=1,128
|
||||
if (text(i) .eq. 0) then
|
||||
write(lun, '(x,128a1)') (text(j), j=1,i-1)
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
! no terminating ASCII NUL found
|
||||
write(lun, *) 'error in TECS_ERR_ROUTINE: illegal error text'
|
||||
end
|
||||
208
tecs/tecs_lsc.c
Normal file
208
tecs/tecs_lsc.c
Normal file
@@ -0,0 +1,208 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "myc_err.h"
|
||||
#include "coc_logfile.h"
|
||||
#include "coc_server.h"
|
||||
#include "tecs_lsc.h"
|
||||
#include "myc_str.h"
|
||||
|
||||
#define MAX_PAR 16
|
||||
#define MAX_ARG 9
|
||||
|
||||
int LscEqPar(char *par, char *res) {
|
||||
char *p, *r, pbuf[SER_BUF_LEN], rbuf[SER_BUF_LEN];
|
||||
int i,n,i1,i2;
|
||||
float f1, f2;
|
||||
|
||||
p=par;
|
||||
r=res;
|
||||
while (p!=NULL) {
|
||||
if (r==NULL) {
|
||||
return(0);
|
||||
}
|
||||
p=str_split(pbuf, p, ',');
|
||||
str_trim(pbuf, pbuf, sizeof(pbuf));
|
||||
r=str_split(rbuf, r, ',');
|
||||
str_trim(rbuf, rbuf, sizeof(rbuf));
|
||||
if (pbuf[0]!='\0' && 0!=strcasecmp(pbuf, rbuf)) {
|
||||
i1=sscanf(pbuf, "%f", &f1);
|
||||
i2=sscanf(rbuf, "%f", &f2);
|
||||
if (i1!=1 || i2!=1 || abs(f1-f2)>1e-4+abs(f1)*5e-6) {
|
||||
logfileOut(LOG_INFO, "%s#%s\n", pbuf, rbuf);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
#define nLIST 30
|
||||
|
||||
char *LscCmd(SerChannel *ser, const char *cmds) {
|
||||
va_list ap;
|
||||
char *blank, *colon, *qu, *res;
|
||||
const char *p, *this, *next, *cmd_ptr, *retreq;
|
||||
const char *list[nLIST];
|
||||
char seg[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN];
|
||||
char cmd[SER_BUF_LEN];
|
||||
char varname[32];
|
||||
DeclStrBuf(sbuf, SER_BUF_LEN);
|
||||
int nres, i, j, response;
|
||||
|
||||
nres=0;
|
||||
response=0;
|
||||
this=cmds;
|
||||
while (this!=NULL) {
|
||||
next=str_split(cmd, this, ';');
|
||||
retreq=strchr(cmd, '>');
|
||||
if (retreq!=NULL) { /* save pointer to return request */
|
||||
i=retreq-cmd;
|
||||
cmd[i]='\0'; /* cut return request */
|
||||
list[nres]=this+i;
|
||||
nres++; assert(nres<=nLIST);
|
||||
}
|
||||
cmd_ptr=sbuf.buf+sbuf.wrpos; /* pointer to command in buffer */
|
||||
p=str_split(seg, cmd, '[');
|
||||
ERR_I(StrPut(&sbuf, seg, StrNONE));
|
||||
while (p!=NULL) { /* substitute variables */
|
||||
p=str_split(varname, p, ']');
|
||||
if (p==NULL) ERR_MSG("missing ']'");
|
||||
ERR_I(CocPutVar(varname, &sbuf, StrNONE));
|
||||
p=str_split(seg, p, '[');
|
||||
ERR_I(StrPut(&sbuf, seg, StrNONE));
|
||||
}
|
||||
ERR_I(str_copy(cmd, cmd_ptr));
|
||||
colon=strchr(cmd_ptr, ':');
|
||||
if (colon!=NULL) { /* command with query */
|
||||
blank=strchr(cmd_ptr, ' ');
|
||||
if (blank==NULL || blank>colon) {
|
||||
*colon=' '; blank=colon;
|
||||
} else {
|
||||
*colon=',';
|
||||
}
|
||||
list[nres]=colon+1; nres++; assert(nres<=nLIST); /* pointer to parameters */
|
||||
list[nres]=cmd_ptr; nres++; assert(nres<=nLIST); /* pointer to command */
|
||||
ERR_I(StrPut(&sbuf, ";", StrNONE));
|
||||
cmd[blank-cmd_ptr]='?'; /* build query */
|
||||
if (colon==blank) colon++;
|
||||
cmd[colon-cmd_ptr]='\0';
|
||||
ERR_I(StrPut(&sbuf, cmd, ';')); /* put query */
|
||||
response=1;
|
||||
} else {
|
||||
qu=strchr(cmd, '?');
|
||||
ERR_I(StrPut(&sbuf, ";", StrNONE));
|
||||
if (qu!=NULL) { /* command is a query */
|
||||
response=1;
|
||||
if (retreq==NULL) {
|
||||
/* ERR_MSG("missing return format"); */
|
||||
}
|
||||
list[nres]=NULL; nres++; assert(nres<=nLIST);
|
||||
} else {
|
||||
if (retreq!=NULL) ERR_MSG("no return request allowed after command without query ");
|
||||
}
|
||||
}
|
||||
this=next;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
ERR_I(StrPut(&sbuf, "busy?",'\0'));
|
||||
} else {
|
||||
sbuf.buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */
|
||||
}
|
||||
ERR_P(res=SerCmd(ser, sbuf.buf));
|
||||
if (0==strncmp("?TMO", res, 4)) ERR_MSG("timeout");
|
||||
/*
|
||||
list[0..nres-1] contains a now:
|
||||
for a command with return request:
|
||||
- a pointer to a the request
|
||||
then, for a command with query:
|
||||
- a pointer to the parameters and
|
||||
- a pointer to the command
|
||||
this is repeated for every command
|
||||
*/
|
||||
|
||||
/* check results */
|
||||
this=res;
|
||||
for (i=0; i<nres; i++) {
|
||||
if (this==NULL) ERR_MSG("not all results received");
|
||||
this=str_split(result, this, ';');
|
||||
retreq=list[i];
|
||||
if (retreq!=NULL) {
|
||||
if (retreq[0]=='>') {
|
||||
i++;
|
||||
} else {
|
||||
retreq=NULL;
|
||||
}
|
||||
}
|
||||
if (list[i]!=NULL) {
|
||||
qu=str_split(par, list[i], ';'); /* get parameters */
|
||||
i++;
|
||||
if (!LscEqPar(par, result)) { /* try again with single command */
|
||||
qu=strchr(qu, ';');
|
||||
assert(list[i]!=NULL);
|
||||
str_copy(cmd, list[i]);
|
||||
if (qu!=NULL) cmd[qu-list[i]]='\0';
|
||||
ERR_P(qu=SerCmd(ser, cmd));
|
||||
if (!LscEqPar(par, qu)) {
|
||||
if (0!=strcmp(result, qu)) {
|
||||
ERR_MSG("result does not match");
|
||||
} else {
|
||||
ERR_MSG("result does not match command");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retreq!=NULL) { /* query */
|
||||
StrLink(&sbuf, result);
|
||||
str_split(par, retreq+1, ';');
|
||||
p=par;
|
||||
while (p!=NULL) {
|
||||
p=str_split(varname, p, ',');
|
||||
if (varname[0]!='\0') {
|
||||
if (p==NULL) { /* last element: get rest of line */
|
||||
ERR_I(CocGetVar(varname, &sbuf, '\0'));
|
||||
} else {
|
||||
ERR_I(CocGetVar(varname, &sbuf, ','));
|
||||
}
|
||||
} else {
|
||||
ERR_P(StrGet(&sbuf, varname, ','));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(res);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
56
tecs/tecs_lsc.h
Normal file
56
tecs/tecs_lsc.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef _TECS_LSC_H_
|
||||
#define _TECS_LSC_H_
|
||||
|
||||
#include "tecs_serial.h"
|
||||
|
||||
char *LscCmd(SerChannel *ser, const char *cmds);
|
||||
/*
|
||||
Send commands to LSC-340.
|
||||
There may be several commands separated by semicolon.
|
||||
A special syntax is used:
|
||||
- Commands containing a colon are commands with query,
|
||||
i.e. the sent parameters are checked. The sent parameters
|
||||
are those after the query, the command before the colon
|
||||
is used as query, after inserting a question mark.
|
||||
- Variable names in square brackets are substitute by their value
|
||||
- Return values may be assigned to variables, separated by
|
||||
a right angle bracket. There may be several variables
|
||||
separated by comma, corresponding to the returned parameters,
|
||||
beeing separated by commas also. If the variable is not terminated
|
||||
by a comma, the whole remaining result is assigned, even if it
|
||||
contains commas. Return values may only be used when a command
|
||||
with wuery was sent, or when the command was a query (containing
|
||||
a question mark).
|
||||
|
||||
Example:
|
||||
|
||||
LscCmd(ser, "RANGE:5>range;SETP 1:[tempH];CRVHDR?[num]>name,head;MODE 2");
|
||||
|
||||
assume that tempH=295 and num=25 the command sent to LSC is:
|
||||
|
||||
RANGE 5;RANGE?;SETP 1,295;SETP?1;CRVHDR?25;MODE 2
|
||||
|
||||
and assume LSC sens back:
|
||||
|
||||
3;295.000E+00;CTI5 ,R10410 ,3,+330.000E+0,2
|
||||
|
||||
then the following variables will be assigned:
|
||||
|
||||
range=3
|
||||
name="CTI5"
|
||||
head="R10410 ,3,+330.000E+0,2"
|
||||
|
||||
All used variables have to be declared with CocDef... (see coc_server.h)
|
||||
*/
|
||||
|
||||
int LscEqPar(char *par, char *res);
|
||||
/*
|
||||
compare if parameters are equal (numbers as numbers, spaces ignored)
|
||||
if any parameter in par is omitted, it is not compared
|
||||
*/
|
||||
|
||||
char *LscReadStat(int stat);
|
||||
|
||||
char *LscHtrStat(int stat);
|
||||
|
||||
#endif /* _TECS_LSC_H_ */
|
||||
756
tecs/tecs_plot.f
Normal file
756
tecs/tecs_plot.f
Normal file
@@ -0,0 +1,756 @@
|
||||
subroutine tecs_plot(auxpar)
|
||||
|
||||
character*(*) auxpar
|
||||
|
||||
integer dmax, nmax, tmax, amax, nmenu, chartperiod, naux
|
||||
parameter (dmax=400, nmax=9, tmax=8, amax=3, nmenu=13
|
||||
1 , chartperiod=5, naux=1)
|
||||
integer minRange, maxRange, oneDay
|
||||
parameter (minRange=60, maxRange=7*24*3600, oneDay=24*3600)
|
||||
integer zoom, right, live
|
||||
parameter (zoom=1, right=2, live=3)
|
||||
real winmin, undef
|
||||
parameter (winmin=60., undef=-1.125/1024./1024./1024.)
|
||||
|
||||
real*4 x1,x2,xmin,xmax,ymin(2),ymax(2),window
|
||||
real*4 xd(dmax, nmax),yd(dmax,nmax), yy0(nmax), yy1(nmax)
|
||||
real*4 ylast1,ylast2,y1,y2
|
||||
real*4 ex,ey,fx,fy,row,ticks,tim0,tim1,menuwid
|
||||
integer l,j,i,n,t,leng,i1,i2,rl,startday,thisday
|
||||
integer ncol, nset, mode
|
||||
integer first,last,step,tbase,lastj
|
||||
integer colorList(nmax)/5,3,2,4,6,8,14,15,8/
|
||||
integer color(nmax)
|
||||
integer retLen(nmax)
|
||||
integer sel/0/, sel1, sel2, auxsel/1/
|
||||
character key*1
|
||||
character text(2,nmenu)*16/
|
||||
1 'L' ,'live off'
|
||||
1 ,'z' ,'sel. zoom'
|
||||
1 ,'+' ,'zoom in'
|
||||
1 ,'-' ,'zoom out'
|
||||
1 ,'x' ,'show all'
|
||||
1 ,'2d' ,'2 days'
|
||||
1 ,'1h' ,'1 hour'
|
||||
1 ,'15m' ,'15 min'
|
||||
1 ,'31.7t','goto date'
|
||||
1 ,'c' ,'show P/He/Aux'
|
||||
1 ,'s' ,'select T'
|
||||
1 ,'f' ,'write file'
|
||||
1 ,'q' ,'quit'/
|
||||
character weekdays(7)*4/
|
||||
1 'Mon','Tue','Wed','Thu','Fri','Sat','Sun'/
|
||||
character buf*8, device*8, name*40, filnam*128, numb*16
|
||||
character title*64, pars*64
|
||||
character*4 tpar(tmax)/'Te','Tr','Tm','Ts','T1','T2','T3','T4'/
|
||||
character*4 apar(amax)/'P', 'He', 'Aux'/
|
||||
character*16 parnam(nmax)
|
||||
logical gap, done
|
||||
logical saveit
|
||||
integer iret, lund, numl, mon, day
|
||||
integer pars_len, title_len, text_len, name_len
|
||||
integer idx(nmax)
|
||||
character line*132
|
||||
real x0
|
||||
logical loop
|
||||
|
||||
! functions
|
||||
integer myc_now, myc_time, myc_date, get_data
|
||||
integer tecs_get_mult, tecs_get_par
|
||||
|
||||
data window/0./
|
||||
|
||||
if (window .eq. 0) window=1800.
|
||||
saveit=.false.
|
||||
mode=live
|
||||
call pgopen(' ')
|
||||
|
||||
call pgqinf('TYPE', device, l)
|
||||
if (device .eq. 'NULL') then
|
||||
call pgclos
|
||||
call pgopen('?')
|
||||
call pgqinf('TYPE', device, l)
|
||||
if (device .eq. 'NULL') then
|
||||
print *,'No PGPLOT-Device defined'
|
||||
goto 9
|
||||
endif
|
||||
call sys_setenv('PGPLOT_DEV', device)
|
||||
endif
|
||||
|
||||
call pgqcol(i,ncol)
|
||||
! print *,i,ncol,' colors ',device
|
||||
if (ncol .ge. 8 .and. device .ne. 'VT125') then
|
||||
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)
|
||||
endif
|
||||
|
||||
call pgask(.false.)
|
||||
call pgupdt
|
||||
l=0
|
||||
x1=0
|
||||
step=0
|
||||
do i=1,amax
|
||||
if (auxpar .eq. apar(i)) then
|
||||
auxsel=i
|
||||
endif
|
||||
enddo
|
||||
|
||||
1 pars=' '
|
||||
nset=0
|
||||
do i=1,tmax
|
||||
nset=nset+1
|
||||
color(nset)=colorList(i)
|
||||
parnam(nset)=tpar(i)
|
||||
call str_trim(pars, pars, pars_len)
|
||||
pars=pars(1:pars_len)//' '//parnam(nset)
|
||||
enddo
|
||||
nset=nset+1
|
||||
color(nset)=colorList(3)
|
||||
parnam(nset)=apar(auxsel)
|
||||
call str_trim(pars, pars, pars_len)
|
||||
pars=pars(1:pars_len)//' '//parnam(nset)
|
||||
|
||||
iret=tecs_get_mult(pars, t, nset, yy0)
|
||||
if (iret .lt. 0) goto 99
|
||||
if (window .eq. 0) then
|
||||
last=t
|
||||
step=maxRange/dmax
|
||||
window=maxRange
|
||||
first=t-min(dmax*step-1,maxRange-step)
|
||||
else if (mode .ge. right) then
|
||||
step=window/(dmax-2)+0.99
|
||||
last=t
|
||||
first=t-min(dmax*step-1,nint(window))
|
||||
else
|
||||
if (mode .eq. zoom) then
|
||||
x2=(x1+x2+window)/2
|
||||
x1=x2-window
|
||||
endif
|
||||
if (x1 .gt. x2-minRange) x1=x2-minRange
|
||||
step=(x2-x1)/(dmax-2)+0.99
|
||||
last=x2+tbase
|
||||
first=x1-step+tbase
|
||||
endif
|
||||
if (step .eq. 0) step=1
|
||||
|
||||
if (step .gt. 60) then ! normalize step
|
||||
step=(step+59)/60*60
|
||||
else if (step .gt. 30) then
|
||||
step=60
|
||||
elseif (step .gt. 20) then
|
||||
step=30
|
||||
else
|
||||
step=(step+4)/5*5
|
||||
endif
|
||||
first=last-(last-first+step-1)/step*step ! round first
|
||||
! print *,step,last-first
|
||||
tbase=first-mod(first,7*oneDay)
|
||||
iret=get_data(pars, first, last, step, tbase
|
||||
1 , xd, yd, dmax, nmax, retLen)
|
||||
if (iret .lt. 0) goto 99
|
||||
|
||||
x2 = last - tbase
|
||||
if (mode .ge. right) then
|
||||
x1=x2-window
|
||||
else
|
||||
x1 = first - tbase
|
||||
endif
|
||||
tim0=t-tbase
|
||||
do i=1,nset
|
||||
leng=retLen(i)
|
||||
do while (leng .gt. 1 .and. yd(leng,i) .eq. undef)
|
||||
leng=leng-1
|
||||
enddo
|
||||
if (leng .eq. 1) leng=0
|
||||
retLen(i)=leng
|
||||
if (mode .eq. live .and. leng .gt. 0) then
|
||||
xd(leng,i)=tim0
|
||||
yd(leng,i)=yy0(i)
|
||||
endif
|
||||
enddo
|
||||
if (sel .ne. 0) then
|
||||
do while (sel .lt. nset .and. retLen(sel) .eq. 0)
|
||||
sel=sel+1
|
||||
enddo
|
||||
if (sel .ge. nset) sel = 0
|
||||
endif
|
||||
if (saveit) goto 9
|
||||
if (mode .eq. live) then
|
||||
x2=max(tim0,x2)+min(1800., window*0.5)
|
||||
endif
|
||||
|
||||
if (window .gt. 50*3600) then
|
||||
ticks=8*3600
|
||||
elseif (window .gt. 25*3600) then
|
||||
ticks=4*3600
|
||||
else
|
||||
ticks=0.0 ! automatic
|
||||
endif
|
||||
|
||||
i1=1
|
||||
i2=nset-naux
|
||||
if (sel .eq. 0) then
|
||||
sel1=i1
|
||||
sel2=i2
|
||||
else
|
||||
sel1=sel
|
||||
sel2=sel
|
||||
endif
|
||||
do rl=1,2
|
||||
if (mode .eq. zoom .and. rl .eq. 1) then
|
||||
ymin(1)=y1
|
||||
ymax(1)=y2
|
||||
else
|
||||
ymin(rl)=1e30
|
||||
ymax(rl)=-1e30
|
||||
ylast1=ymin(rl)
|
||||
ylast2=ymax(rl)
|
||||
do i=sel1,sel2
|
||||
do j=1,retLen(i)
|
||||
if (yd(j,i) .ne. undef) then
|
||||
ymin(rl)=min(ymin(rl),yd(j,i))
|
||||
ymax(rl)=max(ymax(rl),yd(j,i))
|
||||
endif
|
||||
enddo
|
||||
do j=max(1,retLen(i)-4),retLen(i)
|
||||
if (yd(j, i) .ne. undef) then
|
||||
ylast1=min(ylast1,yd(j, i))
|
||||
ylast2=max(ylast2,yd(j, i))
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
ey=(ymax(rl)-ymin(rl))
|
||||
fy=abs(ymax(rl))
|
||||
ymax(rl)=ymax(rl)+max(fy*0.0075,ey*0.01)
|
||||
ymin(rl)=ymin(rl)-max(fy*0.005,ey*0.01)
|
||||
if (mode .eq. live) then
|
||||
ymin(rl)=min(ymin(rl),max(0.0,ylast1-ey*0.4))
|
||||
ymax(rl)=max(ymax(rl),ylast2+ey*0.4)
|
||||
endif
|
||||
endif
|
||||
|
||||
if (ymax(rl) .lt. ymin(rl)) then
|
||||
ymax(rl)=1.0
|
||||
ymin(rl)=0
|
||||
elseif (ymax(rl) .eq. ymin(rl)) then
|
||||
ymax(rl)=ymin(rl)*1.00001+1.0
|
||||
ymin(rl)=-1.0e-3
|
||||
endif
|
||||
|
||||
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||
|
||||
do i=i1,i2
|
||||
call pgsci(color(i))
|
||||
l=0
|
||||
lastj=1
|
||||
do j=1,retLen(i)
|
||||
if (yd(j,i) .eq. undef) then
|
||||
if (j .gt. lastj) then
|
||||
call pgline(j-lastj, xd(lastj,i), yd(lastj,i))
|
||||
endif
|
||||
lastj=j+1
|
||||
else
|
||||
l=j
|
||||
endif
|
||||
enddo
|
||||
if (retLen(i) .gt. lastj)
|
||||
1 call pgline(retLen(i)+1-lastj, xd(lastj,i), yd(lastj,i))
|
||||
retLen(i)=l
|
||||
enddo
|
||||
call pgsci(1)
|
||||
if (rl .eq. 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
|
||||
if (retLen(i) .gt. 0) then
|
||||
name=parnam(i)
|
||||
if (name .eq. 'Tm') then
|
||||
name='Main Sensor'
|
||||
elseif (name .eq. 'Ts') then
|
||||
name='Sample Sensor'
|
||||
elseif (name .eq. 'Tr') then
|
||||
name='SetPoint'
|
||||
endif
|
||||
call str_trim(name, name, name_len)
|
||||
if (sel .eq. i) then
|
||||
name=name(1:name_len)//'*'
|
||||
call str_trim(name, name, name_len)
|
||||
endif
|
||||
call pglen(5, name(1:name_len), fx, fy)
|
||||
call pgsci(color(i))
|
||||
call pgmtxt ('L', 2.5, ey, 0.0, name(1:name_len))
|
||||
ey=ey+fy+0.04
|
||||
endif
|
||||
enddo
|
||||
call pgsci(1)
|
||||
call pgmtxt ('L', 2.5, ey, 0.0, 'T [K]')
|
||||
else
|
||||
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) .eq. 'P' .or. parnam(nset) .eq. 'p') then
|
||||
call pgmtxt ('L', 2.5, 0.5, 0.5, 'Power [W]')
|
||||
elseif (parnam(nset) .eq. 'He') then
|
||||
title='%'
|
||||
iret=tecs_get_par('heUnits', title, 0)
|
||||
call str_trim(title, title, title_len)
|
||||
call pgmtxt ('L', 2.5, 0.5, 0.5,
|
||||
1 'Helium ['//title(1:title_len)//']')
|
||||
else
|
||||
call pgmtxt ('L', 2.5, 0.5, 0.5, parnam(nset))
|
||||
endif
|
||||
endif
|
||||
i1=nset-naux+1
|
||||
i2=nset
|
||||
sel1=i1
|
||||
sel2=i2
|
||||
enddo
|
||||
|
||||
call pgsch(0.7)
|
||||
rl=1
|
||||
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||
|
||||
call pgsci(1)
|
||||
call pgsclp(0)
|
||||
if (mode .eq. live) then
|
||||
text(2,1)='live off'
|
||||
else
|
||||
text(2,1)='live on'
|
||||
endif
|
||||
text(2,10)='show '//apar(mod(auxsel,3)+1)
|
||||
menuwid=0.0
|
||||
do i=1,nmenu
|
||||
call str_trim(text(2,i), text(2,i), text_len)
|
||||
call pglen(5, text(2,i)(1:text_len), fx, fy)
|
||||
call pgmtxt('T', 3.0, menuwid, 0.0, '|'//text(1,i))
|
||||
call pgmtxt('T', 2.5, menuwid, 0.0, '|')
|
||||
call pgmtxt('T', 2.0, menuwid, 0.0, '|'//text(2,i))
|
||||
menuwid=menuwid+fx+0.01
|
||||
enddo
|
||||
call pgmtxt('T', 3.0, menuwid, 0.0, '|')
|
||||
call pgmtxt('T', 2.5, menuwid, 0.0, '|')
|
||||
call pgmtxt('T', 2.0, menuwid, 0.0, '|')
|
||||
menuwid=menuwid+0.01
|
||||
|
||||
call pgsch(0.8)
|
||||
done=.false.
|
||||
row=(ymax(rl)-ymin(rl))/30.
|
||||
ey=ymin(rl)-row*3.5
|
||||
i=max(0,int((x1+oneDay/2)/oneDay))
|
||||
|
||||
ex=(i+0.5)*oneDay
|
||||
do while (ex .le. x2)
|
||||
done=.true.
|
||||
write(buf,'(i8.8)') myc_date(nint(ex)+tbase)
|
||||
call pgptxt(ex, ey, 0.0, 0.5,
|
||||
1 weekdays(mod(i,7)+1)//buf(7:8)//'.'//buf(5:6))
|
||||
ex=ex-12*3600
|
||||
if (ex .gt. x1) then
|
||||
call pgmove(ex, ey)
|
||||
call pgdraw(ex, ey+row)
|
||||
endif
|
||||
ex=ex+oneDay
|
||||
if (ex .lt. x2) then
|
||||
call pgmove(ex, ey)
|
||||
call pgdraw(ex, ey+row)
|
||||
endif
|
||||
i=i+1
|
||||
ex=(i+0.5)*oneDay
|
||||
enddo
|
||||
if (.not. done) then
|
||||
n=nint(x2)/oneDay*oneDay
|
||||
i=nint(x1)-n
|
||||
j=nint(x2)-n
|
||||
if (i .lt. 0) then
|
||||
if (-i .gt. 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 pgmtxt('B', 3.5, ex, ex,
|
||||
1 weekdays(thisday)//buf(7:8)//'.'//buf(5:6))
|
||||
endif
|
||||
|
||||
iret=tecs_get_par('device', title, 0)
|
||||
if (iret .lt. 0) goto 99
|
||||
i=index(title, '(')
|
||||
if (i .gt. 2 ) then
|
||||
title=title(1:i-1)
|
||||
else
|
||||
title='test - no device'
|
||||
endif
|
||||
|
||||
call pgmtxt('T', -1.5, 0.02, 0.0, title)
|
||||
call pgsclp(1)
|
||||
|
||||
call purge_keys ! purge buffer
|
||||
|
||||
numl=0
|
||||
numb=' '
|
||||
7 ex=undef
|
||||
if (mode .eq. live) then
|
||||
! if (device(1:1) .eq. 'X') then
|
||||
! call pgmtxt('T', 0.5, 0.0, 0.0, 'LIVE MODE (click on text window before pressing any further key)')
|
||||
! endif
|
||||
! call get_key(key, 0, chartperiod)
|
||||
i=chartperiod-mod(myc_now(), chartperiod)
|
||||
call get_cursor(ex, ey, key, -i)
|
||||
|
||||
do while (key .eq. char(0) .or. key .eq. ' ') ! no key or space key pressed
|
||||
iret=tecs_get_mult(pars, t, nset, yy1)
|
||||
if (iret .lt. 0) goto 99
|
||||
tim1=t-tbase
|
||||
if (tim1 .gt. x2) then
|
||||
call pgpage
|
||||
window=x2-x1
|
||||
goto 1
|
||||
endif
|
||||
if (tim1 .gt. tim0) then
|
||||
i1=1
|
||||
i2=nset-naux
|
||||
do rl=1,2
|
||||
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||
do i=i1,i2
|
||||
if (yy0(i) .ne. undef .and. yy1(i) .ne. undef) then
|
||||
if ((sel .eq. 0 .or. sel .eq. i) .and.
|
||||
1 (yy1(i) .lt. ymin(rl) .or.
|
||||
1 yy1(i) .gt. ymax(rl))) then
|
||||
call pgpage
|
||||
window=x2-x1
|
||||
goto 1
|
||||
endif
|
||||
call pgsci(color(i))
|
||||
call pgmove(tim0, yy0(i))
|
||||
call pgdraw(tim1, yy1(i))
|
||||
endif
|
||||
yy0(i)=yy1(i)
|
||||
enddo
|
||||
i1=nset-naux+1
|
||||
i2=nset
|
||||
enddo
|
||||
tim0=tim1
|
||||
|
||||
endif
|
||||
i=chartperiod-mod(myc_now(), chartperiod)
|
||||
call get_cursor(ex, ey, key, -i)
|
||||
enddo
|
||||
else
|
||||
call get_cursor(ex, ey, key, 0)
|
||||
endif
|
||||
rl=1
|
||||
call set_win(rl,x1,x2,ymin(rl),ymax(rl))
|
||||
|
||||
8 if (key .ge. 'a') key=char(ichar(key)-32)
|
||||
if (key .eq. '-') then
|
||||
window=min(window*2, 8.0*oneDay)
|
||||
if (mode .eq. zoom) then
|
||||
x1=x1-(x2-x1)/2
|
||||
x2=x2+(x2-x1)/3
|
||||
y1=y1-(y2-y1)/2
|
||||
y2=y2+(y2-y1)/3
|
||||
endif
|
||||
elseif (key .eq. 'X') then
|
||||
window=0
|
||||
mode=0
|
||||
elseif (key .eq. '+' .or. key .eq. ',') then
|
||||
window=max(winmin,window/2)
|
||||
if (mode .eq. zoom) then
|
||||
if (ex .eq. undef) then
|
||||
ex=(x1+x2)/2
|
||||
ey=(min(y2,ymax(1))+max(y1,ymin(1)))/2
|
||||
end if
|
||||
fx=max(winmin,x2-x1)
|
||||
fy=max(y2-y1,1e-3,y2*1e-5)
|
||||
x1=ex-fx/4
|
||||
x2=ex+fx/4
|
||||
y1=ey-fy/4
|
||||
y2=ey+fy/4
|
||||
endif
|
||||
elseif (key .eq. 'Z') then
|
||||
call pgsci(1)
|
||||
if (ex .eq. undef) then
|
||||
call pgmtxt('T', 0.5, 0.0, 0.0,
|
||||
1 'click on two opposite corners of a selection rectangle')
|
||||
call get_cursor(ex, ey, key, 0)
|
||||
else
|
||||
call pgmtxt('T', 0.5, 0.0, 0.0,
|
||||
1 'click on second corner of selection rectangle')
|
||||
endif
|
||||
call pgsci(6)
|
||||
xmin=x1
|
||||
xmax=x2
|
||||
call pgmove(xmin, ey)
|
||||
call pgdraw(xmax, ey)
|
||||
call pgmove(ex, ymin(rl))
|
||||
call pgdraw(ex, ymax(rl))
|
||||
if (device(1:1) .eq. 'X') then
|
||||
fx=ex
|
||||
fy=ey
|
||||
call get_cursor(fx, fy, key, 2)
|
||||
else
|
||||
call get_cursor(fx, fy, key, 0)
|
||||
endif
|
||||
x1=max(xmin,min(ex,fx))
|
||||
x2=min(xmax,max(ex,fx))
|
||||
if (x1 .ge. x2) then
|
||||
x1=xmin
|
||||
x2=xmax
|
||||
endif
|
||||
window=x2-x1
|
||||
y1=max(ymin(1),min(ey,fy))
|
||||
y2=min(ymax(1),max(ey,fy))
|
||||
if (y1 .ge. y2) then
|
||||
y1=ymin(1)
|
||||
y2=ymax(1)
|
||||
endif
|
||||
mode=zoom
|
||||
elseif (key .ge. '0' .and. key .le. '9' .or. key .eq. '.') then ! number
|
||||
if (numl .lt. len(numb)) then
|
||||
numl=numl+1
|
||||
numb(numl:numl)=key
|
||||
call pgsci(1)
|
||||
call pgsch(0.8)
|
||||
call pgmtxt('T', 2.0, menuwid, 0.0, numb(1:numl))
|
||||
endif
|
||||
! call get_cursor(ex, ey, key, -chartperiod)
|
||||
! if (key .ne. char(0)) goto 8
|
||||
if (mode .eq. zoom) mode=0
|
||||
goto 7
|
||||
elseif (key .eq. 'D') then
|
||||
ex=1
|
||||
read(numb, *, iostat=i) ex
|
||||
window=min(maxRange,max(minRange, nint(oneDay*ex)))
|
||||
if (mode .lt. right) mode=right
|
||||
x1=0
|
||||
elseif (key .eq. 'H') then
|
||||
ex=1
|
||||
read(numb, *, iostat=i) ex
|
||||
window=min(maxRange,max(minRange, nint(3600*ex)))
|
||||
if (mode .lt. right) mode=right
|
||||
x1=0
|
||||
elseif (key .eq. 'M') then
|
||||
ex=1
|
||||
read(numb, *, iostat=i) ex
|
||||
window=min(maxRange,max(minRange, nint(60*ex)))
|
||||
if (mode .lt. right) mode=right
|
||||
x1=0
|
||||
elseif (key .eq. 'T' .or. numl .gt. 0 .and.
|
||||
1 (key .eq. char(13) .or. key .eq. char(10))) then
|
||||
j=index(numb,'.')
|
||||
day=0
|
||||
if (j .gt. 1 .and. j .lt. 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
|
||||
mode=0
|
||||
elseif (key .eq. 'L') then
|
||||
if (mode .eq. live) then
|
||||
mode=right
|
||||
else
|
||||
mode=live
|
||||
endif
|
||||
elseif (key .eq. 'F') then
|
||||
saveit=.true.
|
||||
elseif (key .eq. 'Q' .or. key .eq. char(13)
|
||||
1 .or. key .eq. char(10)) then
|
||||
goto 9
|
||||
elseif (key .eq. 'S') then
|
||||
sel=sel+1
|
||||
if (sel .gt. tmax) sel=0
|
||||
if (mode .eq. zoom) mode=0
|
||||
elseif (key .eq. 'C') then
|
||||
auxsel=auxsel+1
|
||||
if (auxsel .gt. amax) auxsel=1
|
||||
elseif (mode .eq. live) then
|
||||
goto 7
|
||||
endif
|
||||
numl=0
|
||||
numb=' '
|
||||
call pgpage
|
||||
goto 1
|
||||
99 call tecs_write_msg(6)
|
||||
9 continue
|
||||
call pgclos
|
||||
call purge_keys
|
||||
print *
|
||||
if (saveit) then
|
||||
lund=41
|
||||
print '(x,a,$)', 'Filename: '
|
||||
read(*,'(a)') filnam
|
||||
open(lund, file=filnam, status='unknown')
|
||||
|
||||
line='time [h]'
|
||||
call str_trim(line, line, l)
|
||||
do j=1,nset
|
||||
idx(j)=0
|
||||
do i=1,retlen(j)
|
||||
if (yd(i,j) .ne. undef) then
|
||||
idx(j)=1
|
||||
l=l+1
|
||||
line(l:l)=char(9)
|
||||
call str_trim(line(l+1:), parnam(j), text_len)
|
||||
l=l+max(9,text_len)
|
||||
goto 109
|
||||
endif
|
||||
enddo
|
||||
109 continue
|
||||
enddo
|
||||
write(lund, '(a)') line(1:l)
|
||||
|
||||
n=1
|
||||
x0=0
|
||||
do while (x0 .lt. 3e7)
|
||||
x0=4e7
|
||||
do j=1,nmax ! find next x
|
||||
if (idx(j) .gt. 0 .and. idx(j) .lt. retlen(j)) then
|
||||
x0=min(x0,xd(idx(j),j))
|
||||
endif
|
||||
enddo
|
||||
if (x0 .lt. 3e7) then
|
||||
write(line,'(f9.4)') x0/3600.
|
||||
l=9
|
||||
do j=1,nmax
|
||||
if (idx(j) .gt. 0) then
|
||||
l=l+1
|
||||
line(l:l)=char(9)
|
||||
if (idx(j) .le. retlen(j)) then
|
||||
if (xd(idx(j),j) .lt. x0+1) then
|
||||
write(line(l+1:), '(f9.4)')
|
||||
1 max(-999.,min(9999.,yd(idx(j),j)))
|
||||
l=l+9
|
||||
idx(j)=idx(j)+1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
enddo
|
||||
write(lund, '(a)') line(1:l)
|
||||
n=n+1
|
||||
endif
|
||||
enddo
|
||||
close(lund)
|
||||
print *, n, ' lines written to ',filnam(1:48)
|
||||
endif
|
||||
|
||||
end
|
||||
|
||||
|
||||
subroutine get_cursor(x, y, key, mode)
|
||||
character*1 key
|
||||
real*4 x, y
|
||||
integer mode
|
||||
integer with_timeout/-1/
|
||||
integer l
|
||||
character res*32
|
||||
|
||||
if (with_timeout .lt. 0) then
|
||||
with_timeout=0
|
||||
call pgqinf('VERSION', res, l)
|
||||
if (res(l:l) .eq. '+') then
|
||||
call pgqinf('TYPE', res, l)
|
||||
if (res(1:1) .eq. 'X') then
|
||||
with_timeout=1
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
if (with_timeout .gt. 0 .or. mode .ge. 0) then
|
||||
call pgband(mode, 0, x, y, x, y, key)
|
||||
else
|
||||
call sys_get_key(key, -mode)
|
||||
endif
|
||||
end
|
||||
|
||||
|
||||
subroutine purge_keys
|
||||
character key*1
|
||||
key=' '
|
||||
do while (key .ne. char(0))
|
||||
call sys_get_key(key, 0)
|
||||
end do
|
||||
end
|
||||
|
||||
|
||||
subroutine set_win(rl, x1, x2, y1, y2)
|
||||
integer rl
|
||||
real x1, x2, y1, y2
|
||||
|
||||
if (rl .eq. 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
|
||||
|
||||
|
||||
integer function get_data(pars, first, last, step, tbase
|
||||
1 , xd, yd, dmax, nmax, retlen)
|
||||
|
||||
character pars*(*)
|
||||
integer first, last, step, tbase, dmax, nmax, retlen(nmax)
|
||||
real*4 xd(dmax,nmax), yd(dmax,nmax)
|
||||
|
||||
integer oneDay, maxn
|
||||
parameter (oneDay = 24*3600, maxn=9)
|
||||
integer tecs_get_data
|
||||
|
||||
integer i,j,rl(maxn),m,k,n,mm
|
||||
|
||||
if (nmax .gt. maxn) stop 'get_data: nmax>maxn'
|
||||
if (last-first .le. oneDay) then
|
||||
get_data=tecs_get_data(pars, first, last, step, tbase
|
||||
1 , xd, yd, dmax, nmax, retLen)
|
||||
else
|
||||
do j=1,nmax
|
||||
retlen(j)=0
|
||||
enddo
|
||||
m=0
|
||||
do i=first/oneDay,last/oneDay
|
||||
get_data=tecs_get_data(pars, max(first,i*oneDay)
|
||||
1 , min(last,(i+1)*oneDay-step), step, tbase
|
||||
1 , xd(m+1, 1), yd(m+1, 1), dmax, nmax, rl)
|
||||
if (get_data .lt. 0) return
|
||||
mm=0
|
||||
do j=1,nmax
|
||||
n=retlen(j)
|
||||
do k=m+1,m+rl(j)
|
||||
n=n+1
|
||||
xd(n,j)=xd(k,j)
|
||||
yd(n,j)=yd(k,j)
|
||||
enddo
|
||||
retlen(j)=n
|
||||
mm=max(mm,n)
|
||||
enddo
|
||||
! print *,mm-m,' points read'
|
||||
m=mm
|
||||
enddo
|
||||
endif
|
||||
end
|
||||
244
tecs/tecs_serial.c
Normal file
244
tecs/tecs_serial.c
Normal file
@@ -0,0 +1,244 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include "rs232c_def.h"
|
||||
#include "asynsrv_def.h"
|
||||
#include "sinq_prototypes.h"
|
||||
#include "myc_err.h"
|
||||
#include "tecs_serial.h"
|
||||
#include "coc_logfile.h"
|
||||
#include "coc_util.h"
|
||||
#include "myc_str.h"
|
||||
#include "myc_mem.h"
|
||||
|
||||
#define ASYNSRV_TYPE 1
|
||||
#define TERMSRV_TYPE 2
|
||||
#define EOT '\r'
|
||||
|
||||
typedef struct {
|
||||
char host[64];
|
||||
int type; /* = ASYNSRV_TYPE */
|
||||
struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */
|
||||
struct RS__MsgStruct to_host;
|
||||
struct RS__RespStruct from_host;
|
||||
} AsynSrvChan;
|
||||
|
||||
typedef struct {
|
||||
char host[64];
|
||||
int type; /* = TERMSRV_TYPE */
|
||||
char res[SER_BUF_LEN];
|
||||
int fd, tmo;
|
||||
int (*idleHdl)(int,int);
|
||||
} TermSrvChan;
|
||||
|
||||
void SerA_error(void) {
|
||||
char *a_txt;
|
||||
int a_cod, a_my, a_vms;
|
||||
|
||||
AsynSrv_ErrInfo(&a_txt, &a_cod, &a_my, &a_vms);
|
||||
ErrMsg("asynsrv error"); ErrTxt(a_txt,0);
|
||||
}
|
||||
|
||||
int SerWait(int tmo_msec, int fd) {
|
||||
struct timeval tmo;
|
||||
fd_set mask;
|
||||
int i;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SerChannel *SerOpen(const char *hostPort, int msecTmo, int (*idleHdl)(int,int)) {
|
||||
AsynSrvChan *aser;
|
||||
TermSrvChan *tser;
|
||||
char hbuf[64], cport[16], host[32];
|
||||
char *p, *c;
|
||||
struct sockaddr_in sadr;
|
||||
int iret;
|
||||
time_t t1, t2;
|
||||
static int ecnt;
|
||||
|
||||
time(&t1);
|
||||
str_copy(hbuf, hostPort);
|
||||
p=str_split(host, hbuf, ':');
|
||||
assert(p!=NULL);
|
||||
c=str_split(cport, p, '/');
|
||||
if (msecTmo==0) msecTmo=5000;
|
||||
if (c!=NULL) {
|
||||
NEW(aser, AsynSrvChan); aser->type=ASYNSRV_TYPE;
|
||||
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);
|
||||
str_copy(aser->host, hostPort);
|
||||
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));
|
||||
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);
|
||||
str_copy(tser->host, hostPort);
|
||||
return ((SerChannel *)tser);
|
||||
}
|
||||
OnError:
|
||||
time(&t2);
|
||||
if (ecnt<4) {
|
||||
logfileOut(LOG_MAIN, "failed after %d sec\n", t2-t1);
|
||||
ecnt++;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int SerSetTmo(SerChannel *serch, int msecTmo) {
|
||||
AsynSrvChan *aser;
|
||||
TermSrvChan *tser;
|
||||
int iret;
|
||||
|
||||
if (serch->type==ASYNSRV_TYPE) {
|
||||
aser=(AsynSrvChan *)serch;
|
||||
iret=AsynSrv_Config(&aser->asyn_info, "msecTmo", msecTmo, NULL);
|
||||
if (iret!=1) { SerA_error(); goto OnError; }
|
||||
} else if (serch->type==TERMSRV_TYPE) {
|
||||
tser=(TermSrvChan *)serch;
|
||||
tser->tmo=msecTmo;
|
||||
}
|
||||
return 0;
|
||||
OnError: return -1;
|
||||
}
|
||||
|
||||
void SerClose(SerChannel *serch) {
|
||||
AsynSrvChan *aser;
|
||||
TermSrvChan *tser;
|
||||
|
||||
if (serch->type==ASYNSRV_TYPE) {
|
||||
aser=(AsynSrvChan *)serch;
|
||||
AsynSrv_Close(&aser->asyn_info, 1);
|
||||
} 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("timeout");
|
||||
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:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* obsolete ?
|
||||
char *SerCmdC(SerChannel *serch, const char *cmnd) {
|
||||
char cmd[SER_BUF_LEN];
|
||||
int l;
|
||||
|
||||
l=strlen(cmnd);
|
||||
if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS);
|
||||
strcpy(cmd, cmnd);
|
||||
return(SerCmd(serch, cmd));
|
||||
OnError: return(NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
20
tecs/tecs_serial.h
Normal file
20
tecs/tecs_serial.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _SERUTIL_H_
|
||||
#define _SERUTIL_H_
|
||||
|
||||
#define SER_BUF_LEN 320
|
||||
|
||||
typedef struct {
|
||||
char host[64];
|
||||
/* private */
|
||||
int type;
|
||||
} SerChannel;
|
||||
|
||||
SerChannel *SerOpen(const char *host, int msecTmo, int (*idleHdl)(int,int));
|
||||
char *SerCmd(SerChannel *ser, char *cmnd);
|
||||
int SerSetTmo(SerChannel *ser, int msecTmo);
|
||||
SerChannel *SerCheck(SerChannel *ser);
|
||||
void SerClose(SerChannel *ser);
|
||||
|
||||
/* char *SerCmdC(SerChannel *ser, const char *cmnd); */
|
||||
|
||||
#endif /* _SERUTIL_H_ */
|
||||
238
tecs/term.c
Normal file
238
tecs/term.c
Normal file
@@ -0,0 +1,238 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "myc_mem.h"
|
||||
#include "sys_select.h"
|
||||
|
||||
#define ESC_TMO 1000
|
||||
#define REF_TMO 100
|
||||
#define HISTORY_LINES 256
|
||||
|
||||
#define L_ARROW '\200'
|
||||
#define R_ARROW '\201'
|
||||
#define U_ARROW '\202'
|
||||
#define D_ARROW '\203'
|
||||
#define EVT_CHAR '\0'
|
||||
#define DEL_CHAR '\b'
|
||||
#define RET_CHAR '\n'
|
||||
|
||||
static char esc_key='\0';
|
||||
|
||||
static fd_set regMask;
|
||||
static int lastFd=-1;
|
||||
|
||||
void term_reg_socket(int fd) {
|
||||
FD_SET(fd, ®Mask);
|
||||
}
|
||||
|
||||
void term_unr_socket(int fd) {
|
||||
FD_CLR(fd, ®Mask);
|
||||
}
|
||||
|
||||
int term_raw_key(char *key, int msecTmo) {
|
||||
fd_set mask;
|
||||
|
||||
mask=regMask;
|
||||
return(sys_select_or_key(&mask, msecTmo, key));
|
||||
}
|
||||
|
||||
int term_wait_fd(int fd, int msecTmo) {
|
||||
fd_set mask;
|
||||
struct timeval tmo;
|
||||
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(fd, &mask);
|
||||
tmo.tv_sec=msecTmo / 1000;
|
||||
tmo.tv_usec=(msecTmo % 1000) * 1000+1;
|
||||
return(select(FD_SETSIZE, &mask, NULL, NULL, &tmo));
|
||||
}
|
||||
|
||||
int term_get_key(char *key, int msecTmo) {
|
||||
int iret;
|
||||
char k;
|
||||
|
||||
if (esc_key==0) {
|
||||
iret=term_raw_key(&k, msecTmo);
|
||||
} else {
|
||||
k=esc_key;
|
||||
}
|
||||
while (k==27) { /* esc */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
switch (k) {
|
||||
case 'O': k='\217'; break; /* ss3 */
|
||||
case '[': k='\233'; break; /* csi */
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
switch (k) {
|
||||
case '\233': /* csi */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
while (k>='0' && k <='9') {
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
}
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
switch (k) { /* L,R,U,D arrows */
|
||||
case 'D': k=L_ARROW; break;
|
||||
case 'C': k=R_ARROW; break;
|
||||
case 'A': k=U_ARROW; break;
|
||||
case 'B': k=D_ARROW; break;
|
||||
default: k='?';
|
||||
}
|
||||
break;
|
||||
case '\217': /* ss3 */
|
||||
iret=term_raw_key(&k, ESC_TMO);
|
||||
if (iret!=STDIN_FILENO) {
|
||||
esc_key=k;
|
||||
*key='\0';
|
||||
return(iret);
|
||||
}
|
||||
if (k=='M') { /* enter */
|
||||
k=RET_CHAR;
|
||||
} else if (k >= 'l' && k <= 'y') {
|
||||
k=k-64;
|
||||
} else {
|
||||
k='?';
|
||||
}
|
||||
break;
|
||||
case '\177': /* del */
|
||||
case '\b': /* bs */
|
||||
k=DEL_CHAR;
|
||||
break;
|
||||
case '\r': /* cr */
|
||||
case '\n': /* lf */
|
||||
k=RET_CHAR;
|
||||
break;
|
||||
case EVT_CHAR: /* time out*/
|
||||
break;
|
||||
default:
|
||||
if (k<' ' || k>'\176') k='?';
|
||||
}
|
||||
*key=k;
|
||||
esc_key='\0';
|
||||
return (STDIN_FILENO);
|
||||
}
|
||||
|
||||
static char *history[HISTORY_LINES]={NULL};
|
||||
/* history array: it's a cyclic buffer, when it is full, the oldest values
|
||||
are overwritten.
|
||||
*/
|
||||
|
||||
static int hist_pos=0; /* position when scrolling through the history */
|
||||
static int hist_end=0; /* end of history. Always history[hist_end]==NULL */
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask) {
|
||||
char key, *lin;
|
||||
int i,j,l,iret,buflen;
|
||||
char tmp[512];
|
||||
|
||||
buf[size-1]='\0'; /* make sure buf is null terminated */
|
||||
l=strlen(buf);
|
||||
if (*pos>l) {
|
||||
*pos=l;
|
||||
} else if (*pos<0) {
|
||||
*pos=0;
|
||||
}
|
||||
iret=term_get_key(&key, 0);
|
||||
while (1) {
|
||||
if (iret==-1 || key == RET_CHAR || key==EVT_CHAR) { /* refresh after a short timeout */
|
||||
assert(l*2+20+strlen(prompt)<sizeof(tmp));
|
||||
tmp[0]='\r';
|
||||
tmp[1]='\0';
|
||||
strcat(tmp, prompt);
|
||||
strcat(tmp, buf);
|
||||
strcat(tmp,"\033[K");
|
||||
j=strlen(tmp);
|
||||
for (i=l; i>*pos; i--) {
|
||||
tmp[j]='\b'; j++;
|
||||
}
|
||||
tmp[j]='\0';
|
||||
fputs(tmp, stdout);
|
||||
if (iret==-1) {
|
||||
iret=term_get_key(&key, -1); /* no timeout */
|
||||
}
|
||||
}
|
||||
switch (key) {
|
||||
case EVT_CHAR:
|
||||
fputs("\r\033[K", stdout);
|
||||
return(iret);
|
||||
|
||||
/* interrupted EXIT */
|
||||
|
||||
case RET_CHAR:
|
||||
/* fputs("\r\033[K", stdout); */
|
||||
i=hist_end-1; if (i<0) i=HISTORY_LINES-1;
|
||||
if ((history[i]==NULL || 0!=strcmp(history[i], buf)) && buf[0]!='\0') { /* do not save equal and empty lines */
|
||||
buflen=strlen(buf)+1;
|
||||
lin=MALLOC(buflen);
|
||||
strncpy(lin, buf, buflen);
|
||||
history[hist_end]=lin;
|
||||
hist_end++; if (hist_end>=HISTORY_LINES) hist_end=0;
|
||||
if (history[hist_end]!=NULL) {
|
||||
FREE(history[hist_end]); /* clear line at end of history */
|
||||
}
|
||||
history[hist_end]==NULL;
|
||||
}
|
||||
hist_pos=hist_end;
|
||||
return(STDIN_FILENO);
|
||||
|
||||
/* normal EXIT */
|
||||
|
||||
case DEL_CHAR:
|
||||
if (*pos>0) {
|
||||
for (i=*pos; buf[i]!='\0'; i++) {
|
||||
buf[i-1] = buf [i];
|
||||
}
|
||||
buf[i-1]='\0';
|
||||
(*pos)--;
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case L_ARROW:
|
||||
if (*pos>0) (*pos)--;
|
||||
break;
|
||||
case R_ARROW:
|
||||
if (buf[*pos]!='\0') (*pos)++;
|
||||
break;
|
||||
case U_ARROW:
|
||||
case D_ARROW:
|
||||
if (key==U_ARROW) {
|
||||
i=hist_pos-1; if (i<0) i=HISTORY_LINES-1;
|
||||
} else {
|
||||
i=hist_pos+1; if (i>=HISTORY_LINES) i=0;
|
||||
}
|
||||
if (history[i]!=NULL) {
|
||||
strncpy(buf, history[i], size-1);
|
||||
buf[size-1]='\0';
|
||||
hist_pos=i;
|
||||
l=strlen(buf);
|
||||
*pos=l;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (l<size-1) {
|
||||
for (i=l; i>*pos; i--) {
|
||||
buf[i]=buf[i-1];
|
||||
}
|
||||
(*pos)++; l++;
|
||||
buf[i]=key;
|
||||
buf[l]='\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
iret=term_get_key(&key, REF_TMO);
|
||||
}
|
||||
}
|
||||
|
||||
19
tecs/term.h
Normal file
19
tecs/term.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef TERM_H_
|
||||
#define TERM_H_
|
||||
|
||||
void term_reg_socket(int fd);
|
||||
/* register socket */
|
||||
|
||||
void term_unr_socket(int fd);
|
||||
/* unregister socket */
|
||||
|
||||
int term_raw_key(char *key, int msecTmo);
|
||||
|
||||
int term_wait_fd(int fd, int msecTmo);
|
||||
/* wait for a read event on fd or timeout */
|
||||
|
||||
int term_get_key(char *key, int msecTmo);
|
||||
|
||||
int term_get_line(char *buf, int size, int *pos, char *prompt, fd_set *mask);
|
||||
|
||||
#endif /* TERM_H_ */
|
||||
Reference in New Issue
Block a user