pmix_status_t pmix_argv_insert(char ***target, int start, char **source) { int i, source_count, target_count; int suffix_count; /* Check for the bozo cases */ if (NULL == target || NULL == *target || start < 0) { return PMIX_ERR_BAD_PARAM; } else if (NULL == source) { return PMIX_SUCCESS; } /* Easy case: appending to the end */ target_count = pmix_argv_count(*target); source_count = pmix_argv_count(source); if (start > target_count) { for (i = 0; i < source_count; ++i) { pmix_argv_append(&target_count, target, source[i]); } } /* Harder: insertting into the middle */ else { /* Alloc out new space */ *target = (char**) realloc(*target, sizeof(char *) * (target_count + source_count + 1)); /* Move suffix items down to the end */ suffix_count = target_count - start; for (i = suffix_count - 1; i >= 0; --i) { (*target)[start + source_count + i] = (*target)[start + i]; } (*target)[start + suffix_count + source_count] = NULL; /* Strdup in the source argv */ for (i = start; i < start + source_count; ++i) { (*target)[i] = strdup(source[i - start]); } } /* All done */ return PMIX_SUCCESS; }
/* * Locates a file with certain permissions from a list of search paths */ char *pmix_path_findv(char *fname, int mode, char **envv, char *wrkdir) { char **dirv; char *fullpath; char *path; int dirc; int i; bool found_dot = false; /* Set the local search paths. */ dirc = 0; dirv = NULL; if (NULL != (path = list_env_get("PATH", envv))) { path_env_load(path, &dirc, &dirv); } /* Replace the "." path by the working directory. */ if (NULL != wrkdir) { for (i = 0; i < dirc; ++i) { if (0 == strcmp(dirv[i], ".")) { found_dot = true; free(dirv[i]); dirv[i] = strdup(wrkdir); if (NULL == dirv[i]){ return NULL; } } } } /* If we didn't find "." in the path and we have a wrkdir, append the wrkdir to the end of the path */ if (!found_dot && NULL != wrkdir) { pmix_argv_append(&dirc, &dirv, wrkdir); } if(NULL == dirv) return NULL; fullpath = pmix_path_find(fname, dirv, mode, envv); pmix_argv_free(dirv); return fullpath; }
pmix_status_t pmix_argv_insert_element(char ***target, int location, char *source) { int i, target_count; int suffix_count; /* Check for the bozo cases */ if (NULL == target || NULL == *target || location < 0) { return PMIX_ERR_BAD_PARAM; } else if (NULL == source) { return PMIX_SUCCESS; } /* Easy case: appending to the end */ target_count = pmix_argv_count(*target); if (location > target_count) { pmix_argv_append(&target_count, target, source); return PMIX_SUCCESS; } /* Alloc out new space */ *target = (char**) realloc(*target, sizeof(char*) * (target_count + 2)); /* Move suffix items down to the end */ suffix_count = target_count - location; for (i = suffix_count - 1; i >= 0; --i) { (*target)[location + 1 + i] = (*target)[location + i]; } (*target)[location + suffix_count + 1] = NULL; /* Strdup in the source */ (*target)[location] = strdup(source); /* All done */ return PMIX_SUCCESS; }
/** * * Loads argument array with $PATH env var. * * Accepts * -path String contiaing the $PATH * -argc Pointer to argc * -argv Pointer to list of argv */ static void path_env_load(char *path, int *pargc, char ***pargv) { char *p; char saved; if (NULL == path) { *pargc = 0; return; } /* Loop through the paths (delimited by PATHENVSEP), adding each one to argv. */ while ('\0' != *path) { /* Locate the delimiter. */ for (p = path; *p && (*p != PMIX_ENV_SEP); ++p) { continue; } /* Add the path. */ if (p != path) { saved = *p; *p = '\0'; pmix_argv_append(pargc, pargv, path); *p = saved; path = p; } /* Skip past the delimiter, if present. */ if (*path) { ++path; } } }
/* * Portable version of setenv(), allowing editing of any environ-like * array */ int pmix_setenv(const char *name, const char *value, bool overwrite, char ***env) { int i; char *newvalue, *compare; size_t len; /* Make the new value */ if (NULL == value) { asprintf(&newvalue, "%s=", name); } else { asprintf(&newvalue, "%s=%s", name, value); } if (NULL == newvalue) { return PMIX_ERR_OUT_OF_RESOURCE; } /* Check the bozo case */ if( NULL == env ) { return PMIX_ERR_BAD_PARAM; } else if (NULL == *env) { i = 0; pmix_argv_append(&i, env, newvalue); free(newvalue); return PMIX_SUCCESS; } /* If this is the "environ" array, use putenv */ if( *env == environ ) { /* THIS IS POTENTIALLY A MEMORY LEAK! But I am doing it because so that we don't violate the law of least astonishmet for PMIX developers (i.e., those that don't check the return code of pmix_setenv() and notice that we returned an error if you passed in the real environ) */ putenv(newvalue); return PMIX_SUCCESS; } /* Make something easy to compare to */ asprintf(&compare, "%s=", name); if (NULL == compare) { free(newvalue); return PMIX_ERR_OUT_OF_RESOURCE; } len = strlen(compare); /* Look for a duplicate that's already set in the env */ for (i = 0; (*env)[i] != NULL; ++i) { if (0 == strncmp((*env)[i], compare, len)) { if (overwrite) { free((*env)[i]); (*env)[i] = newvalue; free(compare); return PMIX_SUCCESS; } else { free(compare); free(newvalue); return PMIX_EXISTS; } } } /* If we found no match, append this value */ i = pmix_argv_count(*env); pmix_argv_append(&i, env, newvalue); /* All done */ free(compare); free(newvalue); return PMIX_SUCCESS; }
int main(int argc, char **argv) { int rc; pmix_value_t value; pmix_value_t *val = &value; pmix_proc_t proc; uint32_t nprocs; char nsp2[PMIX_MAX_NSLEN+1]; pmix_app_t *app; char hostname[PMIX_MAXHOSTNAMELEN]; pmix_proc_t *peers; size_t npeers, ntmp=0; char *nodelist; gethostname(hostname, sizeof(hostname)); /* init us */ if (PMIX_SUCCESS != (rc = PMIx_Init(&myproc, NULL, 0))) { pmix_output(0, "Client ns %s rank %d: PMIx_Init failed: %d", myproc.nspace, myproc.rank, rc); exit(0); } pmix_output(0, "Client ns %s rank %d: Running", myproc.nspace, myproc.rank); /* get our universe size */ (void)strncpy(proc.nspace, myproc.nspace, PMIX_MAX_NSLEN); proc.rank = PMIX_RANK_WILDCARD; if (PMIX_SUCCESS != (rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, &val))) { pmix_output(0, "Client ns %s rank %d: PMIx_Get universe size failed: %d", myproc.nspace, myproc.rank, rc); goto done; } nprocs = val->data.uint32; PMIX_VALUE_RELEASE(val); pmix_output(0, "Client %s:%d universe size %d", myproc.nspace, myproc.rank, nprocs); /* call fence to sync */ PMIX_PROC_CONSTRUCT(&proc); (void)strncpy(proc.nspace, myproc.nspace, PMIX_MAX_NSLEN); proc.rank = PMIX_RANK_WILDCARD; if (PMIX_SUCCESS != (rc = PMIx_Fence(&proc, 1, NULL, 0))) { pmix_output(0, "Client ns %s rank %d: PMIx_Fence failed: %d", myproc.nspace, myproc.rank, rc); goto done; } /* rank=0 calls spawn */ if (0 == myproc.rank) { PMIX_APP_CREATE(app, 1); app->cmd = strdup("gumby"); app->maxprocs = 2; pmix_argv_append(&app->argc, &app->argv, "gumby"); pmix_argv_append(&app->argc, &app->argv, "-n"); pmix_argv_append(&app->argc, &app->argv, "2"); pmix_setenv("PMIX_ENV_VALUE", "3", true, &app->env); PMIX_INFO_CREATE(app->info, 2); (void)strncpy(app->info[0].key, "DARTH", PMIX_MAX_KEYLEN); app->info[0].value.type = PMIX_INT8; app->info[0].value.data.int8 = 12; (void)strncpy(app->info[1].key, "VADER", PMIX_MAX_KEYLEN); app->info[1].value.type = PMIX_DOUBLE; app->info[1].value.data.dval = 12.34; pmix_output(0, "Client ns %s rank %d: calling PMIx_Spawn", myproc.nspace, myproc.rank); if (PMIX_SUCCESS != (rc = PMIx_Spawn(NULL, 0, app, 1, nsp2))) { pmix_output(0, "Client ns %s rank %d: PMIx_Spawn failed: %d", myproc.nspace, myproc.rank, rc); goto done; } PMIX_APP_FREE(app, 1); /* check to see if we got the expected info back */ if (0 != strncmp(nsp2, "DYNSPACE", PMIX_MAX_NSLEN)) { pmix_output(0, "Client ns %s rank %d: PMIx_Spawn returned incorrect nspace: %s", myproc.nspace, myproc.rank, nsp2); goto done; } else { pmix_output(0, "Client ns %s rank %d: PMIx_Spawn succeeded returning nspace: %s", myproc.nspace, myproc.rank, nsp2); } /* get their universe size */ (void)strncpy(proc.nspace, nsp2, PMIX_MAX_NSLEN); proc.rank = PMIX_RANK_WILDCARD; val = NULL; if (PMIX_SUCCESS != (rc = PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, &val)) || NULL == val) { pmix_output(0, "Client ns %s rank %d: PMIx_Get universe size failed: %d", myproc.nspace, myproc.rank, rc); goto done; } ntmp = val->data.uint32; PMIX_VALUE_RELEASE(val); pmix_output(0, "Client %s:%d universe %s size %d", myproc.nspace, myproc.rank, nsp2, (int)ntmp); } /* just cycle the connect/disconnect functions */ if (PMIX_SUCCESS != (rc = PMIx_Connect(&proc, 1, NULL, 0))) { pmix_output(0, "Client ns %s rank %d: PMIx_Connect failed: %d", myproc.nspace, myproc.rank, rc); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Connect succeeded", myproc.nspace, myproc.rank); if (PMIX_SUCCESS != (rc = PMIx_Disconnect(&proc, 1, NULL, 0))) { pmix_output(0, "Client ns %s rank %d: PMIx_Disonnect failed: %d", myproc.nspace, myproc.rank, rc); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Disconnect succeeded", myproc.nspace, myproc.rank); /* finally, test the resolve functions */ if (0 == myproc.rank) { if (PMIX_SUCCESS != (rc = PMIx_Resolve_peers(hostname, NULL, &peers, &npeers))) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers failed for nspace %s: %d", myproc.nspace, myproc.rank, nsp2, rc); goto done; } if ((nprocs+ntmp) != npeers) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers returned incorrect npeers: %d vs %d", myproc.nspace, myproc.rank, (int)(nprocs+ntmp), (int)npeers); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers returned %d npeers", myproc.nspace, myproc.rank, (int)npeers); if (PMIX_SUCCESS != (rc = PMIx_Resolve_nodes(nsp2, &nodelist))) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_nodes failed for nspace %s: %d", myproc.nspace, myproc.rank, nsp2, rc); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_nodes %s", myproc.nspace, myproc.rank, nodelist); } else { if (PMIX_SUCCESS != (rc = PMIx_Resolve_peers(hostname, myproc.nspace, &peers, &npeers))) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers failed for nspace %s: %d", myproc.nspace, myproc.rank, myproc.nspace, rc); goto done; } if (nprocs != npeers) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers returned incorrect npeers: %d vs %d", myproc.nspace, myproc.rank, nprocs, (int)npeers); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_peers returned %d npeers", myproc.nspace, myproc.rank, (int)npeers); if (PMIX_SUCCESS != (rc = PMIx_Resolve_nodes(myproc.nspace, &nodelist))) { pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_nodes failed: %d", myproc.nspace, myproc.rank, rc); goto done; } pmix_output(0, "Client ns %s rank %d: PMIx_Resolve_nodes %s", myproc.nspace, myproc.rank, nodelist); } PMIX_PROC_FREE(peers, npeers); free(nodelist); done: /* call fence to sync */ PMIX_PROC_CONSTRUCT(&proc); (void)strncpy(proc.nspace, myproc.nspace, PMIX_MAX_NSLEN); proc.rank = PMIX_RANK_WILDCARD; if (PMIX_SUCCESS != (rc = PMIx_Fence(&proc, 1, NULL, 0))) { pmix_output(0, "Client ns %s rank %d: PMIx_Fence failed: %d", myproc.nspace, myproc.rank, rc); goto done; } /* finalize us */ pmix_output(0, "Client ns %s rank %d: Finalizing", myproc.nspace, myproc.rank); if (PMIX_SUCCESS != (rc = PMIx_Finalize(NULL, 0))) { fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize failed: %d\n", myproc.nspace, myproc.rank, rc); } else { fprintf(stderr, "Client ns %s rank %d:PMIx_Finalize successfully completed\n", myproc.nspace, myproc.rank); } fflush(stderr); return(0); }