1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2008 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2011 Cisco Systems, Inc. All rights reserved.
14 * Copyright (c) 2015 Los Alamos National Security, LLC. All rights
15 * reserved.
16 * Copyright (c) 2016-2020 Intel, Inc. All rights reserved.
17 * $COPYRIGHT$
18 *
19 * Additional copyrights may follow
20 *
21 * $HEADER$
22 */
23
24 #include "src/include/pmix_config.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 #ifdef HAVE_SYSLOG_H
29 #include <syslog.h>
30 #endif
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include "src/mca/pinstalldirs/pinstalldirs.h"
36 #include "src/util/output.h"
37 #include "src/util/printf.h"
38 #include "src/mca/mca.h"
39 #include "src/mca/base/base.h"
40 #include "src/mca/base/pmix_mca_base_component_repository.h"
41 #include "include/pmix_common.h"
42 #include "src/util/pmix_environ.h"
43
44 /*
45 * Public variables
46 */
47 char *pmix_mca_base_component_path = NULL;
48 int pmix_mca_base_opened = 0;
49 char *pmix_mca_base_system_default_path = NULL;
50 char *pmix_mca_base_user_default_path = NULL;
51 bool pmix_mca_base_component_show_load_errors = (bool) PMIX_SHOW_LOAD_ERRORS_DEFAULT;
52 bool pmix_mca_base_component_track_load_errors = false;
53 bool pmix_mca_base_component_disable_dlopen = false;
54
55 static char *pmix_mca_base_verbose = NULL;
56
57 /*
58 * Private functions
59 */
60 static void set_defaults(pmix_output_stream_t *lds);
61 static void parse_verbose(char *e, pmix_output_stream_t *lds);
62
63
64 /*
65 * Main MCA initialization.
66 */
pmix_mca_base_open(void)67 int pmix_mca_base_open(void)
68 {
69 char *value;
70 pmix_output_stream_t lds;
71 char hostname[PMIX_MAXHOSTNAMELEN] = {0};
72 int var_id;
73 int rc;
74
75 if (pmix_mca_base_opened++) {
76 return PMIX_SUCCESS;
77 }
78
79 /* define the system and user default paths */
80 pmix_mca_base_system_default_path = strdup(pmix_pinstall_dirs.pmixlibdir);
81 #if PMIX_WANT_HOME_CONFIG_FILES
82 value = (char*)pmix_home_directory(geteuid());
83 rc = asprintf(&pmix_mca_base_user_default_path, "%s"PMIX_PATH_SEP".pmix"PMIX_PATH_SEP"components", value);
84 if (0 > rc) {
85 return PMIX_ERR_OUT_OF_RESOURCE;
86 }
87 #endif
88
89
90 /* see if the user wants to override the defaults */
91 if (NULL == pmix_mca_base_user_default_path) {
92 value = strdup(pmix_mca_base_system_default_path);
93 } else {
94 rc = asprintf(&value, "%s%c%s", pmix_mca_base_system_default_path,
95 PMIX_ENV_SEP, pmix_mca_base_user_default_path);
96 if (0 > rc) {
97 return PMIX_ERR_OUT_OF_RESOURCE;
98 }
99 }
100
101 pmix_mca_base_component_path = value;
102 var_id = pmix_mca_base_var_register("pmix", "mca", "base", "component_path",
103 "Path where to look for additional components",
104 PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
105 PMIX_INFO_LVL_9,
106 PMIX_MCA_BASE_VAR_SCOPE_READONLY,
107 &pmix_mca_base_component_path);
108 (void) pmix_mca_base_var_register_synonym(var_id, "pmix", "mca", NULL, "component_path",
109 PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
110 free(value);
111
112 pmix_mca_base_component_show_load_errors = (bool) PMIX_SHOW_LOAD_ERRORS_DEFAULT;;
113 var_id = pmix_mca_base_var_register("pmix", "mca", "base", "component_show_load_errors",
114 "Whether to show errors for components that failed to load or not",
115 PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
116 PMIX_INFO_LVL_9,
117 PMIX_MCA_BASE_VAR_SCOPE_READONLY,
118 &pmix_mca_base_component_show_load_errors);
119 (void) pmix_mca_base_var_register_synonym(var_id, "pmix", "mca", NULL, "component_show_load_errors",
120 PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
121
122 pmix_mca_base_component_track_load_errors = false;
123 var_id = pmix_mca_base_var_register("pmix", "mca", "base", "component_track_load_errors",
124 "Whether to track errors for components that failed to load or not",
125 PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
126 PMIX_INFO_LVL_9,
127 PMIX_MCA_BASE_VAR_SCOPE_READONLY,
128 &pmix_mca_base_component_track_load_errors);
129
130 pmix_mca_base_component_disable_dlopen = false;
131 var_id = pmix_mca_base_var_register("pmix", "mca", "base", "component_disable_dlopen",
132 "Whether to attempt to disable opening dynamic components or not",
133 PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
134 PMIX_INFO_LVL_9,
135 PMIX_MCA_BASE_VAR_SCOPE_READONLY,
136 &pmix_mca_base_component_disable_dlopen);
137 (void) pmix_mca_base_var_register_synonym(var_id, "pmix", "mca", NULL, "component_disable_dlopen",
138 PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
139
140 /* What verbosity level do we want for the default 0 stream? */
141 pmix_mca_base_verbose = "stderr";
142 var_id = pmix_mca_base_var_register("pmix", "mca", "base", "verbose",
143 "Specifies where the default error output stream goes (this is separate from distinct help messages). Accepts a comma-delimited list of: stderr, stdout, syslog, syslogpri:<notice|info|debug>, syslogid:<str> (where str is the prefix string for all syslog notices), file[:filename] (if filename is not specified, a default filename is used), fileappend (if not specified, the file is opened for truncation), level[:N] (if specified, integer verbose level; otherwise, 0 is implied)",
144 PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
145 PMIX_INFO_LVL_9,
146 PMIX_MCA_BASE_VAR_SCOPE_READONLY,
147 &pmix_mca_base_verbose);
148 (void) pmix_mca_base_var_register_synonym(var_id, "pmix", "mca", NULL, "verbose",
149 PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
150
151 memset(&lds, 0, sizeof(lds));
152 if (NULL != pmix_mca_base_verbose) {
153 parse_verbose(pmix_mca_base_verbose, &lds);
154 } else {
155 set_defaults(&lds);
156 }
157 gethostname(hostname, PMIX_MAXHOSTNAMELEN-1);
158 rc = asprintf(&lds.lds_prefix, "[%s:%05d] ", hostname, getpid());
159 if (0 > rc) {
160 return PMIX_ERR_OUT_OF_RESOURCE;
161 }
162 pmix_output_reopen(0, &lds);
163 pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_COMPONENT, 0,
164 "mca: base: opening components at %s", pmix_mca_base_component_path);
165 free(lds.lds_prefix);
166
167 /* Open up the component repository */
168
169 return pmix_mca_base_component_repository_init();
170 }
171
172
173 /*
174 * Set sane default values for the lds
175 */
set_defaults(pmix_output_stream_t * lds)176 static void set_defaults(pmix_output_stream_t *lds)
177 {
178
179 /* Load up defaults */
180
181 PMIX_CONSTRUCT(lds, pmix_output_stream_t);
182 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
183 lds->lds_syslog_priority = LOG_INFO;
184 #endif /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
185 lds->lds_syslog_ident = "ompi";
186 lds->lds_want_stderr = true;
187 }
188
189
190 /*
191 * Parse the value of an environment variable describing verbosity
192 */
parse_verbose(char * e,pmix_output_stream_t * lds)193 static void parse_verbose(char *e, pmix_output_stream_t *lds)
194 {
195 char *edup;
196 char *ptr, *next;
197 bool have_output = false;
198
199 if (NULL == e) {
200 return;
201 }
202
203 edup = strdup(e);
204 ptr = edup;
205
206 /* Now parse the environment variable */
207
208 while (NULL != ptr && strlen(ptr) > 0) {
209 next = strchr(ptr, ',');
210 if (NULL != next) {
211 *next = '\0';
212 }
213
214 if (0 == strcasecmp(ptr, "syslog")) {
215 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
216 lds->lds_want_syslog = true;
217 have_output = true;
218 #else
219 pmix_output(0, "syslog support requested but not available on this system");
220 #endif /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
221 }
222 else if (strncasecmp(ptr, "syslogpri:", 10) == 0) {
223 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
224 lds->lds_want_syslog = true;
225 have_output = true;
226 if (strcasecmp(ptr + 10, "notice") == 0)
227 lds->lds_syslog_priority = LOG_NOTICE;
228 else if (strcasecmp(ptr + 10, "INFO") == 0)
229 lds->lds_syslog_priority = LOG_INFO;
230 else if (strcasecmp(ptr + 10, "DEBUG") == 0)
231 lds->lds_syslog_priority = LOG_DEBUG;
232 #else
233 pmix_output(0, "syslog support requested but not available on this system");
234 #endif /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
235 } else if (strncasecmp(ptr, "syslogid:", 9) == 0) {
236 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
237 lds->lds_want_syslog = true;
238 lds->lds_syslog_ident = ptr + 9;
239 #else
240 pmix_output(0, "syslog support requested but not available on this system");
241 #endif /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
242 }
243
244 else if (strcasecmp(ptr, "stdout") == 0) {
245 lds->lds_want_stdout = true;
246 have_output = true;
247 } else if (strcasecmp(ptr, "stderr") == 0) {
248 lds->lds_want_stderr = true;
249 have_output = true;
250 }
251
252 else if (strcasecmp(ptr, "file") == 0 || strcasecmp(ptr, "file:") == 0) {
253 lds->lds_want_file = true;
254 have_output = true;
255 } else if (strncasecmp(ptr, "file:", 5) == 0) {
256 lds->lds_want_file = true;
257 lds->lds_file_suffix = strdup(ptr + 5);
258 have_output = true;
259 } else if (strcasecmp(ptr, "fileappend") == 0) {
260 lds->lds_want_file = true;
261 lds->lds_want_file_append = 1;
262 have_output = true;
263 }
264
265 else if (strncasecmp(ptr, "level", 5) == 0) {
266 lds->lds_verbose_level = 0;
267 if (ptr[5] == PMIX_ENV_SEP)
268 lds->lds_verbose_level = atoi(ptr + 6);
269 }
270
271 if (NULL == next) {
272 break;
273 }
274 ptr = next + 1;
275 }
276
277 /* If we didn't get an output, default to stderr */
278
279 if (!have_output) {
280 lds->lds_want_stderr = true;
281 }
282
283 /* All done */
284
285 free(edup);
286 }
287