]> git.neil.brown.name Git - metad.git/blob - commands.c
Assorted reformating
[metad.git] / commands.c
1
2 #include        "metad.h"
3 #include        "skip.h"
4
5 /* the commands are handled here */
6
7 static char *gather_arg(char **args)
8 {
9         char *line;
10         int len = 0;
11         int a;
12         for (a=0 ; args[a] ; a++) len += strlen(args[a])+1;
13         line = (char*)malloc(len+1);
14         len = 0;
15         for (a=0 ; args[a] ; a++)
16         {
17                 strcpy(line+len, args[a]);
18                 len += strlen(args[a]);
19                 line[len++] = ' ';
20         }
21         if (len>0)
22                 line[len-1] = '\0';
23         else
24                 line[len] = 0;
25         return line;
26 }
27
28 static void do_version(char **args, char *host, void *con)
29 {
30         char *rv;
31
32         if (con) {
33                 rv = (char*)malloc(strlen(version)+2);
34                 strcpy(rv+1, version);
35                 rv[0] = 2;
36                 set_reply(con, rv, strlen(version)+2);
37         }
38 }
39
40
41 static void do_broad(char **args, char *host, void *con)
42 {
43         /* remaining args are packaged up and broadcast on all interfaces */
44         char *line;
45         line = gather_arg(args+1);
46         logmsg(LOG_INFO, "Broadcast request from %s for %s", host, line);
47         broadcast(line);
48         free(line);
49 }
50
51 static void do_die(char **args, char *host, void *con)
52 {
53         logmsg(LOG_WARNING, "Die request from %s", host);
54         exit(1);
55 }
56
57 static void do_disable(char **args, char *host, void *con)
58 {
59         service_t sv;
60         if (args[1] == NULL)
61                 return_error(con, "No service given for disabling");
62         else if ((sv=find_service(args[1]))==NULL)
63                 return_error(con, "Cannot find service %s to disable it", args[1]);
64         else for ( ; sv ; sv=find_service(NULL))
65                 if (sv->enabled) {
66                         logmsg(LOG_INFO, "Disable request from %s for %s", host, sv->service);
67                         (sv->class->disable_service)(sv);
68                         sv->enabled = 0;
69                 }
70 }
71
72 static void do_enable(char **args, char *host, void *con)
73 {
74         service_t sv;
75         if (args[1] == NULL)
76                 return_error(con, "No service given for enabling");
77         else if ((sv=find_service(args[1]))==NULL)
78                 return_error(con, "Cannot find service %s to enable it", args[1]);
79         else for ( ; sv ; sv=find_service(NULL))
80                 if (!sv->enabled) {
81                         logmsg(LOG_INFO, "Enable request from %s for %s", host, sv->service);
82                         (sv->class->register_service)(sv);
83                         sv->enabled = 1;
84                 }
85 }
86
87
88 static void do_run(char **args, char *host, void *con)
89 {
90         /* attempt to run service called args[1] with METAD_ARG set to remaining args and METAD_HOST set to host
91          */
92         service_t sv;
93         if (args[1] == NULL)
94                 return_error(con, "No service given to run");
95         else if ((sv=find_service(args[1]))==NULL)
96                 return_error(con, "Cannot find service %s to run", args[1]);
97         else {
98                 char *env[3];
99                 char *arg = gather_arg(args+2);
100                 env[0] = strcat(strcpy((char*)malloc(20+strlen(host)), "METAD_REASON=run:"), host);
101                 env[1] = strcat(strcpy((char*)malloc(11+strlen(arg)), "METAD_ARG="), arg);
102                 env[2] = NULL;
103                 for ( ; sv ; sv = find_service(NULL))
104                 {
105                         /* first clear all hold-times */
106                         proc_t *pp;
107                         for (pp=skip_first(sv->proc_list) ; pp ; pp=skip_next(pp))
108                                 if ((*pp)->hold_time != 0)
109                                         (*pp)->hold_time = 1;
110                         sv->next_hold = 2;
111                         logmsg(LOG_INFO,"starting %s for %s : arg = %s", sv->service, host, arg);
112                         new_proc(sv, env);
113                 }
114                 free(arg);
115                 free(env[1]);
116                 free(env[0]);
117         }
118 }
119
120 static void do_kill(char **args, char *host, void *con)
121 {
122         /* args[1] = signal
123          * args[2] = pid or service name
124          */
125         int sig;
126         pid_t pid;
127         service_t sv;
128         if (args[1] == NULL)
129                 return_error(con, "No signal number given for kill");
130         else if ((sig=atoi(args[1]))<= 0)
131                 return_error(con, "Bad signal number given for kill: %s", args[1]);
132         else if (args[2] == NULL)
133                 return_error(con, "No process id or service name given for kill");
134         else if ((pid = atoi(args[2]))>0) {
135                 proc_t *pp = skip_search(allprocs, &pid);
136                 if (pp) {
137                         logmsg(LOG_INFO, "killing %s for %s", args[2], host);
138                         if ((*pp)->exit_time == 0)
139                                 kill((*pp)->pid, sig);
140                         else if ((*pp)->it_forked > 1)
141                                 kill((*pp)->it_forked, sig);
142                 } else
143                         return_error(con, "Cannot find process %s to kill", args[2]);
144         } else if ((sv = find_service(args[2]))!= NULL) {
145                 for ( ; sv ; sv = find_service(NULL)) {
146                         proc_t *pp;
147                         for (pp = skip_first(sv->proc_list) ; pp ; pp = skip_next(pp))
148                                 if ((*pp)->exit_time == 0 || (*pp)->it_forked) {
149                                         logmsg(LOG_INFO,
150                                                "signalling %s:%d with %d for %s", sv->service,
151                                                (*pp)->exit_time?(*pp)->it_forked:(*pp)->pid,
152                                                sig, host);
153                                         if ((*pp)->exit_time == 0)
154                                                 kill((*pp)->pid, sig);
155                                         else if ((*pp)->it_forked > 1)
156                                                 kill((*pp)->it_forked, sig);
157                                 }
158                 }
159         }
160         else
161                 return_error(con, "Cannot find service %s to kill", args[2]);
162 }
163
164
165 static void do_reread(char **args, char *host, void *con)
166 {
167         char *errs = NULL;
168         int old;
169         logmsg(LOG_INFO, "Rereading config file for %s", host);
170         old= errors_to(ERROR_STRING, &errs);
171         if (read_config(services, NULL) != 0)
172                 return_error(con, "%s", errs);
173         errors_to(old, NULL);
174         if (errs) free(errs);
175 }
176
177 static void do_list(char **args, char *host, void *con)
178 {
179         service_t sv, *svp;
180         init_return();
181         send_byte(3); /* listing */
182         if (args[1] == NULL) {
183                 for (svp = skip_first(services) ; svp ; svp = skip_next(svp))
184                         send_service(*svp);
185
186                 send_byte(0); /* finished */
187                 do_send(con);
188         }
189         else if ((sv=find_service(args[1])) != NULL) {
190                 for ( ; sv ; sv = find_service(NULL))
191                         send_service(sv);
192                 send_byte(0);
193                 do_send(con);
194         } else
195                 return_error(con, "Cannot find service %s to list", args[1]);
196 }
197
198 void do_restart(char **args, char *host, void *con)
199 {
200         logmsg(LOG_INFO, "About to restart for %s", host);
201         control_close();
202         prepare_restart();
203         restart();
204         exit(0);
205 }
206
207 static struct commands cmds[] = {
208         { "list",       do_list},
209         { "version",    do_version},
210         { "broad",      do_broad},
211         { "die",        do_die},
212         { "disable",    do_disable},
213         { "enable",     do_enable},
214         { "kick",       do_run},
215         { "run",        do_run},
216         { "kill",       do_kill},
217         { "reread",     do_reread},
218         { "restart",    do_restart},
219         { NULL, NULL}
220 };
221
222 int do_command(char **args, char *host, void *con)
223 {
224         int cmd = 0;
225         for (cmd = 0; cmds[cmd].name ; cmd++)
226                 if (strcasecmp(cmds[cmd].name, args[0])==0)
227                         break;
228         if (cmds[cmd].name) {
229                 (cmds[cmd].proc)(args, host, con);
230                 return 1;
231         } else
232                 return 0;
233 }