/* * get_cmd -- return an RPMEM_CMD with appended list of arguments */ static char * get_cmd(const char **argv) { const char *env_cmd = rpmem_util_cmd_get(); char *cmd = strdup(env_cmd); if (!cmd) return NULL; size_t cmd_len = strlen(cmd) + 1; const char *arg; while ((arg = *argv++) != NULL) { size_t len = strlen(arg); size_t new_cmd_len = cmd_len + len + 1; char *tmp = realloc(cmd, new_cmd_len); if (!tmp) goto err; cmd = tmp; /* append the argument to the command */ cmd[cmd_len - 1] = ' '; memcpy(&cmd[cmd_len], arg, len); cmd[cmd_len + len] = '\0'; cmd_len = new_cmd_len; } return cmd; err: free(cmd); return NULL; }
/* * rpmem_ssh_open -- open ssh connection with specified node */ struct rpmem_ssh * rpmem_ssh_open(const struct rpmem_target_info *info) { struct rpmem_ssh *rps = calloc(1, sizeof(*rps)); if (!rps) goto err_zalloc; char *user_at_node = get_user_at_node(info); if (!user_at_node) goto err_user_node; rps->cmd = rpmem_cmd_init(); if (!rps->cmd) goto err_cmd_init; int ret = rpmem_cmd_push(rps->cmd, get_ssh()); if (ret) goto err_push; if (info->flags & RPMEM_HAS_SERVICE) { /* port number is optional */ ret = rpmem_cmd_push(rps->cmd, "-p"); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, info->service); if (ret) goto err_push; } /* * Disable allocating pseudo-terminal in order to transfer binary * data safely. */ ret = rpmem_cmd_push(rps->cmd, "-T"); if (ret) goto err_push; if (info->flags & RPMEM_FLAGS_USE_IPV4) { ret = rpmem_cmd_push(rps->cmd, "-4"); if (ret) goto err_push; } /* fail if password required for authentication */ ret = rpmem_cmd_push(rps->cmd, "-oBatchMode=yes"); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, user_at_node); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, rpmem_util_cmd_get()); if (ret) goto err_push; ret = rpmem_cmd_run(rps->cmd); if (ret) goto err_run; /* * Read initial status from invoked command. * This is for synchronization purposes and to make it possible * to inform client that command's initialization failed. */ int32_t status; ret = rpmem_ssh_recv(rps, &status, sizeof(status)); if (ret) { if (ret == 1 || errno == ECONNRESET) ERR("%s", rpmem_ssh_strerror(rps)); else ERR("!%s", info->node); goto err_recv_status; } if (status) { ERR("%s: unexpected status received -- '%d'", info->node, status); goto err_status; } RPMEM_LOG(INFO, "received status: %u", status); free(user_at_node); return rps; err_status: err_recv_status: err_run: rpmem_cmd_term(rps->cmd); rpmem_cmd_wait(rps->cmd, NULL); err_push: rpmem_cmd_fini(rps->cmd); err_cmd_init: free(user_at_node); err_user_node: free(rps); err_zalloc: return NULL; }