File indexing completed on 2026-09-21 09:19:58
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifndef PMIX_CMD_LINE_H
0027 #define PMIX_CMD_LINE_H
0028
0029 #include "src/include/pmix_config.h"
0030
0031 #ifdef HAVE_UNISTD_H
0032 # include <unistd.h>
0033 #endif
0034 #include <ctype.h>
0035 #include <stdio.h>
0036 #include <string.h>
0037 #include <getopt.h>
0038
0039 #include "src/class/pmix_list.h"
0040 #include "src/class/pmix_object.h"
0041 #include "src/util/pmix_argv.h"
0042
0043 BEGIN_C_DECLS
0044
0045 typedef struct {
0046 pmix_list_item_t super;
0047 char *key;
0048 char **values;
0049 } pmix_cli_item_t;
0050 PMIX_CLASS_DECLARATION(pmix_cli_item_t);
0051
0052 typedef struct {
0053 pmix_object_t super;
0054 pmix_list_t instances;
0055 char **tail;
0056 } pmix_cli_result_t;
0057 PMIX_CLASS_DECLARATION(pmix_cli_result_t);
0058
0059 #define PMIX_CLI_RESULT_STATIC_INIT \
0060 { \
0061 .super = PMIX_OBJ_STATIC_INIT(pmix_object_t), \
0062 .instances = PMIX_LIST_STATIC_INIT, \
0063 .tail = NULL \
0064 }
0065
0066
0067 #define PMIX_ARG_REQD required_argument
0068 #define PMIX_ARG_NONE no_argument
0069 #define PMIX_ARG_OPTIONAL optional_argument
0070
0071
0072
0073 #define PMIX_CLI_SILENT true
0074 #define PMIX_CLI_WARN false
0075
0076
0077
0078
0079
0080
0081 #define PMIX_OPTION_DEFINE(n, a) \
0082 { \
0083 .name = (n), \
0084 .has_arg = (a), \
0085 .flag = NULL, \
0086 .val = 0 \
0087 }
0088
0089
0090
0091
0092
0093
0094 #define PMIX_OPTION_SHORT_DEFINE(n, a, c) \
0095 { \
0096 .name = (n), \
0097 .has_arg = (a), \
0098 .flag = NULL, \
0099 .val = (c) \
0100 }
0101
0102 #define PMIX_OPTION_END {0, 0, 0, 0}
0103
0104
0105
0106
0107 #define PMIX_CLI_HELP "help"
0108 #define PMIX_CLI_VERSION "version"
0109 #define PMIX_CLI_VERBOSE "verbose"
0110 #define PMIX_CLI_PMIXMCA "pmixmca"
0111 #define PMIX_CLI_PRETTY_PRINT "pretty-print"
0112 #define PMIX_CLI_PARSABLE "parsable"
0113 #define PMIX_CLI_PARSEABLE "parseable"
0114
0115
0116 #define PMIX_CLI_SYS_SERVER_FIRST "system-server-first"
0117 #define PMIX_CLI_SYSTEM_SERVER "system-server"
0118 #define PMIX_CLI_SYS_SERVER_ONLY "system-server-only"
0119 #define PMIX_CLI_DO_NOT_CONNECT "do-not-connect"
0120 #define PMIX_CLI_WAIT_TO_CONNECT "wait-to-connect"
0121 #define PMIX_CLI_NUM_CONNECT_RETRIES "num-connect-retries"
0122 #define PMIX_CLI_PID "pid"
0123 #define PMIX_CLI_NAMESPACE "namespace"
0124 #define PMIX_CLI_NSPACE "nspace"
0125 #define PMIX_CLI_URI "uri"
0126 #define PMIX_CLI_TIMEOUT "timeout"
0127 #define PMIX_CLI_TMPDIR "tmpdir"
0128 #define PMIX_CLI_CONNECTION_ORDER "connect-order"
0129 #define PMIX_CLI_SYS_CONTROLLER "system-controller"
0130
0131
0132 #define PMIX_CLI_REQ_ID "request-id"
0133 #define PMIX_CLI_QUEUE "queue"
0134 #define PMIX_CLI_RESOURCES "resources"
0135 #define PMIX_CLI_NODES "nodes"
0136 #define PMIX_CLI_IMAGE "image"
0137 #define PMIX_CLI_EXCLUDE "exclude"
0138 #define PMIX_CLI_WAIT_ALL_NODES "wait-all-nodes"
0139 #define PMIX_CLI_NODELIST "nodelist"
0140 #define PMIX_CLI_UID "uid"
0141 #define PMIX_CLI_GID "gid"
0142 #define PMIX_CLI_TIME "time"
0143 #define PMIX_CLI_SIGNAL "signal"
0144 #define PMIX_CLI_SHARE "share"
0145 #define PMIX_CLI_EXTEND "extend"
0146 #define PMIX_CLI_SHRINK "shrink"
0147 #define PMIX_CLI_NO_SHELL "no-shell"
0148 #define PMIX_CLI_BEGIN "begin"
0149 #define PMIX_CLI_IMMEDIATE "immediate"
0150 #define PMIX_CLI_DEPENDENCY "dependency"
0151 #define PMIX_CLI_DO_NOT_WAIT "do-not-wait"
0152
0153
0154 #define PMIX_CLI_PAUSE "pause"
0155 #define PMIX_CLI_RESUME "resume"
0156 #define PMIX_CLI_CANCEL "cancel"
0157 #define PMIX_CLI_KILL "kill"
0158 #define PMIX_CLI_RESTART "restart"
0159 #define PMIX_CLI_CHKPT "checkpoint"
0160 #define PMIX_CLI_TARGETS "targets"
0161 #define PMIX_CLI_TERMINATE "terminate"
0162 #define PMIX_CLI_PSET_NAME "pset"
0163 #define PMIX_CLI_FWD_ENVAR "x"
0164 #define PMIX_CLI_SET_ENVAR "set-env"
0165 #define PMIX_CLI_PREPEND_ENVAR "prepend-env"
0166 #define PMIX_CLI_APPEND_ENVAR "append-env"
0167 #define PMIX_CLI_UNSET_ENVAR "unset-env"
0168
0169
0170 #define PMIX_CLI_INFO_ALL "all"
0171 #define PMIX_CLI_INFO_ARCH "arch"
0172 #define PMIX_CLI_INFO_CONFIG "config"
0173 #define PMIX_CLI_INFO_HOSTNAME "hostname"
0174 #define PMIX_CLI_INFO_INTERNAL "internal"
0175 #define PMIX_CLI_INFO_PARAM "param"
0176 #define PMIX_CLI_INFO_PARAMS "params"
0177 #define PMIX_CLI_INFO_PATH "path"
0178 #define PMIX_CLI_INFO_VERSION "show-version"
0179 #define PMIX_CLI_INFO_TYPES "type"
0180 #define PMIX_CLI_INFO_COLOR "color"
0181 #define PMIX_CLI_INFO_SHOW_FAILED "show-failed"
0182 #define PMIX_CLI_INFO_SELECTED_ONLY "selected-only"
0183
0184
0185 typedef void (*pmix_cmd_line_store_fn_t)(const char *name, const char *option,
0186 pmix_cli_result_t *results);
0187
0188 PMIX_EXPORT int pmix_cmd_line_parse(char **argv, char *shorts,
0189 struct option myoptions[],
0190 pmix_cmd_line_store_fn_t storefn,
0191 pmix_cli_result_t *results,
0192 char *helpfile);
0193
0194 static inline pmix_cli_item_t* pmix_cmd_line_get_param(pmix_cli_result_t *results,
0195 const char *key)
0196 {
0197 pmix_cli_item_t *opt;
0198
0199 PMIX_LIST_FOREACH(opt, &results->instances, pmix_cli_item_t) {
0200 if (0 == strcmp(opt->key, key)) {
0201 return opt;
0202 }
0203 }
0204 return NULL;
0205 }
0206
0207 static inline bool pmix_cmd_line_is_taken(pmix_cli_result_t *results,
0208 const char *key)
0209 {
0210 if (NULL == pmix_cmd_line_get_param(results, key)) {
0211 return false;
0212 }
0213 return true;
0214 }
0215
0216 static inline int pmix_cmd_line_get_ninsts(pmix_cli_result_t *results,
0217 const char *key)
0218 {
0219 pmix_cli_item_t *opt;
0220
0221 opt = pmix_cmd_line_get_param(results, key);
0222 if (NULL == opt) {
0223 return 0;
0224 }
0225 return PMIx_Argv_count(opt->values);
0226 }
0227
0228 static inline char* pmix_cmd_line_get_nth_instance(pmix_cli_result_t *results,
0229 const char *key, int idx)
0230 {
0231 pmix_cli_item_t *opt;
0232 int ninst;
0233
0234 opt = pmix_cmd_line_get_param(results, key);
0235 if (NULL == opt) {
0236 return NULL;
0237 }
0238 ninst = PMIx_Argv_count(opt->values);
0239 if (ninst < idx) {
0240 return NULL;
0241 }
0242 return opt->values[idx];
0243 }
0244
0245
0246
0247
0248
0249 static inline bool pmix_check_cli_option(char *ain, char *bin)
0250 {
0251 size_t len1, len2, len, n;
0252 char *a, *b, *p;
0253 char **asplit, **bsplit;
0254 int match, acnt, bcnt;
0255
0256
0257 a = strdup(ain);
0258 b = strdup(bin);
0259
0260
0261
0262
0263
0264 p = strchr(a, '=');
0265 if (NULL != p) {
0266 *p = '\0';
0267 }
0268 p = strchr(b, '=');
0269 if (NULL != p) {
0270 *p = '\0';
0271 }
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 if (NULL != strchr(b, '-') ||
0282 NULL != strchr(a, '-')) {
0283 asplit = PMIx_Argv_split(a, '-');
0284 bsplit = PMIx_Argv_split(b, '-');
0285 acnt = PMIx_Argv_count(asplit);
0286 bcnt = PMIx_Argv_count(bsplit);
0287 if (acnt > bcnt) {
0288 PMIx_Argv_free(asplit);
0289 PMIx_Argv_free(bsplit);
0290 free(a);
0291 free(b);
0292 return false;
0293 }
0294 match = 0;
0295 for (n=0; NULL != asplit[n] && NULL != bsplit[n]; n++) {
0296 len1 = strlen(asplit[n]);
0297 len2 = strlen(bsplit[n]);
0298 len = len1 < len2 ? len1 : len2;
0299 if (0 == strncasecmp(asplit[n], bsplit[n], len)) {
0300 ++match;
0301 } else {
0302 PMIx_Argv_free(asplit);
0303 PMIx_Argv_free(bsplit);
0304 free(a);
0305 free(b);
0306 return false;
0307 }
0308 }
0309 PMIx_Argv_free(asplit);
0310 PMIx_Argv_free(bsplit);
0311 if (match == acnt) {
0312
0313 free(a);
0314 free(b);
0315 return true;
0316 }
0317 free(a);
0318 free(b);
0319 return false;
0320 }
0321
0322
0323
0324 len1 = strlen(a);
0325 len2 = strlen(b);
0326 len = (len1 < len2) ? len1 : len2;
0327 if (0 == strncasecmp(a, b, len)) {
0328 free(a);
0329 free(b);
0330 return true;
0331 }
0332
0333 free(a);
0334 free(b);
0335 return false;
0336 }
0337
0338 #define PMIX_CHECK_CLI_OPTION(a, b) \
0339 pmix_check_cli_option(a, b)
0340
0341 static inline unsigned int pmix_convert_string_to_time(const char *t)
0342 {
0343 char **tmp = PMIx_Argv_split(t, ':');
0344 int sz = PMIx_Argv_count(tmp);
0345 unsigned int tm;
0346
0347
0348
0349
0350 tm = strtoul(tmp[sz-1], NULL, 10);
0351 if (0 <= (sz-2) && NULL != tmp[sz-2]) {
0352 tm += 60 * strtoul(tmp[sz-2], NULL, 10);
0353 }
0354 if (0 <= (sz-3) && NULL != tmp[sz-3]) {
0355 tm += 60 * 60 * strtoul(tmp[sz-3], NULL, 10);
0356 }
0357 if (0 <= (sz-4) && NULL != tmp[sz-4]) {
0358 tm += 24 * 60 * 60 * strtoul(tmp[sz-4], NULL, 10);
0359 }
0360 PMIx_Argv_free(tmp);
0361 return tm;
0362 }
0363
0364 #define PMIX_CONVERT_TIME(s) \
0365 pmix_convert_string_to_time(s)
0366
0367
0368 #define PMIX_CLI_DEBUG_LIST(r) \
0369 do { \
0370 pmix_cli_item_t *_c; \
0371 char *_tail; \
0372 pmix_output(0, "\n[%s:%s:%d]", __FILE__, __func__, __LINE__); \
0373 PMIX_LIST_FOREACH(_c, &(r)->instances, pmix_cli_item_t) { \
0374 pmix_output(0, "KEY: %s", _c->key); \
0375 if (NULL != _c->values) { \
0376 for (int _n=0; NULL != _c->values[_n]; _n++) { \
0377 pmix_output(0, " VAL[%d]: %s", _n, _c->values[_n]); \
0378 } \
0379 } \
0380 } \
0381 _tail = PMIx_Argv_join((r)->tail, ' '); \
0382 pmix_output(0, "TAIL: %s", _tail); \
0383 free(_tail); \
0384 pmix_output(0, "\n"); \
0385 } while(0)
0386
0387 #define PMIX_CLI_REMOVE_DEPRECATED(r, o) \
0388 do { \
0389 pmix_list_remove_item(&(r)->instances, &(o)->super); \
0390 PMIX_RELEASE(o); \
0391 } while(0)
0392 END_C_DECLS
0393
0394 #endif