]> git.neil.brown.name Git - metad.git/blob - meta.c
Assorted reformating
[metad.git] / meta.c
1
2 /* send commands to metad's
3  * -V   display meta version and metad versions
4  *
5  * -u   send datagrams, don't use stream connection
6  * -b   broadcast datagrams on all interfaces
7  *
8  * -r service run the service
9  *  -a args   pass args with previous run command
10  * -k service kick(run) the service
11  * -l service list the service
12  * -L         list all services
13  * -D service disable service
14  * -E service enable service
15  * -K pid/service kill process/service (Sig 15)
16  * -R         reread config
17  * -X         tell metad to exit
18  * -v         be verbose
19  * -C command send the given command
20  *
21  * -B         actually send broadcast requests
22  *
23  * other arguments are host names
24  *
25  */
26
27 #include        <stdio.h>
28 #include        <string.h>
29 #include        "metad.h"
30 #include        "args.h"
31 #include        "dlink.h"
32
33 char *progname;
34
35 void usage(char *fmt, char *arg)
36 {
37         char buf[1024];
38         sprintf(buf, fmt, arg);
39         fprintf(stderr,"%s: %s\n", progname, buf);
40         fprintf(stderr,"Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n", progname);
41 }
42
43 void help()
44 {
45         printf(
46                 "Usage: %s -[h?Vubv] -[LRXB] {-[rklDEK] service} [-C command] hostlist ...\n"
47                 "       -h          This help message\n"
48                 "       -?          As above\n"
49                 "       -V          Print version number of metac and the metad running on any\n"
50                 "                   host listed\n"
51                 "       -u          Send commands in udp datagrams. This is faster than the\n"
52                 "                   normal tcp, but\n"
53                 "                   avoids delays on dead machines.\n"
54                 "       -b          Send each request as a broadcast on any available network\n"
55                 "                   interfaces.\n"
56                 "       -v          Be verbose when listing services.\n"
57                 "       -L          List all services supported by the metad on the remote host.\n"
58                 "       -R          Tell metad to reread it's configuration file.\n"
59                 "       -X          Tell metad to eXit.\n"
60                 "       -B          Tell the metad to rebroadcast the request on it's\n"
61                 "                   interfaces.\n"
62                 "       -r service  Try to start a process running for the service.\n"
63                 "       -k service  Kick a service into action, same as above.\n"
64                 "       -l service  List details of the named service.\n"
65                 "       -D service  Disable a service. No more processes will be started for\n"
66                 "                   that service.\n"
67                 "       -E service  Enable a service. Metad will start processes as\n"
68                 "                   appropriate.\n"
69                 "       -K pid      Of metad is managing a process with number pid, then it\n"
70                 "                   is sent a SIGTERM.\n"
71                 "       -K service  Every process running for the given service is sent a\n"
72                 "                   SIGTERM.\n"
73                 "       -C command  Send the given command (which will usually be quoted).\n"
74                 "    Commands are:\n"
75                 "       run service args       like -r, but allows args to be passed to\n"
76                 "                              the process.\n"
77                 "       kill signum pid-or-service  like -K, but allows a signal number\n"
78                 "                             to be given.\n"
79                 "       restart               tell metad to re-exec itself, for use when a\n"
80                 "                             new version is installed\n"
81                 "     (plus others that duplicate the above flags)\n"
82                 , progname)  ;
83 }
84
85 int main(int argc, char *argv[])
86 {
87         void *cmds = dl_head();
88         void *hosts = dl_head();
89         int local_broad = 0;
90         int remote_broad = 0;
91         int use_dgram = 0;
92         int show_version = 0;
93         int show_help = 0;
94         int verbose = 0;
95         char *c, *c2;
96         void *opts = args_init(argc, argv, "??h?V?u?b?r:a:k:l:L?D:E:K:R?X?v?C:B?");
97         int opt;
98         char *arg;
99         int pos, inv;
100         progname = strrchr(argv[0], '/');
101         if (progname) progname++; else progname = argv[0];
102
103         while ((opt = args_next(opts, &pos, &inv, &arg))!= END_ARGS)
104                 switch(opt)
105                 {
106                 case BAD_FLAG:
107                         usage("Bad option: %s", argv[pos]);
108                         exit(1);
109                 case NO_FLAG:
110                         c = dl_strdup(arg);
111                         dl_add(hosts, c);
112                         break;
113                 case 'h':
114                 case '?':
115                         show_help = 1;
116                         break;
117                 case 'V':               /* my version number */
118                         printf("%s: version %s\n", progname, version);
119                         show_version  =1;
120                         break;
121                 case 'u':
122                         use_dgram = 1;
123                         break;
124                 case 'b':
125                         local_broad = 1;
126                         break;
127                 case 'r':
128                 case 'k':
129                         c = dl_strndup("kick ", 5+strlen(arg)+1);
130                         strcat(c, arg);
131                         dl_add(cmds, c);
132                         break;
133                 case 'a':
134                         c = dl_prev(cmds);
135                         if (c == cmds || (strncmp(c, "kick ", 5)!= 0 && strncmp(c, "run ", 4)!= 0))
136                         {
137                                 usage("%s: -a only valid after -r or -k", NULL);
138                                 exit(1);
139                         }
140                         c2 = dl_strndup(c, strlen(c)+1+strlen(arg)+1);
141                         strcat(c2, " ");
142                         strcat(c2, arg);
143                         dl_del(c); dl_free(c);
144                         dl_add(cmds, c2);
145                         break;
146                 case 'l':
147                         c = dl_strndup("list ", 5+strlen(arg)+1);
148                         strcat(c, arg);
149                         dl_add(cmds, c);
150                         break;
151                 case 'L':
152                         c = dl_strdup("list");
153                         dl_add(cmds, c);
154                         break;
155                 case 'D':
156                         c = dl_strndup("disable ", 8+strlen(arg)+1);
157                         strcat(c, arg);
158                         dl_add(cmds, c);
159                         break;
160                 case 'E':
161                         c = dl_strndup("enable ", 7+strlen(arg)+1);
162                         strcat(c, arg);
163                         dl_add(cmds, c);
164                         break;
165                 case 'K':
166                         c = dl_strndup("kill 15 ", 8+strlen(arg)+1);
167                         strcat(c, arg);
168                         dl_add(cmds, c);
169                         break;
170                 case 'R':
171                         c = dl_strdup("reread");
172                         dl_add(cmds, c);
173                         break;
174                 case 'X':
175                         c = dl_strdup("die");
176                         dl_add(cmds, c);
177                         break;
178                 case 'v':
179                         verbose = 1;
180                         break;
181                 case 'C':
182                         c  = dl_strdup(arg);
183                         dl_add(cmds, c);
184                         break;
185                 case 'B':
186                         remote_broad = 1;
187                         break;
188                 }
189
190         if (show_help) {
191                 help();
192                 exit(0);
193         }
194         if (dl_next(hosts) == hosts && local_broad == 0) {
195                 /* no where to send to... */
196                 if (dl_next(cmds) != cmds) {
197                         fprintf(stderr,"%s: commands were specified with no where to send them!\n", progname);
198                         exit(1);
199                 }
200                 /* nothing to do, though might has displayed version.
201                  * Should probably give usage...
202                  */
203                 if (show_version == 0)
204                         usage("Nothing to do", NULL), exit(1);
205                 exit(0);
206         }
207
208         if (dl_next(hosts) != hosts && local_broad) {
209                 fprintf(stderr, "%s: you probably don't want to broadcast AND list hosts...\n", progname);
210                 exit(1);
211         }
212
213         if (show_version) {
214                 c = dl_strdup("version");
215                 dl_insert(cmds, c);
216         }
217         for (c= dl_next(cmds) ; c != cmds ; c = dl_next(c)) {
218                 char *cmd = (char*)malloc(10 + strlen(c)); /* make sure there is room for port and broad */
219                 char *h;
220
221                 strcpy(cmd, "1 ");
222                 if (remote_broad)
223                         strcat(cmd, "BROAD ");
224                 strcat(cmd, c);
225                 if (local_broad)
226                         broadcast(cmd);
227                 else for (h=dl_next(hosts) ; h != hosts ; h = dl_next(h))
228                 {
229                         if (strcmp(h, ".")== 0)
230                                 send_cmd(cmd, use_dgram, "localhost", verbose);
231                         else
232                                 send_cmd(cmd, use_dgram, h, verbose);
233                 }
234         }
235         exit(0); /* FIXME what exit status */
236 }