PSI sics-cvs-psi_pre-ansto

This commit is contained in:
2003-06-13 00:00:00 +00:00
committed by Douglas Clowes
parent 2e3ddfb6c6
commit 3ffd0d8af4
1099 changed files with 318432 additions and 0 deletions

521
tecs/coc_client.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
#include "fortify.c"
#ifndef FORTIFY
void null(void){}
#endif

87
tecs/instr_hosts.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,3 @@
#include makefile_alpha
include makefile_linux

44
tecs/makefile_alpha Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

3
tecs/tecs.tcl Normal file
View File

@@ -0,0 +1,3 @@
catch {evfactory del temperature} msg
evfactory new temperature tecs
SicsAlias temperature tt

82
tecs/tecs_c.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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, &regMask);
}
void term_unr_socket(int fd) {
FD_CLR(fd, &regMask);
}
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
View 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_ */