static pmix_status_t component_register(void) { pmix_mca_base_component_t *component = &mca_pnet_opa_component.super.base; includeparam = "HFI_*,PSM2_*"; (void)pmix_mca_base_component_var_register(component, "include_envars", "Comma-delimited list of envars to harvest (\'*\' and \'?\' supported)", PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_2, PMIX_MCA_BASE_VAR_SCOPE_LOCAL, &includeparam); if (NULL != includeparam) { mca_pnet_opa_component.include = pmix_argv_split(includeparam, ','); } excludeparam = NULL; (void)pmix_mca_base_component_var_register(component, "exclude_envars", "Comma-delimited list of envars to exclude (\'*\' and \'?\' supported)", PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_2, PMIX_MCA_BASE_VAR_SCOPE_LOCAL, &excludeparam); if (NULL != excludeparam) { mca_pnet_opa_component.exclude = pmix_argv_split(excludeparam, ','); } return PMIX_SUCCESS; }
PMIX_EXPORT int PMI_Get_clique_ranks(int ranks[], int length) { pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; char **rks; int i; pmix_proc_t proc = myproc; proc.rank = PMIX_RANK_WILDCARD; PMI_CHECK(); if (NULL == ranks) { return PMI_ERR_INVALID_ARGS; } if (pmi_singleton) { ranks[0] = 0; return PMI_SUCCESS; } rc = PMIx_Get(&proc, PMIX_LOCAL_PEERS, NULL, 0, &val); if (PMIX_SUCCESS == rc) { /* kv will contain a string of comma-separated * ranks on my node */ rks = pmix_argv_split(val->data.string, ','); for (i = 0; NULL != rks[i] && i < length; i++) { ranks[i] = strtol(rks[i], NULL, 10); } pmix_argv_free(rks); PMIX_VALUE_RELEASE(val); } return convert_err(rc); }
static int pdlopen_component_register(void) { int ret; mca_pdl_pdlopen_component.filename_suffixes_mca_storage = ".so,.dylib,.dll,.sl"; ret = pmix_mca_base_component_var_register(&mca_pdl_pdlopen_component.base.base_version, "filename_suffixes", "Comma-delimited list of filename suffixes that the pdlopen component will try", PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, PMIX_MCA_BASE_VAR_FLAG_SETTABLE, PMIX_INFO_LVL_5, PMIX_MCA_BASE_VAR_SCOPE_LOCAL, &mca_pdl_pdlopen_component.filename_suffixes_mca_storage); if (ret < 0) { return ret; } mca_pdl_pdlopen_component.filename_suffixes = pmix_argv_split(mca_pdl_pdlopen_component.filename_suffixes_mca_storage, ','); return PMIX_SUCCESS; }
static int init(void) { char *mychannels = "stdout,stderr"; pmix_plog_stdfd_module.channels = pmix_argv_split(mychannels, ','); return PMIX_SUCCESS; }
int pmix_compress_bzip_compress_nb(char * fname, char **cname, char **postfix, pid_t *child_pid) { char **argv = NULL; char * base_fname = NULL; char * dir_fname = NULL; int status; bool is_dir; is_dir = is_directory(fname); *child_pid = fork(); if( *child_pid == 0 ) { /* Child */ char * cmd; dir_fname = pmix_dirname(fname); base_fname = pmix_basename(fname); chdir(dir_fname); if( is_dir ) { pmix_asprintf(cname, "%s.tar.bz2", base_fname); pmix_asprintf(&cmd, "tar -jcf %s %s", *cname, base_fname); } else { pmix_asprintf(cname, "%s.bz2", base_fname); pmix_asprintf(&cmd, "bzip2 %s", base_fname); } pmix_output_verbose(10, mca_compress_bzip_component.super.output_handle, "compress:bzip: compress_nb(%s -> [%s])", fname, *cname); pmix_output_verbose(10, mca_compress_bzip_component.super.output_handle, "compress:bzip: compress_nb() command [%s]", cmd); argv = pmix_argv_split(cmd, ' '); status = execvp(argv[0], argv); pmix_output(0, "compress:bzip: compress_nb: Failed to exec child [%s] status = %d\n", cmd, status); exit(PMIX_ERROR); } else if( *child_pid > 0 ) { if( is_dir ) { *postfix = strdup(".tar.bz2"); } else { *postfix = strdup(".bz2"); } pmix_asprintf(cname, "%s%s", fname, *postfix); } else { return PMIX_ERROR; } return PMIX_SUCCESS; }
static pmix_status_t pmix_regex_extract_ppn(char *regexp, char ***procs) { char **rngs, **nds, *t, **ps=NULL; int i, j, k, start, end; /* split on semi-colons for nodes */ nds = pmix_argv_split(regexp, ';'); for (j=0; NULL != nds[j]; j++) { /* for each node, split it by comma */ rngs = pmix_argv_split(nds[j], ','); /* parse each element */ for (i=0; NULL != rngs[i]; i++) { /* look for a range */ if (NULL == (t = strchr(rngs[i], '-'))) { /* just one value */ pmix_argv_append_nosize(&ps, rngs[i]); } else { /* handle the range */ *t = '\0'; start = strtol(rngs[i], NULL, 10); ++t; end = strtol(t, NULL, 10); for (k=start; k <= end; k++) { asprintf(&t, "%d", k); pmix_argv_append_nosize(&ps, t); free(t); } } } pmix_argv_free(rngs); /* create the node entry */ t = pmix_argv_join(ps, ','); pmix_argv_append_nosize(procs, t); free(t); pmix_argv_free(ps); ps = NULL; } pmix_argv_free(nds); return PMIX_SUCCESS; }
int pmix_net_init(void) { char **args, *arg; uint32_t a, b, c, d, bits, addr; int i, count, found_bad = 0; args = pmix_argv_split(pmix_net_private_ipv4, ';'); if( NULL != args ) { count = pmix_argv_count(args); private_ipv4 = (private_ipv4_t*)malloc( (count + 1) * sizeof(private_ipv4_t)); if( NULL == private_ipv4 ) { pmix_output(0, "Unable to allocate memory for the private addresses array" ); pmix_argv_free(args); goto do_local_init; } for( i = 0; i < count; i++ ) { arg = args[i]; (void)sscanf( arg, "%u.%u.%u.%u/%u", &a, &b, &c, &d, &bits ); if( (a > 255) || (b > 255) || (c > 255) || (d > 255) || (bits > 32) ) { if (0 == found_bad) { pmix_show_help("help-pmix-runtime.txt", "malformed net_private_ipv4", true, args[i]); found_bad = 1; } continue; } addr = (a << 24) | (b << 16) | (c << 8) | d; private_ipv4[i].addr = htonl(addr); private_ipv4[i].netmask_bits = bits; } private_ipv4[i].addr = 0; private_ipv4[i].netmask_bits = 0; pmix_argv_free(args); } do_local_init: return pmix_tsd_key_create(&hostname_tsd_key, hostname_cleanup); }
int pmix_mca_base_component_parse_requested (const char *requested, bool *include_mode, char ***requested_component_names) { const char *requested_orig = requested; *requested_component_names = NULL; *include_mode = true; /* See if the user requested anything */ if (NULL == requested || 0 == strlen (requested)) { return PMIX_SUCCESS; } /* Are we including or excluding? We only allow the negate character to be the *first* character of the value (but be nice and allow any number of negate characters in the beginning). */ *include_mode = requested[0] != negate[0]; /* skip over all negate symbols at the beginning */ requested += strspn (requested, negate); /* Double check to ensure that the user did not specify the negate character anywhere else in the value. */ if (NULL != strstr (requested, negate)) { pmix_show_help("help-mca-base.txt", "framework-param:too-many-negates", true, requested_orig); return PMIX_ERROR; } /* Split up the value into individual component names */ *requested_component_names = pmix_argv_split(requested, ','); /* All done */ return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; bool retried = false; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "[%s:%d] connect to server", __FILE__, __LINE__); /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL != (evar = getenv("PMIX_SERVER_URI2USOCK"))) { /* this is a v2.1+ server */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v21"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else if (NULL != (evar = getenv("PMIX_SERVER_URI"))) { /* this is a pre-v2.1 server - must use the v12 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v12"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } /* the server will be using the same bfrops as us */ pmix_client_globals.myserver->nptr->compat.bfrops = pmix_globals.mypeer->nptr->compat.bfrops; /* mark that we are using the V1 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V1; uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERROR); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_namespace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); retry: /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); if (PMIX_ERR_TEMP_UNAVAILABLE == rc) { /* give it two tries */ if (!retried) { retried = true; goto retry; } } return rc; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_usock_recv_handler, pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; PMIX_POST_OBJECT(pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_usock_send_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { char *evar, **uri, *suri; char *filename, *nspace=NULL; pmix_rank_t rank = PMIX_RANK_WILDCARD; char *p, *p2; int sd, rc; size_t n; char myhost[PMIX_MAXHOSTNAMELEN]; bool system_level = false; bool system_level_only = false; pid_t pid = 0; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp: connecting to server"); /* see if the connection info is in the info array - if * so, then that overrides all other options */ /* if I am a client, then we need to look for the appropriate * connection info in the environment */ if (PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { if (NULL != (evar = getenv("PMIX_SERVER_URI21"))) { /* we are talking to a v2.1 server */ pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V21; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V21 SERVER DETECTED"); /* must use the v21 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v21"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else if (NULL != (evar = getenv("PMIX_SERVER_URI2"))) { /* we are talking to a v2.0 server */ pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V20; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V20 SERVER DETECTED"); /* must use the v20 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v20"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else { /* not us */ return PMIX_ERR_NOT_SUPPORTED; } /* the server will be using the same bfrops as us */ pmix_client_globals.myserver->nptr->compat.bfrops = pmix_globals.mypeer->nptr->compat.bfrops; /* mark that we are using the V2 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V2; /* the URI consists of the following elements: * - server nspace.rank * - ptl rendezvous URI */ uri = pmix_argv_split(evar, ';'); if (2 != pmix_argv_count(uri)) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } /* set the server nspace */ p = uri[0]; if (NULL == (p2 = strchr(p, '.'))) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } *p2 = '\0'; ++p2; nspace = strdup(p); rank = strtoull(p2, NULL, 10); /* save the URI, but do not overwrite what we may have received from * the info-key directives */ if (NULL == mca_ptl_tcp_component.super.uri) { mca_ptl_tcp_component.super.uri = strdup(uri[1]); } pmix_argv_free(uri); pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:client attempt connect to %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS != (rc = try_connect(&sd))) { free(nspace); return rc; } goto complete; } /* get here if we are a tool - check any provided directives * to see where they want us to connect to */ if (NULL != info) { for (n=0; n < ninfo; n++) { if (0 == strcmp(info[n].key, PMIX_CONNECT_TO_SYSTEM)) { system_level_only = PMIX_INFO_TRUE(&info[n]); } else if (0 == strcmp(info[n].key, PMIX_CONNECT_SYSTEM_FIRST)) { /* try the system-level */ system_level = PMIX_INFO_TRUE(&info[n]); } else if (0 == strcmp(info[n].key, PMIX_SERVER_PIDINFO)) { pid = info[n].value.data.pid; } else if (0 == strcmp(info[n].key, PMIX_SERVER_URI)) { if (NULL == mca_ptl_tcp_component.super.uri) { free(mca_ptl_tcp_component.super.uri); } mca_ptl_tcp_component.super.uri = strdup(info[n].value.data.string); } else if (0 == strcmp(info[n].key, PMIX_CONNECT_RETRY_DELAY)) { mca_ptl_tcp_component.wait_to_connect = info[n].value.data.uint32; } else if (0 == strcmp(info[n].key, PMIX_CONNECT_MAX_RETRIES)) { mca_ptl_tcp_component.max_retries = info[n].value.data.uint32; } } } /* mark that we are using the V2 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V2; gethostname(myhost, sizeof(myhost)); /* if we were given a URI via MCA param, then look no further */ if (NULL != mca_ptl_tcp_component.super.uri) { /* if the string starts with "file:", then they are pointing * us to a file we need to read to get the URI itself */ if (0 == strncmp(mca_ptl_tcp_component.super.uri, "file:", 5)) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool getting connection info from %s", mca_ptl_tcp_component.super.uri); nspace = NULL; rc = parse_uri_file(&mca_ptl_tcp_component.super.uri[5], &suri, &nspace, &rank); if (PMIX_SUCCESS != rc) { return PMIX_ERR_UNREACH; } free(mca_ptl_tcp_component.super.uri); mca_ptl_tcp_component.super.uri = suri; } else { /* we need to extract the nspace/rank of the server from the string */ p = strchr(mca_ptl_tcp_component.super.uri, ';'); if (NULL == p) { return PMIX_ERR_BAD_PARAM; } *p = '\0'; p++; suri = strdup(p); // save the uri portion /* the '.' in the first part of the original string separates * nspace from rank */ p = strchr(mca_ptl_tcp_component.super.uri, '.'); if (NULL == p) { free(suri); return PMIX_ERR_BAD_PARAM; } *p = '\0'; p++; nspace = strdup(mca_ptl_tcp_component.super.uri); rank = strtoull(p, NULL, 10); /* now update the URI */ free(mca_ptl_tcp_component.super.uri); mca_ptl_tcp_component.super.uri = suri; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool attempt connect using given URI %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS != (rc = try_connect(&sd))) { if (NULL != nspace) { free(nspace); } return rc; } goto complete; } /* if they gave us a pid, then look for it */ if (0 != pid) { if (0 > asprintf(&filename, "pmix.%s.tool.%d", myhost, pid)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool searching for given session server %s", filename); nspace = NULL; rc = df_search(mca_ptl_tcp_component.system_tmpdir, filename, &sd, &nspace, &rank); free(filename); if (PMIX_SUCCESS == rc) { goto complete; } if (NULL != nspace) { free(nspace); } /* since they gave us a specific pid and we couldn't * connect to it, return an error */ return PMIX_ERR_UNREACH; } /* if they asked for system-level, we start there */ if (system_level || system_level_only) { if (0 > asprintf(&filename, "%s/pmix.sys.%s", mca_ptl_tcp_component.system_tmpdir, myhost)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool looking for system server at %s", filename); /* try to read the file */ rc = parse_uri_file(filename, &suri, &nspace, &rank); free(filename); if (PMIX_SUCCESS == rc) { mca_ptl_tcp_component.super.uri = suri; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool attempt connect to system server at %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS == try_connect(&sd)) { goto complete; } free(nspace); } } /* we get here if they either didn't ask for a system-level connection, * or they asked for it and it didn't succeed. If they _only_ wanted * a system-level connection, then we are done */ if (system_level_only) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp: connecting to system failed"); return PMIX_ERR_UNREACH; } /* they didn't give us a pid, so we will search to see what session-level * tools are available to this user. We will take the first connection * that succeeds - this is based on the likelihood that there is only * one session per user on a node */ if (0 > asprintf(&filename, "pmix.%s.tool", myhost)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool searching for session server %s", filename); nspace = NULL; rc = df_search(mca_ptl_tcp_component.system_tmpdir, filename, &sd, &nspace, &rank); free(filename); if (PMIX_SUCCESS != rc) { if (NULL != nspace){ free(nspace); } return PMIX_ERR_UNREACH; } complete: pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "sock_peer_try_connect: Connection across to server succeeded"); /* do a final bozo check */ if (NULL == nspace || PMIX_RANK_WILDCARD == rank) { if (NULL != nspace) { free(nspace); } CLOSE_THE_SOCKET(sd); return PMIX_ERR_UNREACH; } /* mark the connection as made */ pmix_globals.connected = true; pmix_client_globals.myserver->sd = sd; /* setup the server info */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = nspace; } else { free(nspace); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(pmix_client_globals.myserver->nptr->nspace); } pmix_client_globals.myserver->info->pname.rank = rank; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->recv_ev_active = true; PMIX_POST_OBJECT(pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t tcp_init(void) { tcp_available_ports_t *trk; char *p, **grps; size_t n; pmix_output_verbose(2, pmix_pnet_base_framework.framework_output, "pnet: tcp init"); /* if we are not the "gateway", then there is nothing * for us to do */ if (!PMIX_PROC_IS_GATEWAY(pmix_globals.mypeer)) { return PMIX_SUCCESS; } PMIX_CONSTRUCT(&allocations, pmix_list_t); PMIX_CONSTRUCT(&available, pmix_list_t); /* if we have no static ports, then we don't have * anything to manage. However, we cannot just disqualify * ourselves as we may still need to provide inventory. * * NOTE: need to check inventory in addition to MCA param as * the inventory may have reported back static ports */ if (NULL == mca_pnet_tcp_component.static_ports) { return PMIX_SUCCESS; } /* split on semi-colons */ grps = pmix_argv_split(mca_pnet_tcp_component.static_ports, ';'); for (n=0; NULL != grps[n]; n++) { trk = PMIX_NEW(tcp_available_ports_t); if (NULL == trk) { pmix_argv_free(grps); return PMIX_ERR_NOMEM; } /* there must be at least one colon */ if (NULL == (p = strrchr(grps[n], ':'))) { pmix_argv_free(grps); return PMIX_ERR_BAD_PARAM; } /* extract the ports */ *p = '\0'; ++p; pmix_util_parse_range_options(p, &trk->ports); trk->nports = pmix_argv_count(trk->ports); /* see if they provided a plane */ if (NULL != (p = strchr(grps[n], ':'))) { /* yep - save the plane */ *p = '\0'; ++p; trk->plane = strdup(p); } /* the type is just what is left at the front */ trk->type = strdup(grps[n]); pmix_output_verbose(2, pmix_pnet_base_framework.framework_output, "TYPE: %s PLANE %s", trk->type, (NULL == trk->plane) ? "NULL" : trk->plane); pmix_list_append(&available, &trk->super); } pmix_argv_free(grps); return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { char *evar, **uri; char *filename, *host; FILE *fp; char *srvr, *p, *p2; struct sockaddr_in *in; struct sockaddr_in6 *in6; pmix_socklen_t len; int sd, rc; pmix_output_verbose(2, pmix_globals.debug_output, "ptl:tcp: connecting to server"); /* see if the connection info is in the info array - if * so, then that overrides all other options */ /* if I am a client, then we need to look for the appropriate * connection info in the environment */ if (PMIX_PROC_CLIENT == pmix_globals.proc_type) { if (NULL == (evar = getenv("PMIX_SERVER_URI2"))) { /* not us */ return PMIX_ERR_NOT_SUPPORTED; } /* the URI consists of elements: * - server nspace.rank * - ptl rendezvous URI */ uri = pmix_argv_split(evar, ';'); if (2 != pmix_argv_count(uri)) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } /* set the server nspace */ p = uri[0]; if (NULL == (p2 = strchr(p, '.'))) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } *p2 = '\0'; ++p2; pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, p, PMIX_MAX_NSLEN); /* set the server rank */ pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* save the URI, but do not overwrite what we may have received from * the info-key directives */ if (NULL == mca_ptl_tcp_component.super.uri) { mca_ptl_tcp_component.super.uri = strdup(uri[1]); } pmix_argv_free(uri); } else if (PMIX_PROC_TOOL == pmix_globals.proc_type) { /* if we already have a URI, then look no further */ if (NULL == mca_ptl_tcp_component.super.uri) { /* we have to discover the connection info, * if possible. Start by looking for the connection * info in the expected place - if the server supports * tool connections via TCP, then there will be a * "contact.txt" file under the system tmpdir */ filename = pmix_os_path(false, mca_ptl_tcp_component.tmpdir, "pmix-contact.txt", NULL); if (NULL == filename) { return PMIX_ERR_NOMEM; } fp = fopen(filename, "r"); if (NULL == fp) { /* if we cannot open the file, then the server must not * be configured to support tool connections - so abort */ free(filename); return PMIX_ERR_UNREACH; } free(filename); /* get the URI */ srvr = pmix_getline(fp); if (NULL == srvr) { PMIX_ERROR_LOG(PMIX_ERR_FILE_READ_FAILURE); fclose(fp); return PMIX_ERR_UNREACH; } fclose(fp); /* up to the first ';' is the server nspace/rank */ if (NULL == (p = strchr(srvr, ';'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p = '\0'; ++p; // move past the semicolon /* the nspace is the section up to the '.' */ if (NULL == (p2 = strchr(srvr, '.'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p2 = '\0'; ++p2; /* set the server nspace */ pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, srvr, PMIX_MAX_NSLEN); pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* now parse the uti itself */ mca_ptl_tcp_component.super.uri = strdup(p); free(srvr); } } /* mark that we are the active module for this server */ pmix_client_globals.myserver.compat.ptl = &pmix_ptl_tcp_module; /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_tcp_component.connection, 0, sizeof(struct sockaddr_storage)); if (0 == strncmp(mca_ptl_tcp_component.super.uri, "tcp4", 4)) { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; ++p2; host = &p[7]; /* load the address */ in = (struct sockaddr_in*)&mca_ptl_tcp_component.connection; in->sin_family = AF_INET; in->sin_addr.s_addr = inet_addr(host); if (in->sin_addr.s_addr == INADDR_NONE) { free(p); return PMIX_ERR_BAD_PARAM; } in->sin_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in); } else { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; if (']' == p[strlen(p)-1]) { p[strlen(p)-1] = '\0'; } if ('[' == p[7]) { host = &p[8]; } else { host = &p[7]; } /* load the address */ in6 = (struct sockaddr_in6*)&mca_ptl_tcp_component.connection; in6->sin6_family = AF_INET6; if (0 == inet_pton(AF_INET6, host, (void*)&in6->sin6_addr)) { pmix_output (0, "ptl_tcp_parse_uri: Could not convert %s\n", host); free(p); return PMIX_ERR_BAD_PARAM; } in6->sin6_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in6); } free(p); /* establish the connection */ if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_tcp_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver.sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver.recv_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver.recv_event, 0); pmix_client_globals.myserver.recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver.send_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver.send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL == (evar = getenv("PMIX_SERVER_URI"))) { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
/* * Back-end function to actually send the email */ static int send_email(char *msg) { int i, err = PMIX_SUCCESS; char *str = NULL; char *errmsg = NULL; struct sigaction sig, oldsig; bool set_oldsig = false; smtp_session_t session = NULL; smtp_message_t message = NULL; message_status_t ms; pmix_plog_smtp_component_t *c = &mca_plog_smtp_component; if (NULL == c->to_argv) { c->to_argv = pmix_argv_split(c->to, ','); if (NULL == c->to_argv || NULL == c->to_argv[0]) { return PMIX_ERR_OUT_OF_RESOURCE; } } ms.sent_flag = SENT_NONE; ms.prev_string = NULL; ms.msg = msg; /* Temporarily disable SIGPIPE so that if remote servers timeout or hang up on us, it doesn't kill this application. We'll restore the original SIGPIPE handler when we're done. */ sig.sa_handler = SIG_IGN; sigemptyset(&sig.sa_mask); sig.sa_flags = 0; sigaction(SIGPIPE, &sig, &oldsig); set_oldsig = true; /* Try to get a libesmtp session. If so, assume that libesmtp is happy and proceeed */ session = smtp_create_session(); if (NULL == session) { err = PMIX_ERR_NOT_SUPPORTED; errmsg = "stmp_create_session"; goto error; } /* Create the message */ message = smtp_add_message(session); if (NULL == message) { err = PMIX_ERROR; errmsg = "stmp_add_message"; goto error; } /* Set the SMTP server (yes, it's a weird return status!) */ asprintf(&str, "%s:%d", c->server, c->port); if (0 == smtp_set_server(session, str)) { err = PMIX_ERROR; errmsg = "stmp_set_server"; goto error; } free(str); str = NULL; /* Add the sender */ if (0 == smtp_set_reverse_path(message, c->from_addr)) { err = PMIX_ERROR; errmsg = "stmp_set_reverse_path"; goto error; } /* Set the subject and some headers */ asprintf(&str, "PMIx SMTP Plog v%d.%d.%d", c->super.base.pmix_mca_component_major_version, c->super.base.pmix_mca_component_minor_version, c->super.base.pmix_mca_component_release_version); if (0 == smtp_set_header(message, "Subject", c->subject) || 0 == smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1) || 0 == smtp_set_header(message, "To", NULL, NULL) || 0 == smtp_set_header(message, "From", (NULL != c->from_name ? c->from_name : c->from_addr), c->from_addr) || 0 == smtp_set_header(message, "X-Mailer", str) || 0 == smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1)) { err = PMIX_ERROR; errmsg = "smtp_set_header"; goto error; } free(str); str = NULL; /* Add the recipients */ for (i = 0; NULL != c->to_argv[i]; ++i) { if (NULL == smtp_add_recipient(message, c->to_argv[i])) { err = PMIX_ERR_OUT_OF_RESOURCE; errmsg = "stmp_add_recipient"; goto error; } } /* Set the callback to get the message */ if (0 == smtp_set_messagecb(message, message_cb, &ms)) { err = PMIX_ERROR; errmsg = "smtp_set_messagecb"; goto error; } /* Send it! */ if (0 == smtp_start_session(session)) { err = PMIX_ERROR; errmsg = "smtp_start_session"; goto error; } /* Fall through */ error: if (NULL != str) { free(str); } if (NULL != session) { smtp_destroy_session(session); } /* Restore the SIGPIPE handler */ if (set_oldsig) { sigaction(SIGPIPE, &oldsig, NULL); } if (PMIX_SUCCESS != err) { int e; char em[256]; e = smtp_errno(); smtp_strerror(e, em, sizeof(em)); pmix_show_help("help-pmix-plog-smtp.txt", "send_email failed", true, "libesmtp library call failed", errmsg, em, e, msg); } return err; }
static pmix_status_t validate_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, const pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; #if defined(SO_PEERCRED) #ifdef HAVE_STRUCT_SOCKPEERCRED_UID #define HAVE_STRUCT_UCRED_UID struct sockpeercred ucred; #else struct ucred ucred; #endif socklen_t crlen = sizeof (ucred); #endif uid_t euid = -1; gid_t egid = -1; char *ptr; size_t ln; bool takeus; char **types; size_t n, m; uint32_t u32; pmix_output_verbose(2, pmix_globals.debug_output, "psec: native validate_cred %s", (NULL == cred) ? "NULL" : "NON-NULL"); if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - get the remote side's uid/gid */ #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID)) /* Ignore received 'cred' and validate ucred for socket instead. */ pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getsockopt on socket %d for peer credentials", pr->sd); if (getsockopt(pr->sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt SO_PEERCRED failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #if defined(HAVE_STRUCT_UCRED_UID) euid = ucred.uid; egid = ucred.gid; #else euid = ucred.cr_uid; egid = ucred.cr_gid; #endif #elif defined(HAVE_GETPEEREID) pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getpeereid on socket %d for peer credentials", pr->sd); if (0 != getpeereid(pr->sd, &euid, &egid)) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt getpeereid failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #else return PMIX_ERR_NOT_SUPPORTED; #endif } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* this is a tcp protocol, so the cred is actually the uid/gid * passed upwards from the client */ if (NULL == cred) { /* not allowed */ return PMIX_ERR_INVALID_CRED; } ln = cred->size; euid = 0; egid = 0; if (sizeof(uid_t) <= ln) { memcpy(&euid, cred->bytes, sizeof(uid_t)); ln -= sizeof(uid_t); ptr = cred->bytes + sizeof(uid_t); } else { return PMIX_ERR_INVALID_CRED; } if (sizeof(gid_t) <= ln) { memcpy(&egid, ptr, sizeof(gid_t)); } else { return PMIX_ERR_INVALID_CRED; } } else if (PMIX_PROTOCOL_UNDEF != pr->protocol) { /* don't recognize the protocol */ return PMIX_ERR_NOT_SUPPORTED; } /* if we are responding to a local request to validate a credential, * then see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* split the specified string */ types = pmix_argv_split(directives[n].value.data.string, ','); takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); if (!takeus) { return PMIX_ERR_NOT_SUPPORTED; } } } } /* check uid */ if (euid != pr->info->uid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid uid %u", euid); return PMIX_ERR_INVALID_CRED; } /* check gid */ if (egid != pr->info->gid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid gid %u", egid); return PMIX_ERR_INVALID_CRED; } /* validated - mark that we did it */ if (NULL != info) { PMIX_INFO_CREATE(*info, 3); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 3; /* mark that this came from us */ PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING); /* provide the uid it contained */ u32 = euid; PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32); /* provide the gid it contained */ u32 = egid; PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32); } return PMIX_SUCCESS; }
static pmix_status_t create_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; char **types; size_t n, m; bool takeus; uid_t euid; gid_t egid; char *tmp, *ptr; /* ensure initialization */ PMIX_BYTE_OBJECT_CONSTRUCT(cred); /* we may be responding to a local request for a credential, so * see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { /* cycle across the provided info and see if they specified * any desired credential types */ takeus = true; for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* see if we are included */ types = pmix_argv_split(directives[n].value.data.string, ','); /* start by assuming they don't want us */ takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); break; } } if (!takeus) { PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } } if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - nothing to do */ goto complete; } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* tcp protocol - need to provide our effective * uid and gid for validation on remote end */ tmp = (char*)malloc(sizeof(uid_t) + sizeof(gid_t)); if (NULL == tmp) { return PMIX_ERR_NOMEM; } euid = geteuid(); memcpy(tmp, &euid, sizeof(uid_t)); ptr = tmp + sizeof(uid_t); egid = getegid(); memcpy(ptr, &egid, sizeof(gid_t)); cred->bytes = tmp; cred->size = sizeof(uid_t) + sizeof(gid_t); goto complete; } else { /* unrecognized protocol */ PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } complete: if (NULL != info) { /* mark that this came from us */ PMIX_INFO_CREATE(*info, 1); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 1; PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "native", PMIX_STRING); } return PMIX_SUCCESS; }
/* * Scan all the files in a directory (or path) and invoke a callback * on each one. */ static int pdlopen_foreachfile(const char *search_path, int (*func)(const char *filename, void *data), void *data) { int ret; DIR *dp = NULL; char **dirs = NULL; char **good_files = NULL; dirs = pmix_argv_split(search_path, PMIX_ENV_SEP); for (int i = 0; NULL != dirs && NULL != dirs[i]; ++i) { dp = opendir(dirs[i]); if (NULL == dp) { ret = PMIX_ERR_IN_ERRNO; goto error; } struct dirent *de; while (NULL != (de = readdir(dp))) { /* Make the absolute path name */ char *abs_name = NULL; ret = asprintf(&abs_name, "%s/%s", dirs[i], de->d_name); if (0 > ret) { return PMIX_ERR_NOMEM; } if (NULL == abs_name) { ret = PMIX_ERR_IN_ERRNO; goto error; } /* Stat the file */ struct stat buf; if (stat(abs_name, &buf) < 0) { free(abs_name); ret = PMIX_ERR_IN_ERRNO; goto error; } /* Skip if not a file */ if (!S_ISREG(buf.st_mode)) { free(abs_name); continue; } /* Find the suffix */ char *ptr = strrchr(abs_name, '.'); if (NULL != ptr) { /* Skip libtool files */ if (strcmp(ptr, ".la") == 0 || strcmp(ptr, ".lo") == 0) { free (abs_name); continue; } *ptr = '\0'; } /* Have we already found this file? Or already found a file with the same basename (but different suffix)? */ bool found = false; for (int j = 0; NULL != good_files && NULL != good_files[j]; ++j) { if (strcmp(good_files[j], abs_name) == 0) { found = true; break; } } if (!found) { pmix_argv_append_nosize(&good_files, abs_name); } free(abs_name); } closedir(dp); } dp = NULL; /* Invoke the callback on all the found files */ if (NULL != good_files) { for (int i = 0; NULL != good_files[i]; ++i) { ret = func(good_files[i], data); if (PMIX_SUCCESS != ret) { goto error; } } } ret = PMIX_SUCCESS; error: if (NULL != dp) { closedir(dp); } if (NULL != dirs) { pmix_argv_free(dirs); } if (NULL != good_files) { pmix_argv_free(good_files); } return ret; }
void parse_cmd(int argc, char **argv, test_params *params) { int i; /* set output to stderr by default */ file = stdout; if( params->nspace != NULL ) { params->nspace = NULL; } /* parse user options */ for (i=1; i < argc; i++) { if (0 == strcmp(argv[i], "--n") || 0 == strcmp(argv[i], "-n")) { i++; if (NULL != argv[i]) { params->np = strdup(argv[i]); params->nprocs = strtol(argv[i], NULL, 10); if (-1 == params->ns_size) { params->ns_size = params->nprocs; } } } else if (0 == strcmp(argv[i], "--h") || 0 == strcmp(argv[i], "-h")) { /* print help */ fprintf(stderr, "usage: pmix_test [-h] [-e foo] [-b] [-c] [-nb]\n"); fprintf(stderr, "\t-n provides information about the job size (for checking purposes)\n"); fprintf(stderr, "\t-e foo use foo as test client\n"); fprintf(stderr, "\t-v verbose output\n"); fprintf(stderr, "\t-t <> set timeout\n"); fprintf(stderr, "\t-o out redirect clients logs to file out.<rank>\n"); fprintf(stderr, "\t--early-fail force client process with rank 0 to fail before PMIX_Init.\n"); fprintf(stderr, "\t--ns-dist n1:n2:n3 register n namespaces (3 in this example) each with ni ranks (n1, n2 or n3).\n"); fprintf(stderr, "\t--fence \"[<data_exchange><blocking> | ns0:ranks;ns1:ranks...][...]\" specify fences in different configurations.\n"); fprintf(stderr, "\t--use-same-keys relative to the --fence option: put the same keys in the interim between multiple fences.\n"); fprintf(stderr, "\t--job-fence test fence inside its own namespace.\n"); fprintf(stderr, "\t-c relative to the --job-fence option: fence[_nb] callback shall include all collected data\n"); fprintf(stderr, "\t-nb relative to the --job-fence option: use non-blocking fence\n"); fprintf(stderr, "\t--noise \"[ns0:ranks;ns1:ranks...]\" add system noise to specified processes.\n"); fprintf(stderr, "\t--test-publish test publish/lookup/unpublish api.\n"); fprintf(stderr, "\t--test-spawn test spawn api.\n"); fprintf(stderr, "\t--test-connect test connect/disconnect api.\n"); fprintf(stderr, "\t--test-resolve-peers test resolve_peers api.\n"); exit(0); } else if (0 == strcmp(argv[i], "--exec") || 0 == strcmp(argv[i], "-e")) { i++; if (NULL != argv[i]) { params->binary = strdup(argv[i]); } } else if( 0 == strcmp(argv[i], "--verbose") || 0 == strcmp(argv[i],"-v") ){ TEST_VERBOSE_ON(); params->verbose = 1; } else if (0 == strcmp(argv[i], "--timeout") || 0 == strcmp(argv[i], "-t")) { i++; if (NULL != argv[i]) { params->timeout = atoi(argv[i]); if( params->timeout == 0 ){ params->timeout = TEST_DEFAULT_TIMEOUT; } } } else if( 0 == strcmp(argv[i], "-o")) { i++; if (NULL != argv[i]) { params->prefix = strdup(argv[i]); } } else if( 0 == strcmp(argv[i], "-s")) { i++; if (NULL != argv[i]) { params->nspace = strdup(argv[i]); } } else if (0 == strcmp(argv[i], "--rank") || 0 == strcmp(argv[i], "-r")) { i++; if (NULL != argv[i]) { params->rank = strtol(argv[i], NULL, 10); } } else if( 0 == strcmp(argv[i], "--early-fail") ){ params->early_fail = 1; } else if (0 == strcmp(argv[i], "--fence")) { i++; if (NULL != argv[i]) { params->fences = strdup(argv[i]); if (0 != parse_fence(params->fences, 0)) { fprintf(stderr, "Incorrect --fence option format: %s\n", params->fences); exit(1); } } } else if (0 == strcmp(argv[i], "--use-same-keys")) { params->use_same_keys = 1; } else if (0 == strcmp(argv[i], "--job-fence")) { params->test_job_fence = 1; } else if (0 == strcmp(argv[i], "--collect-corrupt")) { params->collect_bad = 1; } else if (0 == strcmp(argv[i], "--collect") || 0 == strcmp(argv[i], "-c")) { params->collect = 1; } else if (0 == strcmp(argv[i], "--non-blocking") || 0 == strcmp(argv[i], "-nb")) { params->nonblocking = 1; } else if (0 == strcmp(argv[i], "--noise")) { i++; if (NULL != argv[i]) { params->noise = strdup(argv[i]); if (0 != parse_noise(params->noise, 0)) { fprintf(stderr, "Incorrect --noise option format: %s\n", params->noise); exit(1); } } } else if (0 == strcmp(argv[i], "--ns-dist")) { i++; if (NULL != argv[i]) { params->ns_dist = strdup(argv[i]); } } else if (0 == strcmp(argv[i], "--ns-size")) { i++; if (NULL != argv[i]) { params->ns_size = strtol(argv[i], NULL, 10); } } else if (0 == strcmp(argv[i], "--ns-id")) { i++; if (NULL != argv[i]) { params->ns_id = strtol(argv[i], NULL, 10); } } else if (0 == strcmp(argv[i], "--base-rank")) { i++; if (NULL != argv[i]) { params->base_rank = strtol(argv[i], NULL, 10); } } else if( 0 == strcmp(argv[i], "--test-publish") ){ params->test_publish = 1; } else if( 0 == strcmp(argv[i], "--test-spawn") ){ params->test_spawn = 1; } else if( 0 == strcmp(argv[i], "--test-connect") ){ params->test_connect = 1; } else if( 0 == strcmp(argv[i], "--test-resolve-peers") ){ params->test_resolve_peers = 1; } else { fprintf(stderr, "unrecognized option: %s\n", argv[i]); exit(1); } } if (NULL == params->binary) { char *basename = NULL; basename = strrchr(argv[0], '/'); if (basename) { *basename = '\0'; /* pmix_test and pmix_clients are the shell scripts that * make sure that actual binary placed in "./.libs" directory * is properly linked. * after launch pmix_test you'll find the following process: * <pmix-root-dir>/test/.libs/lt-pmix_test * * To launch * <pmix-root-dir>/test/pmix_client * instead of * <pmix-root-dir>/test/.libs/pmix_client * we need to do a step back in directory tree. */ asprintf(¶ms->binary, "%s/../pmix_client", argv[0]); *basename = '/'; } else { asprintf(¶ms->binary, "pmix_client"); } } if( params->collect_bad ){ params->collect = params->rank % 2; } // Fix rank if running under SLURM if( 0 > params->rank ){ char *ranklist = getenv("SLURM_GTIDS"); char *rankno = getenv("SLURM_LOCALID"); if( NULL != ranklist && NULL != rankno ){ char **argv = pmix_argv_split(ranklist, ','); int count = pmix_argv_count(argv); int rankidx = strtoul(rankno, NULL, 10); if( rankidx >= count ){ fprintf(stderr, "It feels like we are running under SLURM:\n\t" "SLURM_GTIDS=%s, SLURM_LOCALID=%s\nbut env vars are conflicting\n", ranklist, rankno); exit(1); } params->rank = strtoul(argv[rankidx], NULL, 10); pmix_argv_free(argv); } } // Fix namespace if running under SLURM if( NULL == params->nspace ){ char *nspace = getenv("PMIX_NAMESPACE"); if( NULL != nspace ){ params->nspace = strdup(nspace); } } }
int pmix_compress_bzip_decompress_nb(char * cname, char **fname, pid_t *child_pid) { char **argv = NULL; char * dir_cname = NULL; pid_t loc_pid = 0; int status; bool is_tar = false; if( 0 == strncmp(&(cname[strlen(cname)-8]), ".tar.bz2", strlen(".tar.bz2")) ) { is_tar = true; } *fname = strdup(cname); if( is_tar ) { (*fname)[strlen(cname)-8] = '\0'; } else { (*fname)[strlen(cname)-4] = '\0'; } pmix_output_verbose(10, mca_compress_bzip_component.super.output_handle, "compress:bzip: decompress_nb(%s -> [%s])", cname, *fname); *child_pid = fork(); if( *child_pid == 0 ) { /* Child */ dir_cname = pmix_dirname(cname); chdir(dir_cname); /* Fork(bunzip) */ loc_pid = fork(); if( loc_pid == 0 ) { /* Child */ char * cmd; pmix_asprintf(&cmd, "bunzip2 %s", cname); pmix_output_verbose(10, mca_compress_bzip_component.super.output_handle, "compress:bzip: decompress_nb() command [%s]", cmd); argv = pmix_argv_split(cmd, ' '); status = execvp(argv[0], argv); pmix_output(0, "compress:bzip: decompress_nb: Failed to exec child [%s] status = %d\n", cmd, status); exit(PMIX_ERROR); } else if( loc_pid > 0 ) { /* Parent */ waitpid(loc_pid, &status, 0); if( !WIFEXITED(status) ) { pmix_output(0, "compress:bzip: decompress_nb: Failed to bunzip the file [%s] status = %d\n", cname, status); exit(PMIX_ERROR); } } else { exit(PMIX_ERROR); } /* tar_decompress */ if( is_tar ) { /* Strip off '.bz2' leaving just '.tar' */ cname[strlen(cname)-4] = '\0'; pmix_compress_base_tar_extract(&cname); } /* Once this child is done, then directly exit */ exit(PMIX_SUCCESS); } else if( *child_pid > 0 ) { ; } else { return PMIX_ERROR; } return PMIX_SUCCESS; }