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-2020 Intel, Inc. All rights reserved.
18 * Copyright (c) 2017 IBM Corporation. All rights reserved.
19 * Copyright (c) 2017 Research Organization for Information Science
20 * and Technology (RIST). All rights reserved.
21 * $COPYRIGHT$
22 *
23 * Additional copyrights may follow
24 *
25 * $HEADER$
26 */
27
28 #include "pmix_config.h"
29
30 #include <string.h>
31 #include <ctype.h>
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <errno.h>
38
39 #include "src/class/pmix_list.h"
40 #include "src/class/pmix_pointer_array.h"
41 #include "src/runtime/pmix_rte.h"
42 #include "src/util/output.h"
43 #include "src/util/cmd_line.h"
44 #include "src/util/error.h"
45 #include "src/util/argv.h"
46 #include "src/util/show_help.h"
47
48 #include "src/include/frameworks.h"
49 #include "src/include/pmix_portable_platform.h"
50
51 #include "src/mca/pinstalldirs/pinstalldirs.h"
52 #include "pinfo.h"
53 #include "support.h"
54 #include "src/mca/base/pmix_mca_base_component_repository.h"
55
56 const char *pmix_info_path_prefix = "prefix";
57 const char *pmix_info_path_bindir = "bindir";
58 const char *pmix_info_path_libdir = "libdir";
59 const char *pmix_info_path_incdir = "incdir";
60 const char *pmix_info_path_mandir = "mandir";
61 const char *pmix_info_path_pkglibdir = "pkglibdir";
62 const char *pmix_info_path_sysconfdir = "sysconfdir";
63 const char *pmix_info_path_exec_prefix = "exec_prefix";
64 const char *pmix_info_path_sbindir = "sbindir";
65 const char *pmix_info_path_libexecdir = "libexecdir";
66 const char *pmix_info_path_datarootdir = "datarootdir";
67 const char *pmix_info_path_datadir = "datadir";
68 const char *pmix_info_path_sharedstatedir = "sharedstatedir";
69 const char *pmix_info_path_localstatedir = "localstatedir";
70 const char *pmix_info_path_infodir = "infodir";
71 const char *pmix_info_path_pkgdatadir = "pkgdatadir";
72 const char *pmix_info_path_pkgincludedir = "pkgincludedir";
73
74 bool pmix_info_pretty = true;
75 pmix_mca_base_register_flag_t pmix_info_register_flags = PMIX_MCA_BASE_REGISTER_ALL;
76
77 const char *pmix_info_type_all = "all";
78 const char *pmix_info_type_pmix = "pmix";
79 const char *pmix_info_component_all = "all";
80 const char *pmix_info_param_all = "all";
81
82 const char *pmix_info_ver_full = "full";
83 const char *pmix_info_ver_major = "major";
84 const char *pmix_info_ver_minor = "minor";
85 const char *pmix_info_ver_release = "release";
86 const char *pmix_info_ver_greek = "greek";
87 const char *pmix_info_ver_repo = "repo";
88
89 const char *pmix_info_ver_all = "all";
90 const char *pmix_info_ver_mca = "mca";
91 const char *pmix_info_ver_type = "type";
92 const char *pmix_info_ver_component = "component";
93
94 static int pmix_info_registered = 0;
95
component_map_construct(pmix_info_component_map_t * map)96 static void component_map_construct(pmix_info_component_map_t *map)
97 {
98 map->type = NULL;
99 }
component_map_destruct(pmix_info_component_map_t * map)100 static void component_map_destruct(pmix_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 PMIX_CLASS_INSTANCE(pmix_info_component_map_t,
110 pmix_list_item_t,
111 component_map_construct,
112 component_map_destruct);
113
114 static void pmix_info_show_failed_component(const pmix_mca_base_component_repository_item_t* ri,
115 const char *error_msg);
116
pmix_info_init(int argc,char ** argv,pmix_cmd_line_t * pmix_info_cmd_line)117 int pmix_info_init(int argc, char **argv,
118 pmix_cmd_line_t *pmix_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 /* add the cmd line options */
126 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 'V', NULL, "version", 0,
127 "Show version of Open MPI");
128 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "param", 2,
129 "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\").");
130 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "params", 2,
131 "Synonym for --param");
132 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "internal", 0,
133 "Show internal MCA parameters (not meant to be modified by users)");
134 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "path", 1,
135 "Show paths that Open MPI was configured with. Accepts the following parameters: prefix, bindir, libdir, incdir, mandir, pkglibdir, sysconfdir, all");
136 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "arch", 0,
137 "Show architecture Open MPI was compiled on");
138 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 'c', NULL, "config", 0,
139 "Show configuration options");
140 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 't', NULL, "type", 1,
141 "Show internal MCA parameters with the type specified in parameter.");
142 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 'h', NULL, "help", 0,
143 "Show this help message");
144 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "pretty-print", 0,
145 "When used in conjunction with other parameters, the output is displayed in 'pretty-print' format (default)");
146 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "parsable", 0,
147 "When used in conjunction with other parameters, the output is displayed in a machine-parsable format");
148 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "parseable", 0,
149 "Synonym for --parsable");
150 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "hostname", 0,
151 "Show the hostname that Open MPI was configured and built on");
152 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 'a', NULL, "all", 0,
153 "Show all configuration options and MCA parameters");
154 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 'l', NULL, "level", 1,
155 "Show only variables with at most this level (1-9)");
156 pmix_cmd_line_make_opt3(pmix_info_cmd_line, 's', NULL, "selected-only", 0,
157 "Show only variables from selected components");
158 pmix_cmd_line_make_opt3(pmix_info_cmd_line, '\0', NULL, "show-failed", 0,
159 "Show the components that failed to load along with the reason why they failed.");
160
161 if( PMIX_SUCCESS != pmix_mca_base_open() ) {
162 pmix_show_help("help-pinfo.txt", "lib-call-fail", true, "mca_base_open", __FILE__, __LINE__ );
163 PMIX_RELEASE(pmix_info_cmd_line);
164 exit(1);
165 }
166 pmix_mca_base_cmd_line_setup(pmix_info_cmd_line);
167
168 /* Do the parsing */
169
170 ret = pmix_cmd_line_parse(pmix_info_cmd_line, false, false, argc, argv);
171 if (PMIX_SUCCESS != ret) {
172 if (PMIX_ERR_SILENT != ret) {
173 fprintf(stderr, "%s: command line error (%s)\n", argv[0],
174 PMIx_Error_string(ret));
175 }
176 cmd_error = true;
177 }
178 if (!cmd_error &&
179 (pmix_cmd_line_is_taken(pmix_info_cmd_line, "help") ||
180 pmix_cmd_line_is_taken(pmix_info_cmd_line, "h"))) {
181 char *str, *usage;
182
183 want_help = true;
184 usage = pmix_cmd_line_get_usage_msg(pmix_info_cmd_line);
185 str = pmix_show_help_string("help-pmix-info.txt", "usage", true,
186 usage);
187 if (NULL != str) {
188 printf("%s", str);
189 free(str);
190 }
191 free(usage);
192 }
193
194
195 /* If we had a cmd line parse error, or we showed the help
196 message, it's time to exit. */
197 if (cmd_error || want_help) {
198 pmix_mca_base_close();
199 PMIX_RELEASE(pmix_info_cmd_line);
200 exit(cmd_error ? 1 : 0);
201 }
202
203 pmix_mca_base_cmd_line_process_args(pmix_info_cmd_line, &app_env, &global_env);
204
205
206 /* set the flags */
207 if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "pretty-print")) {
208 pmix_info_pretty = true;
209 } else if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "parsable") || pmix_cmd_line_is_taken(pmix_info_cmd_line, "parseable")) {
210 pmix_info_pretty = false;
211 }
212
213 if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "selected-only")) {
214 /* register only selected components */
215 pmix_info_register_flags = PMIX_MCA_BASE_REGISTER_DEFAULT;
216 }
217
218 if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "show-failed")) {
219 pmix_mca_base_component_track_load_errors = true;
220 }
221
222 return PMIX_SUCCESS;
223 }
224
pmix_info_finalize(void)225 void pmix_info_finalize(void)
226 {
227 pmix_mca_base_close();
228 }
229
info_register_framework(pmix_mca_base_framework_t * framework,pmix_pointer_array_t * component_map)230 static int info_register_framework (pmix_mca_base_framework_t *framework, pmix_pointer_array_t *component_map)
231 {
232 pmix_info_component_map_t *map;
233 int rc;
234 rc = pmix_mca_base_framework_register(framework, pmix_info_register_flags);
235 if (PMIX_SUCCESS != rc && PMIX_ERR_BAD_PARAM != rc) {
236 return rc;
237 }
238
239 if (NULL != component_map) {
240 map = PMIX_NEW(pmix_info_component_map_t);
241 map->type = strdup(framework->framework_name);
242 map->components = &framework->framework_components;
243 map->failed_components = &framework->framework_failed_components;
244 pmix_pointer_array_add(component_map, map);
245 }
246
247 return rc;
248 }
249
pmix_info_register_project_frameworks(const char * project_name,pmix_mca_base_framework_t ** frameworks,pmix_pointer_array_t * component_map)250 int pmix_info_register_project_frameworks (const char *project_name, pmix_mca_base_framework_t **frameworks,
251 pmix_pointer_array_t *component_map)
252 {
253 int i, rc=PMIX_SUCCESS;
254
255 for (i=0; NULL != frameworks[i]; i++) {
256 if (PMIX_SUCCESS != (rc = info_register_framework(frameworks[i], component_map))) {
257 if (PMIX_ERR_BAD_PARAM == rc) {
258 fprintf(stderr, "\nA \"bad parameter\" error was encountered when opening the %s %s framework\n",
259 project_name, frameworks[i]->framework_name);
260 fprintf(stderr, "The output received from that framework includes the following parameters:\n\n");
261 } else if (PMIX_ERR_NOT_AVAILABLE != rc) {
262 fprintf(stderr, "%s_info_register: %s failed\n", project_name, frameworks[i]->framework_name);
263 rc = PMIX_ERROR;
264 } else {
265 continue;
266 }
267
268 break;
269 }
270 }
271
272 return rc;
273 }
274
pmix_info_register_types(pmix_pointer_array_t * mca_types)275 void pmix_info_register_types(pmix_pointer_array_t *mca_types)
276 {
277 int i;
278
279 /* add the top-level types */
280 pmix_pointer_array_add(mca_types, "mca");
281 pmix_pointer_array_add(mca_types, "pmix");
282
283 /* push all the types found by autogen */
284 for (i=0; NULL != pmix_frameworks[i]; i++) {
285 pmix_pointer_array_add(mca_types, pmix_frameworks[i]->framework_name);
286 }
287 }
288
pmix_info_register_framework_params(pmix_pointer_array_t * component_map)289 int pmix_info_register_framework_params(pmix_pointer_array_t *component_map)
290 {
291 int rc;
292
293 if (pmix_info_registered++) {
294 return PMIX_SUCCESS;
295 }
296
297 /* Register mca/base parameters */
298 if( PMIX_SUCCESS != pmix_mca_base_open() ) {
299 pmix_show_help("help-pmix_info.txt", "lib-call-fail", true, "mca_base_open", __FILE__, __LINE__ );
300 return PMIX_ERROR;
301 }
302
303 /* Register the PMIX layer's MCA parameters */
304 if (PMIX_SUCCESS != (rc = pmix_register_params())) {
305 fprintf(stderr, "pmix_info_register: pmix_register_params failed\n");
306 return rc;
307 }
308
309 return pmix_info_register_project_frameworks("pmix", pmix_frameworks, component_map);
310 }
311
312
pmix_info_close_components(void)313 void pmix_info_close_components(void)
314 {
315 int i;
316
317 assert(pmix_info_registered);
318 if (--pmix_info_registered) {
319 return;
320 }
321
322 for (i=0; NULL != pmix_frameworks[i]; i++) {
323 (void) pmix_mca_base_framework_close(pmix_frameworks[i]);
324 }
325
326 /* release our reference to MCA */
327 pmix_mca_base_close ();
328 }
329
330
pmix_info_show_path(const char * type,const char * value)331 void pmix_info_show_path(const char *type, const char *value)
332 {
333 char *pretty, *path;
334
335 pretty = strdup(type);
336 pretty[0] = toupper(pretty[0]);
337
338 if (0 > asprintf(&path, "path:%s", type)) {
339 free(pretty);
340 return;
341 }
342 pmix_info_out(pretty, path, value);
343 free(pretty);
344 free(path);
345 }
346
pmix_info_do_path(bool want_all,pmix_cmd_line_t * cmd_line)347 void pmix_info_do_path(bool want_all, pmix_cmd_line_t *cmd_line)
348 {
349 int i, count;
350 char *scope;
351
352 /* Check bozo case */
353 count = pmix_cmd_line_get_ninsts(cmd_line, "path");
354 for (i = 0; i < count; ++i) {
355 scope = pmix_cmd_line_get_param(cmd_line, "path", i, 0);
356 if (0 == strcmp("all", scope)) {
357 want_all = true;
358 break;
359 }
360 }
361
362 if (want_all) {
363 pmix_info_show_path(pmix_info_path_prefix, pmix_pinstall_dirs.prefix);
364 pmix_info_show_path(pmix_info_path_exec_prefix, pmix_pinstall_dirs.exec_prefix);
365 pmix_info_show_path(pmix_info_path_bindir, pmix_pinstall_dirs.bindir);
366 pmix_info_show_path(pmix_info_path_sbindir, pmix_pinstall_dirs.sbindir);
367 pmix_info_show_path(pmix_info_path_libdir, pmix_pinstall_dirs.libdir);
368 pmix_info_show_path(pmix_info_path_incdir, pmix_pinstall_dirs.includedir);
369 pmix_info_show_path(pmix_info_path_mandir, pmix_pinstall_dirs.mandir);
370 pmix_info_show_path(pmix_info_path_pkglibdir, pmix_pinstall_dirs.pmixlibdir);
371 pmix_info_show_path(pmix_info_path_libexecdir, pmix_pinstall_dirs.libexecdir);
372 pmix_info_show_path(pmix_info_path_datarootdir, pmix_pinstall_dirs.datarootdir);
373 pmix_info_show_path(pmix_info_path_datadir, pmix_pinstall_dirs.datadir);
374 pmix_info_show_path(pmix_info_path_sysconfdir, pmix_pinstall_dirs.sysconfdir);
375 pmix_info_show_path(pmix_info_path_sharedstatedir, pmix_pinstall_dirs.sharedstatedir);
376 pmix_info_show_path(pmix_info_path_localstatedir, pmix_pinstall_dirs.localstatedir);
377 pmix_info_show_path(pmix_info_path_infodir, pmix_pinstall_dirs.infodir);
378 pmix_info_show_path(pmix_info_path_pkgdatadir, pmix_pinstall_dirs.pmixdatadir);
379 pmix_info_show_path(pmix_info_path_pkglibdir, pmix_pinstall_dirs.pmixlibdir);
380 pmix_info_show_path(pmix_info_path_pkgincludedir, pmix_pinstall_dirs.pmixincludedir);
381 } else {
382 count = pmix_cmd_line_get_ninsts(cmd_line, "path");
383 for (i = 0; i < count; ++i) {
384 scope = pmix_cmd_line_get_param(cmd_line, "path", i, 0);
385
386 if (0 == strcmp(pmix_info_path_prefix, scope)) {
387 pmix_info_show_path(pmix_info_path_prefix, pmix_pinstall_dirs.prefix);
388 } else if (0 == strcmp(pmix_info_path_bindir, scope)) {
389 pmix_info_show_path(pmix_info_path_bindir, pmix_pinstall_dirs.bindir);
390 } else if (0 == strcmp(pmix_info_path_libdir, scope)) {
391 pmix_info_show_path(pmix_info_path_libdir, pmix_pinstall_dirs.libdir);
392 } else if (0 == strcmp(pmix_info_path_incdir, scope)) {
393 pmix_info_show_path(pmix_info_path_incdir, pmix_pinstall_dirs.includedir);
394 } else if (0 == strcmp(pmix_info_path_mandir, scope)) {
395 pmix_info_show_path(pmix_info_path_mandir, pmix_pinstall_dirs.mandir);
396 } else if (0 == strcmp(pmix_info_path_pkglibdir, scope)) {
397 pmix_info_show_path(pmix_info_path_pkglibdir, pmix_pinstall_dirs.pmixlibdir);
398 } else if (0 == strcmp(pmix_info_path_sysconfdir, scope)) {
399 pmix_info_show_path(pmix_info_path_sysconfdir, pmix_pinstall_dirs.sysconfdir);
400 } else if (0 == strcmp(pmix_info_path_exec_prefix, scope)) {
401 pmix_info_show_path(pmix_info_path_exec_prefix, pmix_pinstall_dirs.exec_prefix);
402 } else if (0 == strcmp(pmix_info_path_sbindir, scope)) {
403 pmix_info_show_path(pmix_info_path_sbindir, pmix_pinstall_dirs.sbindir);
404 } else if (0 == strcmp(pmix_info_path_libexecdir, scope)) {
405 pmix_info_show_path(pmix_info_path_libexecdir, pmix_pinstall_dirs.libexecdir);
406 } else if (0 == strcmp(pmix_info_path_datarootdir, scope)) {
407 pmix_info_show_path(pmix_info_path_datarootdir, pmix_pinstall_dirs.datarootdir);
408 } else if (0 == strcmp(pmix_info_path_datadir, scope)) {
409 pmix_info_show_path(pmix_info_path_datadir, pmix_pinstall_dirs.datadir);
410 } else if (0 == strcmp(pmix_info_path_sharedstatedir, scope)) {
411 pmix_info_show_path(pmix_info_path_sharedstatedir, pmix_pinstall_dirs.sharedstatedir);
412 } else if (0 == strcmp(pmix_info_path_localstatedir, scope)) {
413 pmix_info_show_path(pmix_info_path_localstatedir, pmix_pinstall_dirs.localstatedir);
414 } else if (0 == strcmp(pmix_info_path_infodir, scope)) {
415 pmix_info_show_path(pmix_info_path_infodir, pmix_pinstall_dirs.infodir);
416 } else if (0 == strcmp(pmix_info_path_pkgdatadir, scope)) {
417 pmix_info_show_path(pmix_info_path_pkgdatadir, pmix_pinstall_dirs.pmixdatadir);
418 } else if (0 == strcmp(pmix_info_path_pkgincludedir, scope)) {
419 pmix_info_show_path(pmix_info_path_pkgincludedir, pmix_pinstall_dirs.pmixincludedir);
420 } else {
421 char *usage = pmix_cmd_line_get_usage_msg(cmd_line);
422 pmix_show_help("help-pmix_info.txt", "usage", true, usage);
423 free(usage);
424 exit(1);
425 }
426 }
427 }
428 }
429
pmix_info_do_params(bool want_all_in,bool want_internal,pmix_pointer_array_t * mca_types,pmix_pointer_array_t * component_map,pmix_cmd_line_t * pmix_info_cmd_line)430 void pmix_info_do_params(bool want_all_in, bool want_internal,
431 pmix_pointer_array_t *mca_types,
432 pmix_pointer_array_t *component_map,
433 pmix_cmd_line_t *pmix_info_cmd_line)
434 {
435 pmix_mca_base_var_info_lvl_t max_level = PMIX_INFO_LVL_1;
436 int count;
437 char *type, *component, *str;
438 bool found;
439 int i;
440 bool want_all = false;
441 char *p;
442
443 if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "param")) {
444 p = "param";
445 } else if (pmix_cmd_line_is_taken(pmix_info_cmd_line, "params")) {
446 p = "params";
447 } else {
448 p = "foo"; /* should never happen, but protect against segfault */
449 }
450
451 if (NULL != (str = pmix_cmd_line_get_param (pmix_info_cmd_line, "level", 0, 0))) {
452 char *tmp;
453
454 errno = 0;
455 max_level = strtol (str, &tmp, 10) + PMIX_INFO_LVL_1 - 1;
456 if (0 != errno || '\0' != tmp[0] || max_level < PMIX_INFO_LVL_1 || max_level > PMIX_INFO_LVL_9) {
457 char *usage = pmix_cmd_line_get_usage_msg(pmix_info_cmd_line);
458 pmix_show_help("help-pmix_info.txt", "invalid-level", true, str);
459 free(usage);
460 exit(1);
461 }
462 } else if (want_all_in) {
463 /* if not specified default to level 9 if all components are requested */
464 max_level = PMIX_INFO_LVL_9;
465 }
466
467 if (want_all_in) {
468 want_all = true;
469 } else {
470 /* See if the special param "all" was given to --param; that
471 * supercedes any individual type
472 */
473 count = pmix_cmd_line_get_ninsts(pmix_info_cmd_line, p);
474 for (i = 0; i < count; ++i) {
475 type = pmix_cmd_line_get_param(pmix_info_cmd_line, p, (int)i, 0);
476 if (0 == strcmp(pmix_info_type_all, type)) {
477 want_all = true;
478 break;
479 }
480 }
481 }
482
483 /* Show the params */
484
485 if (want_all) {
486 pmix_info_show_component_version(mca_types, component_map, pmix_info_type_all,
487 pmix_info_component_all, pmix_info_ver_full,
488 pmix_info_ver_all);
489 for (i = 0; i < mca_types->size; ++i) {
490 if (NULL == (type = (char *)pmix_pointer_array_get_item(mca_types, i))) {
491 continue;
492 }
493 pmix_info_show_mca_params(type, pmix_info_component_all, max_level, want_internal);
494 }
495 } else {
496 for (i = 0; i < count; ++i) {
497 type = pmix_cmd_line_get_param(pmix_info_cmd_line, p, (int)i, 0);
498 component = pmix_cmd_line_get_param(pmix_info_cmd_line, p, (int)i, 1);
499
500 for (found = false, i = 0; i < mca_types->size; ++i) {
501 if (NULL == (str = (char *)pmix_pointer_array_get_item(mca_types, i))) {
502 continue;
503 }
504 if (0 == strcmp(str, type)) {
505 found = true;
506 break;
507 }
508 }
509
510 if (!found) {
511 char *usage = pmix_cmd_line_get_usage_msg(pmix_info_cmd_line);
512 pmix_show_help("help-pmix_info.txt", "not-found", true, type);
513 free(usage);
514 exit(1);
515 }
516
517 pmix_info_show_component_version(mca_types, component_map, type,
518 component, pmix_info_ver_full,
519 pmix_info_ver_all);
520 pmix_info_show_mca_params(type, component, max_level, want_internal);
521 }
522 }
523 }
524
pmix_info_err_params(pmix_pointer_array_t * component_map)525 void pmix_info_err_params(pmix_pointer_array_t *component_map)
526 {
527 pmix_info_component_map_t *map=NULL, *mptr;
528 int i;
529
530 /* all we want to do is display the LAST entry in the
531 * component_map array as this is the one that generated the error
532 */
533 for (i=0; i < component_map->size; i++) {
534 if (NULL == (mptr = (pmix_info_component_map_t*)pmix_pointer_array_get_item(component_map, i))) {
535 continue;
536 }
537 map = mptr;
538 }
539 if (NULL == map) {
540 fprintf(stderr, "pmix_info_err_params: map not found\n");
541 return;
542 }
543 pmix_info_show_mca_params(map->type, pmix_info_component_all, PMIX_INFO_LVL_9, true);
544 fprintf(stderr, "\n");
545 return;
546 }
547
pmix_info_do_type(pmix_cmd_line_t * pmix_info_cmd_line)548 void pmix_info_do_type(pmix_cmd_line_t *pmix_info_cmd_line)
549 {
550 pmix_mca_base_var_info_lvl_t max_level = PMIX_INFO_LVL_1;
551 int count;
552 char *type, *str;
553 int i, j, k, len, ret;
554 char *p;
555 const pmix_mca_base_var_t *var;
556 char** strings, *message;
557 const pmix_mca_base_var_group_t *group;
558 p = "type";
559
560 if (NULL != (str = pmix_cmd_line_get_param (pmix_info_cmd_line, "level", 0, 0))) {
561 char *tmp;
562
563 errno = 0;
564 max_level = strtol (str, &tmp, 10) + PMIX_INFO_LVL_1 - 1;
565 if (0 != errno || '\0' != tmp[0] || max_level < PMIX_INFO_LVL_1 || max_level > PMIX_INFO_LVL_9) {
566 char *usage = pmix_cmd_line_get_usage_msg(pmix_info_cmd_line);
567 pmix_show_help("help-pmix_info.txt", "invalid-level", true, str);
568 free(usage);
569 exit(1);
570 }
571 }
572
573 count = pmix_cmd_line_get_ninsts(pmix_info_cmd_line, p);
574 len = pmix_mca_base_var_get_count ();
575
576 for (k = 0; k < count; ++k) {
577 type = pmix_cmd_line_get_param(pmix_info_cmd_line, p, k, 0);
578 for (i = 0; i < len; ++i) {
579 ret = pmix_mca_base_var_get (i, &var);
580 if (PMIX_SUCCESS != ret) {
581 continue;
582 }
583 if (0 == strcmp(type, pmix_var_type_names[var->mbv_type]) && (var->mbv_info_lvl <= max_level)) {
584 ret = pmix_mca_base_var_dump(var->mbv_index, &strings, !pmix_info_pretty ? PMIX_MCA_BASE_VAR_DUMP_PARSABLE : PMIX_MCA_BASE_VAR_DUMP_READABLE);
585 if (PMIX_SUCCESS != ret) {
586 continue;
587 }
588 (void) pmix_mca_base_var_group_get(var->mbv_group_index, &group);
589 for (j = 0 ; strings[j] ; ++j) {
590 if (0 == j && pmix_info_pretty) {
591 if (0 > asprintf (&message, "MCA %s", group->group_framework)) {
592 continue;
593 }
594 pmix_info_out(message, message, strings[j]);
595 free(message);
596 } else {
597 pmix_info_out("", "", strings[j]);
598 }
599 free(strings[j]);
600 }
601 free(strings);
602 }
603 }
604 }
605 }
606
pmix_info_show_mca_group_params(const pmix_mca_base_var_group_t * group,pmix_mca_base_var_info_lvl_t max_level,bool want_internal)607 static void pmix_info_show_mca_group_params(const pmix_mca_base_var_group_t *group, pmix_mca_base_var_info_lvl_t max_level, bool want_internal)
608 {
609 const int *variables, *groups;
610 const char *group_component;
611 const pmix_mca_base_var_t *var;
612 char **strings, *message;
613 bool requested = true;
614 int ret, i, j, count;
615
616 variables = PMIX_VALUE_ARRAY_GET_BASE(&group->group_vars, const int);
617 count = pmix_value_array_get_size((pmix_value_array_t *)&group->group_vars);
618
619 /* the default component name is "base". depending on how the
620 * group was registered the group may or not have this set. */
621 group_component = group->group_component ? group->group_component : "base";
622
623 /* check if this group may be disabled due to a selection variable */
624 if (0 != strcmp (group_component, "base")) {
625 int var_id;
626
627 /* read the selection parameter */
628 var_id = pmix_mca_base_var_find (group->group_project, group->group_framework, NULL, NULL);
629 if (0 <= var_id) {
630 const pmix_mca_base_var_storage_t *value=NULL;
631 char **requested_components;
632 bool include_mode;
633
634 pmix_mca_base_var_get_value (var_id, &value, NULL, NULL);
635 if (NULL != value && NULL != value->stringval && '\0' != value->stringval[0]) {
636 pmix_mca_base_component_parse_requested (value->stringval, &include_mode, &requested_components);
637
638 for (i = 0, requested = !include_mode ; requested_components[i] ; ++i) {
639 if (0 == strcmp (requested_components[i], group_component)) {
640 requested = include_mode;
641 break;
642 }
643 }
644
645 pmix_argv_free (requested_components);
646 }
647 }
648 }
649
650 const pmix_mca_base_var_group_t *curr_group = NULL;
651 char *component_msg = NULL;
652 if (0 > asprintf(&component_msg, " %s", group_component)) {
653 return;
654 }
655
656 for (i = 0 ; i < count ; ++i) {
657 ret = pmix_mca_base_var_get(variables[i], &var);
658 if (PMIX_SUCCESS != ret || ((var->mbv_flags & PMIX_MCA_BASE_VAR_FLAG_INTERNAL) &&
659 !want_internal) ||
660 max_level < var->mbv_info_lvl) {
661 continue;
662 }
663
664 if (pmix_info_pretty && curr_group != group) {
665 if (0 > asprintf(&message, "MCA%s %s%s", requested ? "" : " (-)",
666 group->group_framework,
667 component_msg ? component_msg : "")) {
668 continue;
669 }
670 pmix_info_out(message, message, "---------------------------------------------------");
671 free(message);
672 curr_group = group;
673 }
674
675 ret = pmix_mca_base_var_dump(variables[i], &strings, !pmix_info_pretty ? PMIX_MCA_BASE_VAR_DUMP_PARSABLE : PMIX_MCA_BASE_VAR_DUMP_READABLE);
676 if (PMIX_SUCCESS != ret) {
677 continue;
678 }
679
680 for (j = 0 ; strings[j] ; ++j) {
681 if (0 == j && pmix_info_pretty) {
682 if (0 > asprintf (&message, "MCA%s %s%s", requested ? "" : " (-)",
683 group->group_framework,
684 component_msg ? component_msg : "")) {
685 continue;
686 }
687 pmix_info_out(message, message, strings[j]);
688 free(message);
689 } else {
690 pmix_info_out("", "", strings[j]);
691 }
692 free(strings[j]);
693 }
694 if (!pmix_info_pretty) {
695 /* generate an entry indicating whether this variable is disabled or not. if the
696 * format in mca_base_var/pvar.c changes this needs to be changed as well */
697 if (0 > asprintf (&message, "mca:%s:%s:param:%s:disabled:%s", group->group_framework,
698 group_component, var->mbv_full_name, requested ? "false" : "true")) {
699 continue;
700 }
701 pmix_info_out("", "", message);
702 free (message);
703 }
704 free(strings);
705 }
706
707 groups = PMIX_VALUE_ARRAY_GET_BASE(&group->group_subgroups, const int);
708 count = pmix_value_array_get_size((pmix_value_array_t *)&group->group_subgroups);
709
710 for (i = 0 ; i < count ; ++i) {
711 ret = pmix_mca_base_var_group_get(groups[i], &group);
712 if (PMIX_SUCCESS != ret) {
713 continue;
714 }
715 pmix_info_show_mca_group_params(group, max_level, want_internal);
716 }
717 free(component_msg);
718 }
719
pmix_info_show_mca_params(const char * type,const char * component,pmix_mca_base_var_info_lvl_t max_level,bool want_internal)720 void pmix_info_show_mca_params(const char *type, const char *component,
721 pmix_mca_base_var_info_lvl_t max_level, bool want_internal)
722 {
723 const pmix_mca_base_var_group_t *group;
724 int ret;
725
726 if (0 == strcmp (component, "all")) {
727 ret = pmix_mca_base_var_group_find("*", type, NULL);
728 if (0 > ret) {
729 return;
730 }
731
732 (void) pmix_mca_base_var_group_get(ret, &group);
733
734 pmix_info_show_mca_group_params(group, max_level, want_internal);
735 } else {
736 ret = pmix_mca_base_var_group_find("*", type, component);
737 if (0 > ret) {
738 return;
739 }
740
741 (void) pmix_mca_base_var_group_get(ret, &group);
742 pmix_info_show_mca_group_params(group, max_level, want_internal);
743 }
744 }
745
746
747
pmix_info_do_arch()748 void pmix_info_do_arch()
749 {
750 pmix_info_out("Configured architecture", "config:arch", PMIX_ARCH);
751 }
752
753
pmix_info_do_hostname()754 void pmix_info_do_hostname()
755 {
756 pmix_info_out("Configure host", "config:host", PMIX_CONFIGURE_HOST);
757 }
758
759
escape_quotes(const char * value)760 static char *escape_quotes(const char *value)
761 {
762 const char *src;
763 int num_quotes = 0;
764 for (src = value; src != NULL && *src != '\0'; ++src) {
765 if ('"' == *src) {
766 ++num_quotes;
767 }
768 }
769
770 // If there are no quotes in the string, there's nothing to do
771 if (0 == num_quotes) {
772 return NULL;
773 }
774
775 // If we have quotes, make a new string. Copy over the old
776 // string, escaping the quotes along the way. This is simple and
777 // clear to read; it's not particularly efficient (performance is
778 // definitely not important here).
779 char *quoted_value;
780 quoted_value = calloc(1, strlen(value) + num_quotes + 1);
781 if (NULL == quoted_value) {
782 return NULL;
783 }
784
785 char *dest;
786 for (src = value, dest = quoted_value; *src != '\0'; ++src, ++dest) {
787 if ('"' == *src) {
788 *dest++ = '\\';
789 }
790 *dest = *src;
791 }
792
793 return quoted_value;
794 }
795
796
797 /*
798 * Private variables - set some reasonable screen size defaults
799 */
800
801 static int centerpoint = 24;
802 static int screen_width = 78;
803
804 /*
805 * Prints the passed message in a pretty or parsable format.
806 */
pmix_info_out(const char * pretty_message,const char * plain_message,const char * value)807 void pmix_info_out(const char *pretty_message, const char *plain_message, const char *value)
808 {
809 size_t len, max_value_width, value_offset;
810 char *spaces = NULL;
811 char *filler = NULL;
812 char *pos, *v, savev, *v_to_free;
813
814 #ifdef HAVE_ISATTY
815 /* If we have isatty(), if this is not a tty, then disable
816 * wrapping for grep-friendly behavior
817 */
818 if (0 == isatty(STDOUT_FILENO)) {
819 screen_width = INT_MAX;
820 }
821 #endif
822
823 #ifdef TIOCGWINSZ
824 if (screen_width < INT_MAX) {
825 struct winsize size;
826 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char*) &size) >= 0) {
827 screen_width = size.ws_col;
828 }
829 }
830 #endif
831
832 /* Sanity check (allow NULL to mean "") */
833 if (NULL == value) {
834 value = "";
835 }
836
837 /* Strip leading and trailing whitespace from the string value */
838 value_offset = strspn(value, " ");
839
840 v = v_to_free = strdup(value + value_offset);
841 len = strlen(v);
842
843 if (len > 0) {
844 while (len > 0 && isspace(v[len-1])) len--;
845 v[len] = '\0';
846 }
847
848 if (pmix_info_pretty && NULL != pretty_message) {
849 if (centerpoint > (int)strlen(pretty_message)) {
850 if (0 > asprintf(&spaces, "%*s", centerpoint -
851 (int)strlen(pretty_message), " ")) {
852 if (NULL != v_to_free) {
853 free(v_to_free);
854 }
855 return;
856 }
857 } else {
858 spaces = strdup("");
859 #if PMIX_ENABLE_DEBUG
860 if (centerpoint < (int)strlen(pretty_message)) {
861 pmix_show_help("help-pmix_info.txt",
862 "developer warning: field too long", false,
863 pretty_message, centerpoint);
864 }
865 #endif
866 }
867 max_value_width = screen_width - strlen(spaces) - strlen(pretty_message) - 2;
868 if (0 < strlen(pretty_message)) {
869 if (0 > asprintf(&filler, "%s%s: ", spaces, pretty_message)) {
870 if (NULL != v_to_free) {
871 free(v_to_free);
872 }
873 return;
874 }
875 } else {
876 if (0 > asprintf(&filler, "%s ", spaces)) {
877 if (NULL != v_to_free) {
878 free(v_to_free);
879 }
880 return;
881 }
882 }
883 free(spaces);
884 spaces = NULL;
885
886 while (true) {
887 if (strlen(v) < max_value_width) {
888 printf("%s%s\n", filler, v);
889 break;
890 } else {
891 if (0 > asprintf(&spaces, "%*s", centerpoint + 2, " ")) {
892 if (NULL != v_to_free) {
893 free(v_to_free);
894 }
895 return;
896 }
897
898 /* Work backwards to find the first space before
899 * max_value_width
900 */
901 savev = v[max_value_width];
902 v[max_value_width] = '\0';
903 pos = (char*)strrchr(v, (int)' ');
904 v[max_value_width] = savev;
905 if (NULL == pos) {
906 /* No space found < max_value_width. Look for the first
907 * space after max_value_width.
908 */
909 pos = strchr(&v[max_value_width], ' ');
910
911 if (NULL == pos) {
912
913 /* There's just no spaces. So just print it and be done. */
914
915 printf("%s%s\n", filler, v);
916 break;
917 } else {
918 *pos = '\0';
919 printf("%s%s\n", filler, v);
920 v = pos + 1;
921 }
922 } else {
923 *pos = '\0';
924 printf("%s%s\n", filler, v);
925 v = pos + 1;
926 }
927
928 /* Reset for the next iteration */
929 free(filler);
930 filler = strdup(spaces);
931 free(spaces);
932 spaces = NULL;
933 }
934 }
935 if (NULL != filler) {
936 free(filler);
937 }
938 if (NULL != spaces) {
939 free(spaces);
940 }
941 } else {
942 if (NULL != plain_message && 0 < strlen(plain_message)) {
943 // Escape any double quotes in the value.
944 char *quoted_value;
945 quoted_value = escape_quotes(value);
946 if (NULL != quoted_value) {
947 value = quoted_value;
948 }
949
950 char *colon = strchr(value, ':');
951 if (NULL != colon) {
952 printf("%s:\"%s\"\n", plain_message, value);
953 } else {
954 printf("%s:%s\n", plain_message, value);
955 }
956
957 if (NULL != quoted_value) {
958 free(quoted_value);
959 }
960 } else {
961 printf("%s\n", value);
962 }
963 }
964 if (NULL != v_to_free) {
965 free(v_to_free);
966 }
967 }
968
969 /*
970 * Prints the passed integer in a pretty or parsable format.
971 */
pmix_info_out_int(const char * pretty_message,const char * plain_message,int value)972 void pmix_info_out_int(const char *pretty_message,
973 const char *plain_message,
974 int value)
975 {
976 char *valstr;
977
978 if (0 > asprintf(&valstr, "%d", (int)value)) {
979 return;
980 }
981 pmix_info_out(pretty_message, plain_message, valstr);
982 free(valstr);
983 }
984
985 /*
986 * Show all the components of a specific type/component combo (component may be
987 * a wildcard)
988 */
pmix_info_show_component_version(pmix_pointer_array_t * mca_types,pmix_pointer_array_t * component_map,const char * type_name,const char * component_name,const char * scope,const char * ver_type)989 void pmix_info_show_component_version(pmix_pointer_array_t *mca_types,
990 pmix_pointer_array_t *component_map,
991 const char *type_name,
992 const char *component_name,
993 const char *scope, const char *ver_type)
994 {
995 bool want_all_components = false;
996 bool want_all_types = false;
997 bool found;
998 pmix_mca_base_component_list_item_t *cli;
999 pmix_mca_base_failed_component_t *cli_failed;
1000 int j;
1001 char *pos;
1002 pmix_info_component_map_t *map;
1003
1004 /* see if all components wanted */
1005 if (0 == strcmp(pmix_info_component_all, component_name)) {
1006 want_all_components = true;
1007 }
1008
1009 /* see if all types wanted */
1010 if (0 != strcmp(pmix_info_type_all, type_name)) {
1011 /* Check to see if the type is valid */
1012
1013 for (found = false, j = 0; j < mca_types->size; ++j) {
1014 if (NULL == (pos = (char*)pmix_pointer_array_get_item(mca_types, j))) {
1015 continue;
1016 }
1017 if (0 == strcmp(pos, type_name)) {
1018 found = true;
1019 break;
1020 }
1021 }
1022
1023 if (!found) {
1024 return;
1025 }
1026 } else {
1027 want_all_types = true;
1028 }
1029
1030 /* Now that we have a valid type, find the right components */
1031 for (j=0; j < component_map->size; j++) {
1032 if (NULL == (map = (pmix_info_component_map_t*)pmix_pointer_array_get_item(component_map, j))) {
1033 continue;
1034 }
1035 if ((want_all_types || 0 == strcmp(type_name, map->type)) && map->components) {
1036 /* found it! */
1037 PMIX_LIST_FOREACH(cli, map->components, pmix_mca_base_component_list_item_t) {
1038 const pmix_mca_base_component_t *component = cli->cli_component;
1039 if (want_all_components ||
1040 0 == strcmp(component->pmix_mca_component_name, component_name)) {
1041 pmix_info_show_mca_version(component, scope, ver_type);
1042 }
1043 }
1044
1045 /* found it! */
1046 PMIX_LIST_FOREACH(cli_failed, map->failed_components, pmix_mca_base_failed_component_t) {
1047 pmix_mca_base_component_repository_item_t *ri = cli_failed->comp;
1048 if (want_all_components ||
1049 0 == strcmp(component_name, ri->ri_name) ) {
1050 pmix_info_show_failed_component(ri, cli_failed->error_msg);
1051 }
1052 }
1053
1054 if (!want_all_types) {
1055 break;
1056 }
1057 }
1058 }
1059 }
1060
1061
pmix_info_show_failed_component(const pmix_mca_base_component_repository_item_t * ri,const char * error_msg)1062 static void pmix_info_show_failed_component(const pmix_mca_base_component_repository_item_t* ri,
1063 const char *error_msg)
1064 {
1065 char *message, *content;
1066
1067 if (pmix_info_pretty) {
1068 if (0 > asprintf(&message, "MCA %s", ri->ri_type)) {
1069 return;
1070 }
1071 if (0 > asprintf(&content, "%s (failed to load) %s", ri->ri_name, error_msg)) {
1072 free(message);
1073 return;
1074 }
1075
1076 pmix_info_out(message, NULL, content);
1077
1078 free(message);
1079 free(content);
1080 } else {
1081 if (0 > asprintf(&message, "mca:%s:%s:failed", ri->ri_type, ri->ri_name)) {
1082 return;
1083 }
1084 if (0 > asprintf(&content, "%s", error_msg)) {
1085 free(message);
1086 return;
1087 }
1088
1089 pmix_info_out(NULL, message, content);
1090
1091 free(message);
1092 free(content);
1093 }
1094 }
1095
1096 /*
1097 * Given a component, display its relevant version(s)
1098 */
pmix_info_show_mca_version(const pmix_mca_base_component_t * component,const char * scope,const char * ver_type)1099 void pmix_info_show_mca_version(const pmix_mca_base_component_t* component,
1100 const char *scope, const char *ver_type)
1101 {
1102 bool printed;
1103 bool want_mca = false;
1104 bool want_type = false;
1105 bool want_component = false;
1106 char *message = NULL, *content = NULL;
1107 char *mca_version;
1108 char *api_version;
1109 char *component_version;
1110 char *tmp;
1111
1112 if (0 == strcmp(ver_type, pmix_info_ver_all) ||
1113 0 == strcmp(ver_type, pmix_info_ver_mca)) {
1114 want_mca = true;
1115 }
1116
1117 if (0 == strcmp(ver_type, pmix_info_ver_all) ||
1118 0 == strcmp(ver_type, pmix_info_ver_type)) {
1119 want_type = true;
1120 }
1121
1122 if (0 == strcmp(ver_type, pmix_info_ver_all) ||
1123 0 == strcmp(ver_type, pmix_info_ver_component)) {
1124 want_component = true;
1125 }
1126
1127 mca_version = pmix_info_make_version_str(scope, component->pmix_mca_major_version,
1128 component->pmix_mca_minor_version,
1129 component->pmix_mca_release_version, "",
1130 "");
1131 api_version = pmix_info_make_version_str(scope, component->pmix_mca_type_major_version,
1132 component->pmix_mca_type_minor_version,
1133 component->pmix_mca_type_release_version, "",
1134 "");
1135 component_version = pmix_info_make_version_str(scope, component->pmix_mca_component_major_version,
1136 component->pmix_mca_component_minor_version,
1137 component->pmix_mca_component_release_version,
1138 "", "");
1139 if (pmix_info_pretty) {
1140 if (0 > asprintf(&message, "MCA %s", component->pmix_mca_type_name)) {
1141 goto exit;
1142 }
1143 printed = false;
1144 if (0 > asprintf(&content, "%s (", component->pmix_mca_component_name)) {
1145 goto exit;
1146 }
1147
1148 if (want_mca) {
1149 if (0 > asprintf(&tmp, "%sMCA v%s", content, mca_version)) {
1150 goto exit;
1151 }
1152 content = tmp;
1153 printed = true;
1154 }
1155
1156 if (want_type) {
1157 if (printed) {
1158 if (0 > asprintf(&tmp, "%s, ", content)) {
1159 goto exit;
1160 }
1161 free(content);
1162 content = tmp;
1163 }
1164 if (0 > asprintf(&tmp, "%sAPI v%s", content, api_version)) {
1165 goto exit;
1166 }
1167 free(content);
1168 content = tmp;
1169 printed = true;
1170 }
1171
1172 if (want_component) {
1173 if (printed) {
1174 if (0 > asprintf(&tmp, "%s, ", content)) {
1175 goto exit;
1176 }
1177 free(content);
1178 content = tmp;
1179 }
1180 if (0 > asprintf(&tmp, "%sComponent v%s", content, component_version)) {
1181 goto exit;
1182 }
1183 free(content);
1184 content = tmp;
1185 printed = true;
1186 }
1187 if (NULL != content) {
1188 if (0 > asprintf(&tmp, "%s)", content)) {
1189 goto exit;
1190 }
1191 } else {
1192 tmp = NULL;
1193 }
1194
1195 pmix_info_out(message, NULL, tmp);
1196 if (NULL != tmp) {
1197 free(tmp);
1198 }
1199
1200 } else {
1201 if (0 > asprintf(&message, "mca:%s:%s:version", component->pmix_mca_type_name, component->pmix_mca_component_name)) {
1202 goto exit;
1203 }
1204 if (want_mca) {
1205 if (0 > asprintf(&tmp, "mca:%s", mca_version)) {
1206 goto exit;
1207 }
1208 pmix_info_out(NULL, message, tmp);
1209 free(tmp);
1210 }
1211 if (want_type) {
1212 if (0 > asprintf(&tmp, "api:%s", api_version)) {
1213 goto exit;
1214 }
1215 pmix_info_out(NULL, message, tmp);
1216 free(tmp);
1217 }
1218 if (want_component) {
1219 if (0 > asprintf(&tmp, "component:%s", component_version)) {
1220 goto exit;
1221 }
1222 pmix_info_out(NULL, message, tmp);
1223 free(tmp);
1224 }
1225 }
1226
1227 exit:
1228 if (NULL != mca_version) {
1229 free(mca_version);
1230 }
1231 if (NULL != api_version) {
1232 free(api_version);
1233 }
1234 if (NULL != component_version) {
1235 free(component_version);
1236 }
1237 if (NULL != message) {
1238 free(message);
1239 }
1240 if (NULL != content) {
1241 free(content);
1242 }
1243 }
1244
1245
pmix_info_make_version_str(const char * scope,int major,int minor,int release,const char * greek,const char * repo)1246 char *pmix_info_make_version_str(const char *scope,
1247 int major, int minor, int release,
1248 const char *greek,
1249 const char *repo)
1250 {
1251 char *str = NULL, *tmp;
1252 char temp[BUFSIZ];
1253
1254 temp[BUFSIZ - 1] = '\0';
1255 if (0 == strcmp(scope, pmix_info_ver_full) ||
1256 0 == strcmp(scope, pmix_info_ver_all)) {
1257 snprintf(temp, BUFSIZ - 1, "%d.%d.%d", major, minor, release);
1258 str = strdup(temp);
1259 if (NULL != greek) {
1260 if (0 > asprintf(&tmp, "%s%s", str, greek)) {
1261 free(str);
1262 return NULL;
1263 }
1264 free(str);
1265 str = tmp;
1266 }
1267 } else if (0 == strcmp(scope, pmix_info_ver_major)) {
1268 snprintf(temp, BUFSIZ - 1, "%d", major);
1269 } else if (0 == strcmp(scope, pmix_info_ver_minor)) {
1270 snprintf(temp, BUFSIZ - 1, "%d", minor);
1271 } else if (0 == strcmp(scope, pmix_info_ver_release)) {
1272 snprintf(temp, BUFSIZ - 1, "%d", release);
1273 } else if (0 == strcmp(scope, pmix_info_ver_greek)) {
1274 str = strdup(greek);
1275 } else if (0 == strcmp(scope, pmix_info_ver_repo)) {
1276 str = strdup(repo);
1277 }
1278
1279 if (NULL == str) {
1280 str = strdup(temp);
1281 }
1282
1283 return str;
1284 }
1285
pmix_info_show_pmix_version(const char * scope)1286 void pmix_info_show_pmix_version(const char *scope)
1287 {
1288 char *tmp, *tmp2;
1289
1290 if (0 > asprintf(&tmp, "%s:version:full", pmix_info_type_pmix)) {
1291 return;
1292 }
1293 tmp2 = pmix_info_make_version_str(scope,
1294 PMIX_MAJOR_VERSION, PMIX_MINOR_VERSION,
1295 PMIX_RELEASE_VERSION,
1296 PMIX_GREEK_VERSION,
1297 PMIX_REPO_REV);
1298 pmix_info_out("PMIX", tmp, tmp2);
1299 free(tmp);
1300 free(tmp2);
1301 if (0 > asprintf(&tmp, "%s:version:repo", pmix_info_type_pmix)) {
1302 return;
1303 }
1304 pmix_info_out("PMIX repo revision", tmp, PMIX_REPO_REV);
1305 free(tmp);
1306 if (0 > asprintf(&tmp, "%s:version:release_date", pmix_info_type_pmix)) {
1307 return;
1308 }
1309 pmix_info_out("PMIX release date", tmp, PMIX_RELEASE_DATE);
1310 free(tmp);
1311 }
1312
1313 /*
1314 * do_config
1315 * Accepts:
1316 * - want_all: boolean flag; TRUE -> display all options
1317 * FALSE -> display selected options
1318 *
1319 * This function displays all the options with which the current
1320 * installation of pmix was configured. There are many options here
1321 * that are carried forward from OMPI-7 and are not mca parameters
1322 * in OMPI-10. I have to dig through the invalid options and replace
1323 * them with OMPI-10 options.
1324 */
pmix_info_do_config(bool want_all)1325 void pmix_info_do_config(bool want_all)
1326 {
1327 char *debug;
1328 char *have_dl;
1329 char *symbol_visibility;
1330
1331 /* setup the strings that don't require allocations*/
1332 debug = PMIX_ENABLE_DEBUG ? "yes" : "no";
1333 have_dl = PMIX_HAVE_PDL_SUPPORT ? "yes" : "no";
1334 symbol_visibility = PMIX_HAVE_VISIBILITY ? "yes" : "no";
1335
1336 /* output values */
1337 pmix_info_out("Configured by", "config:user", PMIX_CONFIGURE_USER);
1338 pmix_info_out("Configured on", "config:timestamp", PMIX_CONFIGURE_DATE);
1339 pmix_info_out("Configure host", "config:host", PMIX_CONFIGURE_HOST);
1340 pmix_info_out("Configure command line", "config:cli", PMIX_CONFIGURE_CLI);
1341
1342 pmix_info_out("Built by", "build:user", PMIX_BUILD_USER);
1343 pmix_info_out("Built on", "build:timestamp", PMIX_BUILD_DATE);
1344 pmix_info_out("Built host", "build:host", PMIX_BUILD_HOST);
1345
1346 pmix_info_out("C compiler", "compiler:c:command", PMIX_CC);
1347 pmix_info_out("C compiler absolute", "compiler:c:absolute", PMIX_CC_ABSOLUTE);
1348 pmix_info_out("C compiler family name", "compiler:c:familyname", _STRINGIFY(PMIX_BUILD_PLATFORM_COMPILER_FAMILYNAME));
1349 pmix_info_out("C compiler version", "compiler:c:version", _STRINGIFY(PMIX_BUILD_PLATFORM_COMPILER_VERSION_STR));
1350
1351 if (want_all) {
1352 pmix_info_out_int("C char size", "compiler:c:sizeof:char", sizeof(char));
1353 pmix_info_out_int("C bool size", "compiler:c:sizeof:bool", sizeof(bool));
1354 pmix_info_out_int("C short size", "compiler:c:sizeof:short", sizeof(short));
1355 pmix_info_out_int("C int size", "compiler:c:sizeof:int", sizeof(int));
1356 pmix_info_out_int("C long size", "compiler:c:sizeof:long", sizeof(long));
1357 pmix_info_out_int("C float size", "compiler:c:sizeof:float", sizeof(float));
1358 pmix_info_out_int("C double size", "compiler:c:sizeof:double", sizeof(double));
1359 pmix_info_out_int("C pointer size", "compiler:c:sizeof:pointer", sizeof(void *));
1360 pmix_info_out_int("C char align", "compiler:c:align:char", PMIX_ALIGNMENT_CHAR);
1361 pmix_info_out("C bool align", "compiler:c:align:bool", "skipped");
1362 pmix_info_out_int("C int align", "compiler:c:align:int", PMIX_ALIGNMENT_INT);
1363 pmix_info_out_int("C float align", "compiler:c:align:float", PMIX_ALIGNMENT_FLOAT);
1364 pmix_info_out_int("C double align", "compiler:c:align:double", PMIX_ALIGNMENT_DOUBLE);
1365 }
1366
1367 if (want_all) {
1368 pmix_info_out("Build CFLAGS", "option:build:cflags", PMIX_BUILD_CFLAGS);
1369 pmix_info_out("Build LDFLAGS", "option:build:ldflags", PMIX_BUILD_LDFLAGS);
1370 pmix_info_out("Build LIBS", "option:build:libs", PMIX_BUILD_LIBS);
1371 }
1372
1373 pmix_info_out("Internal debug support", "option:debug", debug);
1374 pmix_info_out("dl support", "option:dlopen", have_dl);
1375 pmix_info_out("Symbol vis. support", "options:visibility", symbol_visibility);
1376 }
1377