Merge ~dirk.zimoch/epics-base:FixShellCommands into ~epics-core/epics-base/+git/epics-base:7.0

Proposed by Dirk Zimoch
Status: Merged
Approved by: Andrew Johnson
Approved revision: 4190f38db0d88264e2f88a7962880a6dfea09db6
Merged at revision: f0bbae1767f56875beb6cad9fe3c9088725c7fa3
Proposed branch: ~dirk.zimoch/epics-base:FixShellCommands
Merge into: ~epics-core/epics-base/+git/epics-base:7.0
Diff against target: 349 lines (+96/-15)
12 files modified
modules/database/src/ioc/db/dbAccess.c (+10/-1)
modules/database/src/ioc/db/dbBkpt.c (+12/-0)
modules/database/src/ioc/db/dbNotify.c (+5/-1)
modules/database/src/ioc/db/dbState.c (+6/-0)
modules/database/src/ioc/db/db_test.c (+12/-0)
modules/database/src/ioc/misc/dlload.c (+8/-3)
modules/libcom/src/iocsh/iocsh.h (+7/-0)
modules/libcom/src/iocsh/libComRegister.c (+28/-10)
modules/libcom/src/osi/os/Darwin/osdEnv.c (+1/-0)
modules/libcom/src/osi/os/default/osdEnv.c (+1/-0)
modules/libcom/src/osi/os/iOS/osdEnv.c (+1/-0)
modules/libcom/src/osi/os/vxWorks/osdEnv.c (+5/-0)
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+355761@code.launchpad.net

Commit message

Fix several ioc shell functions.

Description of the change

The functions 'echo', 'dlload', 'epicsParamShow', 'setIocLogDisable' and 'errlog' which are available in iocsh were missing in the vxWorks shell. Calling 'errlog' caused a crash because of a thread with that name. These functions have now been added to the vxWorks shell.

Several functions showed buggy behaviour or printed hard to understand error messages when being called without arguments.
* 'epicsEnvSet' without arguments used to set *NULL to *NULL causing problems later
* 'dbLoadDatabase' and 'dbLoadRecords' printed: "dbRead opening file (null)"
* 'dbap', 'dbb' and 'dbd' printed: "Record (null) not found"
* 'gft', 'pft' and 'tpn' printed: "Channel couldn't be created"
* 'dbtpn' printed: "dbtpn: No such channel" but without newline.
They all now print a "Usage: ..." message.
BTW: I found that all the tests for those functions did not include missing (NULL) mandatory string arguments. I suggest to add that case to the tests for every shell function.

Not fixed:
* 'var' is not available on the vxWorks shell but would be difficult to implement.
* 'epicsThreadSleep' called on the vxWorks shell without arguments sleeps for an unpredictable period. This is a problem of using double type arguments on the vxWorks shell.

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

Hi Dirk,

Good idea, a few comments about your specific changes though.

It's only the VxWorks shell (and I guess the RTEMS CEXP shell) that can pass in NULL pointers to some of these commands. Adding the NULL check to any osdEnv.c file except for libcom/src/osi/os/vxWorks/osdEnv.c doesn't make too much sense to me.

I would prefer that we not print anything in dbStateCreate() which is also an API entry point for the dbState subsystem, just return NULL for a NULL input.

Your VxWorks dlload() routine needs a check for a NULL input argument...

Finally a few comments about your Usage messages: Parentheses are not required around arguments to VxWorks or iocsh commands, they're only needed for an IOC using CEXP on RTEMS, and the people who run such IOCs know about the requirement. Parentheses take longer to type and I'd rather we not imply they're needed when they aren't. The iocsh help output shows command usage without parentheses (which are allowed there too), although I wish it prefixed the full command with "Usage:" when shown with argumemts (like you do):

epics> help dbLoadDatabase
dbLoadDatabase 'file name' path substitutions
epics> help dbLoadRecords
dbLoadRecords 'file name' substitutions
epics> help dbb
dbb 'record name'
epics> help dbtpn
dbtpn 'record name' value
epics> help epicsEnvSet
epicsEnvSet name value

That help command only puts quotes around arguments that have spaces in their name, which is different than the requirements of the VxWorks shell (but that is how the iocsh parses arguments). Your use of double-quotes around string arguments shows they are required for VxWorks though, which is fine and correct.

Thanks,

- Andrew

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Hi Andrew,

It all stared when testing EPICS 7 on vxWorks, thus I am a bit focused on vxWorks.

If you do skip a string argument in iocsh, a NULL is passed to the underlying C function if the *Func wrapper does not handle this case separately.

On a Linux IOC I get this:
epics> epicsEnvSet
Missing environment variable name argument.

So this one indeed prints a good error message.

But:
epics> dbLoadDatabase
filename="../../../src/ioc/dbStatic/dbLexRoutines.c" line number=264
dbRead opening file (null)
epics> dbb
   BKPT> Record (null) not found
epics> gft
Channel couldn't be created
epics> dbtpn
dbtpn: No such channelepics>
epics> dbStateCreate
Segmentation fault

I will remove the message from dbStateCreate().

dlload on vxWorks does already print a useful error message:
-> dlload
epicsLoadLibrary failed: S_ioLib_NO_FILENAME
value = 45 = 0x2d = '-'

But I can add a "Usage:" message as well.

You are right about the (). I will remove them.

I will change the usage messages to remove the () but keep the "". The iocsh users probably know that they are not really necessary. What about optional parameters? Put them in []? But that may confuse the inexperienced user who might then type literal [].

Dirk

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

dbStateFind() is not a shell command but should probably check for NULL as well. I'll add it.

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

'gft', 'pft' and 'tpn' used to print a usage message in 3.14:

usage "pv name","value"

But that had been changed to "Channel couldn't be created" in 3.15.

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Also 'pft' and 'tpn' had not checked for a 'value' argument.
In a Linux IOC:
epics> pft existing_record
Segmentation fault

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Apropos epicsEnvSet: I have got requests for a method to remove environment variables. At the moment that is not possible, but would be useful for some scripts. Currently one can only set environment variables to an empty string, but that does not trigger the default value is $(variable=default) expansions.
I propose to use epicsEnvSet with a missing value argument to delete the variable, but I have to check if it possible for all architectures. Some have unsetenv(), some support setenv("variable") without "=value". In vxWorks 5 I had to use a hack (destroy the name by setting the first char to 0).

Should I add that feature here or make a new pull request?

Revision history for this message
Andrew Johnson (anj) wrote :

I think setting an environment variable to an empty string needs to be allowed (without deleting it). Can I request that you add a new command epicsEnvUnset, and since it will affect more than just VxWorks I think a new merge proposal for that from a separate branch would be appropriate. You can tell Launchpad 'this merge proposal depends on that one having already been applied' to save effort and merge conflicts if you need to.

Thanks!

- Andrew

review: Approve
Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Setting a variable to an empty string would not be a problem even without a separate command, because "" is different from NULL:

Empty string:
epicsEnvSet "var",""

Delete:
epicsEnvSet "var"

(Work for both vxWorks shell and iocsh.)

But I will implement epicsEnvUnset because it is the cleaner interface.

Revision history for this message
Andrew Johnson (anj) wrote :

I really don't like adding "#ifdef vxWorks" blocks like this does. We have mechanisms that avoid having such blocks of OS-specific code by putting OS-specific routines in OS-specific source files or by defining OS-specific macros. As a result I can do a git grep '#ifdef vxWorks' on the 7.0 tree and the only hits it finds are in test programs. Also some of the additions here are duplicating code from other routines in the same file, which is another code smell from this merge request.

Maybe we could add a macro to iocsh.h for routines that should be exported for VxWorks, so that for example the dlload command could be implemented like this:

static const iocshFuncDef dlloadFuncDef = {"dlload", 1, dlloadArgs};
IOCSH_STATIC_FUNC void dlload(const char* name)
{
    if (!name || !*name) {
        printf("usage: dlload \"file\"\n");
    }
    else if (!epicsLoadLibrary(name)) {
        printf("epicsLoadLibrary failed: %s\n", epicsLoadError());
    }
}
static void dlloadCallFunc(const iocshArgBuf *args)
{
    dlload(args[0].sval);
}
static void dlloadRegistar(void) {

The IOCSH_STATIC_FUNC macro would expand to static EPICS_ALWAYS_INLINE on everything except VxWorks where it would be empty (Hmm, should GeSys users get these routines as well?). The body of the function is no longer duplicated, there's nothing here which is VxWorks-specific, and if GeSys does need these functions we only have to edit the iocsh.h header to make them available there too.

I'm *not* suggesting that we should have a modules/database/src/ioc/misc/os/vxWorks/dlload.c file, that would be taking this too far and I think the macro solution should work fine.

Sorry to go back on my earlier approval...

review: Needs Fixing
Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

OK. I didn't like the code duplication either, but I wanted to keep the change minimal.
Concerning #ifdef <ARCH>, I actually like it more than separate files. Why? To avoid code duplication.

I will try to implement some macro magic...

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Are RTEMS/GeSys users the only ones using Cexp? If not, the functions should probably be global for everyone. How to find out if someone uses GeSys/Cexp? Should I assume this for any RTEMS and RTEMS only, thus making the functions global for vxWorks and RTEMS and static for every other OS?

Can there be a conflict with existing system functions, in particular for 'dlload' and 'echo'? Originally it was this concern why I implemented the functions for vxWorks only.

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Now I have
#if defined(vxWorks) || defined(__rtems__)
centrally in iocsh.h.
If preferred, I can create separate header files for vxWorks and RTEMS in osi/os/xx instead.

Revision history for this message
Andrew Johnson (anj) wrote :

Cexp only exists for RTEMS, Till wrote it to replicate the functionality of the VxWorks target shell.

I'm okay with that OS-conditional being in iocsh.h, so this looks good now and I will merge it sometime in the next few days — thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c
index cd75351..f52b888 100644
--- a/modules/database/src/ioc/db/dbAccess.c
+++ b/modules/database/src/ioc/db/dbAccess.c
@@ -754,13 +754,22 @@ long dbBufferSize(short dbr_type, long options, long no_elements)
754}754}
755int dbLoadDatabase(const char *file, const char *path, const char *subs)755int dbLoadDatabase(const char *file, const char *path, const char *subs)
756{756{
757 if (!file) {
758 printf("Usage: dbLoadDatabase \"file\", \"path\", \"subs\"\n");
759 return -1;
760 }
757 return dbReadDatabase(&pdbbase, file, path, subs);761 return dbReadDatabase(&pdbbase, file, path, subs);
758}762}
759763
760int dbLoadRecords(const char* file, const char* subs)764int dbLoadRecords(const char* file, const char* subs)
761{765{
762 int status = dbReadDatabase(&pdbbase, file, 0, subs);766 int status;
763767
768 if (!file) {
769 printf("Usage: dbLoadRecords \"file\", \"subs\"\n");
770 return -1;
771 }
772 status = dbReadDatabase(&pdbbase, file, 0, subs);
764 if (!status && dbLoadRecordsHook)773 if (!status && dbLoadRecordsHook)
765 dbLoadRecordsHook(file, subs);774 dbLoadRecordsHook(file, subs);
766 return status;775 return status;
diff --git a/modules/database/src/ioc/db/dbBkpt.c b/modules/database/src/ioc/db/dbBkpt.c
index 8e7bf3a..b3fdd2d 100644
--- a/modules/database/src/ioc/db/dbBkpt.c
+++ b/modules/database/src/ioc/db/dbBkpt.c
@@ -283,6 +283,10 @@ long dbb(const char *record_name)
283 /*283 /*
284 * Convert name to address284 * Convert name to address
285 */285 */
286 if (!record_name) {
287 printf("Usage: dbb \"record_name\"\n");
288 return -1;
289 }
286 status = dbNameToAddr(record_name, &addr);290 status = dbNameToAddr(record_name, &addr);
287 if (status == S_db_notFound)291 if (status == S_db_notFound)
288 printf(" BKPT> Record %s not found\n", record_name);292 printf(" BKPT> Record %s not found\n", record_name);
@@ -403,6 +407,10 @@ long dbd(const char *record_name)
403 /*407 /*
404 * Convert name to address408 * Convert name to address
405 */409 */
410 if (!record_name) {
411 printf("Usage: dbd \"record_name\"\n");
412 return -1;
413 }
406 status = dbNameToAddr(record_name, &addr);414 status = dbNameToAddr(record_name, &addr);
407 if (status == S_db_notFound)415 if (status == S_db_notFound)
408 printf(" BKPT> Record %s not found\n", record_name);416 printf(" BKPT> Record %s not found\n", record_name);
@@ -846,6 +854,10 @@ long dbap(const char *record_name)
846 /*854 /*
847 * Convert name to address855 * Convert name to address
848 */856 */
857 if (!record_name) {
858 printf("Usage: dbap \"record_name\"\n");
859 return -1;
860 }
849 status = dbNameToAddr(record_name, &addr);861 status = dbNameToAddr(record_name, &addr);
850 if (status == S_db_notFound)862 if (status == S_db_notFound)
851 printf(" BKPT> Record %s not found\n", record_name);863 printf(" BKPT> Record %s not found\n", record_name);
diff --git a/modules/database/src/ioc/db/dbNotify.c b/modules/database/src/ioc/db/dbNotify.c
index c718d37..c2420af 100644
--- a/modules/database/src/ioc/db/dbNotify.c
+++ b/modules/database/src/ioc/db/dbNotify.c
@@ -596,9 +596,13 @@ long dbtpn(char *pname, char *pvalue)
596 tpnInfo *ptpnInfo;596 tpnInfo *ptpnInfo;
597 processNotify *ppn=NULL;597 processNotify *ppn=NULL;
598598
599 if (!pname) {
600 printf("Usage: dbtpn \"name\", \"value\"\n");
601 return -1;
602 }
599 chan = dbChannelCreate(pname);603 chan = dbChannelCreate(pname);
600 if (!chan) {604 if (!chan) {
601 printf("dbtpn: No such channel");605 printf("dbtpn: No such channel\n");
602 return -1;606 return -1;
603 }607 }
604 608
diff --git a/modules/database/src/ioc/db/dbState.c b/modules/database/src/ioc/db/dbState.c
index 6de7735..60819a0 100644
--- a/modules/database/src/ioc/db/dbState.c
+++ b/modules/database/src/ioc/db/dbState.c
@@ -37,6 +37,9 @@ dbStateId dbStateFind(const char *name)
37 ELLNODE *node;37 ELLNODE *node;
38 dbStateId id;38 dbStateId id;
3939
40 if (!name)
41 return NULL;
42
40 for (node = ellFirst(&states); node; node = ellNext(node)) {43 for (node = ellFirst(&states); node; node = ellNext(node)) {
41 id = CONTAINER(node, dbState, node);44 id = CONTAINER(node, dbState, node);
42 if (strcmp(id->name, name) == 0)45 if (strcmp(id->name, name) == 0)
@@ -49,6 +52,9 @@ dbStateId dbStateCreate(const char *name)
49{52{
50 dbStateId id;53 dbStateId id;
5154
55 if (!name)
56 return NULL;
57
52 if ((id = dbStateFind(name)))58 if ((id = dbStateFind(name)))
53 return id;59 return id;
5460
diff --git a/modules/database/src/ioc/db/db_test.c b/modules/database/src/ioc/db/db_test.c
index 8d7ad31..3d536f0 100644
--- a/modules/database/src/ioc/db/db_test.c
+++ b/modules/database/src/ioc/db/db_test.c
@@ -40,6 +40,10 @@ int gft(const char *pname)
40 short type;40 short type;
41 int i;41 int i;
4242
43 if (!pname) {
44 printf("Usage: gft \"pv_name\"\n");
45 return -1;
46 }
43 chan = dbChannel_create(pname);47 chan = dbChannel_create(pname);
44 if (!chan) {48 if (!chan) {
45 printf("Channel couldn't be created\n");49 printf("Channel couldn't be created\n");
@@ -94,6 +98,10 @@ int pft(const char *pname, const char *pvalue)
94 unsigned char charvalue;98 unsigned char charvalue;
95 double doublevalue;99 double doublevalue;
96100
101 if (!pname || !pvalue) {
102 printf("Usage: pft \"pv_name\", \"value\"\n");
103 return -1;
104 }
97 chan = dbChannel_create(pname);105 chan = dbChannel_create(pname);
98 if (!chan) {106 if (!chan) {
99 printf("Channel couldn't be created\n");107 printf("Channel couldn't be created\n");
@@ -223,6 +231,10 @@ int tpn(const char *pname, const char *pvalue)
223 tpnInfo *ptpnInfo;231 tpnInfo *ptpnInfo;
224 processNotify *ppn = NULL;232 processNotify *ppn = NULL;
225233
234 if (!pname || !pvalue) {
235 printf("Usage: tpn \"pv_name\", \"value\"\n");
236 return -1;
237 }
226 chan = dbChannel_create(pname);238 chan = dbChannel_create(pname);
227 if (!chan) {239 if (!chan) {
228 printf("Channel couldn't be created\n");240 printf("Channel couldn't be created\n");
diff --git a/modules/database/src/ioc/misc/dlload.c b/modules/database/src/ioc/misc/dlload.c
index 5b0591d..ddf04f4 100644
--- a/modules/database/src/ioc/misc/dlload.c
+++ b/modules/database/src/ioc/misc/dlload.c
@@ -9,14 +9,19 @@
9#include "iocsh.h"9#include "iocsh.h"
10#include "epicsExport.h"10#include "epicsExport.h"
1111
12IOCSH_STATIC_FUNC void dlload(const char* name)
13{
14 if (!epicsLoadLibrary(name)) {
15 printf("epicsLoadLibrary failed: %s\n", epicsLoadError());
16 }
17}
18
12static const iocshArg dlloadArg0 = { "path/library.so", iocshArgString};19static const iocshArg dlloadArg0 = { "path/library.so", iocshArgString};
13static const iocshArg * const dlloadArgs[] = {&dlloadArg0};20static const iocshArg * const dlloadArgs[] = {&dlloadArg0};
14static const iocshFuncDef dlloadFuncDef = {"dlload", 1, dlloadArgs};21static const iocshFuncDef dlloadFuncDef = {"dlload", 1, dlloadArgs};
15static void dlloadCallFunc(const iocshArgBuf *args)22static void dlloadCallFunc(const iocshArgBuf *args)
16{23{
17 if (!epicsLoadLibrary(args[0].sval)) {24 dlload(args[0].sval);
18 printf("epicsLoadLibrary failed: %s\n", epicsLoadError());
19 }
20}25}
2126
22static void dlloadRegistar(void) {27static void dlloadRegistar(void) {
diff --git a/modules/libcom/src/iocsh/iocsh.h b/modules/libcom/src/iocsh/iocsh.h
index 3ef3d95..84b38f2 100644
--- a/modules/libcom/src/iocsh/iocsh.h
+++ b/modules/libcom/src/iocsh/iocsh.h
@@ -14,8 +14,15 @@
14#define INCiocshH14#define INCiocshH
1515
16#include <stdio.h>16#include <stdio.h>
17#include "compilerDependencies.h"
17#include "shareLib.h"18#include "shareLib.h"
1819
20#if defined(vxWorks) || defined(__rtems__)
21#define IOCSH_STATIC_FUNC
22#else
23#define IOCSH_STATIC_FUNC static EPICS_ALWAYS_INLINE
24#endif
25
19#ifdef __cplusplus26#ifdef __cplusplus
20extern "C" {27extern "C" {
21#endif28#endif
diff --git a/modules/libcom/src/iocsh/libComRegister.c b/modules/libcom/src/iocsh/libComRegister.c
index d3a5cfa..88abdc6 100644
--- a/modules/libcom/src/iocsh/libComRegister.c
+++ b/modules/libcom/src/iocsh/libComRegister.c
@@ -27,6 +27,7 @@
27#include "libComRegister.h"27#include "libComRegister.h"
2828
2929
30/* date */
30void date(const char *format)31void date(const char *format)
31{32{
32 epicsTimeStamp now;33 epicsTimeStamp now;
@@ -42,7 +43,6 @@ void date(const char *format)
42 puts(nowText);43 puts(nowText);
43}44}
4445
45/* date */
46static const iocshArg dateArg0 = { "format",iocshArgString};46static const iocshArg dateArg0 = { "format",iocshArgString};
47static const iocshArg * const dateArgs[] = {&dateArg0};47static const iocshArg * const dateArgs[] = {&dateArg0};
48static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs};48static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs};
@@ -52,13 +52,8 @@ static void dateCallFunc (const iocshArgBuf *args)
52}52}
5353
54/* echo */54/* echo */
55static const iocshArg echoArg0 = { "string",iocshArgString};55IOCSH_STATIC_FUNC void echo(char* str)
56static const iocshArg * const echoArgs[1] = {&echoArg0};
57static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs};
58static void echoCallFunc(const iocshArgBuf *args)
59{56{
60 char *str = args[0].sval;
61
62 if (str)57 if (str)
63 dbTranslateEscape(str, str); /* in-place is safe */58 dbTranslateEscape(str, str); /* in-place is safe */
64 else59 else
@@ -66,6 +61,14 @@ static void echoCallFunc(const iocshArgBuf *args)
66 printf("%s\n", str);61 printf("%s\n", str);
67}62}
6863
64static const iocshArg echoArg0 = { "string",iocshArgString};
65static const iocshArg * const echoArgs[1] = {&echoArg0};
66static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs};
67static void echoCallFunc(const iocshArgBuf *args)
68{
69 echo(args[0].sval);
70}
71
69/* chdir */72/* chdir */
70static const iocshArg chdirArg0 = { "directory name",iocshArgString};73static const iocshArg chdirArg0 = { "directory name",iocshArgString};
71static const iocshArg * const chdirArgs[1] = {&chdirArg0};74static const iocshArg * const chdirArgs[1] = {&chdirArg0};
@@ -111,10 +114,15 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args)
111}114}
112115
113/* epicsParamShow */116/* epicsParamShow */
117IOCSH_STATIC_FUNC void epicsParamShow()
118{
119 epicsPrtEnvParams ();
120}
121
114static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL};122static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL};
115static void epicsParamShowCallFunc(const iocshArgBuf *args)123static void epicsParamShowCallFunc(const iocshArgBuf *args)
116{124{
117 epicsPrtEnvParams ();125 epicsParamShow ();
118}126}
119127
120/* epicsPrtEnvParams */128/* epicsPrtEnvParams */
@@ -148,12 +156,17 @@ static void iocLogInitCallFunc(const iocshArgBuf *args)
148}156}
149157
150/* iocLogDisable */158/* iocLogDisable */
159IOCSH_STATIC_FUNC void setIocLogDisable(int val)
160{
161 iocLogDisable = val;
162}
163
151static const iocshArg iocLogDisableArg0 = {"(0,1)=>(false,true)",iocshArgInt};164static const iocshArg iocLogDisableArg0 = {"(0,1)=>(false,true)",iocshArgInt};
152static const iocshArg * const iocLogDisableArgs[1] = {&iocLogDisableArg0};165static const iocshArg * const iocLogDisableArgs[1] = {&iocLogDisableArg0};
153static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs};166static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs};
154static void iocLogDisableCallFunc(const iocshArgBuf *args)167static void iocLogDisableCallFunc(const iocshArgBuf *args)
155{168{
156 iocLogDisable = args[0].ival;169 setIocLogDisable(args[0].ival);
157}170}
158171
159/* iocLogShow */172/* iocLogShow */
@@ -197,12 +210,17 @@ static void errlogInit2CallFunc(const iocshArgBuf *args)
197}210}
198211
199/* errlog */212/* errlog */
213IOCSH_STATIC_FUNC void errlog(const char *message)
214{
215 errlogPrintfNoConsole("%s\n", message);
216}
217
200static const iocshArg errlogArg0 = { "message",iocshArgString};218static const iocshArg errlogArg0 = { "message",iocshArgString};
201static const iocshArg * const errlogArgs[1] = {&errlogArg0};219static const iocshArg * const errlogArgs[1] = {&errlogArg0};
202static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs};220static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs};
203static void errlogCallFunc(const iocshArgBuf *args)221static void errlogCallFunc(const iocshArgBuf *args)
204{222{
205 errlogPrintfNoConsole("%s\n", args[0].sval);223 errlog(args[0].sval);
206}224}
207225
208/* iocLogPrefix */226/* iocLogPrefix */
diff --git a/modules/libcom/src/osi/os/Darwin/osdEnv.c b/modules/libcom/src/osi/os/Darwin/osdEnv.c
index ab3f936..e6206c3 100644
--- a/modules/libcom/src/osi/os/Darwin/osdEnv.c
+++ b/modules/libcom/src/osi/os/Darwin/osdEnv.c
@@ -35,6 +35,7 @@
35 */35 */
36epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)36epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)
37{37{
38 if (!name) return;
38 iocshEnvClear(name);39 iocshEnvClear(name);
39 setenv(name, value, 1);40 setenv(name, value, 1);
40}41}
diff --git a/modules/libcom/src/osi/os/default/osdEnv.c b/modules/libcom/src/osi/os/default/osdEnv.c
index 682bcc9..b284a86 100644
--- a/modules/libcom/src/osi/os/default/osdEnv.c
+++ b/modules/libcom/src/osi/os/default/osdEnv.c
@@ -36,6 +36,7 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
36{36{
37 char *cp;37 char *cp;
3838
39 if (!name) return;
39 iocshEnvClear(name);40 iocshEnvClear(name);
40 41
41 cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet");42 cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet");
diff --git a/modules/libcom/src/osi/os/iOS/osdEnv.c b/modules/libcom/src/osi/os/iOS/osdEnv.c
index a32cce5..fdc4570 100644
--- a/modules/libcom/src/osi/os/iOS/osdEnv.c
+++ b/modules/libcom/src/osi/os/iOS/osdEnv.c
@@ -32,6 +32,7 @@
32 */32 */
33epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)33epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value)
34{34{
35 if (!name) return;
35 iocshEnvClear(name);36 iocshEnvClear(name);
36 setenv(name, value, 1);37 setenv(name, value, 1);
37}38}
diff --git a/modules/libcom/src/osi/os/vxWorks/osdEnv.c b/modules/libcom/src/osi/os/vxWorks/osdEnv.c
index c81f493..9245ae7 100644
--- a/modules/libcom/src/osi/os/vxWorks/osdEnv.c
+++ b/modules/libcom/src/osi/os/vxWorks/osdEnv.c
@@ -37,6 +37,11 @@ epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *val
37{37{
38 char *cp;38 char *cp;
3939
40 if (!name) {
41 printf ("Usage: epicsEnvSet \"name\", \"value\"\n");
42 return;
43 }
44
40 iocshEnvClear(name);45 iocshEnvClear(name);
41 46
42 cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet");47 cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet");

Subscribers

People subscribed via source and target branches