Skip to content
Snippets Groups Projects
Commit 3dd49377 authored by Simon Rose's avatar Simon Rose
Browse files

Add afterInit back to require

parent 30035bf8
No related branches found
No related tags found
No related merge requests found
/* Copyright (C) 2020 Dirk Zimoch */
/* Copyright (C) 2020-2022 European Spallation Source, ERIC */
/* Copyright (C) 2020-2023 European Spallation Source, ERIC */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <ctype.h>
#include <dbAccess.h>
#include <epicsVersion.h>
#include <epicsExport.h>
#include <epicsStdio.h>
#include <errno.h>
#include <initHooks.h>
#include <macLib.h>
#include <stdarg.h>
#include <stdio.h>
#include <iocsh.h>
#include <stdlib.h>
#include <string.h>
#define EPICSVER \
EPICS_VERSION * 10000 + EPICS_REVISION * 100 + EPICS_MODIFICATION
#include <iocsh.h>
#include <osiFileName.h>
DBCORE_API int epicsStdCall iocshCmd(const char *cmd);
#include <epicsExport.h>
#define IS_ABS_PATH(filename) \
(filename[0] == OSI_PATH_SEPARATOR[0]) /* may be different for other OS ? */
#include "expr.h"
#include "require.h"
#define SAVEENV(var) \
do { \
old_##var = getenv(#var); \
if (old_##var) old_##var = strdup(old_##var); \
} while (0)
#define RESTOREENV(var) \
do { \
if (old_##var) { \
putenvprintf("%s=%s", #var, old_##var); \
free(old_##var); \
} \
} while (0)
int runScriptDebug = 0;
int runScript(const char *filename, const char *args) {
MAC_HANDLE *mac = NULL;
FILE *file = NULL;
char *line_raw = NULL;
char *line_exp = NULL;
long line_raw_size = 256;
long line_exp_size = line_raw_size;
long len;
char **pairs;
int status = 0;
char *old_MODULE = NULL;
char *old_MODULE_DIR = NULL;
if (!filename) {
fprintf(stderr, "Usage: runScript filename [macro=value,...]\n");
return -1;
}
if (macCreateHandle(&mac, (const char *[]){"", "environ", NULL, NULL}) != 0)
goto error;
macSuppressWarning(mac, 1);
if ((line_exp = malloc(line_exp_size)) == NULL) goto error;
if ((line_raw = malloc(line_raw_size)) == NULL) goto error;
/* add args to macro definitions */
if (args) {
if (runScriptDebug) printf("runScript: macParseDefns \"%s\"\n", args);
macParseDefns(mac, (char *)args, &pairs);
macInstallMacros(mac, pairs);
free(pairs);
}
if (IS_ABS_PATH(filename)) {
file = fopen(filename, "r");
} else {
const char *dirname;
const char *end;
char *fullname;
const char *path = getenv("SCRIPT_PATH");
int dirlen;
for (dirname = path; dirname != NULL; dirname = end) {
end = strchr(dirname, OSI_PATH_LIST_SEPARATOR[0]);
if (end && end[1] == OSI_PATH_SEPARATOR[0] &&
end[2] == OSI_PATH_SEPARATOR[0]) /* "http://..." and friends */
end = strchr(end + 2, OSI_PATH_LIST_SEPARATOR[0]);
if (end)
dirlen = (int)(end++ - dirname);
else
dirlen = (int)strlen(dirname);
if (dirlen == 0) continue; /* ignore empty path elements */
if (dirname[dirlen - 1] == OSI_PATH_SEPARATOR[0]) dirlen--;
asprintf(&fullname, "%.*s" OSI_PATH_SEPARATOR "%s", dirlen, dirname,
filename);
if (runScriptDebug) printf("runScript: trying %s\n", fullname);
file = fopen(fullname, "r");
if (!file && (errno & 0xffff) != ENOENT) perror(fullname);
free(fullname);
if (file) break;
}
}
if (file == NULL) {
perror(filename);
return errno;
}
/* save some environments variables */
SAVEENV(MODULE);
SAVEENV(MODULE_DIR);
/* execute script line by line after expanding macros with arguments or
* environment */
while (fgets(line_raw, line_raw_size, file)) {
char *p, *x;
/* check if we have a line longer than the buffer size */
while (line_raw[(len = (long)strlen(line_raw)) - 1] != '\n' &&
!feof(file)) {
if (runScriptDebug) printf("runScript partial line: \"%s\"\n", line_raw);
if ((line_raw = realloc(line_raw, line_raw_size *= 2)) == NULL)
goto error;
if (fgets(line_raw + len, line_raw_size - len, file) == NULL) break;
}
while (len > 0 && isspace((unsigned char)line_raw[len - 1]))
line_raw[--len] = 0; /* get rid of '\n' and friends */
if (runScriptDebug)
printf("runScript raw line (%ld chars): '%s'\n", len, line_raw);
/* expand and check the buffer size (different epics versions write
* different may number of bytes)*/
while ((len = labs(
macExpandString(mac, line_raw, line_exp, line_exp_size - 1))) >=
line_exp_size - 2) {
if (runScriptDebug)
printf("runScript: grow expand buffer: len=%ld size=%ld\n", len,
line_exp_size);
free(line_exp);
if ((line_exp = malloc(line_exp_size *= 2)) == NULL) goto error;
}
if (runScriptDebug)
printf("runScript expanded line (%ld chars): '%s'\n", len, line_exp);
printf("%s\n", line_exp);
p = line_exp;
while (isspace((unsigned char)*p)) p++;
if (*p == 0 || *p == '#') continue;
/* find local variable assignments */
if ((x = strpbrk(p, "=(, \t\n\r")) != NULL && *x == '=') {
*x++ = 0;
replaceExpressions(x, line_raw, line_raw_size);
if (runScriptDebug) printf("runScript: assign %s=%s\n", p, line_raw);
macPutValue(mac, p, line_raw);
continue;
}
if (runScriptDebug) printf("runScript: iocshCmd: '%s'\n", line_exp);
status = iocshCmd(line_exp);
if (status != 0) break;
}
goto end;
error:
if (errno) {
status = errno;
perror("runScript");
}
end:
free(line_raw);
free(line_exp);
if (mac) macDeleteHandle(mac);
if (file) fclose(file);
/* restore environment */
RESTOREENV(MODULE);
RESTOREENV(MODULE_DIR);
return status;
}
struct cmditem {
struct cmditem *next;
int type;
......@@ -189,7 +17,7 @@ struct cmditem {
char *a[12];
char cmd[256];
} x;
} * cmdlist, **cmdlast = &cmdlist;
} *cmdlist, **cmdlast = &cmdlist;
void afterInitHook(initHookState state) {
struct cmditem *item;
......@@ -217,9 +45,8 @@ void afterInitHook(initHookState state) {
}
}
static int first_time = 1;
static struct cmditem *newItem(char *cmd, int type) {
static int first_time = 1;
struct cmditem *item;
if (!cmd) {
fprintf(stderr, "usage: afterInit command, args...\n");
......@@ -266,20 +93,6 @@ int afterInit(char *cmd, char *a1, char *a2, char *a3, char *a4, char *a5,
return 0;
}
epicsExportAddress(int, runScriptDebug);
epicsExportAddress(int, exprDebug);
static const iocshFuncDef runScriptDef = {
"runScript", 2,
(const iocshArg *[]){
&(iocshArg){"filename", iocshArgString},
&(iocshArg){"substitutions", iocshArgString},
}};
static void runScriptFunc(const iocshArgBuf *args) {
runScript(args[0].sval, args[1].sval);
}
static const iocshFuncDef afterInitDef = {
"afterInit", 1,
(const iocshArg *[]){
......@@ -300,12 +113,11 @@ static void afterInitFunc(const iocshArgBuf *args) {
}
}
static void runScriptRegister(void) {
static void afterInitRegister(void) {
static int firstTime = 1;
if (firstTime) {
firstTime = 0;
iocshRegister(&runScriptDef, runScriptFunc);
iocshRegister(&afterInitDef, afterInitFunc);
}
}
epicsExportRegistrar(runScriptRegister);
epicsExportRegistrar(afterInitRegister);
registrar(afterInitRegister)
......@@ -37,7 +37,9 @@ APPDB := $(APP)/Db
SOURCES += $(APPSRC)/require.c
SOURCES += $(APPSRC)/version.c
SOURCES += $(APPSRC)/afterInit.c
DBDS += $(APPSRC)/require.dbd
DBDS += $(APPSRC)/afterInit.dbd
SOURCES += $(APPSRC)/dbLoadTemplate.y
DBDS += $(APPSRC)/dbLoadTemplate.dbd
......
......@@ -45,3 +45,11 @@ def test_cellpath_does_not_depend_on_order(wrapper: Wrapper):
rc, *_ = run_ioc_get_output("-r", wrapper.name, "-l", cell_path)
assert rc == 0
def test_after_init():
rc, outs, _ = run_ioc_get_output("-c", "afterInit echo hello")
assert rc == 0
lines = outs.split("\n")
assert "hello" in lines[lines.index("iocInit") :]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment