various improvements
- use dig for resolving host names - ascon.c: fix terminator parsing - property callback: change property before callback - logger.c:default for logger period must be the old value instead of 1 - add frappy type history writing - increase max. logreader line length - HIPNONE returns "null" with json protocol - encode strings properly in formatNameValue - fix memory leak in json2tcl - scriptcontext: do not show debug messages when script starts with underscore or when the "send" property is empty - scriptcontext: remove args for action timestamp - scriptcontext: "que" function will replace an already queued action, e.g. for 'halt - introduced updatestatus script
This commit is contained in:
95
ascon.c
95
ascon.c
@ -1,8 +1,5 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -13,69 +10,11 @@
|
|||||||
#include "splitter.h"
|
#include "splitter.h"
|
||||||
#include "ascon.i"
|
#include "ascon.i"
|
||||||
#include "uselect.h"
|
#include "uselect.h"
|
||||||
|
#include "socketaddr.h"
|
||||||
|
|
||||||
static double lastClose = 0; /* time of last close operation */
|
static double lastClose = 0; /* time of last close operation */
|
||||||
static AsconProtocol *protocols = NULL;
|
static AsconProtocol *protocols = NULL;
|
||||||
|
|
||||||
static int MakeSocketAdr(
|
|
||||||
struct sockaddr *sockaddrPtr, /* socket address */
|
|
||||||
char *hostname, /* name or ip of host. NULL implies INADDR_ANY */
|
|
||||||
int port, /* port number */
|
|
||||||
char dotted_ip[16]) { /* resolved ip adr */
|
|
||||||
/*
|
|
||||||
Workaround for the following case:
|
|
||||||
switching off and on a LakeShore 336 does acquire a new address,
|
|
||||||
but the value in the cache (for gethostbyname) is not updated.
|
|
||||||
node: dig seems to be recommended over nslookup
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct hostent *hostent; /* Host database entry */
|
|
||||||
struct sockaddr_in *sadr = (struct sockaddr_in *)sockaddrPtr;
|
|
||||||
FILE *fil;
|
|
||||||
char line[256];
|
|
||||||
int l;
|
|
||||||
|
|
||||||
(void) memset(sadr, 0, sizeof(*sadr));
|
|
||||||
if (dotted_ip) { /* default value: failure */
|
|
||||||
dotted_ip[0] = 0;
|
|
||||||
}
|
|
||||||
sadr->sin_family = AF_INET;
|
|
||||||
sadr->sin_port = htons((unsigned short)port);
|
|
||||||
if (hostname == NULL) {
|
|
||||||
/* do not need to copy, as INADDR_ANY is all zero bytes */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (inet_pton(AF_INET, hostname, &sadr->sin_addr) == 1) {
|
|
||||||
/* resolved as dotted numbers notation */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
hostent = gethostbyname(hostname);
|
|
||||||
if (hostent == 0) {
|
|
||||||
/* we assume that when gethostname gets no entry, dig will also fail.
|
|
||||||
That way, dig will not be called repeatedly for no reason */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* copy the address: in case dig fails, we use the cached value */
|
|
||||||
memcpy(&sadr->sin_addr, hostent->h_addr_list[0], 4);
|
|
||||||
/* we use hostent->h_name instead of hostname here, as this has already
|
|
||||||
the proper domain added */
|
|
||||||
snprintf(line, sizeof line, "timeout 1 dig +short %s", hostent->h_name);
|
|
||||||
fil = popen(line, "r");
|
|
||||||
if (fil != NULL) {
|
|
||||||
if (fgets(line, sizeof(line), fil) != NULL) {
|
|
||||||
l = strlen(line);
|
|
||||||
if (line[l-1] <= ' ') line[l-1] = 0; /* strip off newline */
|
|
||||||
/* silently ignore return value, if it fails, we take the cached value */
|
|
||||||
inet_pton(AF_INET, line, &sadr->sin_addr);
|
|
||||||
}
|
|
||||||
fclose(fil);
|
|
||||||
}
|
|
||||||
if (dotted_ip) {
|
|
||||||
inet_ntop(AF_INET, &sadr->sin_addr, dotted_ip, 16);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsconError(Ascon *a, char *msg, int errorno)
|
void AsconError(Ascon *a, char *msg, int errorno)
|
||||||
{
|
{
|
||||||
static char *stateText[]={
|
static char *stateText[]={
|
||||||
@ -171,7 +110,7 @@ static void AsconConnect(Ascon * a)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*colon = '\0';
|
*colon = '\0';
|
||||||
ret = MakeSocketAdr(&adr, a->hostport, port, a->ip);
|
ret = MakeSocketAddr(&adr, a->hostport, port, a->ip);
|
||||||
*colon = ':';
|
*colon = ':';
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
AsconError(a, "bad host specification", 0);
|
AsconError(a, "bad host specification", 0);
|
||||||
@ -548,6 +487,22 @@ int AsconStdHandler(Ascon * a)
|
|||||||
return AsconBaseHandler(a);
|
return AsconBaseHandler(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkTerminator(char *term) {
|
||||||
|
int c, l;
|
||||||
|
|
||||||
|
if (term == NULL) return;
|
||||||
|
l = strlen(term);
|
||||||
|
if (l > 1 && term[0] == '"' && term[l-1] == '"') {
|
||||||
|
memmove(term, term+1, l-2);
|
||||||
|
term[l-2] = 0;
|
||||||
|
}
|
||||||
|
if (strncmp(term,"0x",2) == 0) {
|
||||||
|
sscanf(term,"%x",&c);
|
||||||
|
term[0] = (char)c;
|
||||||
|
term[1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Treat hex strings as terminators right. Note that this
|
* Treat hex strings as terminators right. Note that this
|
||||||
* is limited to single character terminators.
|
* is limited to single character terminators.
|
||||||
@ -558,18 +513,10 @@ int AsconStdHandler(Ascon * a)
|
|||||||
*/
|
*/
|
||||||
void AsconCheckTerminators(Ascon *a)
|
void AsconCheckTerminators(Ascon *a)
|
||||||
{
|
{
|
||||||
int c, i, l;
|
int i, l;
|
||||||
|
|
||||||
if (a->sendTerminator != NULL && strncmp(a->sendTerminator,"0x",2) == 0) {
|
checkTerminator(a->sendTerminator);
|
||||||
sscanf(a->sendTerminator,"%x",&c);
|
checkTerminator(a->replyTerminator);
|
||||||
a->sendTerminator[0] = (char)c;
|
|
||||||
a->sendTerminator[1] = '\0';
|
|
||||||
}
|
|
||||||
if (a->replyTerminator != NULL && strncmp(a->replyTerminator,"0x",2) == 0) {
|
|
||||||
sscanf(a->replyTerminator,"%x",&c);
|
|
||||||
a->replyTerminator[0] = (char)c;
|
|
||||||
a->replyTerminator[1] = '\0';
|
|
||||||
}
|
|
||||||
a->compositeTerminator = 0;
|
a->compositeTerminator = 0;
|
||||||
if (a->replyTerminator != NULL && a->replyTerminator[0] == '\'') {
|
if (a->replyTerminator != NULL && a->replyTerminator[0] == '\'') {
|
||||||
l = strlen(a->replyTerminator);
|
l = strlen(a->replyTerminator);
|
||||||
|
@ -1157,6 +1157,10 @@ void SetHdbProperty(pHdb node, char *key, char *value)
|
|||||||
hdbPropertyChange propMes;
|
hdbPropertyChange propMes;
|
||||||
|
|
||||||
if (node != NULL && key != NULL && node->properties != NULL) {
|
if (node != NULL && key != NULL && node->properties != NULL) {
|
||||||
|
propMes.type = propertyChange;
|
||||||
|
propMes.key = key;
|
||||||
|
propMes.value = value;
|
||||||
|
InvokeCallbackChain(node,(pHdbMessage)&propMes);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
StringDictDelete(node->properties, key);
|
StringDictDelete(node->properties, key);
|
||||||
} else if (StringDictExists(node->properties, key)) {
|
} else if (StringDictExists(node->properties, key)) {
|
||||||
@ -1164,10 +1168,6 @@ void SetHdbProperty(pHdb node, char *key, char *value)
|
|||||||
} else {
|
} else {
|
||||||
StringDictAddPair(node->properties, key, value);
|
StringDictAddPair(node->properties, key, value);
|
||||||
}
|
}
|
||||||
propMes.type = propertyChange;
|
|
||||||
propMes.key = key;
|
|
||||||
propMes.value = value;
|
|
||||||
InvokeCallbackChain(node,(pHdbMessage)&propMes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
logger.c
19
logger.c
@ -49,6 +49,12 @@ Logger *LoggerFind(const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
Logger *LoggerList(void)
|
||||||
|
{
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
#define LASTLOGTXT "#last logging entry at:\n"
|
#define LASTLOGTXT "#last logging entry at:\n"
|
||||||
|
|
||||||
@ -158,8 +164,13 @@ int LoggerWrite0(Logger * log, time_t now, int period, char *value)
|
|||||||
strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
|
strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
|
||||||
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", &tm);
|
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", &tm);
|
||||||
|
|
||||||
if (period <= 0)
|
if (period <= 0) {
|
||||||
|
if (log->period > 0) {
|
||||||
|
period = log->period;
|
||||||
|
} else {
|
||||||
period = 1;
|
period = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
writeInfo = (tm.tm_isdst != lasttm.tm_isdst ||
|
writeInfo = (tm.tm_isdst != lasttm.tm_isdst ||
|
||||||
tm.tm_yday != lasttm.tm_yday ||
|
tm.tm_yday != lasttm.tm_yday ||
|
||||||
(period != log->period && log->numeric));
|
(period != log->period && log->numeric));
|
||||||
@ -373,7 +384,7 @@ void LoggerKill(Logger * log)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
static int LoggerMakeDir(char *path)
|
int LoggerMakeDir(char *path)
|
||||||
{
|
{
|
||||||
static char buffer[4096];
|
static char buffer[4096];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -473,6 +484,10 @@ void LoggerFreeAll(void)
|
|||||||
free(p->name);
|
free(p->name);
|
||||||
if (p->old)
|
if (p->old)
|
||||||
free(p->old);
|
free(p->old);
|
||||||
|
if (p->secop_old)
|
||||||
|
free(p->secop_old);
|
||||||
|
if (p->secop_id)
|
||||||
|
free(p->secop_id);
|
||||||
free(p);
|
free(p);
|
||||||
p = next;
|
p = next;
|
||||||
}
|
}
|
||||||
|
7
logger.h
7
logger.h
@ -16,12 +16,16 @@ typedef struct Logger {
|
|||||||
int numeric;
|
int numeric;
|
||||||
int period;
|
int period;
|
||||||
int exact;
|
int exact;
|
||||||
|
void *histWriter;
|
||||||
|
char *secop_old;
|
||||||
|
char *secop_id;
|
||||||
/* private: */
|
/* private: */
|
||||||
char *old;
|
char *old;
|
||||||
int oldsize;
|
int oldsize;
|
||||||
time_t last, lastWrite, omitTime;
|
time_t last, lastWrite, omitTime;
|
||||||
float omitValue;
|
float omitValue;
|
||||||
struct Logger *next;
|
struct Logger *next;
|
||||||
|
int category; /* 0: unimportant, 1: important */
|
||||||
} Logger;
|
} Logger;
|
||||||
|
|
||||||
|
|
||||||
@ -39,5 +43,6 @@ void LoggerChange(Logger * log, int period, char *newname);
|
|||||||
int LoggerVarPath(char *dir, char *path, int pathLen, char *name,
|
int LoggerVarPath(char *dir, char *path, int pathLen, char *name,
|
||||||
struct tm *t);
|
struct tm *t);
|
||||||
void LoggerFreeAll(void);
|
void LoggerFreeAll(void);
|
||||||
|
int LoggerMakeDir(char *path);
|
||||||
|
Logger *LoggerList(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#define LOGGER_NAN -999999.
|
#define LOGGER_NAN -999999.
|
||||||
#define ONE_YEAR (366*24*3600)
|
#define ONE_YEAR (366*24*3600)
|
||||||
#define LLEN 1024
|
#define LLEN 4096
|
||||||
/* max. number of dirs in path */
|
/* max. number of dirs in path */
|
||||||
#define MAX_DIRS 16
|
#define MAX_DIRS 16
|
||||||
|
|
||||||
|
316
logsetup.c
316
logsetup.c
@ -1,8 +1,161 @@
|
|||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "logsetup.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
|
|
||||||
static char *loggerID = "loggerID";
|
static char *loggerID = "loggerID";
|
||||||
|
static char *histDir = NULL;
|
||||||
|
/* static char basepath[1024] = "/"; */
|
||||||
|
|
||||||
|
typedef struct _HistWriter {
|
||||||
|
char *name;
|
||||||
|
int old_hour;
|
||||||
|
FILE *fd;
|
||||||
|
time_t timestamp;
|
||||||
|
} HistWriter;
|
||||||
|
|
||||||
|
HistWriter mainWriter={""};
|
||||||
|
|
||||||
|
int FlushTask(void *data) {
|
||||||
|
HistWriter *wr = data;
|
||||||
|
|
||||||
|
if (wr->fd) fflush(wr->fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int HistPath(char *dir, char *path, int pathLen, struct tm *t)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
|
||||||
|
l = strlen(dir);
|
||||||
|
if (l + 17 >= pathLen) {
|
||||||
|
path[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strcpy(path, dir);
|
||||||
|
strftime(path + l, pathLen - l, "/%Y/%Y-%m-%d/", t);
|
||||||
|
l += 17;
|
||||||
|
path[l] = '\0';
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void HistWriteType(Logger *logger)
|
||||||
|
{
|
||||||
|
HistWriter *wr = logger->histWriter;
|
||||||
|
if (logger->numeric) {
|
||||||
|
fprintf(wr->fd, "#NUM %s %s\n", logger->secop_id, logger->name);
|
||||||
|
} else {
|
||||||
|
fprintf(wr->fd, "#STR %s %s\n", logger->secop_id, logger->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void HistWrite(Logger *logger, pHdb node, time_t t, char *value)
|
||||||
|
{
|
||||||
|
HistWriter *wr = logger->histWriter;
|
||||||
|
char path[1024];
|
||||||
|
time_t now;
|
||||||
|
int l;
|
||||||
|
struct tm tm, tm0;
|
||||||
|
FILE *fd;
|
||||||
|
Logger *lg;
|
||||||
|
char *secop_id;
|
||||||
|
time_t current_hour;
|
||||||
|
int hour_of_day;
|
||||||
|
int reopen = 0;
|
||||||
|
|
||||||
|
secop_id = GetHdbProp(node, "secop_id");
|
||||||
|
if (!secop_id || !secop_id[0]) {
|
||||||
|
if (logger->secop_old) {
|
||||||
|
free(logger->secop_old);
|
||||||
|
logger->secop_old = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!logger->secop_id) logger->secop_id = strdup("");
|
||||||
|
if (strcmp(secop_id, logger->secop_id) != 0) {
|
||||||
|
free(logger->secop_id);
|
||||||
|
logger->secop_id = strdup(secop_id);
|
||||||
|
}
|
||||||
|
time(&now);
|
||||||
|
tm = *localtime(&now);
|
||||||
|
current_hour = now / 3600;
|
||||||
|
if (current_hour != wr->old_hour) {
|
||||||
|
if (wr->fd) {
|
||||||
|
fprintf(wr->fd, "# %ld\n#END\n", (wr->timestamp / 3600 + 1) * 3600);
|
||||||
|
fclose(wr->fd);
|
||||||
|
wr->fd = NULL;
|
||||||
|
}
|
||||||
|
reopen = 1;
|
||||||
|
}
|
||||||
|
if (!wr->fd) {
|
||||||
|
if (histDir == NULL || reopen) {
|
||||||
|
histDir = IFindOption(pSICSOptions, "HistoryDir");
|
||||||
|
if (histDir == NULL) goto failed;
|
||||||
|
HistPath(histDir, path, sizeof path, &tm);
|
||||||
|
if (LoggerMakeDir(path) == 0) goto failed;
|
||||||
|
} else if (!*histDir) {
|
||||||
|
/* history writing not configured, or failed for current hour */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* last midnight: */
|
||||||
|
tm.tm_hour = 0;
|
||||||
|
tm.tm_min = 0;
|
||||||
|
tm.tm_sec = 0;
|
||||||
|
tm.tm_isdst = -1;
|
||||||
|
hour_of_day = (now - mktime(&tm)) / 3600;
|
||||||
|
l = HistPath(histDir, path, sizeof path, &tm);
|
||||||
|
strftime(path + l, sizeof path - l, "%Y-%m-%d", &tm);
|
||||||
|
l += 10;
|
||||||
|
if (l + 12 >= sizeof path) goto failed;
|
||||||
|
snprintf(path + l, sizeof path - l, "_%02d_hist.txt", hour_of_day);
|
||||||
|
fd = fopen(path, "r");
|
||||||
|
if (!fd) {
|
||||||
|
wr->fd = fopen(path, "w");
|
||||||
|
if (!wr->fd) goto failed; /* can not create file */
|
||||||
|
} else {
|
||||||
|
fclose(fd);
|
||||||
|
wr->fd = fopen(path, "a");
|
||||||
|
if (!wr->fd) goto failed; /* no write access to file */
|
||||||
|
}
|
||||||
|
fprintf(wr->fd, "#FRAPPY_HISTORY\n");
|
||||||
|
if (!wr->old_hour) {
|
||||||
|
TaskRegisterP(pServ->pTasker, "flush", FlushTask, 0, 0, wr, 0, 0.1, 0.1);
|
||||||
|
}
|
||||||
|
wr->old_hour = current_hour;
|
||||||
|
fprintf(wr->fd, "# %ld\n", t);
|
||||||
|
wr->timestamp = t;
|
||||||
|
for (lg = LoggerList(); lg != NULL; lg = lg->next) {
|
||||||
|
if (lg->secop_old) {
|
||||||
|
HistWriteType(lg);
|
||||||
|
fprintf(wr->fd, "%s %s\n", lg->secop_id, lg->secop_old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (logger->secop_old) free(logger->secop_old);
|
||||||
|
logger->secop_old = NULL;
|
||||||
|
}
|
||||||
|
if (logger->secop_old == NULL) {
|
||||||
|
if (value[0] == '\0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HistWriteType(logger);
|
||||||
|
logger->secop_old = strdup("");
|
||||||
|
}
|
||||||
|
if (strcmp(logger->secop_old, value) != 0) {
|
||||||
|
if (t != wr->timestamp) {
|
||||||
|
fprintf(wr->fd, "# %ld\n", t);
|
||||||
|
wr->timestamp = t;
|
||||||
|
}
|
||||||
|
fprintf(wr->fd, "%s %s\n", secop_id, value);
|
||||||
|
free(logger->secop_old);
|
||||||
|
logger->secop_old = strdup(value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
failed:
|
||||||
|
histDir = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||||
void *userData,
|
void *userData,
|
||||||
@ -14,7 +167,9 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
|||||||
hdbValue value;
|
hdbValue value;
|
||||||
pHdbDataMessage mm = NULL;
|
pHdbDataMessage mm = NULL;
|
||||||
pHdbDataSearch dsm = NULL;
|
pHdbDataSearch dsm = NULL;
|
||||||
|
pHdbMessage killmsg = NULL;
|
||||||
time_t now;
|
time_t now;
|
||||||
|
char *strvalue;
|
||||||
|
|
||||||
if ((dsm = GetHdbDataSearchMessage(message)) != NULL) {
|
if ((dsm = GetHdbDataSearchMessage(message)) != NULL) {
|
||||||
if (dsm->testPtr == loggerID) {
|
if (dsm->testPtr == loggerID) {
|
||||||
@ -24,6 +179,18 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
|||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((killmsg = GetHdbKillNodeMessage(message)) != NULL) {
|
||||||
|
if (logger->histWriter) {
|
||||||
|
time(&now);
|
||||||
|
HistWrite(logger, node, now, "");
|
||||||
|
if (logger->secop_old) {
|
||||||
|
free(logger->secop_old);
|
||||||
|
logger->secop_old = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hdbContinue;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
@ -31,66 +198,43 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
|||||||
value = *(mm->v);
|
value = *(mm->v);
|
||||||
|
|
||||||
time(&now);
|
time(&now);
|
||||||
/* testwise >= */
|
|
||||||
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
|
||||||
if (GetHdbProp(node, "geterror") == NULL) {
|
if (GetHdbProp(node, "geterror") == NULL) {
|
||||||
str = formatValue(value, node);
|
str = formatValue(value, node);
|
||||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
strvalue = GetCharArray(str);
|
||||||
DeleteDynString(str);
|
|
||||||
} else {
|
} else {
|
||||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), "");
|
str = NULL;
|
||||||
|
strvalue = "";
|
||||||
}
|
}
|
||||||
|
/* testwise >= */
|
||||||
|
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
||||||
|
LoggerWrite(logger, now, LoggerPeriod(logger), strvalue);
|
||||||
|
}
|
||||||
|
if (logger->histWriter) {
|
||||||
|
HistWrite(logger, node, now, strvalue);
|
||||||
|
}
|
||||||
|
if (str) {
|
||||||
|
DeleteDynString(str);
|
||||||
}
|
}
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
int LogMakeInternal(pHdb node, char *path, int period) {
|
||||||
int argc, char *argv[])
|
|
||||||
{
|
|
||||||
pHdb node;
|
|
||||||
pHdbCallback cb;
|
|
||||||
static char basepath[1024] = "/";
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *p, *name;
|
char secop_id[1024];
|
||||||
static char *loggerDir = NULL;
|
char secop_par[1024];
|
||||||
int numeric, period;
|
char *module;
|
||||||
|
int pos, l;
|
||||||
|
pHdb nd;
|
||||||
|
int numeric;
|
||||||
Logger *logger;
|
Logger *logger;
|
||||||
|
char *p, *name;
|
||||||
|
pHdbCallback cb;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (strncmp(path, "/sics/", 6) == 0) {
|
||||||
SCPrintf(pCon, eError,
|
snprintf(buf, sizeof buf, "%s", path+5);
|
||||||
"ERROR: should be: logsetup <node> [<period> [<filename>]]");
|
|
||||||
/* or logsetup <node> clear */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (strcasecmp(argv[1], "basepath") == 0) {
|
|
||||||
if (argc > 2) {
|
|
||||||
snprintf(basepath, sizeof basepath, "%s", argv[2]);
|
|
||||||
}
|
|
||||||
SCPrintf(pCon, eValue, "%s", basepath);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (loggerDir == NULL) {
|
|
||||||
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
|
|
||||||
if (loggerDir == NULL)
|
|
||||||
loggerDir = "./";
|
|
||||||
LoggerSetDir(loggerDir);
|
|
||||||
}
|
|
||||||
if (strcasecmp(argv[1], "directory") == 0) {
|
|
||||||
if (argc > 2) {
|
|
||||||
loggerDir = strdup(argv[2]);
|
|
||||||
}
|
|
||||||
SCPrintf(pCon, eValue, "%s", loggerDir);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
node = FindHdbNode(basepath, argv[1], pCon);
|
|
||||||
if (node == NULL) {
|
|
||||||
SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (argc > 3) {
|
|
||||||
snprintf(buf, sizeof buf, "%s", argv[3]);
|
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, sizeof buf, "%s", argv[1]);
|
snprintf(buf, sizeof buf, "%s", path);
|
||||||
}
|
}
|
||||||
for (p = buf; *p != '\0'; p++) {
|
for (p = buf; *p != '\0'; p++) {
|
||||||
if (*p == '/')
|
if (*p == '/')
|
||||||
@ -101,29 +245,22 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
} else {
|
} else {
|
||||||
name = buf;
|
name = buf;
|
||||||
}
|
}
|
||||||
if (node->value.dataType == HIPFLOAT) {
|
if (node->value.dataType == HIPFLOAT || node->value.dataType == HIPINT) {
|
||||||
numeric = 1;
|
numeric = 1;
|
||||||
} else {
|
} else {
|
||||||
numeric = 0;
|
numeric = 0;
|
||||||
}
|
}
|
||||||
logger = FindHdbCallbackData(node, loggerID);
|
logger = FindHdbCallbackData(node, loggerID);
|
||||||
period = 0;
|
|
||||||
if (argc > 2) {
|
|
||||||
if (logger != NULL && strcasecmp(argv[2], "clear") == 0) {
|
|
||||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), "");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
period = atoi(argv[2]);
|
|
||||||
}
|
|
||||||
if (logger != 0) { /* logger exists already */
|
if (logger != 0) { /* logger exists already */
|
||||||
LoggerChange(logger, period, name);
|
LoggerChange(logger, period, name);
|
||||||
} else {
|
} else {
|
||||||
logger = LoggerMake(name, period, !numeric);
|
logger = LoggerMake(name, period, !numeric);
|
||||||
/* If that failed, we cannot continue - it crashes in the callback */
|
/* If that failed, we cannot continue - it crashes in the callback */
|
||||||
if (logger == NULL) {
|
if (logger == NULL) {
|
||||||
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger->histWriter = &mainWriter;
|
||||||
LoggerSetNumeric(logger, numeric);
|
LoggerSetNumeric(logger, numeric);
|
||||||
SetHdbProperty(node, "logger_name", name);
|
SetHdbProperty(node, "logger_name", name);
|
||||||
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,
|
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,
|
||||||
@ -131,7 +268,70 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
assert(cb);
|
assert(cb);
|
||||||
AppendHipadabaCallback(node, cb);
|
AppendHipadabaCallback(node, cb);
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pHdb node;
|
||||||
|
static char *loggerDir = NULL;
|
||||||
|
int period;
|
||||||
|
Logger *logger;
|
||||||
|
char *p;
|
||||||
|
pDynString result;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 3) {
|
||||||
|
SCPrintf(pCon, eError,
|
||||||
|
"ERROR: should be: logsetup <node> [<period>]");
|
||||||
|
/* or logsetup <node> clear */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* seems not used
|
||||||
|
if (strcasecmp(argv[1], "basepath") == 0) {
|
||||||
|
if (argc > 2) {
|
||||||
|
snprintf(basepath, sizeof basepath, "%s", argv[2]);
|
||||||
|
}
|
||||||
|
SCPrintf(pCon, eValue, "%s", basepath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (loggerDir == NULL) {
|
||||||
|
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
|
||||||
|
if (loggerDir == NULL)
|
||||||
|
loggerDir = "./";
|
||||||
|
LoggerSetDir(loggerDir);
|
||||||
|
}
|
||||||
|
if (strcasecmp(argv[1], "directory") == 0) {
|
||||||
|
/* not used ? M.Z. 10.2020 */
|
||||||
|
if (argc > 2) {
|
||||||
|
loggerDir = strdup(argv[2]);
|
||||||
|
}
|
||||||
|
SCPrintf(pCon, eValue, "%s", loggerDir);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = FindHdbIntern(argv[1]);
|
||||||
|
if (node == NULL) {
|
||||||
|
SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
period = 0; /* default period */
|
||||||
|
if (argc > 2 && argv[2][0]) {
|
||||||
|
if (strcasecmp(argv[2], "clear") == 0) {
|
||||||
|
logger = FindHdbCallbackData(node, loggerID);
|
||||||
|
time(&now);
|
||||||
|
if (logger) { /* silently ignore clear on a missing logger */
|
||||||
|
LoggerWrite(logger, now, LoggerPeriod(logger), "");
|
||||||
|
HistWrite(logger, node, now, "");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
period = atoi(argv[2]);
|
||||||
|
}
|
||||||
|
if (!LogMakeInternal(node, argv[1], period)) {
|
||||||
|
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
logsetup.h
Normal file
14
logsetup.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
logsetup.h
|
||||||
|
|
||||||
|
Markus Zolliker, Oct 2020
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOGSETUP_H
|
||||||
|
#define LOGSETUP_H
|
||||||
|
|
||||||
|
#include "hipadaba.h"
|
||||||
|
|
||||||
|
int LogMakeInternal(pHdb node, char *path, int period);
|
||||||
|
#endif
|
87
make_gen
87
make_gen
@ -8,45 +8,42 @@
|
|||||||
#EPICSOBJ=epicsmotor.o
|
#EPICSOBJ=epicsmotor.o
|
||||||
EPICSOBJ=
|
EPICSOBJ=
|
||||||
|
|
||||||
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
COREOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||||
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|
||||||
sicvar.o nserver.o SICSmain.o motorlist.o\
|
sicvar.o nserver.o SICSmain.o motorlist.o\
|
||||||
sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\
|
sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\
|
||||||
macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \
|
macro.o obpar.o obdes.o drive.o status.o intserv.o \
|
||||||
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
|
devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \
|
||||||
lld_blob.o strrepl.o lin2ang.o fomerge.o loglisten.o \
|
lld_blob.o strrepl.o lin2ang.o loglisten.o \
|
||||||
script.o o2t.o alias.o stringdict.o sdynar.o \
|
script.o o2t.o alias.o stringdict.o sdynar.o \
|
||||||
histmem.o histdriv.o histsim.o interface.o callback.o \
|
interface.o callback.o socketaddr.o \
|
||||||
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \
|
event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \
|
||||||
danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\
|
danu.o varlog.o stptok.o nread.o trigd.o \
|
||||||
scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\
|
scan.o fitcenter.o telnet.o token.o wwildcard.o \
|
||||||
tclev.o hkl.o integrate.o optimise.o dynstring.o nxutil.o \
|
tclev.o integrate.o optimise.o dynstring.o \
|
||||||
uubuffer.o udpquieck.o fourtable.o hexString.o\
|
uubuffer.o udpquieck.o fourtable.o hexString.o\
|
||||||
rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\
|
rmtrail.o help.o confvirtualmot.o \
|
||||||
simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\
|
simchop.o choco.o chadapter.o trim.o scaldate.o \
|
||||||
xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
xytable.o exebuf.o exeman.o \
|
||||||
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
|
circular.o maximize.o sicscron.o scanvar.o \
|
||||||
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o \
|
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o \
|
||||||
synchronize.o definealias.o oscillate.o tasdrive.o \
|
synchronize.o definealias.o oscillate.o \
|
||||||
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
|
userscan.o rs232controller.o \
|
||||||
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
|
motreg.o motreglist.o anticollider.o \
|
||||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
|
||||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
tclintimpl.o sicsdata.o \
|
||||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
initializer.o remob.o tclmotdriv.o protocol.o \
|
||||||
sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
|
sicslist.o hipadaba.o sicshipadaba.o statistics.o \
|
||||||
ascon.o scriptcontext.o logger.o logreader.o logsetup.o \
|
ascon.o scriptcontext.o logger.o logreader.o logsetup.o \
|
||||||
savehdb.o statusfile.o sicshdbfactory.o proxy.o devser.o \
|
savehdb.o statusfile.o sicshdbfactory.o proxy.o devser.o \
|
||||||
moregress.o multicounter.o regresscter.o histregress.o \
|
moregress.o multicounter.o regresscter.o \
|
||||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
sicshdbadapter.o polldriv.o sicspoll.o statemon.o \
|
||||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.o syncedprot.o\
|
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o syncedprot.o\
|
||||||
nxcopy.o nxinterhelper.o nxinter_wrap.o arrayutil.o \
|
arrayutil.o \
|
||||||
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \
|
sctdriveadapter.o sctdriveobj.o reflist.o uselect.o motorsec.o \
|
||||||
sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \
|
|
||||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
|
||||||
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \
|
||||||
histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\
|
sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o\
|
taskobj.o sctcomtask.o multicountersec.o\
|
||||||
lscprot.o secopprot.o\
|
lscprot.o secopprot.o secopprot3.o\
|
||||||
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
messagepipe.o sicsget.o remoteobject.o pmacprot.o charbychar.o binprot.o \
|
||||||
cnvrt.o tclClock.o tclDate.o tclUnixTime.o stack_trace.o logv2.o outcode.o
|
cnvrt.o tclClock.o tclDate.o tclUnixTime.o stack_trace.o logv2.o outcode.o
|
||||||
|
|
||||||
@ -54,7 +51,18 @@ MOTOROBJ = motor.o simdriv.o
|
|||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
VELOOBJ = velo.o velosim.o
|
VELOOBJ = velo.o velosim.o
|
||||||
|
|
||||||
OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
SICSOBJ = ofac.o fomerge.o \
|
||||||
|
histmem.o histdriv.o histsim.o histregress.o hmslave.o fourmess.o histmemsec.o \
|
||||||
|
hmcontrol.o fourlib.o lomax.o hmdata.o frame.o singlebinb.o sansbc.o \
|
||||||
|
cell.o vector.o hklmot.o hkl.o ubfour.o ubcalc.o cone.o \
|
||||||
|
singlex.o sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \
|
||||||
|
singlenb.o simindex.o simidx.o singletas.o \
|
||||||
|
tasdrive.o tasscanub.o tasub.o tasublib.o tasmono.o \
|
||||||
|
nxupdate.o nxdict.o nxutil.o nxdataset.o nxscript.o nxcopy.o nxinterhelper.o nxinter_wrap.o \
|
||||||
|
mcreader.o mccontrol.o mcstascounter.o mcstashm.o \
|
||||||
|
$(COREOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
||||||
|
|
||||||
|
SEAOBJ = sea_ofac.o sea_extra.o $(COREOBJ) $(EXTRA) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ)
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .tcl .htm .c .o .tc
|
.SUFFIXES: .tcl .htm .c .o .tc
|
||||||
@ -62,16 +70,24 @@ OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
|||||||
.tc.c:
|
.tc.c:
|
||||||
tjxp $*.tc $*.c
|
tjxp $*.tc $*.c
|
||||||
|
|
||||||
|
all: seaserver
|
||||||
|
#all: sicserver
|
||||||
|
|
||||||
|
seaserver: libseapsi SeaServer
|
||||||
|
|
||||||
|
sicserver: libpsi libhlib libmat SICServer
|
||||||
|
|
||||||
#--- This .SECONDARY. target is necessary to preserve generated .c files for debugging
|
#--- This .SECONDARY. target is necessary to preserve generated .c files for debugging
|
||||||
.SECONDARY.: sicspoll.c polldriv.c
|
.SECONDARY.: sicspoll.c polldriv.c
|
||||||
|
|
||||||
all: libmat libhlib libpsi SICServer
|
|
||||||
|
|
||||||
# use this target when some of the libraries SUBLIBS might be incomplete
|
# use this target when some of the libraries SUBLIBS might be incomplete
|
||||||
full: purge all
|
full: purge all
|
||||||
|
|
||||||
SICServer: $(OBJ) $(SUBLIBS)
|
SICServer: libmat libhlib libpsi $(SICSOBJ) $(SUBLIBS)
|
||||||
$(CC) $(DBG) -o SICServer $(OBJ) $(LIBS)
|
$(CC) $(DBG) -o SICServer $(SICSOBJ) $(LIBS)
|
||||||
|
|
||||||
|
SeaServer: libseapsi $(SEAOBJ) $(SEASUBLIBS)
|
||||||
|
$(CC) $(DBG) -o SeaServer $(SEAOBJ) $(SEALIBS)
|
||||||
|
|
||||||
matrix/libmatrix.a: libmat
|
matrix/libmatrix.a: libmat
|
||||||
|
|
||||||
@ -88,6 +104,9 @@ $(SICSROOT)/sicspsi/libpsi.a: libpsi
|
|||||||
libpsi:
|
libpsi:
|
||||||
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libpsi.a
|
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libpsi.a
|
||||||
|
|
||||||
|
libseapsi:
|
||||||
|
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libseapsi.a
|
||||||
|
|
||||||
purge:
|
purge:
|
||||||
rm -f SICServer $(SUBLIBS)
|
rm -f SICServer $(SUBLIBS)
|
||||||
|
|
||||||
|
@ -34,6 +34,11 @@ LIBS = -L$(EXTRAROOT)/lib -L$(EXTRAROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS)
|
|||||||
-ltcl -lNeXus /usr/lib64/libhdf5.so \
|
-ltcl -lNeXus /usr/lib64/libhdf5.so \
|
||||||
$(EXTRAROOT)/lib/libjson-c.a \
|
$(EXTRAROOT)/lib/libjson-c.a \
|
||||||
-ldl -lz -lmxml $(EXTRAROOT)/lib/libghttp.a -lm -lc -lpthread -lsqlite3 -lbson-1.0 -lmongoc-1.0
|
-ldl -lz -lmxml $(EXTRAROOT)/lib/libghttp.a -lm -lc -lpthread -lsqlite3 -lbson-1.0 -lmongoc-1.0
|
||||||
|
SEASUBLIBS = $(SICSROOT)/sicspsi/libseapsi.a
|
||||||
|
SEALIBS = -L$(EXTRAROOT)/lib -L$(EXTRAROOT)/lib $(SEASUBLIBS) \
|
||||||
|
-ltcl \
|
||||||
|
$(EXTRAROOT)/lib/libjson-c.a \
|
||||||
|
-ldl -lz -lm -lc -lpthread
|
||||||
|
|
||||||
include make_gen
|
include make_gen
|
||||||
|
|
||||||
|
38
network.c
38
network.c
@ -53,6 +53,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "uselect.h"
|
#include "uselect.h"
|
||||||
|
#include "socketaddr.h"
|
||||||
|
|
||||||
#define PORT 1
|
#define PORT 1
|
||||||
#define SOCKET 2
|
#define SOCKET 2
|
||||||
@ -78,43 +79,6 @@ static void NetError(const char pText[])
|
|||||||
Log(severity,"io","%s", pText);
|
Log(severity,"io","%s", pText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------- Local ------------------------------------
|
|
||||||
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
|
|
||||||
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) {
|
|
||||||
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 int) -1) {
|
|
||||||
return 0; /* 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 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
mkChannel *NETOpenPort(int iPort)
|
mkChannel *NETOpenPort(int iPort)
|
||||||
|
1
ofac.c
1
ofac.c
@ -53,6 +53,7 @@ static void InitGeneral(void)
|
|||||||
INIT(AddCharByCharProtocoll);
|
INIT(AddCharByCharProtocoll);
|
||||||
INIT(AddLscProtocol);
|
INIT(AddLscProtocol);
|
||||||
INIT(AddSecopProtocol);
|
INIT(AddSecopProtocol);
|
||||||
|
INIT(AddSecop3Protocol);
|
||||||
INIT(MakeTrace);
|
INIT(MakeTrace);
|
||||||
INIT(InitTaskOBJ);
|
INIT(InitTaskOBJ);
|
||||||
INIT(RemoteObjectInit);
|
INIT(RemoteObjectInit);
|
||||||
|
10
protocol.c
10
protocol.c
@ -469,10 +469,11 @@ struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer,
|
|||||||
char pError[256];
|
char pError[256];
|
||||||
pError[0] = '\0';
|
pError[0] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
if (strlen(pBuffer) == 0) {
|
if (strlen(pBuffer) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (!SCVerifyConnection(pCon)) {
|
if (!SCVerifyConnection(pCon)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -518,10 +519,15 @@ struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer,
|
|||||||
}
|
}
|
||||||
if (iOut == eHdbValue || iOut == eHdbEvent) {
|
if (iOut == eHdbValue || iOut == eHdbEvent) {
|
||||||
tmp_json = json_tokener_parse(pBuffer);
|
tmp_json = json_tokener_parse(pBuffer);
|
||||||
|
if (strcmp(pBuffer, "null") != 0) {
|
||||||
|
if (tmp_json == NULL) {
|
||||||
|
tmp_json = json_object_new_string(pBuffer);
|
||||||
|
}
|
||||||
if (tmp_json == NULL) {
|
if (tmp_json == NULL) {
|
||||||
linenum = __LINE__;
|
linenum = __LINE__;
|
||||||
goto reporterr;
|
goto reporterr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Strip \r and \n */
|
/* Strip \r and \n */
|
||||||
for (pBufferFrom = pBufferTo = pBuffer;; pBufferFrom++) {
|
for (pBufferFrom = pBufferTo = pBuffer;; pBufferFrom++) {
|
||||||
@ -561,8 +567,10 @@ int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut)
|
|||||||
char pBueffel[MAXMSG], errBuff[MAXMSG];
|
char pBueffel[MAXMSG], errBuff[MAXMSG];
|
||||||
int iRet, errLen = MAXMSG;
|
int iRet, errLen = MAXMSG;
|
||||||
|
|
||||||
|
/*
|
||||||
if (strlen(pBuffer) == 0)
|
if (strlen(pBuffer) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
*/
|
||||||
|
|
||||||
/* log it for any case */
|
/* log it for any case */
|
||||||
iRet = SCGetSockHandle(pCon);
|
iRet = SCGetSockHandle(pCon);
|
||||||
|
15
script.c
15
script.c
@ -43,6 +43,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "fupa.h"
|
#include "fupa.h"
|
||||||
@ -583,7 +584,7 @@ Tcl_Obj *json2tcl(struct json_object *jobj) {
|
|||||||
char buf[100];
|
char buf[100];
|
||||||
int i, len;
|
int i, len;
|
||||||
Tcl_Obj **list;
|
Tcl_Obj **list;
|
||||||
Tcl_Obj *dict, *kobj, *vobj;
|
Tcl_Obj *result, *kobj, *vobj;
|
||||||
Tcl_Obj *val;
|
Tcl_Obj *val;
|
||||||
const char *key;
|
const char *key;
|
||||||
const char *str;
|
const char *str;
|
||||||
@ -605,18 +606,20 @@ Tcl_Obj *json2tcl(struct json_object *jobj) {
|
|||||||
list[i] = json2tcl(json_object_array_get_idx(jobj, i));
|
list[i] = json2tcl(json_object_array_get_idx(jobj, i));
|
||||||
if (!list[i]) return NULL;
|
if (!list[i]) return NULL;
|
||||||
}
|
}
|
||||||
return Tcl_NewListObj(len, list);
|
result = Tcl_NewListObj(len, list);
|
||||||
|
free(list);
|
||||||
|
return result;
|
||||||
case json_type_object:
|
case json_type_object:
|
||||||
dict = Tcl_NewDictObj();
|
result = Tcl_NewDictObj();
|
||||||
if (!dict) return NULL;
|
if (!result) return NULL;
|
||||||
json_object_object_foreach(jobj, key, val) {
|
json_object_object_foreach(jobj, key, val) {
|
||||||
kobj = Tcl_NewStringObj(key, strlen(key));
|
kobj = Tcl_NewStringObj(key, strlen(key));
|
||||||
vobj = json2tcl(val);
|
vobj = json2tcl(val);
|
||||||
if (kobj && vobj) {
|
if (kobj && vobj) {
|
||||||
Tcl_DictObjPut(NULL, dict, kobj, vobj);
|
Tcl_DictObjPut(NULL, result, kobj, vobj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dict;
|
return result;
|
||||||
}
|
}
|
||||||
return Tcl_NewStringObj("None", 4);
|
return Tcl_NewStringObj("None", 4);
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
char path[MAX_HDB_PATH];
|
char path[MAX_HDB_PATH];
|
||||||
|
|
||||||
PushContext(node, controller);
|
PushContext(node, controller);
|
||||||
|
if (script[strlen(script)-1] != '_') { /* suppress these debug messages */
|
||||||
if (controller->debugConn) {
|
if (controller->debugConn) {
|
||||||
GetHdbPath(node, path, sizeof path);
|
GetHdbPath(node, path, sizeof path);
|
||||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||||
@ -353,6 +354,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
GetHdbPath(node, path, sizeof path);
|
GetHdbPath(node, path, sizeof path);
|
||||||
fprintf(controller->fd,"%6.3f script: (on %s) %s\n", secondsOfMinute(), path, script);
|
fprintf(controller->fd,"%6.3f script: (on %s) %s\n", secondsOfMinute(), path, script);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MacroPush(con);
|
MacroPush(con);
|
||||||
l = strlen(script);
|
l = strlen(script);
|
||||||
@ -366,13 +368,19 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
result++;
|
result++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (script[strlen(script)-1] != '_') { /* suppress these error messages */
|
||||||
if (controller->debugConn) {
|
if (controller->debugConn) {
|
||||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||||
"%6.3f error: %s", secondsOfMinute(), result);
|
"%6.3f error: %s", secondsOfMinute(), result);
|
||||||
|
} else {
|
||||||
|
/* just return to tcl */
|
||||||
|
SCPf(SCNotWrite, controller->conn, eLog,
|
||||||
|
"%6.3f error: %s", secondsOfMinute(), result);
|
||||||
}
|
}
|
||||||
if(controller->fd != NULL){
|
if(controller->fd != NULL){
|
||||||
fprintf(controller->fd, "%6.3f error: %s\n", secondsOfMinute(), result);
|
fprintf(controller->fd, "%6.3f error: %s\n", secondsOfMinute(), result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
iRet = 0;
|
iRet = 0;
|
||||||
}
|
}
|
||||||
*resPtr = result;
|
*resPtr = result;
|
||||||
@ -390,6 +398,11 @@ static int SctMatch(void *data1, void *data2)
|
|||||||
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
|
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int NoMatch(void *data1, void *data2)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine is running the script chain. It is called repeatedly
|
* This routine is running the script chain. It is called repeatedly
|
||||||
* with response data from the device serializer (devser). This function
|
* with response data from the device serializer (devser). This function
|
||||||
@ -622,8 +635,16 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
data->name, path, emsg);
|
data->name, path, emsg);
|
||||||
SetHdbProperty(node, eprop, NULL);
|
SetHdbProperty(node, eprop, NULL);
|
||||||
}
|
}
|
||||||
snprintf(timeKey, sizeof timeKey, "%s_time", data->name);
|
blank = strchr(data->name, ' ');
|
||||||
|
if (blank != NULL) {
|
||||||
|
l = blank - data->name;
|
||||||
|
} else {
|
||||||
|
l = strlen(data->name);
|
||||||
|
}
|
||||||
|
/* omit arguments, in case action is a script */
|
||||||
|
snprintf(timeKey, sizeof timeKey, "%.*s_time", (int)l, data->name);
|
||||||
snprintf(timeVal, sizeof timeVal, "%.3f", DoubleTime());
|
snprintf(timeVal, sizeof timeVal, "%.3f", DoubleTime());
|
||||||
|
|
||||||
SetHdbProperty(node, timeKey, timeVal);
|
SetHdbProperty(node, timeKey, timeVal);
|
||||||
send = NULL;
|
send = NULL;
|
||||||
free(script);
|
free(script);
|
||||||
@ -644,6 +665,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
send = GetProp(node, controller->node, "send");
|
send = GetProp(node, controller->node, "send");
|
||||||
if (send == NULL)
|
if (send == NULL)
|
||||||
send = "";
|
send = "";
|
||||||
|
if (*send != '\0') {
|
||||||
if (controller->debugConn) {
|
if (controller->debugConn) {
|
||||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||||
"%6.3f send : %s", secondsOfMinute(), send);
|
"%6.3f send : %s", secondsOfMinute(), send);
|
||||||
@ -656,6 +678,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
|||||||
} else {
|
} else {
|
||||||
traceIO("sctunknown", "send:%s", send);
|
traceIO("sctunknown", "send:%s", send);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return send;
|
return send;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -852,6 +875,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
|||||||
SCPrintf(con, eError, "ERROR: %s", error); /* nicer for the user */
|
SCPrintf(con, eError, "ERROR: %s", error); /* nicer for the user */
|
||||||
SetHdbProperty(node, "target", NULL);
|
SetHdbProperty(node, "target", NULL);
|
||||||
SetHdbProperty(node, "requested", NULL);
|
SetHdbProperty(node, "requested", NULL);
|
||||||
|
DeleteDynString(text);
|
||||||
return hdbAbort;
|
return hdbAbort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1194,7 +1218,7 @@ static int SctWriteCmd(pSICSOBJ ccmd, SConnection * con,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SctQueueNode(SctController * controller, Hdb * node,
|
void SctQueueNode(SctController * controller, Hdb * node,
|
||||||
DevPrio prio, char *action, SConnection * con)
|
DevPrio prio, char *action, int replace, SConnection * con)
|
||||||
{
|
{
|
||||||
SctData *data;
|
SctData *data;
|
||||||
hdbCallback *cb;
|
hdbCallback *cb;
|
||||||
@ -1215,8 +1239,9 @@ void SctQueueNode(SctController * controller, Hdb * node,
|
|||||||
|
|
||||||
data->syncid = SyncedIncr(0);
|
data->syncid = SyncedIncr(0);
|
||||||
data->busy = 1;
|
data->busy = 1;
|
||||||
if (DevQueue(data->controller->devser, data, prio,
|
if (DevQueue(data->controller->devser, data, prio, SctWriteHandler,
|
||||||
SctWriteHandler, SctMatch, SctKillData, SctDataInfo)) {
|
replace ? SctMatch : NoMatch,
|
||||||
|
SctKillData, SctDataInfo)) {
|
||||||
if (con != NULL) {
|
if (con != NULL) {
|
||||||
data->conCtx = SCCopyConnection(con);
|
data->conCtx = SCCopyConnection(con);
|
||||||
}
|
}
|
||||||
@ -1257,7 +1282,8 @@ static int SctQueueCmd(pSICSOBJ ccmd, SConnection * con,
|
|||||||
}
|
}
|
||||||
action = ParText(cmdNode, "action", nPar, "write");
|
action = ParText(cmdNode, "action", nPar, "write");
|
||||||
|
|
||||||
SctQueueNode(controller, node, prio, action, con);
|
SctQueueNode(controller, node, prio, action,
|
||||||
|
strcmp(cmdNode->name, "que") != 0, con);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1970,13 +1996,18 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
|||||||
"write", usMugger, MakeSICSFunc(SctWriteCmd));
|
"write", usMugger, MakeSICSFunc(SctWriteCmd));
|
||||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||||
|
|
||||||
|
|
||||||
cmd = AddSICSHdbPar(controller->node,
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
"queue", usMugger, MakeSICSFunc(SctQueueCmd));
|
"queue", usMugger, MakeSICSFunc(SctQueueCmd));
|
||||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||||
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write"));
|
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write"));
|
||||||
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write"));
|
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write"));
|
||||||
|
|
||||||
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
|
"que", usMugger, MakeSICSFunc(SctQueueCmd));
|
||||||
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||||
|
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write"));
|
||||||
|
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write"));
|
||||||
|
|
||||||
cmd = AddSICSHdbPar(controller->node,
|
cmd = AddSICSHdbPar(controller->node,
|
||||||
"updatescript", usMugger, MakeSICSFunc(SctUpdatescriptCmd));
|
"updatescript", usMugger, MakeSICSFunc(SctUpdatescriptCmd));
|
||||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||||
|
@ -14,10 +14,11 @@ typedef struct SctController SctController;
|
|||||||
* \param node the node
|
* \param node the node
|
||||||
* \param prio the priority
|
* \param prio the priority
|
||||||
* \param action the initial state
|
* \param action the initial state
|
||||||
|
* \param replace 0 queue does not replace, 1: entries with the same node and action are replaced
|
||||||
* \param con an optional connection to be used by the action scripts
|
* \param con an optional connection to be used by the action scripts
|
||||||
*/
|
*/
|
||||||
void SctQueueNode(SctController * controller, Hdb * node,
|
void SctQueueNode(SctController * controller, Hdb * node,
|
||||||
DevPrio prio, char *action, SConnection * con);
|
DevPrio prio, char *action, int replace, SConnection * con);
|
||||||
|
|
||||||
/** \brief call a script and configure the sct command to be used
|
/** \brief call a script and configure the sct command to be used
|
||||||
* in connection with the given node and controller
|
* in connection with the given node and controller
|
||||||
|
@ -56,7 +56,7 @@ static int SCTDRIVHalt(void *data)
|
|||||||
|
|
||||||
self = (pSctDrive) data;
|
self = (pSctDrive) data;
|
||||||
if (GetHdbProperty(self->node, "halt", dummy, sizeof dummy)) {
|
if (GetHdbProperty(self->node, "halt", dummy, sizeof dummy)) {
|
||||||
SctQueueNode(self->c, self->node, HaltPRIO, "halt", NULL);
|
SctQueueNode(self->c, self->node, HaltPRIO, "halt", 1, NULL);
|
||||||
} else if (GetHdbProperty(self->node, "status", dummy, sizeof dummy)) {
|
} else if (GetHdbProperty(self->node, "status", dummy, sizeof dummy)) {
|
||||||
SetHdbProperty(self->node, "status", "idle");
|
SetHdbProperty(self->node, "status", "idle");
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ static int SCTDRIVHalt(void *data)
|
|||||||
self = (pSICSOBJ) data;
|
self = (pSICSOBJ) data;
|
||||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||||
if (GetHdbProperty(self->objectNode, "halt", dummy, sizeof dummy)) {
|
if (GetHdbProperty(self->objectNode, "halt", dummy, sizeof dummy)) {
|
||||||
SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt",
|
SctQueueNode(pPriv->c, self->objectNode, HaltPRIO, "halt", 1,
|
||||||
pPriv->pCon);
|
pPriv->pCon);
|
||||||
} else
|
} else
|
||||||
if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy))
|
if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy))
|
||||||
@ -177,6 +177,7 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
|||||||
Tcl_Interp *pTcl = NULL;
|
Tcl_Interp *pTcl = NULL;
|
||||||
char *result;
|
char *result;
|
||||||
SConnection *con;
|
SConnection *con;
|
||||||
|
int ret;
|
||||||
|
|
||||||
self = (pSICSOBJ) data;
|
self = (pSICSOBJ) data;
|
||||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||||
@ -186,7 +187,8 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
|||||||
*/
|
*/
|
||||||
if (GetHdbProperty(self->objectNode, "writestatus", script, 1024)) {
|
if (GetHdbProperty(self->objectNode, "writestatus", script, 1024)) {
|
||||||
if (strcmp(script, "start") == 0) {
|
if (strcmp(script, "start") == 0) {
|
||||||
return HWBusy;
|
ret = HWBusy;
|
||||||
|
goto Return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +200,9 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
|||||||
SCWrite(pCon,
|
SCWrite(pCon,
|
||||||
"ERROR: configuration problem: no checkstatus script!",
|
"ERROR: configuration problem: no checkstatus script!",
|
||||||
eError);
|
eError);
|
||||||
return HWFault;
|
ret = HWFault;
|
||||||
|
result = "error";
|
||||||
|
goto Return;
|
||||||
}
|
}
|
||||||
result = script;
|
result = script;
|
||||||
} else {
|
} else {
|
||||||
@ -206,7 +210,9 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
|||||||
pPriv->c, &result);
|
pPriv->c, &result);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
SCPrintf(pCon, eError, " script %s returned %s", script, result);
|
SCPrintf(pCon, eError, " script %s returned %s", script, result);
|
||||||
return HWFault;
|
ret = HWFault;
|
||||||
|
result = "error";
|
||||||
|
goto Return;
|
||||||
}
|
}
|
||||||
if (SctDebugConn(pPriv->c)) {
|
if (SctDebugConn(pPriv->c)) {
|
||||||
SCPf(SCPureSockWrite, SctDebugConn(pPriv->c), eError,
|
SCPf(SCPureSockWrite, SctDebugConn(pPriv->c), eError,
|
||||||
@ -214,20 +220,28 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strstr(result, "run") != NULL) {
|
if (strstr(result, "run") != NULL) {
|
||||||
return HWBusy;
|
ret = HWBusy;
|
||||||
} else if (strstr(result, "posfault") != NULL) {
|
} else if (strstr(result, "posfault") != NULL) {
|
||||||
return HWPosFault;
|
ret = HWPosFault;
|
||||||
} else if (strstr(result, "error") != NULL) {
|
} else if (strstr(result, "error") != NULL) {
|
||||||
return HWFault;
|
ret = HWFault;
|
||||||
} else if (strstr(result, "idle") != NULL) {
|
} else if (strstr(result, "idle") != NULL) {
|
||||||
return HWIdle;
|
ret = HWIdle;
|
||||||
} else {
|
} else {
|
||||||
SCPrintf(pCon, eError,
|
SCPrintf(pCon, eError,
|
||||||
"ERROR: invalid status code %s returned from checkstatus script",
|
"ERROR: invalid status code %s returned from checkstatus script",
|
||||||
result);
|
result);
|
||||||
return HWFault;
|
ret = HWFault;
|
||||||
}
|
}
|
||||||
return HWFault;
|
Return:
|
||||||
|
if (GetHdbProperty(self->objectNode, "updatestatus", script, 1024)) {
|
||||||
|
status = SctCallInContext(pCon, script, self->objectNode,
|
||||||
|
pPriv->c, &result);
|
||||||
|
if (status == 0) {
|
||||||
|
SCPrintf(pCon, eError, " %s returned %s", script, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------
|
/*----------------------------------------------------------------
|
||||||
|
145
sea_extra.c
Normal file
145
sea_extra.c
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Extracts from other SICS code and dummy definitions for SEA
|
||||||
|
*
|
||||||
|
* Markus Zolliker Jun 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <site.h>
|
||||||
|
#include <sicsvar.h>
|
||||||
|
#include <danu.h>
|
||||||
|
|
||||||
|
pCounterDriver NewMcStasCounter(char *name) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetHistPreset(pHistMem self) {return 0;};
|
||||||
|
int SetHistPreset(pHistMem self, float fVal) {return 0;};
|
||||||
|
CounterMode GetHistCountMode(pHistMem self) {return 0;};
|
||||||
|
int SetHistCountMode(pHistMem self, CounterMode eNew) {return 0;};
|
||||||
|
long GetHistMonitor(pHistMem self, int i, SConnection *pCon) {return 0;};
|
||||||
|
const float *GetHistTimeBin(pHistMem self, int *iLength) {return 0;};
|
||||||
|
int GetHistLength(pHistMem self) {return 0;};
|
||||||
|
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim) {return 0;};
|
||||||
|
float GetHistCountTime(pHistMem self,SConnection *pCon) {return 0;};
|
||||||
|
int GetHistogram(pHistMem self, SConnection *pCon,
|
||||||
|
int i,int iStart, int iEnd, HistInt *lData, int iDataLen) {return 0;};
|
||||||
|
HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon) {return 0;};
|
||||||
|
int GetHistogramDirect(pHistMem self, SConnection *pCon,
|
||||||
|
int i, int iStart, int iEnd,
|
||||||
|
HistInt *lData, int iDataLen) {return 0;};
|
||||||
|
void HistDirty(pHistMem self) {};
|
||||||
|
HistInt *subSample(pHMdata self, char *command, char *error, int errLen) {return 0;};
|
||||||
|
int Nxinter_SafeInit(Tcl_Interp * pTcl) {return 0;};
|
||||||
|
int NXcopy_Init(Tcl_Interp * pTcl) {return 0;};
|
||||||
|
int isNXScriptWriting(void) {return 0;};
|
||||||
|
|
||||||
|
/* alternative implementation in order to avoid nexus stuff */
|
||||||
|
|
||||||
|
void SNXFormatTime(char *result, int size) {
|
||||||
|
time_t timeStamp;
|
||||||
|
time(&timeStamp);
|
||||||
|
strftime(result, size, "%Y-%m-%d %H:%M:%S", localtime(&timeStamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* from nxscript.c: */
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
char *makeFilename(SicsInterp * pSics, SConnection * pCon)
|
||||||
|
{
|
||||||
|
pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL;
|
||||||
|
char *pRes = NULL;
|
||||||
|
int iLen, iNum, iYear, thousand;
|
||||||
|
char pNumText[10], pBueffel[256];
|
||||||
|
CommandList *pCom = NULL;
|
||||||
|
DIR *dir = NULL;
|
||||||
|
|
||||||
|
/* Try, get all the Variables */
|
||||||
|
pPath = FindVariable(pSics, "sicsdatapath");
|
||||||
|
pPref = FindVariable(pSics, "sicsdataprefix");
|
||||||
|
pCom = FindCommand(pSics, "sicsdatanumber");
|
||||||
|
pEnd = FindVariable(pSics, "sicsdatapostfix");
|
||||||
|
|
||||||
|
if ((!pPath) || (!pPref) || (!pCom) || (!pEnd)) {
|
||||||
|
SCWrite(pCon,
|
||||||
|
"ERROR: cannot read variables for automatic data file name creation",
|
||||||
|
eError);
|
||||||
|
SCWrite(pCon,
|
||||||
|
"ERROR: This is a VERY, VERY, VERY serious installation problem",
|
||||||
|
eError);
|
||||||
|
SCWrite(pCon, "ERROR: your data will be dumped into emergency.hdf",
|
||||||
|
eError);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find length */
|
||||||
|
iLen = strlen(pPath->text) + 4; /* extra 4 for dir number */
|
||||||
|
iLen += strlen(pPref->text);
|
||||||
|
iLen += 10; /* for number + year */
|
||||||
|
iLen += strlen(pEnd->text);
|
||||||
|
iLen += 10; /* safety margin */
|
||||||
|
|
||||||
|
/* allocate memory */
|
||||||
|
pRes = (char *) malloc(iLen * sizeof(char));
|
||||||
|
if (!pRes) {
|
||||||
|
SCWrite(pCon, "ERROR: no memory in makeFilename", eError);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pRes, 0, iLen);
|
||||||
|
|
||||||
|
/* increment the data file number */
|
||||||
|
iNum = IncrementDataNumber(pCom->pData, &iYear);
|
||||||
|
if (iNum < 0) {
|
||||||
|
SCWrite(pCon, "ERROR: cannot increment data number!", eError);
|
||||||
|
SCWrite(pCon, "ERROR: your data will be dumped to emergency.hdf",
|
||||||
|
eError);
|
||||||
|
free(pRes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy(pRes, pPath->text);
|
||||||
|
thousand = (int) floor(iNum / 1000.);
|
||||||
|
snprintf(pNumText, 9, "%3.3d", thousand);
|
||||||
|
strcat(pRes, pNumText);
|
||||||
|
|
||||||
|
/*
|
||||||
|
check for existence of directory and create if neccessary
|
||||||
|
*/
|
||||||
|
dir = opendir(pRes);
|
||||||
|
if (dir == NULL) {
|
||||||
|
mkdir(pRes, S_IRWXU | S_IRGRP | S_IXGRP);
|
||||||
|
snprintf(pBueffel, 255, "Creating dir: %s", pRes);
|
||||||
|
SCWrite(pCon, pBueffel, eLog);
|
||||||
|
} else {
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
build the rest of the filename
|
||||||
|
*/
|
||||||
|
strcat(pRes, "/");
|
||||||
|
strcat(pRes, pPref->text);
|
||||||
|
snprintf(pNumText,sizeof(pNumText)-1, "%4.4d", iYear);
|
||||||
|
strcat(pRes, pNumText);
|
||||||
|
strcat(pRes, "n");
|
||||||
|
snprintf(pNumText,sizeof(pNumText)-1, "%6.6d", iNum);
|
||||||
|
strcat(pRes, pNumText);
|
||||||
|
strcat(pRes, pEnd->text);
|
||||||
|
|
||||||
|
return pRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void changeExtension(char *filename, char *newExtension)
|
||||||
|
{
|
||||||
|
char *pPtr = NULL;
|
||||||
|
|
||||||
|
pPtr = strrchr(filename, (int) '.');
|
||||||
|
assert(pPtr != NULL);
|
||||||
|
|
||||||
|
pPtr++;
|
||||||
|
assert(strlen(pPtr) >= strlen(newExtension));
|
||||||
|
strcpy(pPtr, newExtension);
|
||||||
|
}
|
1068
sea_macro.c
Normal file
1068
sea_macro.c
Normal file
File diff suppressed because it is too large
Load Diff
243
sea_ofac.c
Normal file
243
sea_ofac.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/**
|
||||||
|
* Startup commands and definitions
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke 1996 - ?
|
||||||
|
* heavy modifications to separate PSI specific commands into a
|
||||||
|
* separate library. Mark Koennecke, June 2003
|
||||||
|
*
|
||||||
|
* moved some functions to sicsutil.c
|
||||||
|
* Markus Zolliker Jan 2010
|
||||||
|
*
|
||||||
|
* reduced version for SEA only, June 2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ofac.h"
|
||||||
|
#include "exeman.h"
|
||||||
|
#include "statusfile.h"
|
||||||
|
#include "site.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
#include "sicsglobal.h"
|
||||||
|
|
||||||
|
static unsigned int killStartupCommands = 1;
|
||||||
|
int isDuringInitialization;
|
||||||
|
|
||||||
|
|
||||||
|
extern void DevExecInit(void); /* devexec.c */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void InitGeneral(void)
|
||||||
|
{
|
||||||
|
#define INIT(F) { void F(void); F(); }
|
||||||
|
|
||||||
|
/* insert here initialization routines ... */
|
||||||
|
|
||||||
|
INIT(StatisticsInit);
|
||||||
|
INIT(InitializerInit);
|
||||||
|
INIT(SaveHdbInit); /* must be after InitializerInit */
|
||||||
|
INIT(DefineAliasInit);
|
||||||
|
INIT(SctInit);
|
||||||
|
INIT(SctDriveAdapterInit);
|
||||||
|
INIT(SctDriveObjInit);
|
||||||
|
INIT(SctDriveAdapterInit);
|
||||||
|
INIT(SICSGetInit);
|
||||||
|
INIT(LogReaderInit);
|
||||||
|
INIT(LogSetupInit);
|
||||||
|
INIT(InstallBackground);
|
||||||
|
INIT(MakeProtocol);
|
||||||
|
INIT(UdpInit);
|
||||||
|
INIT(HelpInit);
|
||||||
|
INIT(AddTestProt);
|
||||||
|
INIT(AddGenBinProtocoll);
|
||||||
|
INIT(AddSyncedProt);
|
||||||
|
INIT(AddBinProtocol);
|
||||||
|
INIT(AddPMACProtocoll);
|
||||||
|
INIT(AddCharByCharProtocoll);
|
||||||
|
INIT(AddLscProtocol);
|
||||||
|
INIT(AddSecopProtocol);
|
||||||
|
INIT(AddSecop3Protocol);
|
||||||
|
INIT(MakeTrace);
|
||||||
|
INIT(InitTaskOBJ);
|
||||||
|
INIT(RemoteObjectInit);
|
||||||
|
INIT(Logv2Init);
|
||||||
|
INIT(LogListenInit);
|
||||||
|
INIT(SiteInit); /* site specific initializations */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitIniCommands(SicsInterp * pInter)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* declare and add permanent command */
|
||||||
|
#define PCMD(NAME, FUN) { \
|
||||||
|
int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \
|
||||||
|
int argc, char *argv[]); \
|
||||||
|
AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* declare and add startup command */
|
||||||
|
#define SCMD(NAME, FUN) { \
|
||||||
|
int FUN(SConnection * pCon, SicsInterp * pSics, void *pData, \
|
||||||
|
int argc, char *argv[]); \
|
||||||
|
AddCommandWithFlag(pInter, NAME, FUN, NULL, NULL, 1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* permanent commands in alphabetic order */
|
||||||
|
PCMD("alias", MakeAlias);
|
||||||
|
PCMD("broadcast", Broadcast);
|
||||||
|
PCMD("ClientPut", ClientPut);
|
||||||
|
PCMD("ClientLog", ClientLog);
|
||||||
|
PCMD("config", ConfigCon);
|
||||||
|
PCMD("db", SICSDebug);
|
||||||
|
PCMD("Dir", ListObjects);
|
||||||
|
PCMD("dolater", MakeCron);
|
||||||
|
PCMD("DrivableInvoke", TclDrivableInvoke);
|
||||||
|
PCMD("DynSicsObj", InstallSICSOBJ);
|
||||||
|
PCMD("EVFactory", EVControlFactory);
|
||||||
|
PCMD("FileEval", MacroFileEval);
|
||||||
|
PCMD("findalias", LocateAliasAction);
|
||||||
|
PCMD("fulltransact", TransactAction);
|
||||||
|
PCMD("GetInt", GetSICSInterrupt);
|
||||||
|
PCMD("GumPut", GumPut);
|
||||||
|
PCMD("InternEval", InternalFileEval);
|
||||||
|
PCMD("kill_command", SICSKill);
|
||||||
|
PCMD("list", SicsList);
|
||||||
|
PCMD("MakeAsyncProtocol", AsyncProtocolFactory);
|
||||||
|
PCMD("MakeAsyncQueue", AsyncQueueFactory);
|
||||||
|
PCMD("MakeMulti", MakeMulti);
|
||||||
|
PCMD("MakeOptimise", MakeOptimiser);
|
||||||
|
PCMD("MakeSecMotor", SecMotorFactory);
|
||||||
|
PCMD("Publish", TclPublish);
|
||||||
|
PCMD("Remob", RemobCreate);
|
||||||
|
PCMD("ResetServer", ResetStatus);
|
||||||
|
PCMD("scriptcallback", CallbackScript);
|
||||||
|
PCMD("SetInt", SetSICSInterrupt);
|
||||||
|
PCMD("SetStatus", SetSICSStatus);
|
||||||
|
PCMD("SICSBounds", SICSBounds);
|
||||||
|
PCMD("sicscron", MakeCron);
|
||||||
|
PCMD("sicsdatafactory", SICSDataFactory);
|
||||||
|
PCMD("sicsdescriptor", SICSDescriptor);
|
||||||
|
PCMD("SICSLog", LogOutput);
|
||||||
|
PCMD("sicsprompt", SicsPrompt);
|
||||||
|
PCMD("SICSStatus", SICSStatus);
|
||||||
|
/* PCMD("sicstime", SICSTime); */
|
||||||
|
PCMD("doubletime", SICSDoubleTime);
|
||||||
|
PCMD("SICSType", SICSType);
|
||||||
|
PCMD("Sics_Exitus", SicsExit);
|
||||||
|
PCMD("silent", SICSSilent);
|
||||||
|
PCMD("json2tcl", SICSjson2tcl);
|
||||||
|
PCMD("status", UserStatus);
|
||||||
|
PCMD("TclReplaceDrivable", TclReplaceDrivable);
|
||||||
|
PCMD("transact", TransactAction);
|
||||||
|
PCMD("wait", UserWait);
|
||||||
|
PCMD("yield", UserYield);
|
||||||
|
PCMD("checksum", CheckSum);
|
||||||
|
PCMD("loguserinfo", LogUserInfoWrapper);
|
||||||
|
|
||||||
|
/* startup commands in alphabetic order */
|
||||||
|
SCMD("allowexec", AllowExec);
|
||||||
|
SCMD("AntiCollisionInstall", AntiColliderFactory);
|
||||||
|
SCMD("ChopperAdapter", CHAdapterFactory);
|
||||||
|
SCMD("MakeBatchManager", MakeExeManager);
|
||||||
|
SCMD("MakeChopper", ChocoFactory);
|
||||||
|
SCMD("MakeConfigurableMotor", MakeConfigurableVirtualMotor);
|
||||||
|
SCMD("MakeCounter", MakeCounter);
|
||||||
|
SCMD("MakeDataNumber", DNFactory);
|
||||||
|
SCMD("MakeDiffScan", MakeDiffScan);
|
||||||
|
SCMD("MakeDrive", MakeDrive);
|
||||||
|
SCMD("MakeEnergy", MakeEnergyVar);
|
||||||
|
SCMD("MakeGPIB", MakeGPIB);
|
||||||
|
SCMD("MakeHdbTable", HdbTableFactory);
|
||||||
|
SCMD("MakeLin2Ang", MakeLin2Ang);
|
||||||
|
SCMD("MakeMaximize", MaximizeFactory);
|
||||||
|
SCMD("MakeMono", MonoInit);
|
||||||
|
SCMD("MakeMultiCounter", MakeMultiCounter);
|
||||||
|
SCMD("MakeMultiSec", MakeMultiSec);
|
||||||
|
SCMD("MakeO2T", CreateO2T);
|
||||||
|
SCMD("MakeOscillator", MakeOscillator);
|
||||||
|
SCMD("MakePeakCenter", FitFactory);
|
||||||
|
SCMD("MakeProxy", ProxyFactory);
|
||||||
|
SCMD("MakeRefList", MakeReflectionList);
|
||||||
|
SCMD("MakeRS232Controller", RS232Factory);
|
||||||
|
SCMD("MakeScanCommand", ScanFactory);
|
||||||
|
SCMD("MakeSecCounter", MakeSecCter);
|
||||||
|
SCMD("MakeSicsObj", InstallSICSOBJ);
|
||||||
|
SCMD("MakeSicsPoll", InstallSICSPoll);
|
||||||
|
SCMD("MakeStateMon", StateMonFactory);
|
||||||
|
SCMD("MakeSync", MakeSync);
|
||||||
|
SCMD("MakeTclInt", MakeTclInt);
|
||||||
|
SCMD("MakeWaveLength", MakeWaveLengthVar);
|
||||||
|
SCMD("MakeXYTable", XYFactory);
|
||||||
|
SCMD("Motor", MotorCreate);
|
||||||
|
SCMD("ServerOption", IFServerOption);
|
||||||
|
SCMD("SicsAlias", SicsAlias);
|
||||||
|
SCMD("SicsUser", PWSicsUser);
|
||||||
|
SCMD("TokenInit", TokenInit);
|
||||||
|
SCMD("VarMake", VarFactory);
|
||||||
|
SCMD("VelocitySelector", VelSelFactory);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int InitObjectCommands(pServer pServ, char *file)
|
||||||
|
{
|
||||||
|
SConnection *pCon = NULL;
|
||||||
|
char pBueffel[1024];
|
||||||
|
int iRet;
|
||||||
|
SicsInterp *pSics;
|
||||||
|
pExeList pExe;
|
||||||
|
pEnvMon pEnv = NULL;
|
||||||
|
pSite site = NULL;
|
||||||
|
|
||||||
|
pSics = pServ->pSics;
|
||||||
|
assert(pSics);
|
||||||
|
|
||||||
|
InitGeneral();
|
||||||
|
|
||||||
|
/* general initialization */
|
||||||
|
/* create a connection */
|
||||||
|
pCon = SCCreateDummyConnection(pSics);
|
||||||
|
if (!pCon) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
MakeExeManager(pCon, pSics, NULL, 1, NULL);
|
||||||
|
|
||||||
|
pExe = CreateExeList(pServ->pTasker);
|
||||||
|
pServ->pExecutor = pExe;
|
||||||
|
pEnv = CreateEnvMon();
|
||||||
|
DevExecInit();
|
||||||
|
|
||||||
|
assert(pExe);
|
||||||
|
assert(pEnv);
|
||||||
|
|
||||||
|
InitIniCommands(pSics);
|
||||||
|
/*
|
||||||
|
install site specific commands
|
||||||
|
*/
|
||||||
|
site = getSite();
|
||||||
|
if (site != NULL) {
|
||||||
|
site->AddSiteCommands(pServ->pSics);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstallBckRestore(pCon, pSics);
|
||||||
|
InstallSICSHipadaba(pCon, pSics,NULL,0,NULL);
|
||||||
|
|
||||||
|
/* evaluate the file */
|
||||||
|
snprintf(pBueffel,sizeof(pBueffel)-1, "fileeval %s", file);
|
||||||
|
iRet = InterpExecute(pSics, pCon, pBueffel);
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
SCDeleteConnection(pCon);
|
||||||
|
if (site != NULL && site->RemoveSiteCommands != NULL) {
|
||||||
|
site->RemoveSiteCommands(pSics);
|
||||||
|
}
|
||||||
|
if(killStartupCommands){
|
||||||
|
RemoveStartupCommands();
|
||||||
|
}
|
||||||
|
isDuringInitialization = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void KeepStartupCommands()
|
||||||
|
{
|
||||||
|
killStartupCommands = 0;
|
||||||
|
}
|
196
secopprot3.c
Normal file
196
secopprot3.c
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
|
#include "uselect.h"
|
||||||
|
#include "ascon.h"
|
||||||
|
#include "ascon.i"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* protocol for SECoP
|
||||||
|
*
|
||||||
|
* Markus Zolliker Feb 2019
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* the first item in this linked list contains a partial or empty buffer.
|
||||||
|
all the following are the messages in the queue */
|
||||||
|
|
||||||
|
typedef struct secop_msg {
|
||||||
|
struct secop_msg *next;
|
||||||
|
char *message;
|
||||||
|
} SecopMsg;
|
||||||
|
|
||||||
|
typedef struct secop_buf {
|
||||||
|
SecopMsg *queue;
|
||||||
|
pDynString buffer;
|
||||||
|
} SecopBuf;
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void SecopKillPrivate(void *private) {
|
||||||
|
SecopBuf *msgbuf = private;
|
||||||
|
SecopMsg *msg, *next;
|
||||||
|
|
||||||
|
for (msg = msgbuf->queue; msg != NULL; msg = next) {
|
||||||
|
next = msg->next;
|
||||||
|
if (msg->message) {
|
||||||
|
free(msg->message);
|
||||||
|
}
|
||||||
|
free(msg);
|
||||||
|
}
|
||||||
|
DeleteDynString(msgbuf->buffer);
|
||||||
|
free(msgbuf);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int Secop3ReadChars(int fd, char *bytes, int maxbytes)
|
||||||
|
{
|
||||||
|
fd_set rmask;
|
||||||
|
struct timeval tmo = { 0, 0 };
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
FD_ZERO(&rmask);
|
||||||
|
FD_SET(fd, &rmask);
|
||||||
|
ret = uselect(fd + 1, &rmask, NULL, NULL, &tmo);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
ret = recv(fd, bytes, maxbytes, 0);
|
||||||
|
/* PrintChar(*chr); fflush(stdout); */
|
||||||
|
if (ret > 0)
|
||||||
|
return ret;
|
||||||
|
if (ret == 0) {
|
||||||
|
errno = ECONNRESET;
|
||||||
|
return ASCON_DISCONNECTED;
|
||||||
|
}
|
||||||
|
return ASCON_RECV_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int Secop3ProtHandler(Ascon *a) {
|
||||||
|
int ret;
|
||||||
|
char *result;
|
||||||
|
char *space;
|
||||||
|
char *json;
|
||||||
|
char *specifier;
|
||||||
|
Tcl_Obj *tcllist[3], *tclobj;
|
||||||
|
int l, l1, l2;
|
||||||
|
struct json_object *jobj;
|
||||||
|
char buffer[1024];
|
||||||
|
char *bytes;
|
||||||
|
char *str;
|
||||||
|
SecopBuf *msgbuf;
|
||||||
|
SecopMsg *msg, **msgp;
|
||||||
|
|
||||||
|
if (a->state <= AsconConnectDone) {
|
||||||
|
/* handle connect states */
|
||||||
|
return AsconStdHandler(a);
|
||||||
|
}
|
||||||
|
/* treat incoming messages always */
|
||||||
|
msgbuf = a->private;
|
||||||
|
if (msgbuf == NULL) {
|
||||||
|
msgbuf = calloc(1, sizeof *msgbuf);
|
||||||
|
a->private = msgbuf;
|
||||||
|
a->killPrivate = SecopKillPrivate;
|
||||||
|
msgbuf->buffer = CreateDynString(60, 65536);
|
||||||
|
}
|
||||||
|
ret = Secop3ReadChars(a->fd, buffer, sizeof buffer - 1);
|
||||||
|
while (ret > 0) {
|
||||||
|
assert(ret < sizeof buffer);
|
||||||
|
buffer[ret] = '\0';
|
||||||
|
bytes = buffer;
|
||||||
|
str = strchr(bytes, '\n');
|
||||||
|
while (str) {
|
||||||
|
l = str - bytes;
|
||||||
|
DynStringConcatBytes(msgbuf->buffer, bytes, l);
|
||||||
|
/* append at end of queue */
|
||||||
|
for (msgp = &msgbuf->queue; *msgp != NULL; msgp = &(*msgp)->next);
|
||||||
|
msg = calloc(1, sizeof *msg);
|
||||||
|
*msgp = msg;
|
||||||
|
msg->message = strdup(GetCharArray(msgbuf->buffer));
|
||||||
|
DynStringClear(msgbuf->buffer);
|
||||||
|
bytes += l + 1;
|
||||||
|
str = strchr(bytes, '\n');
|
||||||
|
}
|
||||||
|
DynStringConcat(msgbuf->buffer, bytes);
|
||||||
|
ret = Secop3ReadChars(a->fd, buffer, sizeof buffer - 1);
|
||||||
|
}
|
||||||
|
if (ret < 0) {
|
||||||
|
AsconError(a, "SECOP.1", errno);
|
||||||
|
}
|
||||||
|
switch (a->state) {
|
||||||
|
case AsconWriting:
|
||||||
|
/* do not skip garbage */
|
||||||
|
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||||
|
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||||
|
if (ret < 0) {
|
||||||
|
AsconError(a, "SECOP.2", errno); /* sets state to AsconFailed */
|
||||||
|
} else {
|
||||||
|
a->wrPos += ret;
|
||||||
|
if (a->wrPos >= GetDynStringLength(a->wrBuffer)) {
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
case AsconWriteStart:
|
||||||
|
if (GetDynStringLength(a->wrBuffer) == 0) {
|
||||||
|
/* do not send empty message */
|
||||||
|
a->state = AsconWriteDone;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (a->sendTerminator) {
|
||||||
|
DynStringConcat(a->wrBuffer, a->sendTerminator);
|
||||||
|
}
|
||||||
|
a->wrPos = 0;
|
||||||
|
a->state = AsconWriting;
|
||||||
|
break;
|
||||||
|
case AsconReadStart:
|
||||||
|
a->state = AsconReadDone;
|
||||||
|
msgbuf = a->private;
|
||||||
|
if (msgbuf->queue == NULL) {
|
||||||
|
DynStringClear(a->rdBuffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
msg = msgbuf->queue;
|
||||||
|
msgbuf->queue = msg->next;
|
||||||
|
space = strchr(msg->message, ' ');
|
||||||
|
jobj = NULL;
|
||||||
|
specifier = "";
|
||||||
|
if (space) {
|
||||||
|
l1 = space - msg->message;
|
||||||
|
specifier = space + 1;
|
||||||
|
json = strchr(specifier, ' ');
|
||||||
|
if (json) {
|
||||||
|
l2 = json - specifier;
|
||||||
|
json++;
|
||||||
|
jobj = json_tokener_parse(json);
|
||||||
|
} else {
|
||||||
|
l2 = strlen(specifier);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
l1 = strlen(msg->message);
|
||||||
|
l2 = 0;
|
||||||
|
}
|
||||||
|
tcllist[0] = Tcl_NewStringObj(msg->message, l1);
|
||||||
|
tcllist[1] = Tcl_NewStringObj(specifier, l2);
|
||||||
|
if (jobj) {
|
||||||
|
tcllist[2] = json2tcl(jobj);
|
||||||
|
tclobj = Tcl_NewListObj(3, tcllist);
|
||||||
|
} else {
|
||||||
|
tclobj = Tcl_NewListObj(2, tcllist);
|
||||||
|
}
|
||||||
|
DynStringCopy(a->rdBuffer, Tcl_GetString(tclobj));
|
||||||
|
a->responseValid = 1;
|
||||||
|
json_object_put(jobj); /* free jobj */
|
||||||
|
free(msg->message);
|
||||||
|
free(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
void AddSecop3Protocol() {
|
||||||
|
static AsconProtocol secopprot;
|
||||||
|
secopprot.name = "SECoP3";
|
||||||
|
secopprot.handler = Secop3ProtHandler;
|
||||||
|
secopprot.init = AsconStdInit;
|
||||||
|
AsconInsertProtocol(&secopprot);
|
||||||
|
}
|
128
sicshipadaba.c
128
sicshipadaba.c
@ -41,6 +41,7 @@
|
|||||||
#include "arrayutil.h"
|
#include "arrayutil.h"
|
||||||
#include "HistMem.h"
|
#include "HistMem.h"
|
||||||
#include "asynnet.h"
|
#include "asynnet.h"
|
||||||
|
#include <json-c/json.h>
|
||||||
|
|
||||||
#define MAX_HDB_PATH 1024
|
#define MAX_HDB_PATH 1024
|
||||||
|
|
||||||
@ -455,6 +456,7 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
|||||||
pDynString result, int hdtype)
|
pDynString result, int hdtype)
|
||||||
{
|
{
|
||||||
char *char_arr, *ptr;
|
char *char_arr, *ptr;
|
||||||
|
char token[8], ch;
|
||||||
|
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case normal_protocol:
|
case normal_protocol:
|
||||||
@ -465,6 +467,7 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
|||||||
case json_protocol:
|
case json_protocol:
|
||||||
switch (hdtype) {
|
switch (hdtype) {
|
||||||
case HIPNONE:
|
case HIPNONE:
|
||||||
|
DynStringCopy(result, "null");
|
||||||
break;
|
break;
|
||||||
case HIPINT:
|
case HIPINT:
|
||||||
case HIPFLOAT:
|
case HIPFLOAT:
|
||||||
@ -478,7 +481,27 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
|||||||
DynStringCopy(result, "{\"");
|
DynStringCopy(result, "{\"");
|
||||||
DynStringConcat(result, name);
|
DynStringConcat(result, name);
|
||||||
DynStringConcat(result, "\": \"");
|
DynStringConcat(result, "\": \"");
|
||||||
DynStringConcat(result, value);
|
ptr = NULL;
|
||||||
|
for (ch=*value; ch!=0; ch=*++value) {
|
||||||
|
switch (ch) {
|
||||||
|
case '"': strcpy(token, "\\\"");
|
||||||
|
case '\\': strcpy(token, "\\\\");
|
||||||
|
default:
|
||||||
|
if (ch > 127 || ch < 32) {
|
||||||
|
snprintf(token, sizeof token, "\\u%4.4x", (unsigned char)ch);
|
||||||
|
} else {
|
||||||
|
if (!ptr) ptr = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ptr) {
|
||||||
|
DynStringConcatBytes(result, ptr, value - ptr);
|
||||||
|
}
|
||||||
|
DynStringConcat(result, token);
|
||||||
|
}
|
||||||
|
if (ptr) {
|
||||||
|
DynStringConcatBytes(result, ptr, value - ptr);
|
||||||
|
}
|
||||||
DynStringConcat(result, "\"}");
|
DynStringConcat(result, "\"}");
|
||||||
break;
|
break;
|
||||||
case HIPINTAR:
|
case HIPINTAR:
|
||||||
@ -593,8 +616,11 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
|||||||
pHdbIDMessage idm = NULL;
|
pHdbIDMessage idm = NULL;
|
||||||
pHdbPtrMessage cmm = NULL;
|
pHdbPtrMessage cmm = NULL;
|
||||||
pHdbDataMessage mm = NULL;
|
pHdbDataMessage mm = NULL;
|
||||||
|
hdbPropertyChange *propm = NULL;
|
||||||
|
hdbValue *hvalue;
|
||||||
SConnection *tstCon;
|
SConnection *tstCon;
|
||||||
char updatePath[1024];
|
char updatePath[1024];
|
||||||
|
char *geterror;
|
||||||
|
|
||||||
cbInfo = (HdbCBInfo *) userData;
|
cbInfo = (HdbCBInfo *) userData;
|
||||||
|
|
||||||
@ -650,9 +676,20 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deal with update messages
|
* Deal with update and geterror property messages
|
||||||
*/
|
*/
|
||||||
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
|
||||||
|
if ((propm = GetPropertyChangeMessage(message)) != NULL) {
|
||||||
|
if (strcmp(propm->key, "geterror") != 0) {
|
||||||
|
/* this is a property change of an other property */
|
||||||
|
return hdbContinue;
|
||||||
|
}
|
||||||
|
geterror = propm->value;
|
||||||
|
hvalue = &node->value;
|
||||||
|
} else if ((mm = GetHdbUpdateMessage(message)) != NULL) {
|
||||||
|
geterror = GetHdbProp(node, "geterror");
|
||||||
|
hvalue = mm->v;
|
||||||
|
} else {
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,19 +700,26 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
|||||||
else
|
else
|
||||||
outCode = eEvent;
|
outCode = eEvent;
|
||||||
|
|
||||||
|
if (geterror && *geterror) {
|
||||||
|
/* send geterror */
|
||||||
|
strlcat(updatePath, ".geterror", sizeof updatePath);
|
||||||
|
formatNameValue(protocol, updatePath, geterror, result, HIPTEXT);
|
||||||
|
SCPureSockWrite(cbInfo->pCon, Dyn2Cstring(result), outCode);
|
||||||
|
return hdbContinue;
|
||||||
|
} /* else normal notify */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if transfer = zip always transfer data in zipped form
|
* if transfer = zip always transfer data in zipped form
|
||||||
*/
|
*/
|
||||||
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
|
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
|
||||||
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
|
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
|
||||||
status = sendZippedNodeData(node, *(mm->v), cbInfo->pCon);
|
status = sendZippedNodeData(node, *hvalue, cbInfo->pCon);
|
||||||
DeleteDynString(result);
|
DeleteDynString(result);
|
||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mm->v->arrayLength < 100) {
|
if (hvalue->arrayLength <= 400) {
|
||||||
printedData = formatValue(*(mm->v), node);
|
printedData = formatValue(*hvalue, node);
|
||||||
if (printedData == NULL || result == NULL) {
|
if (printedData == NULL || result == NULL) {
|
||||||
SCWrite(cbInfo->pCon, "ERROR: out of memory formatting data",
|
SCWrite(cbInfo->pCon, "ERROR: out of memory formatting data",
|
||||||
eEvent);
|
eEvent);
|
||||||
@ -686,7 +730,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
|||||||
return hdbContinue;
|
return hdbContinue;
|
||||||
}
|
}
|
||||||
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
|
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
|
||||||
mm->v->dataType);
|
hvalue->dataType);
|
||||||
#ifdef SITE_ANSTO
|
#ifdef SITE_ANSTO
|
||||||
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
||||||
#else
|
#else
|
||||||
@ -792,8 +836,10 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
|||||||
outCode = eHdbEvent;
|
outCode = eHdbEvent;
|
||||||
else
|
else
|
||||||
outCode = eEvent;
|
outCode = eEvent;
|
||||||
|
/* formatNameValue(protocol, "treechange", path, result,
|
||||||
|
node->value.dataType); */
|
||||||
formatNameValue(protocol, "treechange", path, result,
|
formatNameValue(protocol, "treechange", path, result,
|
||||||
node->value.dataType);
|
HIPTEXT);
|
||||||
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
||||||
DeleteDynString(result);
|
DeleteDynString(result);
|
||||||
free(path);
|
free(path);
|
||||||
@ -814,7 +860,9 @@ pHdbCallback MakeTreeChangeCallback(SConnection * pCon, int id)
|
|||||||
if (cbInfo->pCon == NULL) {
|
if (cbInfo->pCon == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
SCsetMacro(cbInfo->pCon, 0);
|
||||||
cbInfo->ID = id;
|
cbInfo->ID = id;
|
||||||
|
cbInfo->internalID = -1;
|
||||||
return MakeHipadabaCallback(TreeChangeCallback, cbInfo, cbKill);
|
return MakeHipadabaCallback(TreeChangeCallback, cbInfo, cbKill);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3024,11 +3072,12 @@ static pDynString formatPlainList(pHdb node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static pDynString formatJSONList(pHdb node)
|
static pDynString formatJSONList(pHdb node, int withValues)
|
||||||
{
|
{
|
||||||
pHdb current;
|
pHdb current;
|
||||||
pDynString result = NULL;
|
pDynString result = NULL;
|
||||||
pDynString data = NULL;
|
pDynString data = NULL;
|
||||||
|
char *str;
|
||||||
|
|
||||||
if (node->child == NULL)
|
if (node->child == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3037,33 +3086,55 @@ static pDynString formatJSONList(pHdb node)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->child->value.dataType == HIPNONE)
|
if (withValues)
|
||||||
DynStringCopy(result, "[");
|
|
||||||
else
|
|
||||||
DynStringCopy(result, "{");
|
DynStringCopy(result, "{");
|
||||||
|
else
|
||||||
|
DynStringCopy(result, "[");
|
||||||
|
|
||||||
current = node->child;
|
current = node->child;
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
DynStringConcat(result, "\"");
|
DynStringConcatChar(result, '"');
|
||||||
DynStringConcat(result, current->name);
|
DynStringConcat(result, current->name);
|
||||||
DynStringConcat(result, "\"");
|
DynStringConcatChar(result, '"');
|
||||||
if (current->value.dataType != HIPNONE) {
|
if (withValues) {
|
||||||
|
DynStringConcat(result, ": ");
|
||||||
|
if (current->value.dataType == HIPTEXT) {
|
||||||
|
DynStringConcatChar(result, '"');
|
||||||
data = formatValue(current->value, current);
|
data = formatValue(current->value, current);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
DynStringConcat(result, ": ");
|
/* lazy approach: remove \ and " */
|
||||||
|
for (str = GetCharArray(data); *str != 0; str++) {
|
||||||
|
if (*str == '\\' || *str == '"') {
|
||||||
|
*str = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
DynStringConcat(result, GetCharArray(data));
|
DynStringConcat(result, GetCharArray(data));
|
||||||
DeleteDynString(data);
|
DeleteDynString(data);
|
||||||
}
|
}
|
||||||
|
DynStringConcatChar(result, '"');
|
||||||
|
} else {
|
||||||
|
if (current->value.dataType != HIPINT && current->value.dataType != HIPFLOAT) {
|
||||||
|
data = NULL;
|
||||||
|
} else {
|
||||||
|
data = formatValue(current->value, current);
|
||||||
|
}
|
||||||
|
if (data != NULL) {
|
||||||
|
DynStringConcat(result, GetCharArray(data));
|
||||||
|
DeleteDynString(data);
|
||||||
|
} else {
|
||||||
|
DynStringConcat(result, "null");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (current->next != NULL)
|
if (current->next != NULL)
|
||||||
DynStringConcat(result, ", ");
|
DynStringConcat(result, ", ");
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->child->value.dataType == HIPNONE)
|
if (withValues)
|
||||||
DynStringConcat(result, "]");
|
|
||||||
else
|
|
||||||
DynStringConcat(result, "}");
|
DynStringConcat(result, "}");
|
||||||
|
else
|
||||||
|
DynStringConcat(result, "]");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -3197,31 +3268,34 @@ static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* do not modify arguments!
|
||||||
if (pathArg == 2) {
|
if (pathArg == 2) {
|
||||||
strtolower(argv[1]);
|
strtolower(argv[1]);
|
||||||
}
|
}
|
||||||
if (strcmp(argv[1], "-val") == 0) {
|
*/
|
||||||
|
outCode = eValue;
|
||||||
|
if (strcasecmp(argv[1], "-val") == 0) {
|
||||||
|
if (isJSON(pCon, 0)) {
|
||||||
|
listData = formatJSONList(node, 1);
|
||||||
|
outCode = eHdbEvent;
|
||||||
|
} else {
|
||||||
listData = formatListWithVal(node);
|
listData = formatListWithVal(node);
|
||||||
} else if (strcmp(argv[1], "-cli") == 0) {
|
}
|
||||||
|
} else if (strcasecmp(argv[1], "-cli") == 0) {
|
||||||
listData = formatClientList(node);
|
listData = formatClientList(node);
|
||||||
} else {
|
} else {
|
||||||
if ((protocol = isJSON(pCon, 0)) == 1) {
|
if ((protocol = isJSON(pCon, 0)) == 1) {
|
||||||
listData = formatJSONList(node);
|
listData = formatJSONList(node, 0);
|
||||||
outCode = eHdbEvent;
|
outCode = eHdbEvent;
|
||||||
} else {
|
} else {
|
||||||
listData = formatPlainList(node);
|
listData = formatPlainList(node);
|
||||||
outCode = eValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (listData == NULL) {
|
if (listData == NULL) {
|
||||||
SCWrite(pCon, "ERROR: failed to format list", eError);
|
SCWrite(pCon, "ERROR: failed to format list", eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((strcmp(argv[1], "-val") == 0) || (strcmp(argv[1], "-cli") == 0)) {
|
|
||||||
SCWrite(pCon, GetCharArray(listData), eValue);
|
|
||||||
} else {
|
|
||||||
SCWrite(pCon, GetCharArray(listData), outCode);
|
SCWrite(pCon, GetCharArray(listData), outCode);
|
||||||
}
|
|
||||||
DeleteDynString(listData);
|
DeleteDynString(listData);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
72
socketaddr.c
Normal file
72
socketaddr.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int MakeSocketAddr(
|
||||||
|
struct sockaddr *sockaddrPtr, /* socket address */
|
||||||
|
char *hostname, /* name or ip of host. NULL implies INADDR_ANY */
|
||||||
|
int port, /* port number */
|
||||||
|
char dotted_ip[16]) { /* resolved ip addr */
|
||||||
|
/*
|
||||||
|
Workaround for cases, where the local cache is not updated (yet)
|
||||||
|
often, gethostbyname gets a cached value, but dig will get a fresh one
|
||||||
|
note after an internet research: dig is recommended over nslookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct hostent *hostent; /* Host database entry */
|
||||||
|
struct sockaddr_in *sadr = (struct sockaddr_in *)sockaddrPtr;
|
||||||
|
FILE *fil;
|
||||||
|
char line[256];
|
||||||
|
int l;
|
||||||
|
|
||||||
|
(void) memset(sadr, 0, sizeof(*sadr));
|
||||||
|
if (dotted_ip) { /* default value: failure */
|
||||||
|
dotted_ip[0] = 0;
|
||||||
|
}
|
||||||
|
sadr->sin_family = AF_INET;
|
||||||
|
sadr->sin_port = htons((unsigned short)port);
|
||||||
|
if (hostname == NULL) {
|
||||||
|
/* do not need to copy, as INADDR_ANY is all zero bytes */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (inet_pton(AF_INET, hostname, &sadr->sin_addr) == 1) {
|
||||||
|
/* resolved as dotted numbers notation */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
hostent = gethostbyname(hostname);
|
||||||
|
if (hostent == 0) {
|
||||||
|
/* we assume that when gethostname gets no entry, dig will also fail.
|
||||||
|
That way, dig will not be called repeatedly for no reason */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* copy the address: in case dig fails, we use the cached value */
|
||||||
|
memcpy(&sadr->sin_addr, hostent->h_addr_list[0], 4);
|
||||||
|
/* we use hostent->h_name instead of hostname here, as this has already
|
||||||
|
the proper domain added */
|
||||||
|
snprintf(line, sizeof line, "timeout 1 dig +short %s", hostent->h_name);
|
||||||
|
fil = popen(line, "r");
|
||||||
|
if (fil != NULL) {
|
||||||
|
if (fgets(line, sizeof(line), fil) != NULL) {
|
||||||
|
l = strlen(line);
|
||||||
|
if (line[l-1] <= ' ') line[l-1] = 0; /* strip off newline */
|
||||||
|
/* silently ignore return value, if it fails, we take the cached value */
|
||||||
|
inet_pton(AF_INET, line, &sadr->sin_addr);
|
||||||
|
}
|
||||||
|
fclose(fil);
|
||||||
|
}
|
||||||
|
if (dotted_ip) {
|
||||||
|
inet_ntop(AF_INET, &sadr->sin_addr, dotted_ip, 16);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||||
|
char *host, /* Host. NULL implies INADDR_ANY */
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
return MakeSocketAddr((struct sockaddr *)sockaddrPtr, host, port, NULL);
|
||||||
|
}
|
23
socketaddr.h
Normal file
23
socketaddr.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int MakeSocketAddr(
|
||||||
|
struct sockaddr *sockaddrPtr, /* socket address */
|
||||||
|
char *hostname, /* name or ip of host. NULL implies INADDR_ANY */
|
||||||
|
int port, /* port number */
|
||||||
|
char dotted_ip[16]); /* resolved ip addr */
|
||||||
|
/*
|
||||||
|
Workaround for cases, where the local cache is not updated (yet)
|
||||||
|
often, gethostbyname gets a cached value, but dig will get a fresh one
|
||||||
|
note after an internet research: dig is recommended over nslookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* compatibility for network.c */
|
||||||
|
int CreateSocketAdress(struct sockaddr_in *sockaddrPtr, /* Socket address */
|
||||||
|
char *host, /* Host. NULL implies INADDR_ANY */
|
||||||
|
int port);
|
Reference in New Issue
Block a user