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
27 #if HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifndef DSHGROUP_PATH
32 #define DSHGROUP_PATH "/etc/dsh/group"
33 #endif
34
35 #include <unistd.h> /* access */
36 #include <stdlib.h> /* getenv */
37 #include <string.h>
38
39 #include "src/pdsh/wcoll.h"
40 #include "src/pdsh/mod.h"
41 #include "src/common/hostlist.h"
42 #include "src/common/xmalloc.h"
43 #include "src/common/err.h"
44 #include "src/common/list.h"
45 #include "src/common/split.h"
46
47 #if STATIC_MODULES
48 # define pdsh_module_info dshgroup_module_info
49 # define pdsh_module_priority dshgroup_module_priority
50 #endif
51
52 int pdsh_module_priority = DEFAULT_MODULE_PRIORITY;
53
54 static hostlist_t read_groupfile(opt_t *opt);
55 static int dshgroup_postop (opt_t *);
56 static int dshgroup_process_opt(opt_t *, int, char *);
57
58 static List groups = NULL;
59 static List exgroups = NULL;
60
61 /*
62 * Export pdsh module operations structure
63 */
64 struct pdsh_module_operations dshgroup_module_ops = {
65 (ModInitF) NULL,
66 (ModExitF) NULL,
67 (ModReadWcollF) read_groupfile,
68 (ModPostOpF) dshgroup_postop,
69 };
70
71 /*
72 * Export rcmd module operations
73 */
74 struct pdsh_rcmd_operations dshgroup_rcmd_ops = {
75 (RcmdInitF) NULL,
76 (RcmdSigF) NULL,
77 (RcmdF) NULL,
78 };
79
80 /*
81 * Export module options
82 */
83 struct pdsh_module_option dshgroup_module_options[] =
84 { { 'g', "groupname", "target hosts in dsh group \"groupname\"",
85 DSH | PCP, (optFunc) dshgroup_process_opt },
86 { 'X', "groupname", "exclude hosts in dsh group \"groupname\"",
87 DSH | PCP, (optFunc) dshgroup_process_opt },
88 PDSH_OPT_TABLE_END
89 };
90
91 /*
92 * Machines module info
93 */
94 struct pdsh_module pdsh_module_info = {
95 "misc",
96 "dshgroup",
97 "Mark Grondona <mgrondona@llnl.gov>",
98 "Read list of targets from dsh-style \"group\" files",
99 DSH | PCP,
100 &dshgroup_module_ops,
101 &dshgroup_rcmd_ops,
102 &dshgroup_module_options[0],
103 };
104
dshgroup_process_opt(opt_t * pdsh_opt,int opt,char * arg)105 static int dshgroup_process_opt(opt_t *pdsh_opt, int opt, char *arg)
106 {
107 switch (opt) {
108 case 'g':
109 groups = list_split_append (groups, ",", arg);
110 break;
111 case 'X':
112 exgroups = list_split_append (exgroups, ",", arg);
113 break;
114 default:
115 err ("%p: dshgroup_process_opt: invalid option `%c'\n", opt);
116 return -1;
117 break;
118 }
119 return 0;
120 }
121
_read_groupfile(const char * group)122 static hostlist_t _read_groupfile (const char *group)
123 {
124 int maxpathlen;
125 char path [4096];
126 char *home = getenv("HOME");
127 char *dshgroup_path = getenv("DSHGROUP_PATH");
128
129 maxpathlen = sizeof (path) - 1;
130
131 if (!dshgroup_path)
132 dshgroup_path = DSHGROUP_PATH;
133
134 if (home) {
135 int n;
136 n = snprintf (path, maxpathlen,"%s/.dsh/group:%s", home, dshgroup_path);
137 if (n <= 0 || n > maxpathlen)
138 errx ("%p: dshgroup: search path (%s/.dsh/group:%s) overflow\n",
139 home, dshgroup_path);
140 }
141 else {
142 err ("%p: dshgroup: warning: Unable to read $HOME env var\n");
143 strncpy (path, dshgroup_path, sizeof (path));
144 }
145
146 return read_wcoll_path (path, group);
147 }
148
_read_groups(List grouplist)149 static hostlist_t _read_groups (List grouplist)
150 {
151 ListIterator i = NULL;
152 hostlist_t hl = NULL;
153 char *group;
154
155 i = list_iterator_create (grouplist);
156
157 while ((group = list_next (i))) {
158 hostlist_t l = _read_groupfile (group);
159
160 if (l == NULL)
161 continue;
162
163 if (hl == NULL) {
164 hl = l;
165 } else {
166 hostlist_push_list (hl, l);
167 hostlist_destroy (l);
168 }
169 }
170
171 list_iterator_destroy (i);
172
173 if (hl != NULL)
174 hostlist_uniq (hl);
175
176 return (hl);
177 }
178
read_groupfile(opt_t * opt)179 static hostlist_t read_groupfile(opt_t *opt)
180 {
181 if (!groups)
182 return NULL;
183
184 if (opt->wcoll && groups)
185 errx("Do not specify both -w and -g");
186
187 return _read_groups (groups);
188 }
189
190 static int
_delete_all(hostlist_t hl,hostlist_t dl)191 _delete_all (hostlist_t hl, hostlist_t dl)
192 {
193 int rc = 0;
194 char * host = NULL;
195 hostlist_iterator_t i = hostlist_iterator_create (dl);
196
197 while ((host = hostlist_next (i))) {
198 rc += hostlist_delete_host (hl, host);
199 free (host);
200 }
201 hostlist_iterator_destroy (i);
202 return (rc);
203 }
204
dshgroup_postop(opt_t * opt)205 static int dshgroup_postop (opt_t *opt)
206 {
207 hostlist_t hl = NULL;
208
209 if (!opt->wcoll || !exgroups)
210 return (0);
211
212 if ((hl = _read_groups (exgroups)) == NULL)
213 return (0);
214
215 _delete_all (opt->wcoll, hl);
216
217 return 0;
218 }
219
220 /*
221 * vi: tabstop=4 shiftwidth=4 expandtab
222 */
223