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+
68193static 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
77204static long init_record (void * prec )
0 commit comments