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/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -13,69 +10,11 @@
|
||||
#include "splitter.h"
|
||||
#include "ascon.i"
|
||||
#include "uselect.h"
|
||||
#include "socketaddr.h"
|
||||
|
||||
static double lastClose = 0; /* time of last close operation */
|
||||
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)
|
||||
{
|
||||
static char *stateText[]={
|
||||
@ -171,7 +110,7 @@ static void AsconConnect(Ascon * a)
|
||||
return;
|
||||
}
|
||||
*colon = '\0';
|
||||
ret = MakeSocketAdr(&adr, a->hostport, port, a->ip);
|
||||
ret = MakeSocketAddr(&adr, a->hostport, port, a->ip);
|
||||
*colon = ':';
|
||||
if (ret == 0) {
|
||||
AsconError(a, "bad host specification", 0);
|
||||
@ -548,6 +487,22 @@ int AsconStdHandler(Ascon * 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
|
||||
* is limited to single character terminators.
|
||||
@ -558,18 +513,10 @@ int AsconStdHandler(Ascon * a)
|
||||
*/
|
||||
void AsconCheckTerminators(Ascon *a)
|
||||
{
|
||||
int c, i, l;
|
||||
int i, l;
|
||||
|
||||
if (a->sendTerminator != NULL && strncmp(a->sendTerminator,"0x",2) == 0) {
|
||||
sscanf(a->sendTerminator,"%x",&c);
|
||||
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';
|
||||
}
|
||||
checkTerminator(a->sendTerminator);
|
||||
checkTerminator(a->replyTerminator);
|
||||
a->compositeTerminator = 0;
|
||||
if (a->replyTerminator != NULL && a->replyTerminator[0] == '\'') {
|
||||
l = strlen(a->replyTerminator);
|
||||
|
@ -1157,6 +1157,10 @@ void SetHdbProperty(pHdb node, char *key, char *value)
|
||||
hdbPropertyChange propMes;
|
||||
|
||||
if (node != NULL && key != NULL && node->properties != NULL) {
|
||||
propMes.type = propertyChange;
|
||||
propMes.key = key;
|
||||
propMes.value = value;
|
||||
InvokeCallbackChain(node,(pHdbMessage)&propMes);
|
||||
if (value == NULL) {
|
||||
StringDictDelete(node->properties, key);
|
||||
} else if (StringDictExists(node->properties, key)) {
|
||||
@ -1164,10 +1168,6 @@ void SetHdbProperty(pHdb node, char *key, char *value)
|
||||
} else {
|
||||
StringDictAddPair(node->properties, key, value);
|
||||
}
|
||||
propMes.type = propertyChange;
|
||||
propMes.key = key;
|
||||
propMes.value = value;
|
||||
InvokeCallbackChain(node,(pHdbMessage)&propMes);
|
||||
}
|
||||
}
|
||||
|
||||
|
21
logger.c
21
logger.c
@ -49,6 +49,12 @@ Logger *LoggerFind(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
Logger *LoggerList(void)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#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(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", &tm);
|
||||
|
||||
if (period <= 0)
|
||||
period = 1;
|
||||
if (period <= 0) {
|
||||
if (log->period > 0) {
|
||||
period = log->period;
|
||||
} else {
|
||||
period = 1;
|
||||
}
|
||||
}
|
||||
writeInfo = (tm.tm_isdst != lasttm.tm_isdst ||
|
||||
tm.tm_yday != lasttm.tm_yday ||
|
||||
(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];
|
||||
struct stat st;
|
||||
@ -473,6 +484,10 @@ void LoggerFreeAll(void)
|
||||
free(p->name);
|
||||
if (p->old)
|
||||
free(p->old);
|
||||
if (p->secop_old)
|
||||
free(p->secop_old);
|
||||
if (p->secop_id)
|
||||
free(p->secop_id);
|
||||
free(p);
|
||||
p = next;
|
||||
}
|
||||
|
7
logger.h
7
logger.h
@ -16,12 +16,16 @@ typedef struct Logger {
|
||||
int numeric;
|
||||
int period;
|
||||
int exact;
|
||||
void *histWriter;
|
||||
char *secop_old;
|
||||
char *secop_id;
|
||||
/* private: */
|
||||
char *old;
|
||||
int oldsize;
|
||||
time_t last, lastWrite, omitTime;
|
||||
float omitValue;
|
||||
struct Logger *next;
|
||||
int category; /* 0: unimportant, 1: important */
|
||||
} Logger;
|
||||
|
||||
|
||||
@ -39,5 +43,6 @@ void LoggerChange(Logger * log, int period, char *newname);
|
||||
int LoggerVarPath(char *dir, char *path, int pathLen, char *name,
|
||||
struct tm *t);
|
||||
void LoggerFreeAll(void);
|
||||
|
||||
int LoggerMakeDir(char *path);
|
||||
Logger *LoggerList(void);
|
||||
#endif
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#define LOGGER_NAN -999999.
|
||||
#define ONE_YEAR (366*24*3600)
|
||||
#define LLEN 1024
|
||||
#define LLEN 4096
|
||||
/* max. number of dirs in path */
|
||||
#define MAX_DIRS 16
|
||||
|
||||
|
320
logsetup.c
320
logsetup.c
@ -1,8 +1,161 @@
|
||||
#include "logger.h"
|
||||
#include "logsetup.h"
|
||||
#include "sics.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
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,
|
||||
void *userData,
|
||||
@ -14,7 +167,9 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
hdbValue value;
|
||||
pHdbDataMessage mm = NULL;
|
||||
pHdbDataSearch dsm = NULL;
|
||||
pHdbMessage killmsg = NULL;
|
||||
time_t now;
|
||||
char *strvalue;
|
||||
|
||||
if ((dsm = GetHdbDataSearchMessage(message)) != NULL) {
|
||||
if (dsm->testPtr == loggerID) {
|
||||
@ -24,6 +179,18 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
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) {
|
||||
return hdbContinue;
|
||||
}
|
||||
@ -31,66 +198,43 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
value = *(mm->v);
|
||||
|
||||
time(&now);
|
||||
|
||||
if (GetHdbProp(node, "geterror") == NULL) {
|
||||
str = formatValue(value, node);
|
||||
strvalue = GetCharArray(str);
|
||||
} else {
|
||||
str = NULL;
|
||||
strvalue = "";
|
||||
}
|
||||
/* testwise >= */
|
||||
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
||||
if (GetHdbProp(node, "geterror") == NULL) {
|
||||
str = formatValue(value, node);
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
||||
DeleteDynString(str);
|
||||
} else {
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), "");
|
||||
}
|
||||
LoggerWrite(logger, now, LoggerPeriod(logger), strvalue);
|
||||
}
|
||||
if (logger->histWriter) {
|
||||
HistWrite(logger, node, now, strvalue);
|
||||
}
|
||||
if (str) {
|
||||
DeleteDynString(str);
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pHdb node;
|
||||
pHdbCallback cb;
|
||||
static char basepath[1024] = "/";
|
||||
int LogMakeInternal(pHdb node, char *path, int period) {
|
||||
char buf[1024];
|
||||
char *p, *name;
|
||||
static char *loggerDir = NULL;
|
||||
int numeric, period;
|
||||
char secop_id[1024];
|
||||
char secop_par[1024];
|
||||
char *module;
|
||||
int pos, l;
|
||||
pHdb nd;
|
||||
int numeric;
|
||||
Logger *logger;
|
||||
char *p, *name;
|
||||
pHdbCallback cb;
|
||||
|
||||
if (argc < 2) {
|
||||
SCPrintf(pCon, eError,
|
||||
"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]);
|
||||
if (strncmp(path, "/sics/", 6) == 0) {
|
||||
snprintf(buf, sizeof buf, "%s", path+5);
|
||||
} else {
|
||||
snprintf(buf, sizeof buf, "%s", argv[1]);
|
||||
snprintf(buf, sizeof buf, "%s", path);
|
||||
}
|
||||
for (p = buf; *p != '\0'; p++) {
|
||||
if (*p == '/')
|
||||
@ -101,29 +245,22 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
} else {
|
||||
name = buf;
|
||||
}
|
||||
if (node->value.dataType == HIPFLOAT) {
|
||||
if (node->value.dataType == HIPFLOAT || node->value.dataType == HIPINT) {
|
||||
numeric = 1;
|
||||
} else {
|
||||
numeric = 0;
|
||||
}
|
||||
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 */
|
||||
LoggerChange(logger, period, name);
|
||||
} else {
|
||||
logger = LoggerMake(name, period, !numeric);
|
||||
/* If that failed, we cannot continue - it crashes in the callback */
|
||||
if (logger == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
logger->histWriter = &mainWriter;
|
||||
LoggerSetNumeric(logger, numeric);
|
||||
SetHdbProperty(node, "logger_name", name);
|
||||
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,
|
||||
@ -131,7 +268,70 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
assert(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;
|
||||
}
|
||||
|
||||
|
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
|
93
make_gen
93
make_gen
@ -8,53 +8,61 @@
|
||||
#EPICSOBJ=epicsmotor.o
|
||||
EPICSOBJ=
|
||||
|
||||
COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ)
|
||||
SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
sicvar.o nserver.o SICSmain.o motorlist.o\
|
||||
COREOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
sicvar.o nserver.o SICSmain.o motorlist.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 \
|
||||
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 \
|
||||
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 \
|
||||
danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\
|
||||
scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\
|
||||
tclev.o hkl.o integrate.o optimise.o dynstring.o nxutil.o \
|
||||
danu.o varlog.o stptok.o nread.o trigd.o \
|
||||
scan.o fitcenter.o telnet.o token.o wwildcard.o \
|
||||
tclev.o integrate.o optimise.o dynstring.o \
|
||||
uubuffer.o udpquieck.o fourtable.o hexString.o\
|
||||
rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\
|
||||
simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\
|
||||
xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
||||
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
|
||||
rmtrail.o help.o confvirtualmot.o \
|
||||
simchop.o choco.o chadapter.o trim.o scaldate.o \
|
||||
xytable.o exebuf.o exeman.o \
|
||||
circular.o maximize.o sicscron.o scanvar.o \
|
||||
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o \
|
||||
synchronize.o definealias.o oscillate.o tasdrive.o \
|
||||
hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \
|
||||
fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \
|
||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||
sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
|
||||
synchronize.o definealias.o oscillate.o \
|
||||
userscan.o rs232controller.o \
|
||||
motreg.o motreglist.o anticollider.o \
|
||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
|
||||
tclintimpl.o sicsdata.o \
|
||||
initializer.o remob.o tclmotdriv.o protocol.o \
|
||||
sicslist.o hipadaba.o sicshipadaba.o statistics.o \
|
||||
ascon.o scriptcontext.o logger.o logreader.o logsetup.o \
|
||||
savehdb.o statusfile.o sicshdbfactory.o proxy.o devser.o \
|
||||
moregress.o multicounter.o regresscter.o histregress.o \
|
||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o frame.o syncedprot.o\
|
||||
nxcopy.o nxinterhelper.o nxinter_wrap.o arrayutil.o \
|
||||
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.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 \
|
||||
moregress.o multicounter.o regresscter.o \
|
||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o \
|
||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o syncedprot.o\
|
||||
arrayutil.o \
|
||||
sctdriveadapter.o sctdriveobj.o reflist.o uselect.o motorsec.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\
|
||||
singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o\
|
||||
lscprot.o secopprot.o\
|
||||
sicsutil.o strlutil.o genbinprot.o trace.o\
|
||||
taskobj.o sctcomtask.o multicountersec.o\
|
||||
lscprot.o secopprot.o secopprot3.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
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.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: .tcl .htm .c .o .tc
|
||||
@ -62,16 +70,24 @@ OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ)
|
||||
.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
|
||||
.SECONDARY.: sicspoll.c polldriv.c
|
||||
|
||||
all: libmat libhlib libpsi SICServer
|
||||
|
||||
# use this target when some of the libraries SUBLIBS might be incomplete
|
||||
full: purge all
|
||||
|
||||
SICServer: $(OBJ) $(SUBLIBS)
|
||||
$(CC) $(DBG) -o SICServer $(OBJ) $(LIBS)
|
||||
SICServer: libmat libhlib libpsi $(SICSOBJ) $(SUBLIBS)
|
||||
$(CC) $(DBG) -o SICServer $(SICSOBJ) $(LIBS)
|
||||
|
||||
SeaServer: libseapsi $(SEAOBJ) $(SEASUBLIBS)
|
||||
$(CC) $(DBG) -o SeaServer $(SEAOBJ) $(SEALIBS)
|
||||
|
||||
matrix/libmatrix.a: libmat
|
||||
|
||||
@ -88,6 +104,9 @@ $(SICSROOT)/sicspsi/libpsi.a: libpsi
|
||||
libpsi:
|
||||
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libpsi.a
|
||||
|
||||
libseapsi:
|
||||
cd $(SICSROOT)/sicspsi; make $(MFLAGS) libseapsi.a
|
||||
|
||||
purge:
|
||||
rm -f SICServer $(SUBLIBS)
|
||||
|
||||
|
@ -34,6 +34,11 @@ LIBS = -L$(EXTRAROOT)/lib -L$(EXTRAROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS)
|
||||
-ltcl -lNeXus /usr/lib64/libhdf5.so \
|
||||
$(EXTRAROOT)/lib/libjson-c.a \
|
||||
-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
|
||||
|
||||
|
38
network.c
38
network.c
@ -53,6 +53,7 @@
|
||||
#include <fcntl.h>
|
||||
#include "sics.h"
|
||||
#include "uselect.h"
|
||||
#include "socketaddr.h"
|
||||
|
||||
#define PORT 1
|
||||
#define SOCKET 2
|
||||
@ -78,43 +79,6 @@ static void NetError(const char 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)
|
||||
|
1
ofac.c
1
ofac.c
@ -53,6 +53,7 @@ static void InitGeneral(void)
|
||||
INIT(AddCharByCharProtocoll);
|
||||
INIT(AddLscProtocol);
|
||||
INIT(AddSecopProtocol);
|
||||
INIT(AddSecop3Protocol);
|
||||
INIT(MakeTrace);
|
||||
INIT(InitTaskOBJ);
|
||||
INIT(RemoteObjectInit);
|
||||
|
18
protocol.c
18
protocol.c
@ -469,10 +469,11 @@ struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer,
|
||||
char pError[256];
|
||||
pError[0] = '\0';
|
||||
|
||||
|
||||
/*
|
||||
if (strlen(pBuffer) == 0) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!SCVerifyConnection(pCon)) {
|
||||
return 0;
|
||||
@ -518,9 +519,14 @@ struct json_object *mkJSON_Object(SConnection * pCon, char *pBuffer,
|
||||
}
|
||||
if (iOut == eHdbValue || iOut == eHdbEvent) {
|
||||
tmp_json = json_tokener_parse(pBuffer);
|
||||
if (tmp_json == NULL) {
|
||||
linenum = __LINE__;
|
||||
goto reporterr;
|
||||
if (strcmp(pBuffer, "null") != 0) {
|
||||
if (tmp_json == NULL) {
|
||||
tmp_json = json_object_new_string(pBuffer);
|
||||
}
|
||||
if (tmp_json == NULL) {
|
||||
linenum = __LINE__;
|
||||
goto reporterr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Strip \r and \n */
|
||||
@ -561,9 +567,11 @@ int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut)
|
||||
char pBueffel[MAXMSG], errBuff[MAXMSG];
|
||||
int iRet, errLen = MAXMSG;
|
||||
|
||||
/*
|
||||
if (strlen(pBuffer) == 0)
|
||||
return 1;
|
||||
|
||||
*/
|
||||
|
||||
/* log it for any case */
|
||||
iRet = SCGetSockHandle(pCon);
|
||||
|
||||
|
15
script.c
15
script.c
@ -43,6 +43,7 @@
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "fupa.h"
|
||||
@ -583,7 +584,7 @@ Tcl_Obj *json2tcl(struct json_object *jobj) {
|
||||
char buf[100];
|
||||
int i, len;
|
||||
Tcl_Obj **list;
|
||||
Tcl_Obj *dict, *kobj, *vobj;
|
||||
Tcl_Obj *result, *kobj, *vobj;
|
||||
Tcl_Obj *val;
|
||||
const char *key;
|
||||
const char *str;
|
||||
@ -605,18 +606,20 @@ Tcl_Obj *json2tcl(struct json_object *jobj) {
|
||||
list[i] = json2tcl(json_object_array_get_idx(jobj, i));
|
||||
if (!list[i]) return NULL;
|
||||
}
|
||||
return Tcl_NewListObj(len, list);
|
||||
result = Tcl_NewListObj(len, list);
|
||||
free(list);
|
||||
return result;
|
||||
case json_type_object:
|
||||
dict = Tcl_NewDictObj();
|
||||
if (!dict) return NULL;
|
||||
result = Tcl_NewDictObj();
|
||||
if (!result) return NULL;
|
||||
json_object_object_foreach(jobj, key, val) {
|
||||
kobj = Tcl_NewStringObj(key, strlen(key));
|
||||
vobj = json2tcl(val);
|
||||
if (kobj && vobj) {
|
||||
Tcl_DictObjPut(NULL, dict, kobj, vobj);
|
||||
Tcl_DictObjPut(NULL, result, kobj, vobj);
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
return result;
|
||||
}
|
||||
return Tcl_NewStringObj("None", 4);
|
||||
}
|
||||
|
@ -344,14 +344,16 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
char path[MAX_HDB_PATH];
|
||||
|
||||
PushContext(node, controller);
|
||||
if (controller->debugConn) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%6.3f script: (on %s) %s", secondsOfMinute(), path, script);
|
||||
}
|
||||
if (controller->fd != NULL) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
fprintf(controller->fd,"%6.3f script: (on %s) %s\n", secondsOfMinute(), path, script);
|
||||
if (script[strlen(script)-1] != '_') { /* suppress these debug messages */
|
||||
if (controller->debugConn) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%6.3f script: (on %s) %s", secondsOfMinute(), path, script);
|
||||
}
|
||||
if (controller->fd != NULL) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
fprintf(controller->fd,"%6.3f script: (on %s) %s\n", secondsOfMinute(), path, script);
|
||||
}
|
||||
}
|
||||
|
||||
MacroPush(con);
|
||||
@ -366,12 +368,18 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
result++;
|
||||
}
|
||||
}
|
||||
if (controller->debugConn) {
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%6.3f error: %s", secondsOfMinute(), result);
|
||||
}
|
||||
if(controller->fd != NULL){
|
||||
if (script[strlen(script)-1] != '_') { /* suppress these error messages */
|
||||
if (controller->debugConn) {
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%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){
|
||||
fprintf(controller->fd, "%6.3f error: %s\n", secondsOfMinute(), result);
|
||||
}
|
||||
}
|
||||
iRet = 0;
|
||||
}
|
||||
@ -390,6 +398,11 @@ static int SctMatch(void *data1, void *data2)
|
||||
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
|
||||
* 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);
|
||||
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());
|
||||
|
||||
SetHdbProperty(node, timeKey, timeVal);
|
||||
send = NULL;
|
||||
free(script);
|
||||
@ -644,17 +665,19 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
send = GetProp(node, controller->node, "send");
|
||||
if (send == NULL)
|
||||
send = "";
|
||||
if (controller->debugConn) {
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%6.3f send : %s", secondsOfMinute(), send);
|
||||
}
|
||||
if (controller->fd != NULL) {
|
||||
fprintf(controller->fd, "%6.3f send : %s\n", secondsOfMinute(), send);
|
||||
}
|
||||
if(data != NULL && data->controller != NULL){
|
||||
traceIO(data->controller->node->name, "send:%s", send);
|
||||
} else {
|
||||
traceIO("sctunknown", "send:%s", send);
|
||||
if (*send != '\0') {
|
||||
if (controller->debugConn) {
|
||||
SCPf(SCPureSockWrite, controller->debugConn, eLog,
|
||||
"%6.3f send : %s", secondsOfMinute(), send);
|
||||
}
|
||||
if (controller->fd != NULL) {
|
||||
fprintf(controller->fd, "%6.3f send : %s\n", secondsOfMinute(), send);
|
||||
}
|
||||
if(data != NULL && data->controller != NULL){
|
||||
traceIO(data->controller->node->name, "send:%s", send);
|
||||
} else {
|
||||
traceIO("sctunknown", "send:%s", send);
|
||||
}
|
||||
}
|
||||
return send;
|
||||
}
|
||||
@ -852,6 +875,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
SCPrintf(con, eError, "ERROR: %s", error); /* nicer for the user */
|
||||
SetHdbProperty(node, "target", NULL);
|
||||
SetHdbProperty(node, "requested", NULL);
|
||||
DeleteDynString(text);
|
||||
return hdbAbort;
|
||||
}
|
||||
}
|
||||
@ -1194,7 +1218,7 @@ static int SctWriteCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
}
|
||||
|
||||
void SctQueueNode(SctController * controller, Hdb * node,
|
||||
DevPrio prio, char *action, SConnection * con)
|
||||
DevPrio prio, char *action, int replace, SConnection * con)
|
||||
{
|
||||
SctData *data;
|
||||
hdbCallback *cb;
|
||||
@ -1215,8 +1239,9 @@ void SctQueueNode(SctController * controller, Hdb * node,
|
||||
|
||||
data->syncid = SyncedIncr(0);
|
||||
data->busy = 1;
|
||||
if (DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, SctKillData, SctDataInfo)) {
|
||||
if (DevQueue(data->controller->devser, data, prio, SctWriteHandler,
|
||||
replace ? SctMatch : NoMatch,
|
||||
SctKillData, SctDataInfo)) {
|
||||
if (con != NULL) {
|
||||
data->conCtx = SCCopyConnection(con);
|
||||
}
|
||||
@ -1257,7 +1282,8 @@ static int SctQueueCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1970,13 +1996,18 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
"write", usMugger, MakeSICSFunc(SctWriteCmd));
|
||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"queue", usMugger, MakeSICSFunc(SctQueueCmd));
|
||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||
AddSICSHdbPar(cmd, "prio", 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,
|
||||
"updatescript", usMugger, MakeSICSFunc(SctUpdatescriptCmd));
|
||||
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
||||
|
@ -14,10 +14,11 @@ typedef struct SctController SctController;
|
||||
* \param node the node
|
||||
* \param prio the priority
|
||||
* \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
|
||||
*/
|
||||
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
|
||||
* in connection with the given node and controller
|
||||
|
@ -56,7 +56,7 @@ static int SCTDRIVHalt(void *data)
|
||||
|
||||
self = (pSctDrive) data;
|
||||
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)) {
|
||||
SetHdbProperty(self->node, "status", "idle");
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ static int SCTDRIVHalt(void *data)
|
||||
self = (pSICSOBJ) data;
|
||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||
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);
|
||||
} else
|
||||
if (GetHdbProperty(self->objectNode, "status", dummy, sizeof dummy))
|
||||
@ -177,7 +177,8 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
||||
Tcl_Interp *pTcl = NULL;
|
||||
char *result;
|
||||
SConnection *con;
|
||||
|
||||
int ret;
|
||||
|
||||
self = (pSICSOBJ) data;
|
||||
pPriv = (pDrivObjPriv) self->pPrivate;
|
||||
|
||||
@ -186,7 +187,8 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
||||
*/
|
||||
if (GetHdbProperty(self->objectNode, "writestatus", script, 1024)) {
|
||||
if (strcmp(script, "start") == 0) {
|
||||
return HWBusy;
|
||||
ret = HWBusy;
|
||||
goto Return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +200,9 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
||||
SCWrite(pCon,
|
||||
"ERROR: configuration problem: no checkstatus script!",
|
||||
eError);
|
||||
return HWFault;
|
||||
ret = HWFault;
|
||||
result = "error";
|
||||
goto Return;
|
||||
}
|
||||
result = script;
|
||||
} else {
|
||||
@ -206,7 +210,9 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
||||
pPriv->c, &result);
|
||||
if (status == 0) {
|
||||
SCPrintf(pCon, eError, " script %s returned %s", script, result);
|
||||
return HWFault;
|
||||
ret = HWFault;
|
||||
result = "error";
|
||||
goto Return;
|
||||
}
|
||||
if (SctDebugConn(pPriv->c)) {
|
||||
SCPf(SCPureSockWrite, SctDebugConn(pPriv->c), eError,
|
||||
@ -214,20 +220,28 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon)
|
||||
}
|
||||
}
|
||||
if (strstr(result, "run") != NULL) {
|
||||
return HWBusy;
|
||||
ret = HWBusy;
|
||||
} else if (strstr(result, "posfault") != NULL) {
|
||||
return HWPosFault;
|
||||
ret = HWPosFault;
|
||||
} else if (strstr(result, "error") != NULL) {
|
||||
return HWFault;
|
||||
ret = HWFault;
|
||||
} else if (strstr(result, "idle") != NULL) {
|
||||
return HWIdle;
|
||||
ret = HWIdle;
|
||||
} else {
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: invalid status code %s returned from checkstatus script",
|
||||
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);
|
||||
}
|
140
sicshipadaba.c
140
sicshipadaba.c
@ -41,6 +41,7 @@
|
||||
#include "arrayutil.h"
|
||||
#include "HistMem.h"
|
||||
#include "asynnet.h"
|
||||
#include <json-c/json.h>
|
||||
|
||||
#define MAX_HDB_PATH 1024
|
||||
|
||||
@ -455,6 +456,7 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
||||
pDynString result, int hdtype)
|
||||
{
|
||||
char *char_arr, *ptr;
|
||||
char token[8], ch;
|
||||
|
||||
switch (protocol) {
|
||||
case normal_protocol:
|
||||
@ -465,6 +467,7 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
||||
case json_protocol:
|
||||
switch (hdtype) {
|
||||
case HIPNONE:
|
||||
DynStringCopy(result, "null");
|
||||
break;
|
||||
case HIPINT:
|
||||
case HIPFLOAT:
|
||||
@ -478,7 +481,27 @@ int formatNameValue(Protocol protocol, char *name, char *value,
|
||||
DynStringCopy(result, "{\"");
|
||||
DynStringConcat(result, name);
|
||||
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, "\"}");
|
||||
break;
|
||||
case HIPINTAR:
|
||||
@ -593,8 +616,11 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
pHdbIDMessage idm = NULL;
|
||||
pHdbPtrMessage cmm = NULL;
|
||||
pHdbDataMessage mm = NULL;
|
||||
hdbPropertyChange *propm = NULL;
|
||||
hdbValue *hvalue;
|
||||
SConnection *tstCon;
|
||||
char updatePath[1024];
|
||||
char *geterror;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -663,19 +700,26 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
else
|
||||
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 (GetHdbProperty(node, "transfer", value, 80) == 1) {
|
||||
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
|
||||
status = sendZippedNodeData(node, *(mm->v), cbInfo->pCon);
|
||||
status = sendZippedNodeData(node, *hvalue, cbInfo->pCon);
|
||||
DeleteDynString(result);
|
||||
return hdbContinue;
|
||||
}
|
||||
}
|
||||
if (mm->v->arrayLength < 100) {
|
||||
printedData = formatValue(*(mm->v), node);
|
||||
if (hvalue->arrayLength <= 400) {
|
||||
printedData = formatValue(*hvalue, node);
|
||||
if (printedData == NULL || result == NULL) {
|
||||
SCWrite(cbInfo->pCon, "ERROR: out of memory formatting data",
|
||||
eEvent);
|
||||
@ -686,7 +730,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
return hdbContinue;
|
||||
}
|
||||
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
|
||||
mm->v->dataType);
|
||||
hvalue->dataType);
|
||||
#ifdef SITE_ANSTO
|
||||
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
||||
#else
|
||||
@ -792,8 +836,10 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
outCode = eHdbEvent;
|
||||
else
|
||||
outCode = eEvent;
|
||||
/* formatNameValue(protocol, "treechange", path, result,
|
||||
node->value.dataType); */
|
||||
formatNameValue(protocol, "treechange", path, result,
|
||||
node->value.dataType);
|
||||
HIPTEXT);
|
||||
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
|
||||
DeleteDynString(result);
|
||||
free(path);
|
||||
@ -814,7 +860,9 @@ pHdbCallback MakeTreeChangeCallback(SConnection * pCon, int id)
|
||||
if (cbInfo->pCon == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
SCsetMacro(cbInfo->pCon, 0);
|
||||
cbInfo->ID = id;
|
||||
cbInfo->internalID = -1;
|
||||
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;
|
||||
pDynString result = NULL;
|
||||
pDynString data = NULL;
|
||||
char *str;
|
||||
|
||||
if (node->child == NULL)
|
||||
return NULL;
|
||||
@ -3037,22 +3086,44 @@ static pDynString formatJSONList(pHdb node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->child->value.dataType == HIPNONE)
|
||||
DynStringCopy(result, "[");
|
||||
else
|
||||
if (withValues)
|
||||
DynStringCopy(result, "{");
|
||||
else
|
||||
DynStringCopy(result, "[");
|
||||
|
||||
current = node->child;
|
||||
while (current != NULL) {
|
||||
DynStringConcat(result, "\"");
|
||||
DynStringConcatChar(result, '"');
|
||||
DynStringConcat(result, current->name);
|
||||
DynStringConcat(result, "\"");
|
||||
if (current->value.dataType != HIPNONE) {
|
||||
data = formatValue(current->value, current);
|
||||
if (data != NULL) {
|
||||
DynStringConcat(result, ": ");
|
||||
DynStringConcat(result, GetCharArray(data));
|
||||
DeleteDynString(data);
|
||||
DynStringConcatChar(result, '"');
|
||||
if (withValues) {
|
||||
DynStringConcat(result, ": ");
|
||||
if (current->value.dataType == HIPTEXT) {
|
||||
DynStringConcatChar(result, '"');
|
||||
data = formatValue(current->value, current);
|
||||
if (data != NULL) {
|
||||
/* lazy approach: remove \ and " */
|
||||
for (str = GetCharArray(data); *str != 0; str++) {
|
||||
if (*str == '\\' || *str == '"') {
|
||||
*str = '_';
|
||||
}
|
||||
}
|
||||
DynStringConcat(result, GetCharArray(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)
|
||||
@ -3060,10 +3131,10 @@ static pDynString formatJSONList(pHdb node)
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (node->child->value.dataType == HIPNONE)
|
||||
DynStringConcat(result, "]");
|
||||
else
|
||||
if (withValues)
|
||||
DynStringConcat(result, "}");
|
||||
else
|
||||
DynStringConcat(result, "]");
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -3197,31 +3268,34 @@ static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do not modify arguments!
|
||||
if (pathArg == 2) {
|
||||
strtolower(argv[1]);
|
||||
}
|
||||
if (strcmp(argv[1], "-val") == 0) {
|
||||
listData = formatListWithVal(node);
|
||||
} else if (strcmp(argv[1], "-cli") == 0) {
|
||||
*/
|
||||
outCode = eValue;
|
||||
if (strcasecmp(argv[1], "-val") == 0) {
|
||||
if (isJSON(pCon, 0)) {
|
||||
listData = formatJSONList(node, 1);
|
||||
outCode = eHdbEvent;
|
||||
} else {
|
||||
listData = formatListWithVal(node);
|
||||
}
|
||||
} else if (strcasecmp(argv[1], "-cli") == 0) {
|
||||
listData = formatClientList(node);
|
||||
} else {
|
||||
if ((protocol = isJSON(pCon, 0)) == 1) {
|
||||
listData = formatJSONList(node);
|
||||
listData = formatJSONList(node, 0);
|
||||
outCode = eHdbEvent;
|
||||
} else {
|
||||
listData = formatPlainList(node);
|
||||
outCode = eValue;
|
||||
}
|
||||
}
|
||||
if (listData == NULL) {
|
||||
SCWrite(pCon, "ERROR: failed to format list", eError);
|
||||
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);
|
||||
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