diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index d8ea79fe1..b373881f2 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -15,6 +15,12 @@
Changes made on the 3.15 branch since 3.15.3
+New string input device support "getenv"
+
+A new "getenv" device support for both the stringin and lsi (long string
+input) record types can be used to read the value of an environment variable
+from the IOC at runtime. See base/db/softIocExit.db for sample usage.
+
Build rules and DELAY_INSTALL_LIBS
A new order-only prerequisite build rule has been added to ensure that
diff --git a/src/std/dev/Makefile b/src/std/dev/Makefile
index 6bdbbd997..8e4e242f9 100644
--- a/src/std/dev/Makefile
+++ b/src/std/dev/Makefile
@@ -66,6 +66,7 @@ dbRecStd_SRCS += devSoSoftCallback.c
dbRecStd_SRCS += devTimestamp.c
dbRecStd_SRCS += devStdio.c
+dbRecStd_SRCS += devEnviron.c
dbRecStd_SRCS += asSubRecordFunctions.c
diff --git a/src/std/dev/devEnviron.c b/src/std/dev/devEnviron.c
new file mode 100644
index 000000000..9672d6ce5
--- /dev/null
+++ b/src/std/dev/devEnviron.c
@@ -0,0 +1,128 @@
+/*************************************************************************\
+* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
+* National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/* devEnviron.c */
+
+#include
+#include
+
+#include "alarm.h"
+#include "dbCommon.h"
+#include "devSup.h"
+#include "errlog.h"
+#include "recGbl.h"
+#include "recSup.h"
+
+#include "lsiRecord.h"
+#include "stringinRecord.h"
+#include "epicsExport.h"
+
+/* lsi device support */
+
+static long add_lsi(dbCommon *pcommon) {
+ lsiRecord *prec = (lsiRecord *) pcommon;
+
+ if (prec->inp.type != INST_IO)
+ return S_dev_badInpType;
+
+ return 0;
+}
+
+static long del_lsi(dbCommon *pcommon) {
+ return 0;
+}
+
+static struct dsxt dsxtLsiEnviron = {
+ add_lsi, del_lsi
+};
+
+static long init_lsi(int pass)
+{
+ if (pass == 0)
+ devExtend(&dsxtLsiEnviron);
+
+ return 0;
+}
+
+static long read_lsi(lsiRecord *prec)
+{
+ const char *val = getenv(prec->inp.value.instio.string);
+
+ if (val) {
+ strncpy(prec->val, val, prec->sizv);
+ prec->val[prec->sizv - 1] = 0;
+ prec->len = strlen(prec->val);
+ prec->udf = FALSE;
+ }
+ else {
+ prec->val[0] = 0;
+ prec->len = 1;
+ prec->udf = TRUE;
+ recGblSetSevr(prec, UDF_ALARM, prec->udfs);
+ }
+
+ return 0;
+}
+
+lsidset devLsiEnviron = {
+ 5, NULL, init_lsi, NULL, NULL, read_lsi
+};
+epicsExportAddress(dset, devLsiEnviron);
+
+
+/* stringin device support */
+
+static long add_stringin(dbCommon *pcommon) {
+ stringinRecord *prec = (stringinRecord *) pcommon;
+
+ if (prec->inp.type != INST_IO)
+ return S_dev_badInpType;
+
+ return 0;
+}
+
+static long del_stringin(dbCommon *pcommon) {
+ return 0;
+}
+
+static struct dsxt dsxtSiEnviron = {
+ add_stringin, del_stringin
+};
+
+static long init_stringin(int pass)
+{
+ if (pass == 0)
+ devExtend(&dsxtSiEnviron);
+
+ return 0;
+}
+
+static long read_stringin(stringinRecord *prec)
+{
+ const char *val = getenv(prec->inp.value.instio.string);
+
+ if (val) {
+ strncpy(prec->val, val, MAX_STRING_SIZE);
+ prec->val[MAX_STRING_SIZE - 1] = 0;
+ prec->udf = FALSE;
+ }
+ else {
+ prec->val[0] = 0;
+ prec->udf = TRUE;
+ recGblSetSevr(prec, UDF_ALARM, prec->udfs);
+ }
+
+ return 0;
+}
+
+static struct {
+ dset common;
+ DEVSUPFUN read;
+} devSiEnviron = {
+ {5, NULL, init_stringin, NULL, NULL}, read_stringin
+};
+epicsExportAddress(dset, devSiEnviron);
diff --git a/src/std/dev/devSoft.dbd b/src/std/dev/devSoft.dbd
index d6cb14de9..4a6665612 100644
--- a/src/std/dev/devSoft.dbd
+++ b/src/std/dev/devSoft.dbd
@@ -58,5 +58,8 @@ device(lso,INST_IO,devLsoStdio,"stdio")
device(printf,INST_IO,devPrintfStdio,"stdio")
device(stringout,INST_IO,devSoStdio,"stdio")
+device(lsi,INST_IO,devLsiEnviron,"getenv")
+device(stringin,INST_IO,devSiEnviron,"getenv")
+
device(bi, INST_IO, devBiDbState, "Db State")
device(bo, INST_IO, devBoDbState, "Db State")
diff --git a/src/std/softIoc/softIocExit.db b/src/std/softIoc/softIocExit.db
index b5c027d70..c530f778a 100644
--- a/src/std/softIoc/softIocExit.db
+++ b/src/std/softIoc/softIocExit.db
@@ -1,7 +1,15 @@
-# $Revision-Id$
-#
+# softIocExit.db
+
record(sub,"$(IOC):exit") {
- field(DESC,"Exit subroutine")
- field(SCAN,"Passive")
- field(SNAM,"exit")
+ field(DESC,"Exit subroutine")
+ field(SCAN,"Passive")
+ field(SNAM,"exit")
+}
+
+record(stringin,"$(IOC):BaseVersion") {
+ field(DESC,"EPICS Base Version")
+ field(DTYP,"getenv")
+ field(INP,"@EPICS_VERSION_FULL")
+ field(PINI,"YES")
+ field(DISP,1)
}