From 0d0394707c4440c67e89a2c4eaf906b78e665b39 Mon Sep 17 00:00:00 2001 From: cvs Date: Wed, 5 Apr 2000 08:32:32 +0000 Subject: [PATCH] renamed most source files --- tecs/Makefile | 7 +- tecs/coc.c | 4 +- tecs/coc_client.c | 188 +++++++++++++++++++++++++++++++++ tecs/coc_client.h | 21 ++++ tecs/coc_logfile.c | 239 ++++++++++++++++++++++++++++++++++++++++++ tecs/coc_logfile.h | 20 ++++ tecs/coc_server.c | 242 ++++++++++++++++++++++++++++++++++++++++++ tecs/coc_server.h | 40 +++++++ tecs/coc_util.c | 249 ++++++++++++++++++++++++++++++++++++++++++++ tecs/coc_util.h | 47 +++++++++ tecs/dlog.c | 36 ++++--- tecs/err_handling.c | 95 +++++++++++++++++ tecs/err_handling.h | 83 +++++++++++++++ tecs/lsc.c | 92 ++-------------- tecs/str_buf.c | 4 +- tecs/str_util.c | 4 +- tecs/str_util.h | 2 +- tecs/tecs.c | 30 +++--- tecs/tecs_cli.c | 143 +++++++++++++++++++++++++ tecs/tecs_cli.h | 47 +++++++++ tecs/tecs_dlog.c | 244 +++++++++++++++++++++++++++++++++++++++++++ tecs/tecs_dlog.h | 54 ++++++++++ tecs/tecs_lsc.c | 179 +++++++++++++++++++++++++++++++ tecs/tecs_lsc.h | 52 +++++++++ tecs/tecs_serial.c | 97 +++++++++++++++++ tecs/tecs_serial.h | 13 +++ 26 files changed, 2115 insertions(+), 117 deletions(-) create mode 100644 tecs/coc_client.c create mode 100644 tecs/coc_client.h create mode 100644 tecs/coc_logfile.c create mode 100644 tecs/coc_logfile.h create mode 100644 tecs/coc_server.c create mode 100644 tecs/coc_server.h create mode 100644 tecs/coc_util.c create mode 100644 tecs/coc_util.h create mode 100644 tecs/err_handling.c create mode 100644 tecs/err_handling.h create mode 100644 tecs/tecs_cli.c create mode 100644 tecs/tecs_cli.h create mode 100644 tecs/tecs_dlog.c create mode 100644 tecs/tecs_dlog.h create mode 100644 tecs/tecs_lsc.c create mode 100644 tecs/tecs_lsc.h create mode 100644 tecs/tecs_serial.c create mode 100644 tecs/tecs_serial.h diff --git a/tecs/Makefile b/tecs/Makefile index d657706f..ef971653 100644 --- a/tecs/Makefile +++ b/tecs/Makefile @@ -3,8 +3,9 @@ # # Markus Zolliker, March 2000 #-------------------------------------------------------------------------- -OBJ= tecc.o client.o coc.o errhdl.o str_util.o str_buf.o \ - server.o lsc.o serutil.o logfile.o dlog.o +OBJ= tecs_cli.o coc_client.o coc_util.o err_handling.o \ + str_util.o str_buf.o coc_server.o tecs_lsc.o tecs_serial.o \ + coc_logfile.o tecs_dlog.o #------------ for DigitalUnix CC=cc @@ -19,8 +20,6 @@ tecs: $(OBJ) ranlib libtecsl.a - rm TecsServer cc -o TecsServer -g tecs.c -lm -L. -ltecsl -L../hardsup -lhlib - - rm tcli - cc -o tcli -g tcli.c -lm -L. -ltecsl clean: rm *.o diff --git a/tecs/coc.c b/tecs/coc.c index c0c3d5a4..850e7678 100644 --- a/tecs/coc.c +++ b/tecs/coc.c @@ -56,7 +56,7 @@ int CocRecv(int fd, Str_Buf *buf) { struct timeval tmo={0,1}; fd_set mask; - int i, ret; + int i; tmo.tv_sec=5; /* timeout 5 sec. */ @@ -68,7 +68,7 @@ int CocRecv(int fd, Str_Buf *buf) ERR_SI(buf->wrpos=recv(fd, buf->buf, buf->dsize, 0)); if (buf->wrpos==0) { ERR_COD(ECONNRESET); } str_get_start(buf); - return(ret); + return(buf->wrpos); OnError: return(-1); } diff --git a/tecs/coc_client.c b/tecs/coc_client.c new file mode 100644 index 00000000..a52b0c68 --- /dev/null +++ b/tecs/coc_client.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include "err_handling.h" +#include "coc_client.h" +#include "str_util.h" + +/*-------------------------------------------------------------------------*/ + +int CocConnect(CocConn *conn, int allowConnRefused) { + 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 (allowConnRefused && errno==ECONNREFUSED) return(1); + ERR_COD(errno); + } + return(0); + OnError: return(-1); +} + +int CocOpen(CocConn *conn) +{ + int i, try, tmo; + + ERR_I(i=CocConnect(conn, conn->startcmd[0]!='\0')); + if (i==0) return(0); + + printf("%s\n", conn->startcmd); + ERR_I(system(conn->startcmd)); + + try=15; + tmo=100; /* wait total ca. 10 sec. for 15 tries */ + while (try>0) { + try--; + CocDelay(tmo); tmo=tmo*5/4; + ERR_I(i=CocConnect(conn, try>0)); + if (i==0) return(0); + } + ERR_MSG("error in CocConnect"); + OnError: return(-1); +} + +/*-------------------------------------------------------------------------*/ + +int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd) { + assert(conn!=NULL); + if (bufsize==0) bufsize=1024; + ERR_P(conn->cmdbuf=str_create_buf(bufsize, '\0')); + ERR_P(conn->resbuf=str_create_buf(bufsize, '\0')); + 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; + conn->varList=NULL; + CocVarList(&conn->varList); + ERR_I(CocOpen(conn)); + ERR_I(CocSendMagic(conn, conn->magic)); + return(0); + OnError: return(-1); +} + +/*-------------------------------------------------------------------------*/ + +int CocSendMagic(CocConn *conn, char *magic) { + char *err; + + if (magic[0]!='#') ERR_MSG("magic must start with '#'"); + str_put_start(conn->resbuf); /* use return buffer for command in order to preserve command buffer */ + ERR_I(str_put_str(conn->resbuf, magic)); + ERR_SI(send(conn->fd, conn->resbuf->buf, conn->resbuf->wrpos, 0)); + ERR_I(CocRecv(conn->fd, conn->resbuf)); + ERR_P(err=str_get_str(conn->resbuf, NULL)); + if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0); goto OnError; } + ERR_I(str_get_end(conn->resbuf)); + return(0); + OnError: return(-1); +} + +/*-------------------------------------------------------------------------*/ + +int CocTryCmd(CocConn *conn) +{ if (conn->fd<0) { + ERR_I(CocOpen(conn)); + ERR_I(CocSendMagic(conn, conn->magic)); + } + ERR_SI(send(conn->fd, conn->cmdbuf->buf, conn->cmdbuf->wrpos, 0)); + ERR_I(CocRecv(conn->fd, conn->resbuf)); + return(0); + OnError: return(-1); +} + +/*-------------------------------------------------------------------------*/ + +int CocCmd(CocConn *conn, const char *rwList) +{ int iret, cnt, setmode, i; + char *err; + const char *t, *s; + char nam[32]; + CocVar *var; + void *adr; + + assert(conn!=NULL); + str_put_start(conn->cmdbuf); + s=rwList; + setmode=0; + do { + t=strchr(s, ','); + if (t==NULL) t=s+strlen(s); + if (*s=='[') { + if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "[")); + s++; + setmode=1; + } + i=t-s; + assert(i<32); + str_ncpy(nam, s, i+1); + if (setmode) { + if (nam[i-1]==']') { i--; nam[i]='\0'; setmode=0; } + ERR_I(str_put_str(conn->cmdbuf, nam)); + ERR_I(CocPutVar(conn->varList, conn->cmdbuf, nam, 0)); + if (!setmode) ERR_I(str_put_str(conn->cmdbuf, "]")); + } else { + var=CocFindVar(conn->varList, nam, NULL); + if (var==NULL) ERR_MSG("variable not found"); + ERR_I(str_put_str(conn->cmdbuf, nam)); + } + s=t+1; + } while (*t!='\0'); + + cnt=3; + while (1) { + cnt--; + if (cnt<=0) { + ERR_I(CocTryCmd(conn)); + break; + } + iret=CocTryCmd(conn); + if (iret>=0) break; + close(conn->fd); + conn->fd=-1; + if (ErrCode!=ECONNRESET && ErrCode!=EPIPE) goto OnError; + ErrWrite("try again, error was"); + } + ERR_P(err=str_get_str(conn->resbuf, NULL)); + if (*err!='\0') { ErrMsg(err); ErrTxt(": (response from server)",0 ); goto OnError; } + + /* read values */ + s=rwList; + setmode=0; + do { + t=strchr(s, ','); + if (t==NULL) t=s+strlen(s); + if (*s=='[') { + s++; + setmode=1; + } + i=t-s; + if (setmode) { + if (*(t-1)==']') setmode=0; + } else { + str_ncpy(nam, s, i+1); + ERR_I(CocGetVar(conn->varList, conn->resbuf, nam, 0)); + } + s=t+1; + } while (*t!='\0'); + ERR_I(str_get_end(conn->resbuf)); + return(0); + + OnError: return(-1); +} + +void CocCloseClient(CocConn *conn) { + assert(conn!=NULL); + close(conn->fd); + str_free_buf(conn->cmdbuf); + str_free_buf(conn->resbuf); + CocFreeVarList(&conn->varList); +} diff --git a/tecs/coc_client.h b/tecs/coc_client.h new file mode 100644 index 00000000..4df8bd06 --- /dev/null +++ b/tecs/coc_client.h @@ -0,0 +1,21 @@ +#ifndef _COC_CLIENT_H_ +#define _COC_CLIENT_H_ + +#include "coc_util.h" + +typedef struct { + int fd, port; + CocVar *varList; + Str_Buf *cmdbuf; /* for sending command */ + Str_Buf *resbuf; /* for response */ + char host[64]; + char magic[32]; + char startcmd[512]; +} CocConn; + +int CocInitClient(CocConn *conn, char *host, int port, char *magic, int bufsize, char *startcmd); +int CocSendMagic(CocConn *conn, char *magic); +int CocCmd(CocConn *conn, const char *rwList); +void CocCloseClient(CocConn *conn); + +#endif /* _COC_CLIENT_H_ */ diff --git a/tecs/coc_logfile.c b/tecs/coc_logfile.c new file mode 100644 index 00000000..0df4fb74 --- /dev/null +++ b/tecs/coc_logfile.c @@ -0,0 +1,239 @@ +/* switch off ANSI_C_SOURCE for VMS-extended fopen, even when compiling with /ANSI */ +#ifdef __VMS +#ifdef __HIDE_FORBIDDEN_NAMES +#undef __HIDE_FORBIDDEN_NAMES +#include +#define __HIDE_FORBIDDEN_NAMES +#else +#include +#endif +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include "coc_logfile.h" +#include "err_handling.h" +#include "str_util.h" + +static FILE *fil=NULL; +static char lnam[256]="", filnam[256]=""; +static char ebuf[20000]=""; +static char *eptr=&ebuf[0]; +static int lastStamp=0; +static int notDated=0; +static int logMask=0; +static int wrtMask=0; + +int ftime (struct timeb *__timeptr); /* for some reason not defined in timeb.h with flag -std1 */ + +static int logfileStd; +static int dirty, writeAll; + +void logfileOpen(int first) { + struct tm *tim; + struct timeb btim; + + if (logfileStd) { + fil=stdout; + return; + } + assert(fil==NULL); + if (first) { + ftime(&btim); + tim=localtime(&btim.time); + if (notDated) { + if (lnam[0]=='\0') { + str_copy(filnam, "test.log"); + } else { + str_copy(filnam, lnam); + str_append(filnam, ".log"); + } + } else { + sprintf(filnam, "%s%04d-%02d-%02d.log", lnam, tim->tm_year+1900, tim->tm_mon+1, tim->tm_mday); + } + } else { + assert(filnam[0]!='\0'); + } +#ifdef __VMS + if (first && notDated) { + fil=fopen(filnam, "w", "SHR=UPD"); /* new version at restart */ + } else { + fil=fopen(filnam, "a", "SHR=UPD"); + } +#else + if (first && notDated) { + fil=fopen(filnam, "w"); /* overwrite at restart */ + } else { + fil=fopen(filnam, "a"); + } +#endif +} + +void logfileInit(char *path, int nodate, int use_stdout, int write_all) { + str_copy(lnam, path); + lastStamp=-1; + logfileStd=use_stdout; + writeAll=write_all; + notDated=nodate; + logfileOpen(1); +} + +void logfileOut(int mask, const char *fmt, ...) +{ va_list ap; + + assert(mask>0 && mask<32); + va_start(ap, fmt); + + if (writeAll) { +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + vfprintf(fil, fmt, ap); + wrtMask=LOG_ALL; + } else { + if (eptr!=NULL) { + if (eptr-ebuf > sizeof(ebuf)-512) { + sprintf(eptr, "... buffer full ... \1\1"); + eptr=NULL; + } else { + vsprintf(eptr, fmt, ap); + assert(NULL==strchr(eptr, '\1')); + eptr+=strlen(eptr); + eptr[0]='\1'; /* put \1 as separator between blocks */ + eptr[1]=mask; + eptr[2]='\0'; + eptr+=2; + } + } + wrtMask=wrtMask | mask; + } + va_end(ap); +} + +void logfileMask(int mask) { + logMask=logMask | mask; +} + +void logfileStamp(void) { + struct tm *tim; + struct timeb btim; + int stamp; + + ftime(&btim); + tim=localtime(&btim.time); + stamp=tim->tm_hour*60+tim->tm_min; + if (stamp!=lastStamp) { + if (stamp new day -> new logfile */ + if (fil!=NULL) { fclose(fil); fil=NULL; } + logfileOpen(1); + } +#ifdef __VMS + else if (fil==NULL) logfileOpen(0); +#endif + lastStamp=stamp; + fprintf(fil, "--- %02d:%02d:%02d ---\n", tim->tm_hour, tim->tm_min, tim->tm_sec); + dirty=0; + } +} + +void logfileWrite0(int mask) { + char *s, *next; + + logMask=logMask | mask; + if (dirty) logfileStamp(); /* there was something written since last time */ + + s=ebuf; + if (writeAll || *s!='\0' && wrtMask & logMask) { + logfileStamp(); /* write stamp before write something */ + next=strchr(s, '\1'); + while (next!=NULL) { + *next='\0'; + next++; + if (*next & logMask) { + fprintf(fil, "%s", s); + dirty=1; + } + s=next+1; + next=strchr(s, '\1'); + } + } + ebuf[0]='\0'; + eptr=&ebuf[0]; + logMask=0; + wrtMask=0; +} + +void logfileWrite(int mask) { + +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(mask); +#ifdef __VMS + if (!logfileStd) { fclose(fil); fil=NULL; } +#else + fflush(fil); +#endif + +} + +void logfileShowErr(char *text) +{ +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(LOG_ALL); /* write all */ + ErrWrite(text); +#ifdef __VMS + if (!logfileStd) { fclose(fil); fil=NULL; } +#else + fflush(fil); +#endif +} + +void logfileClose() +{ +#ifdef __VMS + if (fil==NULL) logfileOpen(0); +#endif + logfileWrite0(LOG_MAIN+LOG_WARN); + lastStamp-=1; + logfileStamp(); + if (fil!=NULL) { fclose(fil); fil=NULL; } + filnam[0]='\0'; +} + +void logfileOutBuf(int mask, Str_Buf *buf) +{ char str[256]; + int rd0, sep; + + rd0=buf->rdpos; + if (buf->rdpos < 0 || buf->rdpos >= buf->dsize + || buf->wrpos < 0 || buf->wrpos >= buf->dsize) { + logfileOut(mask, ""); return; + } + sep=0; + while (buf->rdpos < buf->wrpos) { + str_get_str(buf, str); + if (buf->sep=='\0') { + if (sep) logfileOut(mask, " "); + if (*str=='\0') { + logfileOut(mask, "."); + } else { + logfileOut(mask, "%s", str); + } + sep=1; + } else { + if (sep) logfileOut(mask, "%c", buf->sep); + logfileOut(mask, "%s", str); + sep=1; + } + } + buf->rdpos=rd0; +} diff --git a/tecs/coc_logfile.h b/tecs/coc_logfile.h new file mode 100644 index 00000000..fdf9791a --- /dev/null +++ b/tecs/coc_logfile.h @@ -0,0 +1,20 @@ +#ifndef _COC_LOGFILE_H_ +#define _COC_LOGFILE_H_ + +#include "str_buf.h" + +#define LOG_ALL 31 +#define LOG_SER 8 +#define LOG_NET 4 +#define LOG_WARN 2 +#define LOG_MAIN 1 + +void logfileInit(char *path, int nodate, int use_stdout, int write_all); +void logfileOut(int mask, const char *fmt, ...); +void logfileOutBuf(int mask, Str_Buf *buf); +void logfileShowErr(char *text); +void logfileMask(int mask); +void logfileWrite(int mask); +void logfileClose(void); + +#endif /* _COC_LOGFILE_H_ */ diff --git a/tecs/coc_server.c b/tecs/coc_server.c new file mode 100644 index 00000000..a77713fd --- /dev/null +++ b/tecs/coc_server.c @@ -0,0 +1,242 @@ +/* needed to define accept() and gethostbyaddr() correctly when using flag -std1 +*/ +#ifdef __unix__ +#ifndef _XOPEN_SOURCE_EXTENDED +#define _XOPEN_SOURCE_EXTENDED +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "err_handling.h" +#include "coc_logfile.h" +#include "coc_server.h" +#include "str_util.h" + +static Str_Buf *buf, *bufo; + +static fd_set mask, rmask; +static int maxfd; +struct CocClient *cList, *cLastCmd=NULL; +static int mainFd; +static int modified; + +int CocInitServer(int bufsize, int port) { + int i; + struct sockaddr_in sadr; + char *err; + + if (bufsize==0) bufsize=1024; + ERR_P(buf=str_create_buf(bufsize, '\0')); + ERR_P(bufo=str_create_buf(bufsize,'\0')); + cList=malloc(sizeof(*cList)); /* empty header */ + + /* first try to connect to an existing server */ + + 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))); + logfileOut(LOG_MAIN, "created server on port %d\n", port); + ERR_SI(listen(mainFd, 8)); + FD_ZERO(&mask); + FD_SET(mainFd, &mask); + maxfd=mainFd+1; + return(0); + OnError: return(-1); +} + +int CocHandle1Request(int tmo_msec, int fd) { + struct sockaddr_in cadr; + struct hostent *h; + struct timeval tmo={0,1}; + struct CocClient *cl, *cl0; + int i, newfd, setmode; + size_t cadrlen; + char *err, *varname; + + 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)) { + ERR_SI(newfd=accept(mainFd, (struct sockaddr *)&cadr, &cadrlen)); + FD_SET(newfd, &mask); + if (newfd>=maxfd) maxfd=newfd+1; + cl=cList; + cl->fd=newfd; + cl->mode=0; + cl->cmd[0]='\0'; + cl->res[0]='\0'; + cList=malloc(sizeof(*cList)); + cList->next=cl; + h=gethostbyaddr(&cadr.sin_addr, 4, AF_INET); + if (h==NULL) { + logfileOut(LOG_MAIN, "(%d) open from %s\n", newfd, "local"); + } else { + logfileOut(LOG_MAIN, "(%d) open from %s\n", newfd, h->h_name); + } + } else { + cl0=cList; cl=cl0->next; + while (cl!=NULL) { + if (FD_ISSET(cl->fd, &rmask)) { + buf->wrpos=recv(cl->fd, buf->buf, buf->dsize, 0); + if (buf->wrpos<=0) { + logfileOut(LOG_MAIN, "(%d) disconnected\n",cl->fd); + close(cl->fd); + FD_CLR(cl->fd, &mask); + cl0->next=cl->next; + free(cl); + cl=cl0; + } else { + + str_put_start(bufo); + str_get_start(buf); + ERR_I(str_put_str(bufo, "")); /* empty error message */ + setmode=0; + err=NULL; + ERR_P(varname=str_get_str(buf, NULL)); + logfileOut(LOG_NET, "(%d) ", cl->fd); + if (varname[0]=='#') { /* access code */ + if (0==strcmp(varname,"#rdacc")) { + logfileOut(LOG_MAIN, "set read mode\n"); + cl->mode=1; + } else if (0==strcmp(varname,"#rwacs")) { + logfileOut(LOG_MAIN, "set write mode\n"); + cl->mode=2; + } else { + err="bad access code"; + } + } else if (cl->mode==0) { + err="no access"; + } else { + while (1) { + if (varname[0]=='[') { + if (cl->mode<2) { err="no write access"; break; } + setmode=1; /* switch to set mode */ + } else if (varname[0]==']') { /* switch to read mode */ + setmode=0; + } else if (setmode) { + if (0==strcmp("$", varname)) { /* special case: command */ + ERR_P(str_get_str(buf, cl->cmd)); + cl->res[0]='\0'; + } else { + i=CocGetVar(serverVarList, buf, varname, 1); + if (i<0) { err=ErrMessage; break; } + } + modified=1; + } else { + if (0==strcmp("$", varname)) { /* special case: response */ + ERR_I(str_put_str(bufo, cl->res)); + cl->res[0]='\0'; + } else { + i=CocPutVar(serverVarList, bufo, varname, 0); + if (i<0) { err=ErrMessage; break; } + } + } + if (buf->rdpos>=buf->wrpos) { + ERR_I(str_get_end(buf)); + break; + } + ERR_P(varname=str_get_str(buf, NULL)); + } + str_get_start(buf); + logfileOutBuf(LOG_NET, buf); + str_get_start(bufo); + logfileOut(LOG_NET, " |"); + logfileOutBuf(LOG_NET, bufo); + } + if (err==NULL) { + logfileOut(LOG_NET, "\n"); + } else { + str_put_start(bufo); /* reset output */ + str_put_str(bufo, err); /* put error message */ + logfileOut(LOG_NET, " (%s)\n", err); + logfileMask(LOG_NET); + } + ERR_SI(send(cl->fd, bufo->buf, bufo->wrpos, 0)); + } + } + cl0=cl; cl=cl->next; + } + } + if (modified) return(2); + return(3); + OnError: return(-1); +} + +int CocHandleRequests(int tmo_msec, int fd) { + struct timeb tim1, tim0; + int tdif, iret; + + if (modified && fd==0) { /* earlier modification */ + modified=0; + return(2); + } + ftime(&tim0); + tdif=tmo_msec; + while (tdif>=0) { + ERR_I(iret=CocHandle1Request(tdif, fd)); + if (fd==0) { + if (iret==2) return(2); /* modification of a varaible */ + } else { + if (iret==1) return(1); /* event on fd */ + } + if (iret==0) return(0); /* timeout */ + ftime(&tim1); + tdif=tmo_msec-((tim1.time-tim0.time)*1000+tim1.millitm-tim0.millitm); + } + return(0); /* timeout */ + OnError: return(-1); +} + +struct CocClient *CocGetNextCmd() { + struct CocClient *cl; + + cl=cLastCmd; + while (cl!=NULL) { + if (cl->cmd[0]!='\0') { + cLastCmd=cl->next; + return(cl); + } + cl=cl->next; + } + cl=cList->next; + while (cl!=NULL && cl!=cLastCmd) { + if (cl->cmd[0]!='\0') { + cLastCmd=cl->next; + return(cl); + } + cl=cl->next; + } + return(NULL); +} + +void CocCloseServer() { + struct CocClient *cl, *cl0; + + cl=cList->next; + while (cl!=NULL) { + close(cl->fd); + cl0=cl; + cl=cl->next; + free(cl0); + } + free(cList); + close(mainFd); + str_free_buf(buf); str_free_buf(bufo); + logfileClose(); +} diff --git a/tecs/coc_server.h b/tecs/coc_server.h new file mode 100644 index 00000000..3df226ef --- /dev/null +++ b/tecs/coc_server.h @@ -0,0 +1,40 @@ +#ifndef _SERVER_H_ +#define _SERVER_H_ + +#include "coc_util.h" + +struct CocClient { struct CocClient *next; int fd; int mode; char cmd[80]; char res[80]; }; + +int CocInitServer(int bufsize, 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) + +*/ + +struct CocClient *CocGetNextCmd(void); +/* + get next client with a pending command +*/ + +void CocCloseServer(void); + +#endif /* _SERVER_H_ */ diff --git a/tecs/coc_util.c b/tecs/coc_util.c new file mode 100644 index 00000000..73253bbd --- /dev/null +++ b/tecs/coc_util.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "err_handling.h" +#include "str_util.h" +#include "coc_util.h" +/*-------------------------------------------------------------------------*/ +/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */ + +CocVar *serverVarList=NULL; +static CocVar **varListHdl=&serverVarList; +int CocRD=0; +int CocWR=0; + +int CocCreateSockAdr( + struct sockaddr_in *sockaddrPtr, /* Socket address */ + const char *host, /* Host. NULL implies INADDR_ANY */ + int port) /* Port number */ +{ + struct hostent *hostent; /* Host database entry */ + struct in_addr addr; /* For 64/32 bit madness */ + + (void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in)); + sockaddrPtr->sin_family = AF_INET; + sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF)); + if (host == NULL || 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 CocRecv(int fd, Str_Buf *buf) +{ + struct timeval tmo={0,1}; + fd_set mask; + int i; + + tmo.tv_sec=5; /* timeout 5 sec. */ + + FD_ZERO(&mask); + FD_SET(fd, &mask); + ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo)); + if (i==0) ERR_MSG("time out"); + + ERR_SI(buf->wrpos=recv(fd, buf->buf, buf->dsize, 0)); + if (buf->wrpos==0) { ERR_COD(ECONNRESET); } + str_get_start(buf); + return(buf->wrpos); + OnError: return(-1); +} + +void CocVarList(CocVar **varList) { + assert(varList!=NULL); + varListHdl=varList; +} + +void CocList() { + CocVar *p; + + p=*varListHdl; + while (p!=NULL) { + printf("%s %d\n", p->name, p->type); + p=p->next; + } +} + +CocVar *CocFindVar1(CocVar *varList, const char *name) { + CocVar *p; + + p=varList; + while (p!=NULL && 0!=strcmp(p->name,name)) p=p->next; + return(p); +} + +CocVar *CocFindVar(CocVar *varList, const char *name, void **adr) { + CocVar *p, *t; + const char *f; + void *base; + char nam[32]; + + f=str_split(nam, name, '.'); + if (f==NULL) { + f=str_split(nam, name, '-'); + if (f!=NULL) { + if (f[0]!='>') { + f=NULL; + } else { + f++; + } + } + } + if (f!=NULL) { + if (adr!=NULL) *adr=NULL; + p=CocFindVar1(varList, nam); + if (p==NULL) { return(NULL); } + t=p->strucType; + if (t==NULL) { return(NULL); } + str_copy(nam, t->name); + str_append(nam, ":"); + str_append(nam, f); + if (adr!=NULL) { + base=p->var; + if (p->type==COC_PTR) base=*(void **)base; + *adr=base; + } + } else if (adr!=NULL) { + *adr=NULL; + } + p=CocFindVar1(varList, nam); + if (p!=NULL && p->type==COC_ALIAS) { /* recursive call for alias */ + p=CocFindVar(varList, p->var, adr); + } + return(p); +} + +CocVar *CocDefVar(const char *name, void *var, int type, int *flag) { + CocVar *p; + const char *f; + void *adr; + + assert(varListHdl!=NULL); + p=CocFindVar1(*varListHdl, name); + if (p==NULL) { + p=malloc(sizeof(*p)); + p->next=*varListHdl; + *varListHdl=p; + str_copy(p->name, name); + } + p->var=var; + p->type=type; + p->flag=flag; + return(p); +} + +void CocDefVarS(const char *name, const char *tname, void *var, int type) { + CocVar *p, *t; + + assert(type==COC_PTR || type==COC_STRUCT); + p=CocDefVar(name, var, type, &CocRD); + p->strucType=CocDefVar(tname, NULL, COC_TYPE, &CocRD); +} + +int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { + CocVar *var; + void *adr; + + var=CocFindVar(varList, name, &adr); + if (var==NULL) ERR_MSG("undefined variable"); + if (adr==NULL) { + adr=var->var; + } else { + adr=(char *)adr + (int)var->var; + } + if (secure) { /* we are the server */ + if (var->flag==&CocRD) ERR_MSG("variable is read only"); + } + if (var->type==-1) { + ERR_I(str_get_int(buf, (int *)adr)); + } else if (var->type==-2) { + ERR_I(str_get_float(buf, (float *)adr)); + } else if (var->type>1) { + ERR_P(str_nget_str(buf, (char *)adr, var->type)); + } else { + ERR_MSG("unknown type"); + } + if (secure) { /* we are the server */ + (*var->flag)++; + } + return(0); + OnError: return(-1); +} + +int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure) { + CocVar *var; + void *adr; + char *c; + + var=CocFindVar(varList, name, &adr); + if (var==NULL) ERR_MSG("undefined variable"); + if (adr==NULL) { + adr=var->var; + } else { + adr=(char *)adr + (int)var->var; + } + if (secure) { /* we are the client */ + if (var->flag==&CocRD) ERR_MSG("variable is read only"); + } + if (var->type==-1) { + ERR_I(str_put_int(buf, *(int *)adr)); + } else if (var->type==-2) { + ERR_I(str_put_float(buf, *(float *)adr)); + } else if (var->type>1) { + ERR_I(str_put_str(buf, adr)); + } else { + ERR_MSG("unknown type"); + } + if (secure) { /* we are a client */ + if (var->flag!=NULL) (*var->flag)++; + } + return(0); + OnError: return(-1); +} + +void CocFreeVarList(CocVar **varList) { + CocVar *p, *v; + + if (varList==NULL) varList=&serverVarList; + v=*varList; + while (v!=NULL) { + p=v; + v=p->next; + p->next=NULL; + free(p); + } + *varList=NULL; +} + +void CocDelay(int msec) { + struct timeval tmo; + + tmo.tv_sec=msec / 1000; + tmo.tv_usec=(msec % 1000)*1000+1; + select(1,NULL,NULL,NULL,&tmo); +} diff --git a/tecs/coc_util.h b/tecs/coc_util.h new file mode 100644 index 00000000..2c39f2b2 --- /dev/null +++ b/tecs/coc_util.h @@ -0,0 +1,47 @@ +#ifndef _COC_UTIL_H_ +#define _COC_UTIL_H_ + +#include +#include "str_buf.h" + +int CocCreateSockAdr( + struct sockaddr_in *sockaddrPtr, /* Socket address */ + const char *host, /* Host. NULL implies INADDR_ANY */ + int port); /* Port number */ +int CocRecv(int fd, Str_Buf *buf); + +typedef struct { void *next; char name[32]; void *var; int *flag; int type; void *strucType; } CocVar; + +extern int CocRD; +extern int CocWR; +CocVar *serverVarList; + +CocVar *CocDefVar(const char *name, void *var, int type, int *flag); +void CocDefVarS(const char *name, const char *tname, void *var, int type); +void CocVarList(CocVar **varlist); +void CocFreeVarList(CocVar **varList); +CocVar *CocFindVar(CocVar *varList, const char *name, void **adr); +int CocPutVar(CocVar *varList, Str_Buf *buf, const char *name, int secure); +int CocGetVar(CocVar *varList, Str_Buf *buf, const char *name, int secure); + +#define COC_INT -1 +#define COC_FLT -2 +#define COC_PTR -3 +#define COC_STRUCT -4 +#define COC_TYPE -5 +#define COC_ALIAS -6 +#define CocDefInt(V,F) CocDefVar(#V,&V,COC_INT,&F) +#define CocDefFlt(V,F) CocDefVar(#V,&V,COC_FLT,&F) +#define CocDefStr(V,F) CocDefVar(#V,V,sizeof(V),&F) +#define CocDefPtr(V,S) CocDefVarS(#V,#S,&V,COC_PTR*(V!=(S *)NULL)); +#define CocDefStruct(V,S) CocDefVarS(#V,#S,&V,COC_STRUCT*(&V!=(S *)NULL)); +#define CocIntFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_INT,&F); +#define CocFltFld(S,V,F) CocDefVar(#S":"#V,&((S *)NULL)->V,COC_FLT,&F); +#define CocStrFld(S,V,F) CocDefVar(#S":"#V,((S *)NULL)->V,sizeof(((S *)NULL)->V),&F); +#define CocDefCmd(V) CocDefVar("$",V,sizeof(V),&CocWR) +#define CocDefStrPtr(V,S,F) CocDefVar(#V,V,S,&F) +#define CocAlias(A,V) CocDefVar(#A, #V, COC_ALIAS, &CocRD); + +void CocDelay(int msec); + +#endif /* _COC_UTIL_H_ */ diff --git a/tecs/dlog.c b/tecs/dlog.c index 52bcfe11..b54f4abb 100644 --- a/tecs/dlog.c +++ b/tecs/dlog.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,8 @@ #define DEFINED(F) (abs((F)-dset->undef)>1.0e-5*(F)) +static time_t gmtoff; + int DlogWrite(DlogSet *dset, int idx, void *data) { int p; @@ -50,23 +53,26 @@ int DlogRead(DlogSet *dset, int idx, void *data) { } int DlogOpen(DlogSet *dset, char *name, int write) { - int i, p, np, fd; + int i, p, np, fd, flags; + time_t tim; + struct tm *timp; fd=0; str_copy(dset->name, name); if (write) { -#ifdef __VMS - ERR_SI(fd=open(name, O_RDWR | O_SYNC, 0, "SHR=UPD")); -#else - ERR_SI(fd=open(name, O_RDWR | O_SYNC, 0)); -#endif + flags=O_RDWR | O_SYNC; } else { -#ifdef __VMS - ERR_SI(fd=open(name, O_RDONLY | O_SYNC, 0, "SHR=UPD")); -#else - ERR_SI(fd=open(name, O_RDONLY | O_SYNC, 0)); -#endif + flags=O_RDONLY | O_SYNC; } +#ifdef __VMS + ERR_SI(fd=open(name, flags, 0, "SHR=UPD")); + gmtoff=0; +#else + ERR_SI(fd=open(name, flags, 0)); + time(&tim); + timp=localtime(&tim); + gmtoff=timp->tm_gmtoff; +#endif dset->fd=fd; p=(char *)&dset->fd - (char *)dset; @@ -162,7 +168,7 @@ int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float x[], flo } i0=i1; - *starttime = dset->start + i1 * dset->period; + *starttime = dset->start + i1 * dset->period + gmtoff; n=0; undef=2; while (i0<=i) { @@ -203,7 +209,7 @@ int DlogGetMany(DlogSet *dset, int nset, int nmax, double *starttime, float x[], return(-1); } -int Dlog_Get_(char *name, int *nset, int *nmax, double *starttime, float x[], float y[], int index[], int namlen) { +int dlog_get_(char *name, int *nset, int *nmax, double *starttime, float x[], float y[], int index[], int namlen) { DlogSet dset; char buf[64]; int ntot; @@ -214,13 +220,13 @@ int Dlog_Get_(char *name, int *nset, int *nmax, double *starttime, float x[], fl DlogClose(&dset); return(ntot); OnError: - ErrShow("error in Dlog_Get"); + ErrShow("error in dlog_get_"); return(-1); } int Dlog_Get(char **name, int *nset, int *nmax, double *starttime, float x[], float y[], int index[]) { /* for VMS */ - return(Dlog_Get_(name[1], nset, nmax, starttime, x, y, index, *(short *)name)); + return(dlog_get_(name[1], nset, nmax, starttime, x, y, index, *(short *)name)); } int DlogUpd(DlogSet *dset) { diff --git a/tecs/err_handling.c b/tecs/err_handling.c new file mode 100644 index 00000000..06bec9c9 --- /dev/null +++ b/tecs/err_handling.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include "err_handling.h" + +#define SLEN 64 +#define MLEN 64 + +static char *txt[SLEN]; +static int sp=0; + +int ErrCode; +char *ErrMessage=NULL; +void (*outrtn)()=NULL; +void *outarg; + +void ErrTxt(char *text, int systemError) +{ + if (systemError) { sp=0; ErrCode=errno; ErrMessage=strerror(errno); } + if (spsize; + if (l>=256) l=255; + strncpy(buf, desc->text, l); + buf[l]='\0'; + ErrWrite(buf); +} + +#endif + +void ERR_EXIT(char *text) { + ErrWrite(text); exit(1); +} diff --git a/tecs/err_handling.h b/tecs/err_handling.h new file mode 100644 index 00000000..75303362 --- /dev/null +++ b/tecs/err_handling.h @@ -0,0 +1,83 @@ +#ifndef _ERR_HANDLING_H_ +#define _ERR_HANDLING_H_ + +#include + +/* ErrHDL Error handling utilities + ------------------------------- + Makes code more readable by hiding annoying error condition checks. + +Macros and routines: + + Spelling in uppercase indicates, that it the program flow + may be modified (jump to OnError label or program exit). + + + ERR_x + + Usage Error condition Error message taken from + ----------------------------------------------------------------------------------------- + ERR_SI(res=routine1(...)) res<0 errno + ERR_SP(ptr=routine2(...)) ptr==NULL errno + ERR_I(res=routine3(...)) res<0 stored by routine3 using errhdl mechanism + ERR_P(ptr=routine4(...)) ptr==NULL stored by routine4 using errhdl mechanism + + The result assignment "res=" or "ptr=" is optional. + + Description: + The routine routineX is called. + If the result indicates an error, the source text is saved and the + program continues at the OnError label. + The error message and the source code of the calling instructions is + saved for a later call to ErrShow or ErrExit. + + ERR_EXIT("program_name") + + Show error and exit program. + + ERR_MSG("message") + + Signals an error condition. If "message" is replaced by a variable, + take care that it is not modified until ErrShow is called. + + ERR_COD(cod) + + Signals an error condition as code from errno.h + + ErrShow("program_name") + ErrWrite(fil, "program_name") + + Show actual error message with traceback information to stdout + or a file fil + +Global Variables (read only) + + int ErrCode + + actual error message code + = errno for system errors or + = -1 for custom errors signaled by ERRMSG + + char *ErrMessage + + actual error message +*/ + +#define ERR_SI(R) { if(0>(R)) { ErrTxt(#R,1); goto OnError; }; } +#define ERR_SP(R) { if(NULL==(R)) { ErrTxt(#R,1); goto OnError; }; } +#define ERR_I(R) { if(0>(R)) { ErrTxt(#R,0); goto OnError; }; } +#define ERR_P(R) { if(NULL==(R)) { ErrTxt(#R,0); goto OnError; }; } +#define ERR_MSG(R) { ErrMsg(R); goto OnError; } +#define ERR_COD(R) { ErrCod(R); goto OnError; } + +void ErrTxt(char *text, int systemError); +void ErrMsg(char *msg); +void ErrCod(int code); +void ErrWrite(char *text); +void ERR_EXIT(char *text); +void ErrLog(char *text); + +extern int ErrCode; +extern char *ErrMessage; + +#endif /* _ERR_HANDLING_H_ */ diff --git a/tecs/lsc.c b/tecs/lsc.c index 9b32ec6a..840e41f2 100644 --- a/tecs/lsc.c +++ b/tecs/lsc.c @@ -150,21 +150,18 @@ char *LscCmd(SerChannel *ser, const char *cmds) { } } if (retreq!=NULL) { /* query */ - if (retreq[1]=='>') { /* >> get whole response */ - str_link_buf(&sbuf, result, 0, ';'); - str_split(varname, retreq+2, ';'); - ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0)); - } else { - str_link_buf(&sbuf, result, 0, ','); - str_split(par, retreq+1, ';'); - p=par; - while (p!=NULL) { - p=str_split(varname, p, ','); - if (varname[0]!='\0') { - ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0)); - } else { - ERR_P(str_get_str(&sbuf, NULL)); + str_link_buf(&sbuf, result, 0, ','); + 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 */ + sbuf.sep='\0'; } + ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0)); + } else { + ERR_P(str_get_str(&sbuf, NULL)); } } } @@ -172,70 +169,3 @@ char *LscCmd(SerChannel *ser, const char *cmds) { return(res); OnError: return(NULL); } - -int LscCmdChk(SerChannel *ser, char *cmds) { - char *b, *o, *cn, *c, *d, *r, *res; - char *clist[MC], *plist[MC], *rlist[MC], *olist[MC]; - char obuf[SER_BUF_LEN], r1[SER_BUF_LEN]; - int i,n,m,j,cnt,l; - - if (NULL!=strchr(cmds, '?')) ERR_COD(EINVAL); - cn=cmds; - o=&obuf[0]; - m=MC; - do { - n=m; - cn=str_splitx(cn, ';', clist, &n); - for (i=0; id) { - *d=' '; b=d; - } else { - *d=','; - } - plist[i]=d+1; - l=strlen(c); - if ((o-&obuf[0])+l+(d-c)+2>SER_BUF_LEN) ERR_COD(ENOBUFS); - olist[i]=o; - strcpy(o, c); o+=l; - *o=';'; o++; - strncpy(o, c, d-c); - o[b-c]='?'; o+=d-c; - if (b==d) o++; - *o=';'; o++; - }; - o--; *o='\0'; - cnt=0; - do { - cnt++; - if (cnt>3) ERR_MSG("can not set parameter"); - ERR_P(res=SerCmd(ser, obuf)); - if (cnt>0) { - if (0==strcmp(r1, res)) break; /* got two times the same result */ - } - strcpy(r1, res); - j=n; - r=str_splitx(res, ';', rlist, &n); - if (r==NULL || n!=j) continue; - for (i=0; i +#include #include #include #include #include -#include "errhdl.h" +#include "err_handling.h" #include "str_util.h" #include "str_buf.h" diff --git a/tecs/str_util.c b/tecs/str_util.c index ede8724c..9d4346ce 100644 --- a/tecs/str_util.c +++ b/tecs/str_util.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -5,7 +7,7 @@ #include #include #include -#include "errhdl.h" +#include "err_handling.h" #include "str_util.h" char *str_splitx(char *str, char sep, char *list[], int *n) { diff --git a/tecs/str_util.h b/tecs/str_util.h index 741fd265..e231abf6 100644 --- a/tecs/str_util.h +++ b/tecs/str_util.h @@ -74,7 +74,7 @@ void str_nupcase(char *dst, const char *src, int dstlen); */ #ifdef __VMS_VER -#if _VMS_VER<70000000 +#if __VMS_VER<70000000 int strcasecmp(const char *str1, const char *str2); /* diff --git a/tecs/tecs.c b/tecs/tecs.c index c2137f91..117d65a7 100644 --- a/tecs/tecs.c +++ b/tecs/tecs.c @@ -1,14 +1,16 @@ #include +#include +#include #include #include #include #include -#include "errhdl.h" -#include "server.h" -#include "logfile.h" +#include "err_handling.h" +#include "coc_server.h" +#include "coc_logfile.h" #include "str_util.h" -#include "lsc.h" -#include "dlog.h" +#include "tecs_lsc.h" +#include "tecs_dlog.h" #define TABLE_FILE "lsc.tab" #define NO_CODE 999 @@ -146,7 +148,7 @@ int instCurve(char *nam, char *channel) { if (num>20) ERR_MSG("illegal standard curve number"); retstat=-1; /* an error could be fixed */ - ERR_P(LscCmd(ser, "CRVHDR?[num]>>head")); + ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); } else { @@ -189,7 +191,7 @@ int instCurve(char *nam, char *channel) { if (num<21 || num>60) ERR_MSG("illegal curve number"); retstat=-1; /* an error could be fixed */ - ERR_P(LscCmd(ser, "CRVHDR?[num]>>head")); + ERR_P(LscCmd(ser, "CRVHDR?[num]>head")); e=strchr(entry, '\n'); if (e!=NULL) { *e='\0'; e++; } @@ -216,7 +218,7 @@ int instCurve(char *nam, char *channel) { n=3; do { - ERR_P(LscCmd(ser, "CRVDEL [num];CRVHDR?[num]>buf1")); + ERR_P(LscCmd(ser, "CRVDEL [num];CRVHDR?[num]>buf1,")); buf1[4]='\0'; i=strcmp(buf1, "User"); n--; @@ -359,7 +361,7 @@ int loadCache() { bufi[2]=buf3; bufi[3]=buf4; for (i=60; i>21; i-=4) { - sprintf(buf, "CRVHDR?%d>>buf1;CRVHDR?%d>>buf2;CRVHDR?%d>>buf3;CRVHDR?%d>>buf4", i, i-1, i-2, i-3); + sprintf(buf, "CRVHDR?%d>buf1;CRVHDR?%d>buf2;CRVHDR?%d>buf3;CRVHDR?%d>buf4", i, i-1, i-2, i-3); ERR_P(LscCmd(ser, buf)); k=0; for (j=i; j>i-4; j--) { @@ -422,7 +424,7 @@ int SetTemp(int switchOn) { str_copy(chan, ch); tempH=tempC+tShift; if (switchOn) { - ERR_P(LscCmd(ser, "CSET 1:[chan],1;RANGE:5;SETP 1:[tempH]")); + ERR_P(LscCmd(ser, "CSET 1:[chan],1,1,0;RANGE:[iRange];SETP 1:[tempH]")); } else { ERR_P(LscCmd(ser, "CSET 1:[chan],1;SETP 1:[tempH]")); } @@ -445,7 +447,7 @@ int ReadTemp() { if (noResp) { /* check serial number */ k=serialNo; - ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo")); + ERR_P(LscCmd(ser, "*IDN?>buf1,buf2,serialNo,")); if (0!=strcmp(buf1, "LSCI") || 0!=strcmp(buf2, "MODEL340") || serialNo==0) return(0); if (k!=serialNo) { if (cryo.manual || cryo.code!=0) cryo.dirty=1; @@ -615,7 +617,11 @@ int Settings() { } } power=pw; - ERR_P(LscCmd(ser, "CLIMIT 1:[tLimit],0,0,[iAmp],[iRange];CSET 1:[cryo.ch1],1,1,0")); /* some times .ch2? */ + logfileOut(LOG_MAIN, "power %f\n", power, iAmp, iRange); + ERR_P(LscCmd(ser, "CLIMIT 1:[tLimit],0,0,[iAmp],[iRange]")); + tempC=0.001; tShift=0; + ERR_I(SetTemp(1)); + tempC=0; } if (samp.nSens>=cryo.nSens) { maxfld=2*samp.nSens; diff --git a/tecs/tecs_cli.c b/tecs/tecs_cli.c new file mode 100644 index 00000000..22f87b70 --- /dev/null +++ b/tecs/tecs_cli.c @@ -0,0 +1,143 @@ +#include +#include +#include "err_handling.h" +#include "str_util.h" +#include "tecs_cli.h" + +static char device[80], command[80]; +static int quit; +static float tempX, tempP, tempC; + +pTecsClient TeccInit(char *startcmd, int port) { + CocConn *conn; + + ERR_SP(conn=(CocConn *)malloc(sizeof(*conn))); + ERR_I(CocInitClient(conn, "", port, "#rwacs", 0, startcmd)); + CocDefFlt(tempC, CocRD); + CocDefFlt(tempP, CocRD); + CocDefFlt(tempX, CocRD); + CocDefStr(device, CocWR); + CocDefInt(quit, CocWR); + CocDefCmd(command); + + return((pTecsClient)conn); + OnError: return(NULL); +} + +int TeccSetDev(pTecsClient conn, char *dev) { + str_copy(device, dev); + ERR_I(CocCmd(conn, "[device]")); + return(0); + OnError: return(-1); +} + +char *TeccGetDev(pTecsClient conn) { + ERR_I(CocCmd(conn, "device")); + return(device); + OnError: return(NULL); +} + +int TeccGet3(pTecsClient conn, float *tC, float *tX, float *tP) { + ERR_I(CocCmd(conn, "tempC,tempX,tempP")); + *tC=tempC; + *tX=tempX; + *tP=tempP; + return(0); + OnError: return(-1); +} + +int TeccGet(pTecsClient conn, float *temp) { + ERR_I(CocCmd(conn, "tempP")); + *temp=tempP; + return(0); + OnError: return(-1); +} + +int TeccSet(pTecsClient conn, float temp) { + tempC=temp; + ERR_I(CocCmd(conn, "[tempC]")); + return(0); + OnError: return(-1); +} + +int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen) { + char *res; + int cnt; + + str_copy(command, cmd); + ERR_I(CocCmd(conn, "[$]")); + cnt=40; + CocDelay(100); + while (cnt>0) { + ERR_I(CocCmd(conn, "$")); + if (command[0]!='\0') { + str_ncpy(reply, command, replyLen); + return(0); + } + CocDelay(250); + cnt--; + } + str_ncpy(reply, "", replyLen); + return(0); + OnError: return(-1); +} + +int TeccQuitServer(pTecsClient conn) { + quit=1; + ERR_I(CocCmd(conn, "[quit]")); + return(0); + OnError: return(-1); +} + +void TeccClose(pTecsClient conn) { + if (conn!=NULL) { + CocCloseClient(conn); + free(conn); + } +} + +#ifdef __VMS + +int TeccSetDevVms(pTecsClient conn, char **dev) { + int l; + + l=*(short *)dev; + if (l>=sizeof(device)) l=sizeof(device)-1; + strncpy(device, dev[1], l); + while (l>0 && device[l-1]==' ') l--; /* trim */ + device[l]='\0'; + ERR_I(CocCmd(conn, "[device]")); + return(0); + OnError: return(-1); +} + +int TeccGetDevVms(pTecsClient conn, char **dev) { + int l, ld; + + ERR_I(CocCmd(conn, "device")); + ld=strlen(device); + l=*(short *)dev; + if (ld>=l) ld=l; + strncpy(dev[1], device, ld); + return(ld); + OnError: return(-1); +} + +int TeccSendVms(pTecsClient conn, char **cmd, char **reply) { + int l, lr; + char cbuf[80], rbuf[80]; + + l=*(short *)cmd; + if (l>=sizeof(cbuf)) l=sizeof(cbuf)-1; + strncpy(cbuf, cmd[1], l); + while (l>0 && cbuf[l-1]==' ') l--; /* trim */ + cbuf[l]='\0'; + ERR_I(TeccSend(conn, cbuf, rbuf, sizeof(rbuf))); + lr=strlen(rbuf); + l=*(short *)reply; + if (lr>=l) lr=l; + strncpy(reply[1], rbuf, lr); + return(lr); + OnError: return(-1); +} +#endif diff --git a/tecs/tecs_cli.h b/tecs/tecs_cli.h new file mode 100644 index 00000000..3ae8072d --- /dev/null +++ b/tecs/tecs_cli.h @@ -0,0 +1,47 @@ +#ifndef _TECS_CLI_H_ +#define _TECS_CLI_H_ + +#include "coc_client.h" +/* + tecc.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 TeccSetDev(pTecsClient conn, char *dev); +/* set device type +------------------------------------------------------------------------*/ + +char *TeccGetDev(pTecsClient conn); +/* get device type +------------------------------------------------------------------------*/ + +int TeccGet(pTecsClient conn, float *temp); +/* set temperature +------------------------------------------------------------------------*/ + +int TeccSet(pTecsClient conn, float temp); +/* get temperature +------------------------------------------------------------------------*/ + +int TeccSend(pTecsClient conn, char *cmd, char *reply, int replyLen); +/* send a command transparently to the controller + replyLen is the maximal length of reply +------------------------------------------------------------------------*/ + +void TeccClose(pTecsClient conn); +/* close connection and free ressources +------------------------------------------------------------------------*/ + +int TeccKillServer(pTecsClient conn); +/* kill the server process +------------------------------------------------------------------------*/ + +#endif /* _TECS_CLI_H_ */ diff --git a/tecs/tecs_dlog.c b/tecs/tecs_dlog.c new file mode 100644 index 00000000..ddca50cf --- /dev/null +++ b/tecs/tecs_dlog.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "err_handling.h" +#include "str_util.h" +#include "tecs_dlog.h" + +#define VERSION 1.1 + +#define DEFINED(F) (abs((F)-dset->undef)>1.0e-5*(F)) + +static time_t gmtoff; + +int DlogWrite(DlogSet *dset, int idx, void *data) { + int p; + + p = dset->headsize + (idx % dset->nlen) * dset->fsize; + if (p!=dset->pos) { + ERR_SI(lseek(dset->fd, p, SEEK_SET)); + } + ERR_SI(write(dset->fd, data, dset->fsize)); + dset->pos = p + dset->fsize; + return(0); + OnError: + return(-1); +} + +int DlogRead(DlogSet *dset, int idx, void *data) { + int p; + + p = dset->headsize + (idx % dset->nlen) * dset->fsize; + if (p!=dset->pos) { + ERR_SI(lseek(dset->fd, p, SEEK_SET)); + } + ERR_SI(read(dset->fd, data, dset->fsize)); + dset->pos = p + dset->fsize; + return(0); + OnError: + return(-1); +} + +int DlogOpen(DlogSet *dset, char *name, int write) { + int i, p, np, fd, flags; + time_t tim; + struct tm *timp; + + fd=0; + str_copy(dset->name, name); + if (write) { + flags=O_RDWR | O_SYNC; + } else { + flags=O_RDONLY | O_SYNC; + } +#ifdef __VMS + ERR_SI(fd=open(name, flags, 0, "SHR=UPD")); + gmtoff=0; +#else + ERR_SI(fd=open(name, flags, 0)); + time(&tim); + timp=localtime(&tim); + gmtoff=timp->tm_gmtoff; +#endif + dset->fd=fd; + + p=(char *)&dset->fd - (char *)dset; + ERR_SI(read(dset->fd, dset, p)); + dset->pos=p; + if ((int)(dset->version*1000+0.5) != (int)(VERSION*1000+0.5)) ERR_MSG("version mismatch"); + if (dset->headsize != p) ERR_MSG("illegal dlog file"); + return(0); + OnError: + if (fd!=0) close(fd); + return(-1); +} + +int DlogCreate(DlogSet *dset, char *name, time_t start, int nset, int nlen, int period, float undef) { + int fd, i, j, p; + va_list ap; + float f[DLOG_MAX_SET]; + + fd=0; + if (nset>DLOG_MAX_SET) ERR_MSG("nset too large"); + dset->nset=nset; + dset->nlen=nlen; + dset->start=start; + dset->last=start-period; + dset->period=period; + dset->undef=undef; + dset->version=VERSION; + str_copy(dset->name, name); + + for (i=0; iundef; + } + ERR_SI(fd=open(name, O_RDWR | O_CREAT | O_SYNC | O_TRUNC, 0666)); + dset->fd=fd; + p=(char *)&dset->fd - (char *)dset; + dset->headsize = p; + dset->fsize = nset * sizeof(float); + ERR_SI(write(dset->fd, dset, p)); + dset->pos=p; + return(0); + OnError: + if (fd!=0) close(fd); + return(-1); +} + +int DlogPut(DlogSet *dset, time_t time, int nset, float val[]) { + int i, i0, j; + float f[DLOG_MAX_SET], f0[DLOG_MAX_SET]; + + if (nset > dset->nset) nset = dset->nset; + + for (j=0; j < nset; j++) { f[j]=val[j]; } + for (j=nset; j < dset->nset; j++) { f[j]=dset->undef; } + + i = ( time - dset->start ) / dset->period; + i0 = ( dset->last - dset->start ) / dset->period; + + if (i0==i) { + ERR_I(DlogRead(dset, i, f0)); + for (j=0; jf[j] || /* take maximum (for odd i) */ + !i%2 && f0[j]nset; j++) { f0[j]=dset->undef; } + i0++; + while (i0last=time; + return(0); + OnError: + return(-1); +} + +int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float x[], float y[]) { + int i0, i1, i, n, undef; + float f[DLOG_MAX_SET]; + + if (iset<0) ERR_MSG("illegal iset"); + if (iset>=dset->nset) return(0); + + i = ( dset->last - dset->start ) / dset->period; + if (i - dset->nlen > 0) { + i1 = i - dset->nlen + 1; + } else { + i1 = 0; + } + i0=i1; + + *starttime = dset->start + i1 * dset->period + gmtoff; + n=0; + undef=2; + while (i0<=i) { + if (n>=nmax) return(n); + ERR_I(DlogRead(dset, i0, f)); + i0++; + if (DEFINED(f[iset])) { + x[n]=(float)(i0-i1)*dset->period; + y[n]=f[iset]; + n++; + undef=0; + } else if (undef==0) { + undef=1; + } else if (undef==1) { + undef=2; + x[n]=0; + y[n]=0; + n++; + } + } + return(n); + OnError: + return(-1); +} + +int DlogGetMany(DlogSet *dset, int nset, int nmax, double *starttime, float x[], float y[], int index[]) { + int n, k, nmx, ntot; + + ntot=0; + for (k=0; kfd, 0, SEEK_SET)); + ERR_SI(write(dset->fd, &dset->last, sizeof(int))); + dset->pos=sizeof(int); +#ifdef __VMS + close(dset->fd); + DlogOpen(dset, dset->name, 1); +#endif + return(0); + OnError: + return(-1); +} + +int DlogClose(DlogSet *dset) { + ERR_I(DlogUpd(dset)); + close(dset->fd); + return(0); + OnError: + return(-1); +} diff --git a/tecs/tecs_dlog.h b/tecs/tecs_dlog.h new file mode 100644 index 00000000..fd662078 --- /dev/null +++ b/tecs/tecs_dlog.h @@ -0,0 +1,54 @@ +#ifndef _DLOG_H_ +#define _DLOG_H_ + +#include + +#define DLOG_MAX_SET 32 + +typedef struct { + time_t last, start; + float version, undef; + int period, headsize, fsize, nset, nlen; + int fd, pos; + char name[128]; +} DlogSet; + + +int DlogOpen(DlogSet *dset, char *name, int write); +/* open existing dlog set */ + +int DlogCreate(DlogSet *dset, char *name, time_t start, int nset, int nlen, int period, float undef); +/* create new dlog file */ + +int DlogPut(DlogSet *dset, time_t time, int nset, float val[]); +/* put values to dlog set */ + +int DlogGet(DlogSet *dset, int iset, int nmax, double *starttime, float *x, float *y); +/* get one dataset from dlog set + + iset is the dataset to be returned + nmax is the maximal number of points to be returned + x, y: the data (arrays declared with at least nmax elements) + + on success, the return value is the effective length of returned data +*/ + +int DlogGetMany(DlogSet *dset, int nset, int nmax, double *starttime, float x[], float y[], int index[]); +/* get many datasets from dlog set + + nset is the nember of datasets to be returned + nmax is the maximal number of points to be returned + x, y: the data, one dataset after an other (arrays declared with at least nmax elements) + index must be an array of at least nset elements. + it returns the start indices in x[] and y[] of the data sets. + + on success, the return value is the effective length of returned data +*/ + +int DlogUpd(DlogSet *dset); +/* update pointer */ + +int DlogClose(DlogSet *dset); +/* close dlog set */ + +#endif /* _DLOG_H_ */ diff --git a/tecs/tecs_lsc.c b/tecs/tecs_lsc.c new file mode 100644 index 00000000..adb1bd35 --- /dev/null +++ b/tecs/tecs_lsc.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include "err_handling.h" +#include "coc_logfile.h" +#include "coc_util.h" +#include "tecs_lsc.h" +#include "str_util.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_WARN, "%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], buf[SER_BUF_LEN], result[SER_BUF_LEN], par[SER_BUF_LEN]; + char cmd[SER_BUF_LEN]; + char varname[32]; + Str_Buf sbuf; + int nres, i, j, response; + + nres=0; + response=0; + str_link_buf(&sbuf, buf, sizeof(buf), STR_NOSEPARATOR); + 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(str_put_str(&sbuf, seg)); + while (p!=NULL) { /* substitute variables */ + p=str_split(varname, p, ']'); + if (p==NULL) ERR_MSG("missing '\'"); + ERR_I(CocPutVar(serverVarList, &sbuf, varname, 0)); + p=str_split(seg, p, '['); + ERR_I(str_put_str(&sbuf, seg)); + } + 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(str_put_str(&sbuf, ";")); + cmd[blank-cmd_ptr]='?'; /* build query */ + if (colon==blank) colon++; + cmd[colon-cmd_ptr]='\0'; + ERR_I(str_put_str(&sbuf, cmd)); /* put query */ + ERR_I(str_put_str(&sbuf, ";")); + response=1; + } else { + qu=strchr(cmd, '?'); + ERR_I(str_put_str(&sbuf, ";")); + 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(str_put_str(&sbuf, "busy?")); + } else { + buf[sbuf.wrpos-1]='\0'; /* strip off trailing ";" */ + } + ERR_P(res=SerCmd(ser, buf)); + if (0==strcmp("?TMO", res)) 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') { + 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 */ + str_link_buf(&sbuf, result, 0, ','); + 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 */ + sbuf.sep='\0'; + } + ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0)); + } else { + ERR_P(str_get_str(&sbuf, NULL)); + } + } + } + } + return(res); + OnError: return(NULL); +} diff --git a/tecs/tecs_lsc.h b/tecs/tecs_lsc.h new file mode 100644 index 00000000..1cace358 --- /dev/null +++ b/tecs/tecs_lsc.h @@ -0,0 +1,52 @@ +#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_util.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 +*/ + +#endif /* _TECS_LSC_H_ */ diff --git a/tecs/tecs_serial.c b/tecs/tecs_serial.c new file mode 100644 index 00000000..6b0049b6 --- /dev/null +++ b/tecs/tecs_serial.c @@ -0,0 +1,97 @@ +#include + +#include +#include "rs232c_def.h" +#include "asynsrv_def.h" +#include "sinq_prototypes.h" +#include "err_handling.h" +#include "tecs_serial.h" +#include "coc_logfile.h" +#include "str_util.h" + +#define A_CHK(R) if (1!=(R)) { SerA_error(); ErrTxt(#R,0); goto OnError; } + +void (*idleHandler)(int,int); + +struct SerChan { + struct AsynSrv__info asyn_info; /* Contains skt, host, port & chan */ + struct RS__MsgStruct to_host; + struct RS__RespStruct from_host; + char cmd[SER_BUF_LEN]; +}; + +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); +} + +SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)) { + struct SerChan *ser; + char hbuf[64], cport[16]; + char *p, *c; + int port, chan; + + idleHandler=idleHdl; + ser=calloc(1, sizeof(*ser)); + str_copy(hbuf, host); + p=str_split(ser->asyn_info.host, hbuf, ':'); + port=4000; + chan=0; + if (p!=NULL) { + c=str_split(cport, p, '/'); + if (c!=NULL) chan=atoi(c); + port=atoi(cport); + } + ser->asyn_info.port=port; + ser->asyn_info.chan=chan; + logfileOut(LOG_MAIN, "open connection to %s:%d/%d\n", ser->asyn_info.host, ser->asyn_info.port, ser->asyn_info.chan); + A_CHK(AsynSrv_Open(&ser->asyn_info)); + if (msecTmo==0) msecTmo=5000; + A_CHK(AsynSrv_Config(&ser->asyn_info, "msecTmo", msecTmo, "idleHdl", idleHdl, NULL)); + return((SerChannel *)ser); + OnError: return(NULL); +} + +int SerClose(SerChannel *serch) { + struct SerChan *ser; + + ser=(struct SerChan *)serch; + A_CHK(AsynSrv_Close(&ser->asyn_info, 0)); + return(0); + OnError: return(-1); +} + +char *SerCmdC(SerChannel *serch, const char *cmnd) { + char 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); +} + +char *SerCmd(SerChannel *serch, char *cmnd) { + int l; + struct SerChan *ser; + char *result; + + l=strlen(cmnd); + if (l>=SER_BUF_LEN-1) ERR_COD(ENOBUFS); + + ser=(struct SerChan *)serch; + logfileOut(LOG_SER, ">%s\n", cmnd); + cmnd[l]=ser->asyn_info.eot[1]; + cmnd[l+1]='\0'; + A_CHK(AsynSrv_SendCmnds(&ser->asyn_info, &ser->to_host, &ser->from_host, cmnd, NULL)); + result=AsynSrv_GetReply(&ser->asyn_info, &ser->from_host, NULL); + if (result==NULL) ERR_MSG("empty result"); + /* if (idleHandler!=NULL) idleHandler(50,0); */ + logfileOut(LOG_SER, "<%s\n", result); + return(result); + OnError: return(NULL); +} diff --git a/tecs/tecs_serial.h b/tecs/tecs_serial.h new file mode 100644 index 00000000..b1fa5e35 --- /dev/null +++ b/tecs/tecs_serial.h @@ -0,0 +1,13 @@ +#ifndef _SERUTIL_H_ +#define _SERUTIL_H_ + +#define SER_BUF_LEN 320 + +typedef struct { int private; } SerChannel; + +SerChannel *SerOpen(const char *host, int msecTmo, void (*idleHdl)(int,int)); +char *SerCmdC(SerChannel *ser, const char *cmnd); +char *SerCmd(SerChannel *ser, char *cmnd); +int SerClose(SerChannel *ser); + +#endif /* _SERUTIL_H_ */