/** * Forms a complete pathname and checks it for existance and * permissions * * Accepts: * -fname File name * -path Path prefix * -mode Target permissions which must be satisfied * * Returns: * -Full pathname of located file Success * -NULL Failure */ char *pmix_path_access(char *fname, char *path, int mode) { char *fullpath = NULL; struct stat buf; /* Allocate space for the full pathname. */ if (NULL == path) { fullpath = pmix_os_path(false, fname, NULL); } else { fullpath = pmix_os_path(false, path, fname, NULL); } if (NULL == fullpath) return NULL; /* first check to see - is this a file or a directory? We * only want files */ if (0 != stat(fullpath, &buf)) { /* couldn't stat the path - obviously, this also meets the * existence check, if that was requested */ free(fullpath); return NULL; } if (!(S_IFREG & buf.st_mode) && !(S_IFLNK & buf.st_mode)) { /* this isn't a regular file or a symbolic link, so * ignore it */ free(fullpath); return NULL; } /* check the permissions */ if ((X_OK & mode) && !(S_IXUSR & buf.st_mode)) { /* if they asked us to check executable permission, * and that isn't set, then return NULL */ free(fullpath); return NULL; } if ((R_OK & mode) && !(S_IRUSR & buf.st_mode)) { /* if they asked us to check read permission, * and that isn't set, then return NULL */ free(fullpath); return NULL; } if ((W_OK & mode) && !(S_IWUSR & buf.st_mode)) { /* if they asked us to check write permission, * and that isn't set, then return NULL */ free(fullpath); return NULL; } /* must have met all criteria! */ return fullpath; }
/** * Try to figure out the absolute path based on the application name * (usually argv[0]). If the path is already absolute return a copy, if * it start with . look into the current directory, if not dig into * the $PATH. * In case of error or if executable was not found (as an example if * the application did a cwd between the start and this call), the * function will return NULL. Otherwise, an newly allocated string * will be returned. */ char* pmix_find_absolute_path( char* app_name ) { char* abs_app_name; char cwd[PMIX_PATH_MAX], *pcwd; if( pmix_path_is_absolute(app_name) ) { /* already absolute path */ abs_app_name = app_name; } else if ( '.' == app_name[0] || NULL != strchr(app_name, PMIX_PATH_SEP[0])) { /* the app is in the current directory or below it */ pcwd = getcwd( cwd, PMIX_PATH_MAX ); if( NULL == pcwd ) { /* too bad there is no way we can get the app absolute name */ return NULL; } abs_app_name = pmix_os_path( false, pcwd, app_name, NULL ); } else { /* Otherwise try to search for the application in the PATH ... */ abs_app_name = pmix_path_findv( app_name, X_OK, NULL, NULL ); } if( NULL != abs_app_name ) { char* resolved_path = (char*)malloc(PMIX_PATH_MAX); if (NULL == realpath( abs_app_name, resolved_path )) { return NULL; } if( abs_app_name != app_name ) free(abs_app_name); return resolved_path; } return NULL; }
static pmix_status_t df_search(char *dirname, char *prefix, int *sd, char **nspace, pmix_rank_t *rank) { char *suri, *nsp, *newdir; pmix_rank_t rk; pmix_status_t rc; struct stat buf; DIR *cur_dirp; struct dirent *dir_entry; if (NULL == (cur_dirp = opendir(dirname))) { return PMIX_ERR_NOT_FOUND; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp: searching directory %s", dirname); /* search the entries for something that starts with the provided prefix */ while (NULL != (dir_entry = readdir(cur_dirp))) { /* ignore the . and .. entries */ if (0 == strcmp(dir_entry->d_name, ".") || 0 == strcmp(dir_entry->d_name, "..")) { continue; } newdir = pmix_os_path(false, dirname, dir_entry->d_name, NULL); if (-1 == stat(newdir, &buf)) { free(newdir); continue; } /* if it is a directory, down search */ if (S_ISDIR(buf.st_mode)) { rc = df_search(newdir, prefix, sd, nspace, rank); free(newdir); if (PMIX_SUCCESS == rc) { closedir(cur_dirp); return rc; } continue; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp: checking %s vs %s", dir_entry->d_name, prefix); /* see if it starts with our prefix */ if (0 == strncmp(dir_entry->d_name, prefix, strlen(prefix))) { /* try to read this file */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp: reading file %s", newdir); rc = parse_uri_file(newdir, &suri, &nsp, &rk); if (PMIX_SUCCESS == rc) { if (NULL != mca_ptl_tcp_component.super.uri) { free(mca_ptl_tcp_component.super.uri); } mca_ptl_tcp_component.super.uri = suri; /* go ahead and try to connect */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix:tcp: attempting to connect to %s", suri); if (PMIX_SUCCESS == try_connect(sd)) { (*nspace) = nsp; *rank = rk; closedir(cur_dirp); free(newdir); return PMIX_SUCCESS; } free(nsp); } } free(newdir); } closedir(cur_dirp); return PMIX_ERR_NOT_FOUND; }
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; }