Skip to content

Commit 75a0734

Browse files
authored
Merge pull request #57 from tynanford/master
Add setReccasterEnvironmentVars iocsh function for custom env vars
2 parents fa4f2f5 + 10b2c93 commit 75a0734

File tree

9 files changed

+335
-8
lines changed

9 files changed

+335
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ dropin.cache
1313
client/configure/*.local
1414

1515
*~
16+
.*.swp

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ The RecCaster client currently sends the following information
1515
about its Process Database.
1616

1717
* The EPICS Base Version
18-
* A white listed set of envronment variables
19-
* The name and type of all records
18+
* A white listed set of environment variables
19+
* The name, type, and description of all records
2020
* Any info() tags associated with these records
21+
* Any additional environment variables specified in addReccasterEnvVars iocsh calls
2122

2223
RecCaster Usage
2324
---------------

client/castApp/src/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ testtcp_SRCS += testtcp.c
4040
testtcp_SYS_LIBS_WIN32 = ws2_32
4141
TESTS += testtcp
4242

43+
TESTPROD_HOST += testAddEnvVars
44+
testAddEnvVars_SRCS += testAddEnvVars.c
45+
testAddEnvVars_SYS_LIBS_WIN32 = ws2_32
46+
TESTS += testAddEnvVars
47+
4348
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
4449

4550
#===========================

client/castApp/src/caster.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void casterInit(caster_t *self)
123123

124124
void casterShutdown(caster_t *self)
125125
{
126+
int i;
126127
epicsUInt32 junk = htonl(0xdeadbeef);
127128

128129
epicsMutexMustLock(self->lock);
@@ -134,6 +135,13 @@ void casterShutdown(caster_t *self)
134135

135136
epicsEventMustWait(self->shutdownEvent);
136137

138+
epicsMutexMustLock(self->lock);
139+
for (i = 0; i < self->num_extra_envs; i++) {
140+
free(self->extra_envs[i]);
141+
}
142+
free(self->extra_envs);
143+
epicsMutexUnlock(self->lock);
144+
137145
epicsEventDestroy(self->shutdownEvent);
138146
self->shutdownEvent = NULL;
139147
epicsSocketDestroy(self->wakeup[0]);

client/castApp/src/caster.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
epicsShareExtern double reccastTimeout;
2121
epicsShareExtern double reccastMaxHoldoff;
2222

23+
extern const char* default_envs[];
24+
2325
typedef enum {
2426
casterUDPSetup,
2527
casterTCPSetup,
@@ -65,6 +67,10 @@ typedef struct _caster_t {
6567

6668
int shutdown;
6769
char lastmsg[MAX_STRING_SIZE];
70+
71+
char **extra_envs;
72+
int num_extra_envs;
73+
6874
} caster_t;
6975

7076
epicsShareFunc
@@ -92,6 +98,9 @@ int casterSendInfo(caster_t *c, ssize_t rid, const char* name, const char* val);
9298
epicsShareFunc
9399
int casterPushPDB(void *junk, caster_t *caster);
94100

101+
epicsShareFunc
102+
void addReccasterEnvVars(caster_t* self, int argc, char **argv);
103+
95104
/* internal */
96105

97106
epicsShareFunc

client/castApp/src/castinit.c

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11

22
#include <stdio.h>
33
#include <string.h>
4+
#include <stdlib.h>
45

56
#include <initHooks.h>
67
#include <epicsExit.h>
78
#include <epicsMutex.h>
89
#include <epicsAssert.h>
10+
#include <iocsh.h>
11+
#include <errlog.h>
912

1013
#include <devSup.h>
1114
#include <dbScan.h>
@@ -52,7 +55,6 @@ static void casthook(initHookState state)
5255
if(state!=initHookAfterIocRunning)
5356
return;
5457

55-
casterInit(&thecaster);
5658

5759
thecaster.getrecords = &casterPushPDB;
5860
thecaster.onmsg = &dsetshowmsg;
@@ -65,13 +67,138 @@ static void casthook(initHookState state)
6567
epicsAtExit(&castexit, NULL);
6668
}
6769

70+
/*
71+
Example call: addReccasterEnvVars("SECTOR") or addReccasterEnvVars("SECTOR", "BUILDING")
72+
Appends the given env variables to the extra_envs list to be sent in addition to the default_envs array
73+
*/
74+
void addReccasterEnvVars(caster_t* self, int argc, char **argv)
75+
{
76+
size_t i, j;
77+
int ret = 0;
78+
79+
argv++; argc--; /* skip function arg */
80+
if(argc < 1) {
81+
errlogSevPrintf(errlogMinor, "At least one argument expected for addReccasterEnvVars\n");
82+
return;
83+
}
84+
85+
epicsMutexMustLock(self->lock);
86+
if(self->shutdown) {
87+
/* shutdown in progress, silent no-op */
88+
epicsMutexUnlock(self->lock);
89+
return;
90+
}
91+
else if(self->current != casterStateInit) {
92+
/* Attempt to add after iocInit(), when we may be connected.
93+
To fully support, would need to force reconnect or resend w/ updated envs list. */
94+
errlogSevPrintf(errlogMinor, "addReccasterEnvVars called after iocInit() when reccaster might already be connected. Not supported\n");
95+
epicsMutexUnlock(self->lock);
96+
return;
97+
}
98+
int new_extra_envs_size = self->num_extra_envs + argc;
99+
int num_new_extra_envs = self->num_extra_envs;
100+
101+
char **new_extra_envs = calloc(new_extra_envs_size, sizeof(*new_extra_envs));
102+
if(new_extra_envs == NULL) {
103+
errlogSevPrintf(errlogMajor, "Error in memory allocation of new_extra_envs from addReccasterEnvVars\n");
104+
epicsMutexUnlock(self->lock);
105+
return;
106+
}
107+
/* copy self->extra_envs into new_extra_envs with room for new envs */
108+
for(i=0; i < self->num_extra_envs; i++) {
109+
if((new_extra_envs[i] = strdup(self->extra_envs[i])) == NULL) {
110+
errlogSevPrintf(errlogMinor, "strdup error for copying %s to new_extra_envs[%zu] from addReccasterEnvVars\n", self->extra_envs[i], i);
111+
ret = 1;
112+
break;
113+
}
114+
}
115+
int found_dup;
116+
/* sanitize input - check for dups and empty args */
117+
if(!ret) {
118+
for(i=0; i < argc; i++) {
119+
if(argv[i] == NULL) {
120+
errlogSevPrintf(errlogMinor, "Arg is NULL for addReccasterEnvVars\n");
121+
continue;
122+
}
123+
else if(argv[i][0] == '\0') {
124+
errlogSevPrintf(errlogMinor, "Arg is empty for addReccasterEnvVars\n");
125+
continue;
126+
}
127+
found_dup = 0;
128+
/* check if dup in self->default_envs */
129+
for(j = 0; default_envs[j]; j++) {
130+
if(strcmp(argv[i], default_envs[j]) == 0) {
131+
found_dup = 1;
132+
errlogSevPrintf(errlogMinor, "Env var %s is already in env list sent by reccaster by default\n", argv[i]);
133+
break;
134+
}
135+
}
136+
if(found_dup) {
137+
continue;
138+
}
139+
/* check if dup in self->extra_envs */
140+
for(j = 0; j < num_new_extra_envs; j++) {
141+
if(new_extra_envs[j] == NULL) {
142+
continue;
143+
}
144+
if(strcmp(argv[i], new_extra_envs[j]) == 0) {
145+
found_dup = 1;
146+
errlogSevPrintf(errlogMinor, "Env var %s is already in extra_envs list\n", argv[i]);
147+
break;
148+
}
149+
}
150+
if(found_dup) {
151+
continue;
152+
}
153+
if((new_extra_envs[num_new_extra_envs] = strdup(argv[i])) == NULL) {
154+
errlogSevPrintf(errlogMinor, "strdup error for copying %s to new_extra_envs[%d] from addReccasterEnvVars\n", argv[i], num_new_extra_envs);
155+
ret = 1;
156+
break;
157+
}
158+
/* this is a valid arg and we have added the new env var to our array, increment new_extra_envs count */
159+
num_new_extra_envs++;
160+
}
161+
}
162+
/* if we have no allocation issues and have at least one new env var that is valid, add to self->extra_envs */
163+
if(!ret && num_new_extra_envs > self->num_extra_envs) {
164+
/* from this point, nothing can fail */
165+
char ** tmp;
166+
tmp = self->extra_envs; /* swap pointers so we can clean up new_extra_envs on success/failure */
167+
self->extra_envs = new_extra_envs;
168+
new_extra_envs = tmp;
169+
170+
new_extra_envs_size = self->num_extra_envs; /* with swap of pointers also swap size */
171+
self->num_extra_envs = num_new_extra_envs;
172+
}
173+
/* cleanup new_extra_envs[] on success or failure */
174+
for(i = 0; i < new_extra_envs_size; i++) {
175+
free(new_extra_envs[i]);
176+
}
177+
free(new_extra_envs);
178+
epicsMutexUnlock(self->lock);
179+
180+
if(ret) {
181+
errlogSevPrintf(errlogMajor, "Error in addReccasterEnvVars - reccaster might not send the extra env vars specified\n");
182+
}
183+
}
184+
185+
static const iocshArg addReccasterEnvVarsArg0 = { "environmentVar", iocshArgArgv };
186+
static const iocshArg * const addReccasterEnvVarsArgs[] = { &addReccasterEnvVarsArg0 };
187+
static const iocshFuncDef addReccasterEnvVarsFuncDef = { "addReccasterEnvVars", 1, addReccasterEnvVarsArgs };
188+
static void addReccasterEnvVarsCallFunc(const iocshArgBuf *args)
189+
{
190+
addReccasterEnvVars(&thecaster, args[0].aval.ac, args[0].aval.av);
191+
}
192+
68193
static void reccasterRegistrar(void)
69194
{
70195
initHookRegister(&casthook);
196+
casterInit(&thecaster);
71197
thepriv.lock = epicsMutexMustCreate();
72198
scanIoInit(&thepriv.scan);
73199
thepriv.laststate=casterStateInit;
74200
strcpy(thepriv.lastmsg, "Initializing");
201+
iocshRegister(&addReccasterEnvVarsFuncDef,addReccasterEnvVarsCallFunc);
75202
}
76203

77204
static long init_record(void* prec)

client/castApp/src/dbcb.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#include "caster.h"
1212

13-
static const char* envs[] =
13+
const char* default_envs[] =
1414
{
1515
/* automatic (if unset) */
1616
"HOSTNAME",
@@ -25,6 +25,10 @@ static const char* envs[] =
2525
"EPICS_CA_ADDR_LIST",
2626
"EPICS_CA_AUTO_ADDR_LIST",
2727
"EPICS_CA_MAX_ARRAY_BYTES",
28+
"RSRV_SERVER_PORT",
29+
30+
/* PVA related */
31+
"PVAS_SERVER_PORT",
2832

2933
/* Common */
3034
"PWD",
@@ -58,13 +62,23 @@ static int pushEnv(caster_t *caster)
5862
if(ret)
5963
ERRRET(ret, caster, "Failed to send epics version");
6064

61-
for(i=0; !ret && envs[i]; i++) {
62-
const char *val = getenv(envs[i]);
65+
for(i=0; !ret && default_envs[i]; i++) {
66+
const char *val = getenv(default_envs[i]);
6367
if(val && val[0]!='\0')
64-
ret = casterSendInfo(caster, 0, envs[i], val);
68+
ret = casterSendInfo(caster, 0, default_envs[i], val);
6569
if(ret)
66-
casterMsg(caster, "Error sending env %s", envs[i]);
70+
casterMsg(caster, "Error sending env %s", default_envs[i]);
71+
}
72+
73+
epicsMutexMustLock(caster->lock);
74+
for (i = 0; !ret && i < caster->num_extra_envs; i++) {
75+
const char *val = getenv(caster->extra_envs[i]);
76+
if (val && val[0] != '\0')
77+
ret = casterSendInfo(caster, 0, caster->extra_envs[i], val);
78+
if (ret)
79+
casterMsg(caster, "Error sending env %s", caster->extra_envs[i]);
6780
}
81+
epicsMutexUnlock(caster->lock);
6882

6983
return ret;
7084
}

0 commit comments

Comments
 (0)