This is Unofficial EPICS BASE Doxygen Site
softMain.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2003 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to the Software License Agreement
7 * found in the file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /* Copyed from EPICS Base 3.16 branch */
11 
12 /* Author: Andrew Johnson Date: 2003-04-08 */
13 
14 /* Usage:
15  * softIoc [-D softIoc.dbd] [-h] [-S] [-s] [-a ascf]
16  * [-m macro=value,macro2=value2] [-d file.db]
17  * [-x prefix] [st.cmd]
18  *
19  * If used the -D option must come first, and specify the
20  * path to the softIoc.dbd file. The compile-time install
21  * location is saved in the binary as a default.
22  *
23  * Usage information will be printed if -h is given, then
24  * the program will exit normally.
25  *
26  * The -S option prevents an interactive shell being started
27  * after all arguments have been processed.
28  *
29  * Previous versions accepted a -s option to cause a shell
30  * to be started; this option is still accepted but ignored
31  * since a command shell is now started by default.
32  *
33  * Access Security can be enabled with the -a option giving
34  * the name of the configuration file; if any macros were
35  * set with -m before the -a option was given, they will be
36  * used as access security substitution macros.
37  *
38  * Any number of -m and -d arguments can be interspersed;
39  * the macros are applied to the following .db files. Each
40  * later -m option causes earlier macros to be discarded.
41  *
42  * The -x option loads the softIocExit.db with the macro
43  * IOC set to the string provided. This database contains
44  * a subroutine record named $(IOC):exit which has its field
45  * SNAM set to "exit". When this record is processed, the
46  * subroutine that runs will call epicsExit() with the value
47  * of the field A determining whether the exit status is
48  * EXIT_SUCCESS if (A == 0.0) or EXIT_FAILURE (A != 0.0).
49  *
50  * A st.cmd file is optional. If any databases were loaded
51  * the st.cmd file will be run *after* iocInit. To perform
52  * iocsh commands before iocInit, all database loading must
53  * be performed by the script itself, or by the user from
54  * the interactive IOC shell.
55  */
56 
57 #include <stddef.h>
58 #include <stdlib.h>
59 #include <stddef.h>
60 #include <string.h>
61 #include <stdio.h>
62 
63 #include "registryFunction.h"
64 #include "epicsThread.h"
65 #include "epicsExit.h"
66 #include "epicsStdio.h"
67 #include "dbStaticLib.h"
68 #include "subRecord.h"
69 #include "dbAccess.h"
70 #include "asDbLib.h"
71 #include "iocInit.h"
72 #include "iocsh.h"
73 
74 extern "C" int softIocPVA_registerRecordDeviceDriver(struct dbBase *pdbbase);
75 
76 #ifdef __rtems__
77 #define DBD_FILE "dbd/softIocPVA.dbd"
78 #define EXIT_FILE "db/softIocExit.db"
79 #else
80 #define DBD_FILE FINAL_LOCATION "/dbd/softIocPVA.dbd"
81 #define EXIT_FILE FINAL_LOCATION "/db/softIocExit.db"
82 #endif
83 
84 #ifdef VERSION_INT
85 #if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
86 #define USE_EXIT_LATER
87 #endif
88 #endif
89 const char *arg0;
90 const char *base_dbd = DBD_FILE;
91 const char *exit_db = EXIT_FILE;
92 
93 
94 static void exitSubroutine(subRecord *precord) {
95 #ifdef USE_EXIT_LATER
96  epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
97 #else
98  epicsExit((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
99 #endif
100 }
101 
102 static void usage(int status) {
103  printf("Usage: %s [-D softIoc.dbd] [-h] [-S] [-a ascf]\n", arg0);
104  puts("\t[-m macro=value,macro2=value2] [-d file.db]");
105  puts("\t[-x prefix] [st.cmd]");
106  puts("Compiled-in path to softIocPVA.dbd is:");
107  printf("\t%s\n", base_dbd);
108  epicsExit(status);
109 }
110 
111 
112 int main(int argc, char *argv[])
113 {
114  char *dbd_file = const_cast<char*>(base_dbd);
115  char *macros = NULL;
116  char xmacro[PVNAME_STRINGSZ + 4];
117  int startIocsh = 1; /* default = start shell */
118  int loadedDb = 0;
119 
120  arg0 = strrchr(*argv, '/');
121  if (!arg0) {
122  arg0 = *argv;
123  } else {
124  ++arg0; /* skip the '/' */
125  }
126 
127  --argc, ++argv;
128 
129  /* Do this here in case the dbd file not available */
130  if (argc>0 && **argv=='-' && (*argv)[1]=='h') {
131  usage(EXIT_SUCCESS);
132  }
133 
134  if (argc>1 && **argv=='-' && (*argv)[1]=='D') {
135  dbd_file = *++argv;
136  argc -= 2;
137  ++argv;
138  }
139 
140  if (dbLoadDatabase(dbd_file, NULL, NULL)) {
141  epicsExit(EXIT_FAILURE);
142  }
143 
145  registryFunctionAdd("exit", (REGISTRYFUNCTION) exitSubroutine);
146 
147  while (argc>1 && **argv == '-') {
148  switch ((*argv)[1]) {
149  case 'a':
150  if (macros) asSetSubstitutions(macros);
151  asSetFilename(*++argv);
152  --argc;
153  break;
154 
155  case 'd':
156  if (dbLoadRecords(*++argv, macros)) {
157  epicsExit(EXIT_FAILURE);
158  }
159  loadedDb = 1;
160  --argc;
161  break;
162 
163  case 'h':
164  usage(EXIT_SUCCESS);
165 
166  case 'm':
167  macros = *++argv;
168  --argc;
169  break;
170 
171  case 'S':
172  startIocsh = 0;
173  break;
174 
175  case 's':
176  break;
177 
178  case 'x':
179  epicsSnprintf(xmacro, sizeof xmacro, "IOC=%s", *++argv);
180  if (dbLoadRecords(exit_db, xmacro)) {
181  epicsExit(EXIT_FAILURE);
182  }
183  loadedDb = 1;
184  --argc;
185  break;
186 
187  default:
188  printf("%s: option '%s' not recognized\n", arg0, *argv);
189  usage(EXIT_FAILURE);
190  }
191  --argc;
192  ++argv;
193  }
194 
195  if (argc>0 && **argv=='-') {
196  switch((*argv)[1]) {
197  case 'a':
198  case 'd':
199  case 'm':
200  case 'x':
201  printf("%s: missing argument to option '%s'\n", arg0, *argv);
202  usage(EXIT_FAILURE);
203 
204  case 'h':
205  usage(EXIT_SUCCESS);
206 
207  case 'S':
208  startIocsh = 0;
209  break;
210 
211  case 's':
212  break;
213 
214  default:
215  printf("%s: option '%s' not recognized\n", arg0, *argv);
216  usage(EXIT_FAILURE);
217  }
218  --argc;
219  ++argv;
220  }
221 
222  if (loadedDb) {
223  iocInit();
224  epicsThreadSleep(0.2);
225  }
226 
227  /* run user's startup script */
228  if (argc>0) {
229  if (iocsh(*argv)) epicsExit(EXIT_FAILURE);
230  epicsThreadSleep(0.2);
231  loadedDb = 1; /* Give it the benefit of the doubt... */
232  }
233 
234  /* start an interactive shell if it was requested */
235  if (startIocsh) {
236  iocsh(NULL);
237  } else {
238  if (loadedDb) {
240  } else {
241  printf("%s: Nothing to do!\n", arg0);
242  usage(EXIT_FAILURE);
243  }
244  }
245  epicsExit(EXIT_SUCCESS);
246  /*Note that the following statement will never be executed*/
247  return 0;
248 }
#define PVNAME_STRINGSZ
Size of a record name including the nil terminator.
Definition: dbDefs.h:72
void(* REGISTRYFUNCTION)(void)
pvd::Status status
#define printf
Definition: epicsStdio.h:41
LIBCOM_API void epicsExitLater(int status)
Arrange to call epicsExit() later from a low priority thread.
Definition: epicsExit.c:204
#define NULL
Definition: catime.c:38
#define DBD_FILE
Definition: softMain.cpp:80
int asSetSubstitutions(const char *substitutions)
Definition: asDbLib.c:91
int epicsStdCall iocsh(const char *pathname)
Definition: iocsh.cpp:1011
#define puts
Definition: epicsStdio.h:46
int softIocPVA_registerRecordDeviceDriver(struct dbBase *pdbbase)
LIBCOM_API void epicsExit(int status)
Calls epicsExitCallAtExits(), then the OS exit() routine.
Definition: epicsExit.c:182
Extended replacement for the Posix exit and atexit routines.
LIBCOM_API void epicsStdCall epicsThreadExitMain(void)
Definition: osdThread.c:683
const char * arg0
Definition: softMain.cpp:89
epicsShareFunc int registryFunctionAdd(const char *name, REGISTRYFUNCTION func)
const char * base_dbd
Definition: softMain.cpp:90
int main(int argc, char *argv[])
Definition: softMain.cpp:116
int iocInit(void)
Definition: iocInit.c:108
#define EXIT_FILE
Definition: softMain.cpp:81
LIBCOM_API void epicsStdCall epicsThreadSleep(double seconds)
Block the calling thread for at least the specified time.
Definition: osdThread.c:790
Definition: dbBase.h:170
C++ and C descriptions for a thread.
int asSetFilename(const char *acf)
Definition: asDbLib.c:70
const char * exit_db
Definition: softMain.cpp:91
void usage(void)
Definition: cainfo.c:36
LIBCOM_API int epicsStdCall epicsSnprintf(char *str, size_t size, const char *format,...) EPICS_PRINTF_STYLE(3