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