1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
4  *                         University Research and Technology
5  *                         Corporation.  All rights reserved.
6  * Copyright (c) 2004-2011 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) 2006-2015 Cisco Systems, Inc.  All rights reserved.
14  * Copyright (c) 2010-2016 Los Alamos National Security, LLC. All rights
15  *                         reserved.
16  * Copyright (c) 2011-2012 University of Houston. All rights reserved.
17  * Copyright (c) 2016-2017 Intel, Inc. All rights reserved.
18  * Copyright (c) 2017 IBM Corporation.  All rights reserved.
19  * $COPYRIGHT$
20  *
21  * Additional copyrights may follow
22  *
23  * $HEADER$
24  */
25 
26 #include "opal_config.h"
27 
28 #include <string.h>
29 #include <ctype.h>
30 
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 
35 #include <errno.h>
36 
37 #include "opal/class/opal_list.h"
38 #include "opal/class/opal_pointer_array.h"
39 
40 #include "opal/util/output.h"
41 #include "opal/util/cmd_line.h"
42 #include "opal/util/error.h"
43 #include "opal/util/argv.h"
44 #include "opal/util/show_help.h"
45 #include "opal/runtime/opal.h"
46 #include "opal/dss/dss.h"
47 #include "opal/mca/base/mca_base_pvar.h"
48 
49 #include "opal/include/opal/frameworks.h"
50 
51 #include "opal/mca/installdirs/installdirs.h"
52 
53 #include "opal/runtime/opal_info_support.h"
54 #include "opal/mca/base/mca_base_component_repository.h"
55 
56 const char *opal_info_path_prefix = "prefix";
57 const char *opal_info_path_bindir = "bindir";
58 const char *opal_info_path_libdir = "libdir";
59 const char *opal_info_path_incdir = "incdir";
60 const char *opal_info_path_mandir = "mandir";
61 const char *opal_info_path_pkglibdir = "pkglibdir";
62 const char *opal_info_path_sysconfdir = "sysconfdir";
63 const char *opal_info_path_exec_prefix = "exec_prefix";
64 const char *opal_info_path_sbindir = "sbindir";
65 const char *opal_info_path_libexecdir = "libexecdir";
66 const char *opal_info_path_datarootdir = "datarootdir";
67 const char *opal_info_path_datadir = "datadir";
68 const char *opal_info_path_sharedstatedir = "sharedstatedir";
69 const char *opal_info_path_localstatedir = "localstatedir";
70 const char *opal_info_path_infodir = "infodir";
71 const char *opal_info_path_pkgdatadir = "pkgdatadir";
72 const char *opal_info_path_pkgincludedir = "pkgincludedir";
73 
74 bool opal_info_pretty = true;
75 mca_base_register_flag_t opal_info_register_flags = MCA_BASE_REGISTER_ALL;
76 
77 const char *opal_info_type_all = "all";
78 const char *opal_info_type_opal = "opal";
79 const char *opal_info_component_all = "all";
80 const char *opal_info_param_all = "all";
81 
82 const char *opal_info_ver_full = "full";
83 const char *opal_info_ver_major = "major";
84 const char *opal_info_ver_minor = "minor";
85 const char *opal_info_ver_release = "release";
86 const char *opal_info_ver_greek = "greek";
87 const char *opal_info_ver_repo = "repo";
88 
89 const char *opal_info_ver_all = "all";
90 const char *opal_info_ver_mca = "mca";
91 const char *opal_info_ver_type = "type";
92 const char *opal_info_ver_component = "component";
93 
94 static int opal_info_registered = 0;
95 
component_map_construct(opal_info_component_map_t * map)96 static void component_map_construct(opal_info_component_map_t *map)
97 {
98     map->type = NULL;
99 }
component_map_destruct(opal_info_component_map_t * map)100 static void component_map_destruct(opal_info_component_map_t *map)
101 {
102     if (NULL != map->type) {
103         free(map->type);
104     }
105     /* the type close functions will release the
106      * list of components
107      */
108 }
109 OBJ_CLASS_INSTANCE(opal_info_component_map_t,
110                    opal_list_item_t,
111                    component_map_construct,
112                    component_map_destruct);
113 
114 static void opal_info_show_failed_component(const mca_base_component_repository_item_t* ri,
115                                             const char *error_msg);
116 
opal_info_init(int argc,char ** argv,opal_cmd_line_t * opal_info_cmd_line)117 int opal_info_init(int argc, char **argv,
118                    opal_cmd_line_t *opal_info_cmd_line)
119 {
120     int ret;
121     bool want_help = false;
122     bool cmd_error = false;
123     char **app_env = NULL, **global_env = NULL;
124 
125     /* Initialize the argv parsing handle */
126     if (OPAL_SUCCESS != (ret = opal_init_util(&argc, &argv))) {
127         opal_show_help("help-opal_info.txt", "lib-call-fail", true,
128                        "opal_init_util", __FILE__, __LINE__, NULL);
129         exit(ret);
130     }
131 
132     /* add the cmd line options */
133     opal_cmd_line_make_opt3(opal_info_cmd_line, 'V', NULL, "version", 0,
134                             "Show version of Open MPI");
135     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "param", 2,
136                             "Show MCA parameters.  The first parameter is the framework (or the keyword \"all\"); the second parameter is the specific component name (or the keyword \"all\").");
137     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "params", 2,
138                             "Synonym for --param");
139     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "internal", 0,
140                             "Show internal MCA parameters (not meant to be modified by users)");
141     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "path", 1,
142                             "Show paths that Open MPI was configured with.  Accepts the following parameters: prefix, bindir, libdir, incdir, mandir, pkglibdir, sysconfdir, all");
143     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "arch", 0,
144                             "Show architecture Open MPI was compiled on");
145     opal_cmd_line_make_opt3(opal_info_cmd_line, 'c', NULL, "config", 0,
146                             "Show configuration options");
147     opal_cmd_line_make_opt3(opal_info_cmd_line, 't', NULL, "type", 1,
148                             "Show internal MCA parameters with the type specified in parameter.");
149     opal_cmd_line_make_opt3(opal_info_cmd_line, 'h', NULL, "help", 0,
150                             "Show this help message");
151     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "pretty-print", 0,
152                             "When used in conjunction with other parameters, the output is displayed in 'pretty-print' format (default)");
153     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "parsable", 0,
154                             "When used in conjunction with other parameters, the output is displayed in a machine-parsable format");
155     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "parseable", 0,
156                             "Synonym for --parsable");
157     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "hostname", 0,
158                             "Show the hostname that Open MPI was configured and built on");
159     opal_cmd_line_make_opt3(opal_info_cmd_line, 'a', NULL, "all", 0,
160                             "Show all configuration options and MCA parameters");
161     opal_cmd_line_make_opt3(opal_info_cmd_line, 'l', NULL, "level", 1,
162                             "Show only variables with at most this level (1-9)");
163     opal_cmd_line_make_opt3(opal_info_cmd_line, 's', NULL, "selected-only", 0,
164                             "Show only variables from selected components");
165     opal_cmd_line_make_opt3(opal_info_cmd_line, '\0', NULL, "show-failed", 0,
166                             "Show the components that failed to load along with the reason why they failed.");
167 
168     /* set our threading level */
169     opal_set_using_threads(false);
170 
171     /* Get MCA parameters, if any */
172     if( OPAL_SUCCESS != mca_base_open() ) {
173         opal_show_help("help-opal_info.txt", "lib-call-fail", true, "mca_base_open", __FILE__, __LINE__ );
174         opal_finalize_util();
175         return OPAL_ERROR;
176     }
177     mca_base_cmd_line_setup(opal_info_cmd_line);
178 
179     /* Initialize the opal_output system */
180     if (!opal_output_init()) {
181         return OPAL_ERROR;
182     }
183 
184     /* Do the parsing */
185     ret = opal_cmd_line_parse(opal_info_cmd_line, false, false, argc, argv);
186     if (OPAL_SUCCESS != ret) {
187         cmd_error = true;
188         if (OPAL_ERR_SILENT != ret) {
189             fprintf(stderr, "%s: command line error (%s)\n", argv[0],
190                     opal_strerror(ret));
191         }
192     }
193     if (!cmd_error &&
194         (opal_cmd_line_is_taken(opal_info_cmd_line, "help") ||
195          opal_cmd_line_is_taken(opal_info_cmd_line, "h"))) {
196         char *str, *usage;
197 
198         want_help = true;
199         usage = opal_cmd_line_get_usage_msg(opal_info_cmd_line);
200         str = opal_show_help_string("help-opal_info.txt", "usage",
201                                     true, usage);
202         if (NULL != str) {
203             printf("%s", str);
204             free(str);
205         }
206         free(usage);
207     }
208 
209     /* If we had a cmd line parse error, or we showed the help
210        message, it's time to exit. */
211     if (cmd_error || want_help) {
212         mca_base_close();
213         OBJ_RELEASE(opal_info_cmd_line);
214         opal_finalize_util();
215         exit(cmd_error ? 1 : 0);
216     }
217 
218     mca_base_cmd_line_process_args(opal_info_cmd_line, &app_env, &global_env);
219 
220 
221     /* set the flags */
222     if (opal_cmd_line_is_taken(opal_info_cmd_line, "pretty-print")) {
223         opal_info_pretty = true;
224     } else if (opal_cmd_line_is_taken(opal_info_cmd_line, "parsable") || opal_cmd_line_is_taken(opal_info_cmd_line, "parseable")) {
225         opal_info_pretty = false;
226     }
227 
228     if (opal_cmd_line_is_taken(opal_info_cmd_line, "selected-only")) {
229         /* register only selected components */
230         opal_info_register_flags = MCA_BASE_REGISTER_DEFAULT;
231     }
232 
233     if( opal_cmd_line_is_taken(opal_info_cmd_line, "show-failed") ) {
234         mca_base_component_track_load_errors = true;
235     }
236 
237     return OPAL_SUCCESS;
238 }
239 
opal_info_finalize(void)240 void opal_info_finalize(void)
241 {
242     opal_finalize_util();
243 }
244 
info_register_framework(mca_base_framework_t * framework,opal_pointer_array_t * component_map)245 static int info_register_framework (mca_base_framework_t *framework, opal_pointer_array_t *component_map)
246 {
247     opal_info_component_map_t *map;
248     int rc;
249 
250     rc = mca_base_framework_register(framework, opal_info_register_flags);
251     if (OPAL_SUCCESS != rc && OPAL_ERR_BAD_PARAM != rc) {
252         return rc;
253     }
254 
255     if (NULL != component_map) {
256         map = OBJ_NEW(opal_info_component_map_t);
257         map->type = strdup(framework->framework_name);
258         map->components = &framework->framework_components;
259         map->failed_components = &framework->framework_failed_components;
260         opal_pointer_array_add(component_map, map);
261     }
262 
263     return rc;
264 }
265 
opal_info_register_project_frameworks(const char * project_name,mca_base_framework_t ** frameworks,opal_pointer_array_t * component_map)266 int opal_info_register_project_frameworks (const char *project_name, mca_base_framework_t **frameworks,
267                                            opal_pointer_array_t *component_map)
268 {
269     int i, rc=OPAL_SUCCESS;
270 
271     for (i=0; NULL != frameworks[i]; i++) {
272         if (OPAL_SUCCESS != (rc = info_register_framework(frameworks[i], component_map))) {
273             if (OPAL_ERR_BAD_PARAM == rc) {
274                 fprintf(stderr, "\nA \"bad parameter\" error was encountered when opening the %s %s framework\n",
275                         project_name, frameworks[i]->framework_name);
276                 fprintf(stderr, "The output received from that framework includes the following parameters:\n\n");
277             } else if (OPAL_ERR_NOT_AVAILABLE != rc) {
278                 fprintf(stderr, "%s_info_register: %s failed\n", project_name, frameworks[i]->framework_name);
279                 rc = OPAL_ERROR;
280             } else {
281                 continue;
282             }
283 
284             break;
285         }
286     }
287 
288     return rc;
289 }
290 
opal_info_register_types(opal_pointer_array_t * mca_types)291 void opal_info_register_types(opal_pointer_array_t *mca_types)
292 {
293     int i;
294 
295     /* add the top-level types */
296     opal_pointer_array_add(mca_types, "mca");
297     opal_pointer_array_add(mca_types, "opal");
298 
299     /* push all the types found by autogen */
300     for (i=0; NULL != opal_frameworks[i]; i++) {
301         opal_pointer_array_add(mca_types, opal_frameworks[i]->framework_name);
302     }
303 }
304 
opal_info_register_framework_params(opal_pointer_array_t * component_map)305 int opal_info_register_framework_params(opal_pointer_array_t *component_map)
306 {
307     int rc;
308 
309     if (opal_info_registered++) {
310         return OPAL_SUCCESS;
311     }
312 
313     /* Register mca/base parameters */
314     if( OPAL_SUCCESS != mca_base_open() ) {
315         opal_show_help("help-opal_info.txt", "lib-call-fail", true, "mca_base_open", __FILE__, __LINE__ );
316         return OPAL_ERROR;
317     }
318 
319     /* Register the OPAL layer's MCA parameters */
320     if (OPAL_SUCCESS != (rc = opal_register_params())) {
321         fprintf(stderr, "opal_info_register: opal_register_params failed\n");
322         return rc;
323     }
324 
325     return opal_info_register_project_frameworks("opal", opal_frameworks, component_map);
326 }
327 
328 
opal_info_close_components(void)329 void opal_info_close_components(void)
330 {
331     int i;
332 
333     assert(opal_info_registered);
334     if (--opal_info_registered) {
335         return;
336     }
337 
338     for (i=0; NULL != opal_frameworks[i]; i++) {
339         (void) mca_base_framework_close(opal_frameworks[i]);
340     }
341 
342     /* release our reference to MCA */
343     mca_base_close ();
344 }
345 
346 
opal_info_show_path(const char * type,const char * value)347 void opal_info_show_path(const char *type, const char *value)
348 {
349     char *pretty, *path;
350 
351     pretty = strdup(type);
352     pretty[0] = toupper(pretty[0]);
353 
354     asprintf(&path, "path:%s", type);
355     opal_info_out(pretty, path, value);
356     free(pretty);
357     free(path);
358 }
359 
opal_info_do_path(bool want_all,opal_cmd_line_t * cmd_line)360 void opal_info_do_path(bool want_all, opal_cmd_line_t *cmd_line)
361 {
362     int i, count;
363     char *scope;
364 
365     /* Check bozo case */
366     count = opal_cmd_line_get_ninsts(cmd_line, "path");
367     for (i = 0; i < count; ++i) {
368         scope = opal_cmd_line_get_param(cmd_line, "path", i, 0);
369         if (0 == strcmp("all", scope)) {
370             want_all = true;
371             break;
372         }
373     }
374 
375     if (want_all) {
376         opal_info_show_path(opal_info_path_prefix, opal_install_dirs.prefix);
377         opal_info_show_path(opal_info_path_exec_prefix, opal_install_dirs.exec_prefix);
378         opal_info_show_path(opal_info_path_bindir, opal_install_dirs.bindir);
379         opal_info_show_path(opal_info_path_sbindir, opal_install_dirs.sbindir);
380         opal_info_show_path(opal_info_path_libdir, opal_install_dirs.libdir);
381         opal_info_show_path(opal_info_path_incdir, opal_install_dirs.includedir);
382         opal_info_show_path(opal_info_path_mandir, opal_install_dirs.mandir);
383         opal_info_show_path(opal_info_path_pkglibdir, opal_install_dirs.opallibdir);
384         opal_info_show_path(opal_info_path_libexecdir, opal_install_dirs.libexecdir);
385         opal_info_show_path(opal_info_path_datarootdir, opal_install_dirs.datarootdir);
386         opal_info_show_path(opal_info_path_datadir, opal_install_dirs.datadir);
387         opal_info_show_path(opal_info_path_sysconfdir, opal_install_dirs.sysconfdir);
388         opal_info_show_path(opal_info_path_sharedstatedir, opal_install_dirs.sharedstatedir);
389         opal_info_show_path(opal_info_path_localstatedir, opal_install_dirs.localstatedir);
390         opal_info_show_path(opal_info_path_infodir, opal_install_dirs.infodir);
391         opal_info_show_path(opal_info_path_pkgdatadir, opal_install_dirs.opaldatadir);
392         opal_info_show_path(opal_info_path_pkglibdir, opal_install_dirs.opallibdir);
393         opal_info_show_path(opal_info_path_pkgincludedir, opal_install_dirs.opalincludedir);
394     } else {
395         count = opal_cmd_line_get_ninsts(cmd_line, "path");
396         for (i = 0; i < count; ++i) {
397             scope = opal_cmd_line_get_param(cmd_line, "path", i, 0);
398 
399             if (0 == strcmp(opal_info_path_prefix, scope)) {
400                 opal_info_show_path(opal_info_path_prefix, opal_install_dirs.prefix);
401             } else if (0 == strcmp(opal_info_path_bindir, scope)) {
402                 opal_info_show_path(opal_info_path_bindir, opal_install_dirs.bindir);
403             } else if (0 == strcmp(opal_info_path_libdir, scope)) {
404                 opal_info_show_path(opal_info_path_libdir, opal_install_dirs.libdir);
405             } else if (0 == strcmp(opal_info_path_incdir, scope)) {
406                 opal_info_show_path(opal_info_path_incdir, opal_install_dirs.includedir);
407             } else if (0 == strcmp(opal_info_path_mandir, scope)) {
408                 opal_info_show_path(opal_info_path_mandir, opal_install_dirs.mandir);
409             } else if (0 == strcmp(opal_info_path_pkglibdir, scope)) {
410                 opal_info_show_path(opal_info_path_pkglibdir, opal_install_dirs.opallibdir);
411             } else if (0 == strcmp(opal_info_path_sysconfdir, scope)) {
412                 opal_info_show_path(opal_info_path_sysconfdir, opal_install_dirs.sysconfdir);
413             } else if (0 == strcmp(opal_info_path_exec_prefix, scope)) {
414                 opal_info_show_path(opal_info_path_exec_prefix, opal_install_dirs.exec_prefix);
415             } else if (0 == strcmp(opal_info_path_sbindir, scope)) {
416                 opal_info_show_path(opal_info_path_sbindir, opal_install_dirs.sbindir);
417             } else if (0 == strcmp(opal_info_path_libexecdir, scope)) {
418                 opal_info_show_path(opal_info_path_libexecdir, opal_install_dirs.libexecdir);
419             } else if (0 == strcmp(opal_info_path_datarootdir, scope)) {
420                 opal_info_show_path(opal_info_path_datarootdir, opal_install_dirs.datarootdir);
421             } else if (0 == strcmp(opal_info_path_datadir, scope)) {
422                 opal_info_show_path(opal_info_path_datadir, opal_install_dirs.datadir);
423             } else if (0 == strcmp(opal_info_path_sharedstatedir, scope)) {
424                 opal_info_show_path(opal_info_path_sharedstatedir, opal_install_dirs.sharedstatedir);
425             } else if (0 == strcmp(opal_info_path_localstatedir, scope)) {
426                 opal_info_show_path(opal_info_path_localstatedir, opal_install_dirs.localstatedir);
427             } else if (0 == strcmp(opal_info_path_infodir, scope)) {
428                 opal_info_show_path(opal_info_path_infodir, opal_install_dirs.infodir);
429             } else if (0 == strcmp(opal_info_path_pkgdatadir, scope)) {
430                 opal_info_show_path(opal_info_path_pkgdatadir, opal_install_dirs.opaldatadir);
431             } else if (0 == strcmp(opal_info_path_pkgincludedir, scope)) {
432                 opal_info_show_path(opal_info_path_pkgincludedir, opal_install_dirs.opalincludedir);
433             } else {
434                 char *usage = opal_cmd_line_get_usage_msg(cmd_line);
435                 opal_show_help("help-opal_info.txt", "usage", true, usage);
436                 free(usage);
437                 exit(1);
438             }
439         }
440     }
441 }
442 
opal_info_do_params(bool want_all_in,bool want_internal,opal_pointer_array_t * mca_types,opal_pointer_array_t * component_map,opal_cmd_line_t * opal_info_cmd_line)443 void opal_info_do_params(bool want_all_in, bool want_internal,
444                          opal_pointer_array_t *mca_types,
445                          opal_pointer_array_t *component_map,
446                          opal_cmd_line_t *opal_info_cmd_line)
447 {
448     mca_base_var_info_lvl_t max_level = OPAL_INFO_LVL_1;
449     int count;
450     char *type, *component, *str;
451     bool found;
452     int i;
453     bool want_all = false;
454     char *p;
455 
456     if (opal_cmd_line_is_taken(opal_info_cmd_line, "param")) {
457         p = "param";
458     } else if (opal_cmd_line_is_taken(opal_info_cmd_line, "params")) {
459         p = "params";
460     } else {
461         p = "foo";  /* should never happen, but protect against segfault */
462     }
463 
464     if (NULL != (str = opal_cmd_line_get_param (opal_info_cmd_line, "level", 0, 0))) {
465         char *tmp;
466 
467         errno = 0;
468         max_level = strtol (str, &tmp, 10) + OPAL_INFO_LVL_1 - 1;
469         if (0 != errno || '\0' != tmp[0] || max_level < OPAL_INFO_LVL_1 || max_level > OPAL_INFO_LVL_9) {
470             char *usage = opal_cmd_line_get_usage_msg(opal_info_cmd_line);
471             opal_show_help("help-opal_info.txt", "invalid-level", true, str);
472             free(usage);
473             exit(1);
474         }
475     } else if (want_all_in) {
476         /* if not specified default to level 9 if all components are requested */
477         max_level = OPAL_INFO_LVL_9;
478     }
479 
480     if (want_all_in) {
481         want_all = true;
482     } else {
483         /* See if the special param "all" was given to --param; that
484          * supercedes any individual type
485          */
486         count = opal_cmd_line_get_ninsts(opal_info_cmd_line, p);
487         for (i = 0; i < count; ++i) {
488             type = opal_cmd_line_get_param(opal_info_cmd_line, p, (int)i, 0);
489             if (0 == strcmp(opal_info_type_all, type)) {
490                 want_all = true;
491                 break;
492             }
493         }
494     }
495 
496     /* Show the params */
497 
498     if (want_all) {
499         opal_info_show_component_version(mca_types, component_map, opal_info_type_all,
500                                          opal_info_component_all, opal_info_ver_full,
501                                          opal_info_ver_all);
502         for (i = 0; i < mca_types->size; ++i) {
503             if (NULL == (type = (char *)opal_pointer_array_get_item(mca_types, i))) {
504                 continue;
505             }
506             opal_info_show_mca_params(type, opal_info_component_all, max_level, want_internal);
507         }
508     } else {
509         for (i = 0; i < count; ++i) {
510             type = opal_cmd_line_get_param(opal_info_cmd_line, p, (int)i, 0);
511             component = opal_cmd_line_get_param(opal_info_cmd_line, p, (int)i, 1);
512 
513             for (found = false, i = 0; i < mca_types->size; ++i) {
514                 if (NULL == (str = (char *)opal_pointer_array_get_item(mca_types, i))) {
515                     continue;
516                 }
517                 if (0 == strcmp(str, type)) {
518                     found = true;
519                     break;
520                 }
521             }
522 
523             if (!found) {
524                 char *usage = opal_cmd_line_get_usage_msg(opal_info_cmd_line);
525                 opal_show_help("help-opal_info.txt", "not-found", true, type);
526                 free(usage);
527                 exit(1);
528             }
529 
530             opal_info_show_component_version(mca_types, component_map, type,
531                                              component, opal_info_ver_full,
532                                              opal_info_ver_all);
533             opal_info_show_mca_params(type, component, max_level, want_internal);
534         }
535     }
536 }
537 
opal_info_err_params(opal_pointer_array_t * component_map)538 void opal_info_err_params(opal_pointer_array_t *component_map)
539 {
540     opal_info_component_map_t *map=NULL, *mptr;
541     int i;
542 
543     /* all we want to do is display the LAST entry in the
544      * component_map array as this is the one that generated the error
545      */
546     for (i=0; i < component_map->size; i++) {
547         if (NULL == (mptr = (opal_info_component_map_t*)opal_pointer_array_get_item(component_map, i))) {
548             continue;
549         }
550         map = mptr;
551     }
552     if (NULL == map) {
553         fprintf(stderr, "opal_info_err_params: map not found\n");
554         return;
555     }
556     opal_info_show_mca_params(map->type, opal_info_component_all, OPAL_INFO_LVL_9, true);
557     fprintf(stderr, "\n");
558     return;
559 }
560 
opal_info_do_type(opal_cmd_line_t * opal_info_cmd_line)561 void opal_info_do_type(opal_cmd_line_t *opal_info_cmd_line)
562 {
563     mca_base_var_info_lvl_t max_level = OPAL_INFO_LVL_1;
564     int count;
565     char *type, *str;
566     int i, j, k, len, ret;
567     char *p;
568     const mca_base_var_t *var;
569     char** strings, *message;
570     const mca_base_var_group_t *group;
571     p = "type";
572 
573     if (NULL != (str = opal_cmd_line_get_param (opal_info_cmd_line, "level", 0, 0))) {
574         char *tmp;
575 
576         errno = 0;
577         max_level = strtol (str, &tmp, 10) + OPAL_INFO_LVL_1 - 1;
578         if (0 != errno || '\0' != tmp[0] || max_level < OPAL_INFO_LVL_1 || max_level > OPAL_INFO_LVL_9) {
579             char *usage = opal_cmd_line_get_usage_msg(opal_info_cmd_line);
580             opal_show_help("help-opal_info.txt", "invalid-level", true, str);
581             free(usage);
582             exit(1);
583         }
584     }
585 
586     count = opal_cmd_line_get_ninsts(opal_info_cmd_line, p);
587     len = mca_base_var_get_count ();
588 
589     for (k = 0; k < count; ++k) {
590         type = opal_cmd_line_get_param(opal_info_cmd_line, p, k, 0);
591         for (i = 0; i < len; ++i) {
592             ret = mca_base_var_get (i, &var);
593             if (OPAL_SUCCESS != ret) {
594                 continue;
595             }
596             if (0 == strcmp(type, ompi_var_type_names[var->mbv_type]) && (var->mbv_info_lvl <= max_level)) {
597                 ret = mca_base_var_dump(var->mbv_index, &strings, !opal_info_pretty ? MCA_BASE_VAR_DUMP_PARSABLE : MCA_BASE_VAR_DUMP_READABLE);
598                 if (OPAL_SUCCESS != ret) {
599                     continue;
600                 }
601                 (void) mca_base_var_group_get(var->mbv_group_index, &group);
602                 for (j = 0 ; strings[j] ; ++j) {
603                     if (0 == j && opal_info_pretty) {
604                         asprintf (&message, "MCA %s", group->group_framework);
605                         opal_info_out(message, message, strings[j]);
606                         free(message);
607                     } else {
608                         opal_info_out("", "", strings[j]);
609                     }
610                     free(strings[j]);
611                 }
612                 free(strings);
613             }
614         }
615     }
616 }
617 
opal_info_show_mca_group_params(const mca_base_var_group_t * group,mca_base_var_info_lvl_t max_level,bool want_internal)618 static void opal_info_show_mca_group_params(const mca_base_var_group_t *group, mca_base_var_info_lvl_t max_level, bool want_internal)
619 {
620     const int *variables, *groups;
621     const mca_base_pvar_t *pvar;
622     const char *group_component;
623     const mca_base_var_t *var;
624     char **strings, *message;
625     bool requested = true;
626     int ret, i, j, count;
627 
628     variables = OPAL_VALUE_ARRAY_GET_BASE(&group->group_vars, const int);
629     count = opal_value_array_get_size((opal_value_array_t *)&group->group_vars);
630 
631     /* the default component name is "base". depending on how the
632      * group was registered the group may or not have this set.  */
633     group_component = group->group_component ? group->group_component : "base";
634 
635     /* check if this group may be disabled due to a selection variable */
636     if (0 != strcmp (group_component, "base")) {
637         int var_id;
638 
639         /* read the selection parameter */
640         var_id = mca_base_var_find (group->group_project, group->group_framework, NULL, NULL);
641         if (0 <= var_id) {
642             const mca_base_var_storage_t *value=NULL;
643             char **requested_components;
644             bool include_mode;
645 
646             mca_base_var_get_value (var_id, &value, NULL, NULL);
647             if (NULL != value && NULL != value->stringval && '\0' != value->stringval[0]) {
648                 mca_base_component_parse_requested (value->stringval, &include_mode, &requested_components);
649 
650                 for (i = 0, requested = !include_mode ; requested_components[i] ; ++i) {
651                     if (0 == strcmp (requested_components[i], group_component)) {
652                         requested = include_mode;
653                         break;
654                     }
655                 }
656 
657                 opal_argv_free (requested_components);
658             }
659         }
660     }
661 
662     const mca_base_var_group_t *curr_group = NULL;
663     char *component_msg = NULL;
664     asprintf(&component_msg, " %s", group_component);
665 
666     for (i = 0 ; i < count ; ++i) {
667         ret = mca_base_var_get(variables[i], &var);
668         if (OPAL_SUCCESS != ret || ((var->mbv_flags & MCA_BASE_VAR_FLAG_INTERNAL) &&
669                                     !want_internal) ||
670             max_level < var->mbv_info_lvl) {
671             continue;
672         }
673 
674         if (opal_info_pretty && curr_group != group) {
675             asprintf(&message, "MCA%s %s%s", requested ? "" : " (-)",
676                      group->group_framework,
677                      component_msg ? component_msg : "");
678             opal_info_out(message, message, "---------------------------------------------------");
679             free(message);
680             curr_group = group;
681         }
682 
683         ret = mca_base_var_dump(variables[i], &strings, !opal_info_pretty ? MCA_BASE_VAR_DUMP_PARSABLE : MCA_BASE_VAR_DUMP_READABLE);
684         if (OPAL_SUCCESS != ret) {
685             continue;
686         }
687 
688         for (j = 0 ; strings[j] ; ++j) {
689             if (0 == j && opal_info_pretty) {
690                 asprintf (&message, "MCA%s %s%s", requested ? "" : " (-)",
691                           group->group_framework,
692                           component_msg ? component_msg : "");
693                 opal_info_out(message, message, strings[j]);
694                 free(message);
695             } else {
696                 opal_info_out("", "", strings[j]);
697             }
698             free(strings[j]);
699         }
700         if (!opal_info_pretty) {
701             /* generate an entry indicating whether this variable is disabled or not. if the
702              * format in mca_base_var/pvar.c changes this needs to be changed as well */
703             asprintf (&message, "mca:%s:%s:param:%s:disabled:%s", group->group_framework,
704                       group_component, var->mbv_full_name, requested ? "false" : "true");
705             opal_info_out("", "", message);
706             free (message);
707         }
708         free(strings);
709     }
710 
711     variables = OPAL_VALUE_ARRAY_GET_BASE(&group->group_pvars, const int);
712     count = opal_value_array_get_size((opal_value_array_t *)&group->group_pvars);
713 
714     for (i = 0 ; i < count ; ++i) {
715         ret = mca_base_pvar_get(variables[i], &pvar);
716         if (OPAL_SUCCESS != ret || max_level < pvar->verbosity) {
717             continue;
718         }
719 
720         if (opal_info_pretty && curr_group != group) {
721             asprintf(&message, "MCA%s %s%s", requested ? "" : " (-)",
722                      group->group_framework,
723                      component_msg ? component_msg : "");
724             opal_info_out(message, message, "---------------------------------------------------");
725             free(message);
726             curr_group = group;
727         }
728 
729         ret = mca_base_pvar_dump (variables[i], &strings, !opal_info_pretty ? MCA_BASE_VAR_DUMP_PARSABLE : MCA_BASE_VAR_DUMP_READABLE);
730         if (OPAL_SUCCESS != ret) {
731             continue;
732         }
733 
734         for (j = 0 ; strings[j] ; ++j) {
735             if (0 == j && opal_info_pretty) {
736                 asprintf (&message, "MCA%s %s%s", requested ? "" : " (-)",
737                           group->group_framework,
738                           component_msg ? component_msg : "");
739                 opal_info_out(message, message, strings[j]);
740                 free(message);
741             } else {
742                 opal_info_out("", "", strings[j]);
743             }
744             free(strings[j]);
745         }
746         if (!opal_info_pretty) {
747             /* generate an entry indicating whether this variable is disabled or not. if the
748              * format in mca_base_var/pvar.c changes this needs to be changed as well */
749             asprintf (&message, "mca:%s:%s:pvar:%s:disabled:%s", group->group_framework,
750                       group_component, pvar->name, requested ? "false" : "true");
751             opal_info_out("", "", message);
752             free (message);
753         }
754         free(strings);
755     }
756 
757     groups = OPAL_VALUE_ARRAY_GET_BASE(&group->group_subgroups, const int);
758     count = opal_value_array_get_size((opal_value_array_t *)&group->group_subgroups);
759 
760     for (i = 0 ; i < count ; ++i) {
761         ret = mca_base_var_group_get(groups[i], &group);
762         if (OPAL_SUCCESS != ret) {
763             continue;
764         }
765         opal_info_show_mca_group_params(group, max_level, want_internal);
766     }
767     free(component_msg);
768 }
769 
opal_info_show_mca_params(const char * type,const char * component,mca_base_var_info_lvl_t max_level,bool want_internal)770 void opal_info_show_mca_params(const char *type, const char *component,
771                                mca_base_var_info_lvl_t max_level, bool want_internal)
772 {
773     const mca_base_var_group_t *group;
774     int ret;
775 
776     if (0 == strcmp (component, "all")) {
777         ret = mca_base_var_group_find("*", type, NULL);
778         if (0 > ret) {
779             return;
780         }
781 
782         (void) mca_base_var_group_get(ret, &group);
783 
784         opal_info_show_mca_group_params(group, max_level, want_internal);
785     } else {
786         ret = mca_base_var_group_find("*", type, component);
787         if (0 > ret) {
788             return;
789         }
790 
791         (void) mca_base_var_group_get(ret, &group);
792         opal_info_show_mca_group_params(group, max_level, want_internal);
793     }
794 }
795 
796 
797 
opal_info_do_arch()798 void opal_info_do_arch()
799 {
800     opal_info_out("Configured architecture", "config:arch", OPAL_ARCH);
801 }
802 
803 
opal_info_do_hostname()804 void opal_info_do_hostname()
805 {
806     opal_info_out("Configure host", "config:host", OPAL_CONFIGURE_HOST);
807 }
808 
809 
escape_quotes(const char * value)810 static char *escape_quotes(const char *value)
811 {
812     const char *src;
813     int num_quotes = 0;
814     for (src = value; src != NULL && *src != '\0'; ++src) {
815         if ('"' == *src) {
816             ++num_quotes;
817         }
818     }
819 
820     // If there are no quotes in the string, there's nothing to do
821     if (0 == num_quotes) {
822         return NULL;
823     }
824 
825     // If we have quotes, make a new string.  Copy over the old
826     // string, escaping the quotes along the way.  This is simple and
827     // clear to read; it's not particularly efficient (performance is
828     // definitely not important here).
829     char *quoted_value;
830     quoted_value = calloc(1, strlen(value) + num_quotes + 1);
831     if (NULL == quoted_value) {
832         return NULL;
833     }
834 
835     char *dest;
836     for (src = value, dest = quoted_value; *src != '\0'; ++src, ++dest) {
837         if ('"' == *src) {
838             *dest++ = '\\';
839         }
840         *dest = *src;
841     }
842 
843     return quoted_value;
844 }
845 
846 
847 /*
848  * Private variables - set some reasonable screen size defaults
849  */
850 
851 static int centerpoint = 24;
852 static int screen_width = 78;
853 
854 /*
855  * Prints the passed message in a pretty or parsable format.
856  */
opal_info_out(const char * pretty_message,const char * plain_message,const char * value)857 void opal_info_out(const char *pretty_message, const char *plain_message, const char *value)
858 {
859     size_t len, max_value_width, value_offset;
860     char *spaces = NULL;
861     char *filler = NULL;
862     char *pos, *v, savev, *v_to_free;
863 
864 #ifdef HAVE_ISATTY
865     /* If we have isatty(), if this is not a tty, then disable
866      * wrapping for grep-friendly behavior
867      */
868     if (0 == isatty(STDOUT_FILENO)) {
869         screen_width = INT_MAX;
870     }
871 #endif
872 
873 #ifdef TIOCGWINSZ
874     if (screen_width < INT_MAX) {
875         struct winsize size;
876         if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char*) &size) >= 0) {
877             screen_width = size.ws_col;
878         }
879     }
880 #endif
881 
882     /* Sanity check (allow NULL to mean "") */
883     if (NULL == value) {
884         value = "";
885     }
886 
887     /* Strip leading and trailing whitespace from the string value */
888     value_offset = strspn(value, " ");
889 
890     v = v_to_free = strdup(value + value_offset);
891     len = strlen(v);
892 
893     if (len > 0) {
894         while (len > 0 && isspace(v[len-1])) len--;
895         v[len] = '\0';
896     }
897 
898     if (opal_info_pretty && NULL != pretty_message) {
899         if (centerpoint > (int)strlen(pretty_message)) {
900             asprintf(&spaces, "%*s", centerpoint -
901                      (int)strlen(pretty_message), " ");
902         } else {
903             spaces = strdup("");
904 #if OPAL_ENABLE_DEBUG
905             if (centerpoint < (int)strlen(pretty_message)) {
906                 opal_show_help("help-opal_info.txt",
907                                "developer warning: field too long", false,
908                                pretty_message, centerpoint);
909             }
910 #endif
911         }
912         max_value_width = screen_width - strlen(spaces) - strlen(pretty_message) - 2;
913         if (0 < strlen(pretty_message)) {
914             asprintf(&filler, "%s%s: ", spaces, pretty_message);
915         } else {
916             asprintf(&filler, "%s  ", spaces);
917         }
918         free(spaces);
919         spaces = NULL;
920 
921         while (true) {
922             if (strlen(v) < max_value_width) {
923                 printf("%s%s\n", filler, v);
924                 break;
925             } else {
926                 asprintf(&spaces, "%*s", centerpoint + 2, " ");
927 
928                 /* Work backwards to find the first space before
929                  * max_value_width
930                  */
931                 savev = v[max_value_width];
932                 v[max_value_width] = '\0';
933                 pos = (char*)strrchr(v, (int)' ');
934                 v[max_value_width] = savev;
935                 if (NULL == pos) {
936                     /* No space found < max_value_width.  Look for the first
937                      * space after max_value_width.
938                      */
939                     pos = strchr(&v[max_value_width], ' ');
940 
941                     if (NULL == pos) {
942 
943                         /* There's just no spaces.  So just print it and be done. */
944 
945                         printf("%s%s\n", filler, v);
946                         break;
947                     } else {
948                         *pos = '\0';
949                         printf("%s%s\n", filler, v);
950                         v = pos + 1;
951                     }
952                 } else {
953                     *pos = '\0';
954                     printf("%s%s\n", filler, v);
955                     v = pos + 1;
956                 }
957 
958                 /* Reset for the next iteration */
959                 free(filler);
960                 filler = strdup(spaces);
961                 free(spaces);
962                 spaces = NULL;
963             }
964         }
965         if (NULL != filler) {
966             free(filler);
967         }
968         if (NULL != spaces) {
969             free(spaces);
970         }
971     } else {
972         if (NULL != plain_message && 0 < strlen(plain_message)) {
973             // Escape any double quotes in the value.
974             char *quoted_value;
975             quoted_value = escape_quotes(value);
976             if (NULL != quoted_value) {
977                 value = quoted_value;
978             }
979 
980             char *colon = strchr(value, ':');
981             if (NULL != colon) {
982                 printf("%s:\"%s\"\n", plain_message, value);
983             } else {
984                 printf("%s:%s\n", plain_message, value);
985             }
986 
987             if (NULL != quoted_value) {
988                 free(quoted_value);
989             }
990         } else {
991             printf("%s\n", value);
992         }
993     }
994     if (NULL != v_to_free) {
995         free(v_to_free);
996     }
997 }
998 
999 /*
1000  * Prints the passed integer in a pretty or parsable format.
1001  */
opal_info_out_int(const char * pretty_message,const char * plain_message,int value)1002 void opal_info_out_int(const char *pretty_message,
1003                        const char *plain_message,
1004                        int value)
1005 {
1006     char *valstr;
1007 
1008     asprintf(&valstr, "%d", (int)value);
1009     opal_info_out(pretty_message, plain_message, valstr);
1010     free(valstr);
1011 }
1012 
1013 /*
1014  * Show all the components of a specific type/component combo (component may be
1015  * a wildcard)
1016  */
opal_info_show_component_version(opal_pointer_array_t * mca_types,opal_pointer_array_t * component_map,const char * type_name,const char * component_name,const char * scope,const char * ver_type)1017 void opal_info_show_component_version(opal_pointer_array_t *mca_types,
1018                                       opal_pointer_array_t *component_map,
1019                                       const char *type_name,
1020                                       const char *component_name,
1021                                       const char *scope, const char *ver_type)
1022 {
1023     bool want_all_components = false;
1024     bool want_all_types = false;
1025     bool found;
1026     mca_base_component_list_item_t *cli;
1027     mca_base_failed_component_t *cli_failed;
1028     int j;
1029     char *pos;
1030     opal_info_component_map_t *map;
1031 
1032     /* see if all components wanted */
1033     if (0 == strcmp(opal_info_component_all, component_name)) {
1034         want_all_components = true;
1035     }
1036 
1037     /* see if all types wanted */
1038     if (0 != strcmp(opal_info_type_all, type_name)) {
1039         /* Check to see if the type is valid */
1040 
1041         for (found = false, j = 0; j < mca_types->size; ++j) {
1042             if (NULL == (pos = (char*)opal_pointer_array_get_item(mca_types, j))) {
1043                 continue;
1044             }
1045             if (0 == strcmp(pos, type_name)) {
1046                 found = true;
1047                 break;
1048             }
1049         }
1050 
1051         if (!found) {
1052             return;
1053         }
1054     } else {
1055         want_all_types = true;
1056     }
1057 
1058     /* Now that we have a valid type, find the right components */
1059     for (j=0; j < component_map->size; j++) {
1060         if (NULL == (map = (opal_info_component_map_t*)opal_pointer_array_get_item(component_map, j))) {
1061             continue;
1062         }
1063         if ((want_all_types || 0 == strcmp(type_name, map->type)) && map->components) {
1064             /* found it! */
1065             OPAL_LIST_FOREACH(cli, map->components, mca_base_component_list_item_t) {
1066                 const mca_base_component_t *component = cli->cli_component;
1067                 if (want_all_components ||
1068                     0 == strcmp(component->mca_component_name, component_name)) {
1069                     opal_info_show_mca_version(component, scope, ver_type);
1070                 }
1071             }
1072 
1073             /* found it! */
1074             OPAL_LIST_FOREACH(cli_failed, map->failed_components, mca_base_failed_component_t) {
1075                 mca_base_component_repository_item_t *ri = cli_failed->comp;
1076                 if (want_all_components ||
1077                     0 == strcmp(component_name, ri->ri_name) ) {
1078                     opal_info_show_failed_component(ri, cli_failed->error_msg);
1079                 }
1080             }
1081 
1082             if (!want_all_types) {
1083                 break;
1084             }
1085         }
1086     }
1087 }
1088 
1089 
opal_info_show_failed_component(const mca_base_component_repository_item_t * ri,const char * error_msg)1090 static void opal_info_show_failed_component(const mca_base_component_repository_item_t* ri,
1091                                             const char *error_msg)
1092 {
1093     char *message, *content;
1094 
1095     if (opal_info_pretty) {
1096         asprintf(&message, "MCA %s", ri->ri_type);
1097         asprintf(&content, "%s (failed to load) %s", ri->ri_name, error_msg);
1098 
1099         opal_info_out(message, NULL, content);
1100 
1101         free(message);
1102         free(content);
1103     } else {
1104         asprintf(&message, "mca:%s:%s:failed", ri->ri_type, ri->ri_name);
1105         asprintf(&content, "%s", error_msg);
1106 
1107         opal_info_out(NULL, message, content);
1108 
1109         free(message);
1110         free(content);
1111     }
1112 }
1113 
1114 /*
1115  * Given a component, display its relevant version(s)
1116  */
opal_info_show_mca_version(const mca_base_component_t * component,const char * scope,const char * ver_type)1117 void opal_info_show_mca_version(const mca_base_component_t* component,
1118                                 const char *scope, const char *ver_type)
1119 {
1120     bool printed;
1121     bool want_mca = false;
1122     bool want_type = false;
1123     bool want_component = false;
1124     char *message, *content;
1125     char *mca_version;
1126     char *api_version;
1127     char *component_version;
1128     char *tmp;
1129 
1130     if (0 == strcmp(ver_type, opal_info_ver_all) ||
1131         0 == strcmp(ver_type, opal_info_ver_mca)) {
1132         want_mca = true;
1133     }
1134 
1135     if (0 == strcmp(ver_type, opal_info_ver_all) ||
1136         0 == strcmp(ver_type, opal_info_ver_type)) {
1137         want_type = true;
1138     }
1139 
1140     if (0 == strcmp(ver_type, opal_info_ver_all) ||
1141         0 == strcmp(ver_type, opal_info_ver_component)) {
1142         want_component = true;
1143     }
1144 
1145     mca_version = opal_info_make_version_str(scope, component->mca_major_version,
1146                                              component->mca_minor_version,
1147                                              component->mca_release_version, "",
1148                                              "");
1149     api_version = opal_info_make_version_str(scope, component->mca_type_major_version,
1150                                              component->mca_type_minor_version,
1151                                              component->mca_type_release_version, "",
1152                                              "");
1153     component_version = opal_info_make_version_str(scope, component->mca_component_major_version,
1154                                                    component->mca_component_minor_version,
1155                                                    component->mca_component_release_version,
1156                                                    "", "");
1157     if (opal_info_pretty) {
1158         asprintf(&message, "MCA %s", component->mca_type_name);
1159         printed = false;
1160         asprintf(&content, "%s (", component->mca_component_name);
1161 
1162         if (want_mca) {
1163             asprintf(&tmp, "%sMCA v%s", content, mca_version);
1164             free(content);
1165             content = tmp;
1166             printed = true;
1167         }
1168 
1169         if (want_type) {
1170             if (printed) {
1171                 asprintf(&tmp, "%s, ", content);
1172                 free(content);
1173                 content = tmp;
1174             }
1175             asprintf(&tmp, "%sAPI v%s", content, api_version);
1176             free(content);
1177             content = tmp;
1178             printed = true;
1179         }
1180 
1181         if (want_component) {
1182             if (printed) {
1183                 asprintf(&tmp, "%s, ", content);
1184                 free(content);
1185                 content = tmp;
1186             }
1187             asprintf(&tmp, "%sComponent v%s", content, component_version);
1188             free(content);
1189             content = tmp;
1190             printed = true;
1191         }
1192         if (NULL != content) {
1193             asprintf(&tmp, "%s)", content);
1194             free(content);
1195         } else {
1196             tmp = NULL;
1197         }
1198 
1199         opal_info_out(message, NULL, tmp);
1200         free(message);
1201         if (NULL != tmp) {
1202             free(tmp);
1203         }
1204 
1205     } else {
1206         asprintf(&message, "mca:%s:%s:version", component->mca_type_name, component->mca_component_name);
1207         if (want_mca) {
1208             asprintf(&tmp, "mca:%s", mca_version);
1209             opal_info_out(NULL, message, tmp);
1210             free(tmp);
1211         }
1212         if (want_type) {
1213             asprintf(&tmp, "api:%s", api_version);
1214             opal_info_out(NULL, message, tmp);
1215             free(tmp);
1216         }
1217         if (want_component) {
1218             asprintf(&tmp, "component:%s", component_version);
1219             opal_info_out(NULL, message, tmp);
1220             free(tmp);
1221         }
1222         free(message);
1223     }
1224 
1225     if (NULL != mca_version) {
1226         free(mca_version);
1227     }
1228     if (NULL != api_version) {
1229         free(api_version);
1230     }
1231     if (NULL != component_version) {
1232         free(component_version);
1233     }
1234 }
1235 
1236 
opal_info_make_version_str(const char * scope,int major,int minor,int release,const char * greek,const char * repo)1237 char *opal_info_make_version_str(const char *scope,
1238                                  int major, int minor, int release,
1239                                  const char *greek,
1240                                  const char *repo)
1241 {
1242     char *str = NULL, *tmp;
1243     char temp[BUFSIZ];
1244 
1245     temp[BUFSIZ - 1] = '\0';
1246     if (0 == strcmp(scope, opal_info_ver_full) ||
1247         0 == strcmp(scope, opal_info_ver_all)) {
1248         snprintf(temp, BUFSIZ - 1, "%d.%d.%d", major, minor, release);
1249         str = strdup(temp);
1250         if (NULL != greek) {
1251             asprintf(&tmp, "%s%s", str, greek);
1252             free(str);
1253             str = tmp;
1254         }
1255     } else if (0 == strcmp(scope, opal_info_ver_major)) {
1256         snprintf(temp, BUFSIZ - 1, "%d", major);
1257     } else if (0 == strcmp(scope, opal_info_ver_minor)) {
1258         snprintf(temp, BUFSIZ - 1, "%d", minor);
1259     } else if (0 == strcmp(scope, opal_info_ver_release)) {
1260         snprintf(temp, BUFSIZ - 1, "%d", release);
1261     } else if (0 == strcmp(scope, opal_info_ver_greek)) {
1262         str = strdup(greek);
1263     } else if (0 == strcmp(scope, opal_info_ver_repo)) {
1264         str = strdup(repo);
1265     }
1266 
1267     if (NULL == str) {
1268         str = strdup(temp);
1269     }
1270 
1271     return str;
1272 }
1273 
opal_info_show_opal_version(const char * scope)1274 void opal_info_show_opal_version(const char *scope)
1275 {
1276     char *tmp, *tmp2;
1277 
1278     asprintf(&tmp, "%s:version:full", opal_info_type_opal);
1279     tmp2 = opal_info_make_version_str(scope,
1280                                       OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION,
1281                                       OPAL_RELEASE_VERSION,
1282                                       OPAL_GREEK_VERSION,
1283                                       OPAL_REPO_REV);
1284     opal_info_out("OPAL", tmp, tmp2);
1285     free(tmp);
1286     free(tmp2);
1287     asprintf(&tmp, "%s:version:repo", opal_info_type_opal);
1288     opal_info_out("OPAL repo revision", tmp, OPAL_REPO_REV);
1289     free(tmp);
1290     asprintf(&tmp, "%s:version:release_date", opal_info_type_opal);
1291     opal_info_out("OPAL release date", tmp, OPAL_RELEASE_DATE);
1292     free(tmp);
1293 }
1294