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