235 lines
6.1 KiB
C
235 lines
6.1 KiB
C
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include "errhdl.h"
|
|
#include "logfile.h"
|
|
#include "coc.h"
|
|
#include "lsc.h"
|
|
#include "util.h"
|
|
|
|
#define MC LSC_MAX_CMDS
|
|
#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);
|
|
}
|
|
|
|
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[MC*3];
|
|
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++;
|
|
}
|
|
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++; /* pointer to parameters */
|
|
list[nres]=cmd_ptr; nres++; /* 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++;
|
|
} 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<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)) ERR_MSG("result does not match");
|
|
}
|
|
}
|
|
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') {
|
|
ERR_I(CocGetVar(serverVarList, &sbuf, varname, 0));
|
|
} else {
|
|
ERR_P(str_get_str(&sbuf, NULL));
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
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; i<n; i++) {
|
|
c=clist[i];
|
|
b=strchr(c, ' ');
|
|
d=strchr(c, ':');
|
|
if (d==NULL) ERR_COD(EINVAL);
|
|
if (b==NULL || b>d) {
|
|
*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<n; i++) { /* compare parameters */
|
|
if (! LscEqPar(plist[i], rlist[i])) {
|
|
j=0; break;
|
|
logfileMask(LOG_SER);
|
|
}
|
|
}
|
|
} while (j==0);
|
|
} while (cn!=NULL);
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
int LscCmdChkC(SerChannel *ser, const char *cmds) {
|
|
char buf[128];
|
|
assert(strlen(cmds)<128);
|
|
strcpy(buf, cmds);
|
|
return(LscCmdChk(ser, buf));
|
|
}
|
|
|