/* * rpmem_ssh_execv -- open ssh connection and run $RPMEMD_CMD with * additional NULL-terminated list of arguments. */ struct rpmem_ssh * rpmem_ssh_execv(const struct rpmem_target_info *info, const char **argv) { 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; char *cmd = get_cmd(argv); if (!cmd) goto err_cmd; 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, cmd); if (ret) goto err_push; ret = rpmem_cmd_run(rps->cmd); if (ret) goto err_run; free(user_at_node); free(cmd); return rps; err_run: err_push: free(cmd); err_cmd: rpmem_cmd_fini(rps->cmd); err_cmd_init: free(user_at_node); err_user_node: free(rps); err_zalloc: 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; }