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-2017 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-2017 Cisco Systems, Inc.  All rights reserved
14  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
15  *                         reserved.
16  * Copyright (c) 2017      IBM Corporation.  All rights reserved.
17  * $COPYRIGHT$
18  *
19  * Additional copyrights may follow
20  *
21  * $HEADER$
22  */
23 
24 #include "opal_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 "opal/mca/installdirs/installdirs.h"
36 #include "opal/util/output.h"
37 #include "opal/util/printf.h"
38 #include "opal/mca/mca.h"
39 #include "opal/mca/base/base.h"
40 #include "opal/mca/base/mca_base_component_repository.h"
41 #include "opal/constants.h"
42 #include "opal/util/opal_environ.h"
43 
44 /*
45  * Public variables
46  */
47 char *mca_base_component_path = NULL;
48 int mca_base_opened = 0;
49 char *mca_base_system_default_path = NULL;
50 char *mca_base_user_default_path = NULL;
51 bool mca_base_component_show_load_errors =
52     (bool) OPAL_SHOW_LOAD_ERRORS_DEFAULT;
53 bool mca_base_component_track_load_errors = false;
54 bool mca_base_component_disable_dlopen = false;
55 
56 static char *mca_base_verbose = NULL;
57 
58 /*
59  * Private functions
60  */
61 static void set_defaults(opal_output_stream_t *lds);
62 static void parse_verbose(char *e, opal_output_stream_t *lds);
63 
64 
65 /*
66  * Main MCA initialization.
67  */
mca_base_open(void)68 int mca_base_open(void)
69 {
70     char *value;
71     opal_output_stream_t lds;
72     char hostname[OPAL_MAXHOSTNAMELEN];
73     int var_id;
74 
75     if (mca_base_opened++) {
76         return OPAL_SUCCESS;
77     }
78 
79     /* define the system and user default paths */
80 #if OPAL_WANT_HOME_CONFIG_FILES
81     mca_base_system_default_path = strdup(opal_install_dirs.opallibdir);
82     asprintf(&mca_base_user_default_path, "%s"OPAL_PATH_SEP".openmpi"OPAL_PATH_SEP"components", opal_home_directory());
83 #else
84     asprintf(&mca_base_system_default_path, "%s", opal_install_dirs.opallibdir);
85 #endif
86 
87     /* see if the user wants to override the defaults */
88     if (NULL == mca_base_user_default_path) {
89         value = strdup(mca_base_system_default_path);
90     } else {
91         asprintf(&value, "%s%c%s", mca_base_system_default_path,
92                  OPAL_ENV_SEP, mca_base_user_default_path);
93     }
94 
95     mca_base_component_path = value;
96     var_id = mca_base_var_register("opal", "mca", "base", "component_path",
97                                    "Path where to look for additional components",
98                                    MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
99                                    OPAL_INFO_LVL_9,
100                                    MCA_BASE_VAR_SCOPE_READONLY,
101                                    &mca_base_component_path);
102     (void) mca_base_var_register_synonym(var_id, "opal", "mca", NULL, "component_path",
103                                          MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
104     free(value);
105 
106     mca_base_component_show_load_errors =
107         (bool) OPAL_SHOW_LOAD_ERRORS_DEFAULT;
108     var_id = mca_base_var_register("opal", "mca", "base", "component_show_load_errors",
109                                    "Whether to show errors for components that failed to load or not",
110                                    MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
111                                    OPAL_INFO_LVL_9,
112                                    MCA_BASE_VAR_SCOPE_READONLY,
113                                    &mca_base_component_show_load_errors);
114     (void) mca_base_var_register_synonym(var_id, "opal", "mca", NULL, "component_show_load_errors",
115                                          MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
116 
117     mca_base_component_track_load_errors = false;
118     var_id = mca_base_var_register("opal", "mca", "base", "component_track_load_errors",
119                                    "Whether to track errors for components that failed to load or not",
120                                    MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
121                                    OPAL_INFO_LVL_9,
122                                    MCA_BASE_VAR_SCOPE_READONLY,
123                                    &mca_base_component_track_load_errors);
124 
125     mca_base_component_disable_dlopen = false;
126     var_id = mca_base_var_register("opal", "mca", "base", "component_disable_dlopen",
127                                    "Whether to attempt to disable opening dynamic components or not",
128                                    MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
129                                    OPAL_INFO_LVL_9,
130                                    MCA_BASE_VAR_SCOPE_READONLY,
131                                    &mca_base_component_disable_dlopen);
132     (void) mca_base_var_register_synonym(var_id, "opal", "mca", NULL, "component_disable_dlopen",
133                                          MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
134 
135     /* What verbosity level do we want for the default 0 stream? */
136     char *str = getenv("OPAL_OUTPUT_INTERNAL_TO_STDOUT");
137     if (NULL != str && str[0] == '1') {
138         mca_base_verbose = "stdout";
139     }
140     else {
141         mca_base_verbose = "stderr";
142     }
143     var_id = mca_base_var_register("opal", "mca", "base", "verbose",
144                                    "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)",
145                                    MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0,
146                                    OPAL_INFO_LVL_9,
147                                    MCA_BASE_VAR_SCOPE_READONLY,
148                                    &mca_base_verbose);
149     (void) mca_base_var_register_synonym(var_id, "opal", "mca", NULL, "verbose",
150                                          MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
151 
152     memset(&lds, 0, sizeof(lds));
153     if (NULL != mca_base_verbose) {
154         parse_verbose(mca_base_verbose, &lds);
155     } else {
156         set_defaults(&lds);
157     }
158     gethostname(hostname, sizeof(hostname));
159     asprintf(&lds.lds_prefix, "[%s:%05d] ", hostname, getpid());
160     opal_output_reopen(0, &lds);
161     opal_output_verbose (MCA_BASE_VERBOSE_COMPONENT, 0, "mca: base: opening components");
162     free(lds.lds_prefix);
163 
164     /* Open up the component repository */
165 
166     return mca_base_component_repository_init();
167 }
168 
169 
170 /*
171  * Set sane default values for the lds
172  */
set_defaults(opal_output_stream_t * lds)173 static void set_defaults(opal_output_stream_t *lds)
174 {
175 
176     /* Load up defaults */
177 
178     OBJ_CONSTRUCT(lds, opal_output_stream_t);
179 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
180     lds->lds_syslog_priority = LOG_INFO;
181     lds->lds_syslog_ident = "ompi";
182 #endif
183     lds->lds_want_stderr = true;
184 }
185 
186 
187 /*
188  * Parse the value of an environment variable describing verbosity
189  */
parse_verbose(char * e,opal_output_stream_t * lds)190 static void parse_verbose(char *e, opal_output_stream_t *lds)
191 {
192     char *edup;
193     char *ptr, *next;
194     bool have_output = false;
195 
196     if (NULL == e) {
197         return;
198     }
199 
200     edup = strdup(e);
201     ptr = edup;
202 
203     /* Now parse the environment variable */
204 
205     while (NULL != ptr && strlen(ptr) > 0) {
206         next = strchr(ptr, ',');
207         if (NULL != next) {
208             *next = '\0';
209         }
210 
211         if (0 == strcasecmp(ptr, "syslog")) {
212 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
213             lds->lds_want_syslog = true;
214             have_output = true;
215 #else
216             opal_output(0, "syslog support requested but not available on this system");
217 #endif  /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
218         }
219         else if (strncasecmp(ptr, "syslogpri:", 10) == 0) {
220 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
221             lds->lds_want_syslog = true;
222             have_output = true;
223             if (strcasecmp(ptr + 10, "notice") == 0)
224                 lds->lds_syslog_priority = LOG_NOTICE;
225             else if (strcasecmp(ptr + 10, "INFO") == 0)
226                 lds->lds_syslog_priority = LOG_INFO;
227             else if (strcasecmp(ptr + 10, "DEBUG") == 0)
228                 lds->lds_syslog_priority = LOG_DEBUG;
229 #else
230             opal_output(0, "syslog support requested but not available on this system");
231 #endif  /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
232         } else if (strncasecmp(ptr, "syslogid:", 9) == 0) {
233 #if defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H)
234             lds->lds_want_syslog = true;
235             lds->lds_syslog_ident = ptr + 9;
236 #else
237             opal_output(0, "syslog support requested but not available on this system");
238 #endif  /* defined(HAVE_SYSLOG) && defined(HAVE_SYSLOG_H) */
239         }
240 
241         else if (strcasecmp(ptr, "stdout") == 0) {
242             lds->lds_want_stdout = true;
243             have_output = true;
244         } else if (strcasecmp(ptr, "stderr") == 0) {
245             lds->lds_want_stderr = true;
246             have_output = true;
247         }
248 
249         else if (strcasecmp(ptr, "file") == 0 || strcasecmp(ptr, "file:") == 0) {
250             lds->lds_want_file = true;
251             have_output = true;
252         } else if (strncasecmp(ptr, "file:", 5) == 0) {
253             lds->lds_want_file = true;
254             lds->lds_file_suffix = strdup(ptr + 5);
255             have_output = true;
256         } else if (strcasecmp(ptr, "fileappend") == 0) {
257             lds->lds_want_file = true;
258             lds->lds_want_file_append = 1;
259             have_output = true;
260         }
261 
262         else if (strncasecmp(ptr, "level", 5) == 0) {
263             lds->lds_verbose_level = 0;
264             if (ptr[5] == OPAL_ENV_SEP)
265                 lds->lds_verbose_level = atoi(ptr + 6);
266         }
267 
268         if (NULL == next) {
269             break;
270         }
271         ptr = next + 1;
272     }
273 
274     /* If we didn't get an output, default to stderr */
275 
276     if (!have_output) {
277         lds->lds_want_stderr = true;
278     }
279 
280     /* All done */
281 
282     free(edup);
283 }
284