/src/pdsh/rcmd.c

https://code.google.com/ · C · 432 lines · 291 code · 87 blank · 54 comment · 62 complexity · f311124f9d0b785b6750311ce82bb47f MD5 · raw file

  1. /*****************************************************************************\
  2. * $Id$
  3. *****************************************************************************
  4. * Copyright (C) 2005-2006 The Regents of the University of California.
  5. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6. * Written by Mark Grondona <mgrondona@llnl.gov>.
  7. * UCRL-CODE-2003-005.
  8. *
  9. * This file is part of Pdsh, a parallel remote shell program.
  10. * For details, see <http://www.llnl.gov/linux/pdsh/>.
  11. *
  12. * Pdsh is free software; you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. *
  17. * Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY
  18. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with Pdsh; if not, write to the Free Software Foundation, Inc.,
  24. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  25. \*****************************************************************************/
  26. #if HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29. #include <assert.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <errno.h>
  33. #include "src/common/err.h"
  34. #include "src/common/xmalloc.h"
  35. #include "src/common/xstring.h"
  36. #include "src/common/list.h"
  37. #include "opt.h"
  38. #include "mod.h"
  39. #include "rcmd.h"
  40. /*
  41. * Ordered preference for determining default rcmd method.
  42. * Warning: If none of these modules are loaded, there will be no default.
  43. */
  44. static char * rcmd_rank[] =
  45. #if defined(RCMD_RANK_LIST)
  46. { RCMD_RANK_LIST, NULL };
  47. #else
  48. { "mrsh", "rsh", "ssh", "krb4", "qsh", "mqsh", "exec", "xcpu", NULL };
  49. #endif /* RCMD_RANK_LIST */
  50. struct rcmd_module {
  51. char * name;
  52. mod_t mod;
  53. struct rcmd_options options;
  54. RcmdInitF init;
  55. RcmdSigF signal;
  56. RcmdF rcmd;
  57. RcmdDestroyF rcmd_destroy;
  58. };
  59. struct node_rcmd_info {
  60. char *hostname;
  61. char *username;
  62. struct rcmd_module *rmod;
  63. };
  64. static List host_info_list = NULL;
  65. static List rcmd_module_list = NULL;
  66. static struct rcmd_module *default_rcmd_module = NULL;
  67. static struct rcmd_module *current_rcmd_module = NULL;
  68. static struct node_rcmd_info *
  69. node_rcmd_info_create (char *hostname, char *user, struct rcmd_module *module)
  70. {
  71. struct node_rcmd_info *n = Malloc (sizeof (*n));
  72. if (!n)
  73. return NULL;
  74. n->hostname = Strdup (hostname);
  75. n->username = Strdup (user);
  76. n->rmod = module;
  77. return (n);
  78. }
  79. static void node_rcmd_info_destroy (struct node_rcmd_info *n)
  80. {
  81. if (!n)
  82. return;
  83. Free ((void **)&n->hostname);
  84. if (n->username)
  85. Free ((void **)&n->username);
  86. Free ((void **)&n);
  87. }
  88. struct rcmd_module * rcmd_module_create (mod_t mod)
  89. {
  90. struct rcmd_module *rmod = Malloc (sizeof (*rmod));
  91. rmod->mod = mod;
  92. rmod->name = mod_get_name (mod);
  93. if (!(rmod->init = (RcmdInitF) mod_get_rcmd_init(mod))) {
  94. err("Unable to resolve \"rcmd_init\" in module \"%s\"\n",
  95. mod_get_name(mod));
  96. goto fail;
  97. }
  98. if (!(rmod->signal = (RcmdSigF) mod_get_rcmd_signal(mod))) {
  99. err("Unable to resolve \"rcmd_signal\" in module \"%s\"\n",
  100. mod_get_name(mod));
  101. goto fail;
  102. }
  103. if (!(rmod->rcmd = (RcmdF) mod_get_rcmd(mod))) {
  104. err("Unable to resolve \"rcmd\" in module \"%s\"\n",
  105. mod_get_name(mod));
  106. goto fail;
  107. }
  108. /*
  109. * Destroy function not required
  110. */
  111. rmod->rcmd_destroy = (RcmdDestroyF) mod_get_rcmd_destroy (mod);
  112. rmod->options.resolve_hosts = 1;
  113. return (rmod);
  114. fail:
  115. Free ((void **) &rmod);
  116. return (NULL);
  117. }
  118. static void rcmd_module_destroy (struct rcmd_module *rmod)
  119. {
  120. Free ((void **) &rmod);
  121. }
  122. static int find_rcmd_module (struct rcmd_module *x, char *name)
  123. {
  124. return (strcmp (x->name, name) == 0);
  125. }
  126. static int find_host (struct node_rcmd_info *x, char *hostname)
  127. {
  128. return (strcmp (x->hostname, hostname) == 0);
  129. }
  130. static struct node_rcmd_info * host_rcmd_info (char *host)
  131. {
  132. if (host_info_list == NULL)
  133. return (NULL);
  134. return (list_find_first (host_info_list, (ListFindF) find_host, host));
  135. }
  136. static struct rcmd_module * rcmd_module_register (char *name)
  137. {
  138. mod_t mod = NULL;
  139. struct rcmd_module *rmod = NULL;
  140. if (rcmd_module_list == NULL)
  141. rcmd_module_list = list_create ((ListDelF) rcmd_module_destroy);
  142. else
  143. rmod = list_find_first (rcmd_module_list,
  144. (ListFindF) find_rcmd_module,
  145. name);
  146. if (rmod != NULL)
  147. return (rmod);
  148. if (!(mod = mod_get_module ("rcmd", name))) {
  149. err ("No such rcmd module \"%s\"\n", name);
  150. return (NULL);
  151. }
  152. if (!(rmod = rcmd_module_create (mod)))
  153. return (NULL);
  154. if (!list_append (rcmd_module_list, rmod)) {
  155. err ("Failed to append rcmd module \"%s\"\n", name);
  156. rcmd_module_destroy (rmod);
  157. return (NULL);
  158. }
  159. return (rmod);
  160. }
  161. static int hostlist_register_rcmd (const char *hosts, struct rcmd_module *rmod,
  162. char *user)
  163. {
  164. hostlist_t hl = hostlist_create (hosts);
  165. char * host;
  166. if (hl == NULL)
  167. return (-1);
  168. if (host_info_list == NULL)
  169. host_info_list = list_create ((ListDelF) node_rcmd_info_destroy);
  170. while ((host = hostlist_pop (hl))) {
  171. struct node_rcmd_info *n = NULL;
  172. /*
  173. * Do not override previously installed host info. First registered
  174. * rcmd type for a host wins. This allows command line to override
  175. * everything else.
  176. */
  177. if (list_find_first (host_info_list, (ListFindF) find_host, host))
  178. continue;
  179. if ((n = node_rcmd_info_create (host, user, rmod)) == NULL)
  180. errx ("Failed to create rcmd info for host \"%s\"\n", host);
  181. list_append (host_info_list, n);
  182. free (host);
  183. }
  184. hostlist_destroy (hl);
  185. return (0);
  186. }
  187. /*
  188. * Walk through list of default candidate modules, starting at head,
  189. * and return the first module that is loaded.
  190. * Unless rcmd_default_module is already registered.
  191. */
  192. char * rcmd_get_default_module (void)
  193. {
  194. mod_t mod = NULL;
  195. int i = 0;
  196. const char *name = NULL;
  197. if (default_rcmd_module != NULL)
  198. return (default_rcmd_module->name);
  199. while ((name = rcmd_rank[i++]) && !mod)
  200. mod = mod_get_module ("rcmd", name);
  201. return mod ? mod_get_name (mod) : NULL;
  202. }
  203. int rcmd_register_default_rcmd (char *rcmd_name)
  204. {
  205. struct rcmd_module *rmod = NULL;
  206. if (!(rmod = rcmd_module_register (rcmd_name)))
  207. return (-1);
  208. default_rcmd_module = rmod;
  209. return (0);
  210. }
  211. int rcmd_register_defaults (char *hosts, char *rcmd_name, char *user)
  212. {
  213. struct rcmd_module *rmod = NULL;
  214. if (rcmd_name && !(rmod = rcmd_module_register (rcmd_name)))
  215. return (-1);
  216. /* If host list is NULL, we are registering a new global default
  217. * rcmd module. Set the convenience pointer and return
  218. */
  219. if (hosts == NULL) {
  220. default_rcmd_module = rmod;
  221. return (0);
  222. }
  223. if (hostlist_register_rcmd (hosts, rmod, user) < 0)
  224. return (-1);
  225. return (0);
  226. }
  227. struct rcmd_info * rcmd_info_create (struct rcmd_module *rmod)
  228. {
  229. struct rcmd_info *r = Malloc (sizeof (*r));
  230. if (r == NULL)
  231. return (NULL);
  232. r->fd = -1;
  233. r->efd = -1;
  234. r->rmod = rmod;
  235. r->opts = &rmod->options;
  236. r->arg = NULL;
  237. r->ruser = NULL;
  238. return (r);
  239. }
  240. void rcmd_info_destroy (struct rcmd_info *r)
  241. {
  242. Free ((void **) &r);
  243. }
  244. struct rcmd_info * rcmd_create (char *host)
  245. {
  246. struct rcmd_info *rcmd = NULL;
  247. struct rcmd_module *rmod = NULL;
  248. struct node_rcmd_info *n = NULL;
  249. if ((n = host_rcmd_info (host))) {
  250. rmod = n->rmod;
  251. }
  252. /*
  253. * If no rcmd module use default
  254. */
  255. if (rmod == NULL) {
  256. if ((rmod = default_rcmd_module) == NULL) {
  257. err ("%p: No rcmd module for \"%s\"\n", host);
  258. return (NULL);
  259. }
  260. }
  261. if ((rcmd = rcmd_info_create (rmod)) == NULL) {
  262. err ("%p: Unable to allocate rcmd info for \"%s\"\n", host);
  263. return (NULL);
  264. }
  265. if (n != NULL && n->username)
  266. rcmd->ruser = n->username;
  267. return (rcmd);
  268. }
  269. int rcmd_connect (struct rcmd_info *rcmd, char *ahost, char *addr,
  270. char *locuser, char *remuser, char *cmd, int nodeid,
  271. bool error_fd)
  272. {
  273. /*
  274. * rcmd->ruser overrides default
  275. */
  276. if (rcmd->ruser)
  277. remuser = rcmd->ruser;
  278. rcmd->fd = (*rcmd->rmod->rcmd) (ahost, addr, locuser, remuser, cmd, nodeid,
  279. error_fd ? &rcmd->efd : NULL, &rcmd->arg);
  280. return (rcmd->fd);
  281. }
  282. int rcmd_destroy (struct rcmd_info *rcmd)
  283. {
  284. int rc = 0;
  285. if (rcmd == NULL)
  286. return (0);
  287. if (rcmd->rmod->rcmd_destroy)
  288. rc = (*rcmd->rmod->rcmd_destroy) (rcmd->arg);
  289. rcmd_info_destroy (rcmd);
  290. return (rc);
  291. }
  292. int rcmd_signal (struct rcmd_info *rcmd, int signum)
  293. {
  294. assert (rcmd != NULL);
  295. assert (rcmd->rmod != NULL);
  296. return (*rcmd->rmod->signal) (rcmd->efd, rcmd->arg, signum);
  297. }
  298. int rcmd_init (opt_t *opt)
  299. {
  300. struct rcmd_module *r = NULL;
  301. ListIterator i;
  302. if (!rcmd_module_list) {
  303. if (default_rcmd_module == NULL)
  304. return (-1);
  305. current_rcmd_module = default_rcmd_module;
  306. (*default_rcmd_module->init) (opt);
  307. current_rcmd_module = NULL;
  308. return (0);
  309. }
  310. i = list_iterator_create (rcmd_module_list);
  311. while ((r = list_next (i))) {
  312. current_rcmd_module = r;
  313. (*r->init) (opt);
  314. current_rcmd_module = NULL;
  315. }
  316. list_iterator_destroy (i);
  317. return (0);
  318. }
  319. int rcmd_exit (void)
  320. {
  321. if (host_info_list)
  322. list_destroy (host_info_list);
  323. if (rcmd_module_list)
  324. list_destroy (rcmd_module_list);
  325. return (0);
  326. }
  327. int rcmd_opt_set (int id, void * value)
  328. {
  329. if (current_rcmd_module == NULL) {
  330. errno = ESRCH;
  331. return (-1);
  332. }
  333. switch (id) {
  334. case RCMD_OPT_RESOLVE_HOSTS:
  335. current_rcmd_module->options.resolve_hosts = (long int) value;
  336. break;
  337. default:
  338. errno = EINVAL;
  339. return (-1);
  340. }
  341. return (0);
  342. }
  343. /*
  344. * vi: ts=4 sw=4 expandtab
  345. */