]> andersk Git - moira.git/blob - dcm/dcm.c
possible NULL reference
[moira.git] / dcm / dcm.c
1 /*
2  * The Data Control Manager for MOIRA.
3  *
4  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
5  * For copying and distribution information, see the file
6  * "mit-copyright.h".
7  *
8  * $Source$
9  * $Author$
10  * $Header$
11  */
12
13 #ifndef lint
14 static char rcsid_dcm_c[] = "$Header$";
15 #endif lint
16
17 #include <stdio.h>
18 #include <update.h>
19 #include <sys/file.h>
20 #include <sys/time.h>
21 #include <sys/wait.h>
22 #include <signal.h>
23 #include <ctype.h>
24 #include <moira.h>
25 #include <moira_site.h>
26 #include "dcm.h"
27 #include "mit-copyright.h"
28
29 extern char *ctime();
30 extern char *getenv();
31 extern int log_flags;
32 extern char *error_message();
33 char *itoa();
34 int gqval();
35 long time();
36
37
38 /* declared global so that we can get the current time from different places. */
39 struct timeval tv;
40
41
42 main(argc, argv)
43 int argc;
44 char *argv[];
45 {
46         int i;
47         char **arg = argv;
48         char *qargv[3];
49         char *s;
50         int status;
51
52         whoami = argv[0];
53         s = getenv("DEBUG");
54         dbg = s ? atoi(s) : 0;
55         umask(UMASK);
56         log_flags = 0;
57         setlinebuf(stderr);
58         setlinebuf(stdout);
59         
60         while(++arg - argv < argc) {
61             if (**arg == '-')
62                 switch((*arg)[1]) {
63                 case 'd':
64                     dbg =  atoi((*arg)[2]? *arg+2: *++arg);
65                     break;
66                 }
67         }
68         set_com_err_hook(dcm_com_err_hook);
69         
70         /* if /etc/nodcm exists, punt quietly. */
71         if (!access(NODCMFILE, F_OK)) {
72                 exit(1);
73         } 
74
75         if (status = mr_connect("")) {
76             com_err(whoami, status, " on mr_connect");
77             leave("connect failed");
78         }
79
80         if (status = mr_auth("dcm")) {
81             com_err(whoami, status, " on \"authenticate\"");
82             leave("auth failed");
83         }
84
85         /* if DCM is not enabled, exit after logging */
86         qargv[0] = "dcm_enable";
87         if (status = mr_query("get_value", 1, qargv, gqval, &i)) {
88             com_err(whoami, status, " check dcm_enable");
89             leave("query failed");
90         }
91         if (i == 0) {
92             errno = 0;
93             leave("dcm_enable not set");
94         } 
95
96         /* do it! */
97         do_services();
98         errno = 0;
99         leave("");
100 }
101
102
103 /* Used by the get_value query when checking for dcm_enable. */
104
105 gqval(argc, argv, hint)
106 int argc;
107 char **argv;
108 int *hint;
109 {
110     *hint = atoi(argv[0]);
111     return(UPCALL_STOP);
112 }
113
114
115 /* Used by qualified_get_server to make a list of servers to check */
116
117 qgetsv(argc, argv, sq)
118 int argc;
119 char **argv;
120 struct save_queue *sq;
121 {
122     sq_save_data(sq, strsave(argv[0]));
123     return(UPCALL_CONT);
124 }
125
126
127 /* Used by get_server_info to record all of the returned information */
128
129 getsvinfo(argc, argv, sserv)
130 int argc;
131 char **argv;
132 struct service *sserv;
133 {
134     sserv->service = strsave(argv[0]);
135     sserv->interval = atoi(argv[1]);
136     sserv->target = strsave(argv[2]);
137     sserv->script = strsave(argv[3]);
138     sserv->dfgen = atoi(argv[4]);
139     sserv->dfcheck = atoi(argv[5]);
140     sserv->type = strsave(argv[6]);
141     sserv->enable = atoi(argv[7]);
142     sserv->inprogress = atoi(argv[8]);
143     sserv->harderror = atoi(argv[9]);
144     sserv->errmsg = strsave(argv[10]);
145     return(UPCALL_STOP);
146 }
147
148
149 /* Scan the services and process any that need it. */
150
151 do_services()
152 {
153     char *qargv[6];
154     struct save_queue *sq, *sq_create();
155     char *service, dfgen_prog[64], dfgen_cmd[128];
156     struct service svc;
157     int status, lock_fd, ex, (*cstat)();
158     struct timezone tz;
159     register char *p;
160     union wait waits;
161
162     if (dbg & DBG_VERBOSE)
163         com_err(whoami, 0, "starting pass over services");
164
165     qargv[0] = "true";
166     qargv[1] = "dontcare";
167     qargv[2] = "false";
168     sq = sq_create();
169     if (status = mr_query_with_retry("qualified_get_server", 3, qargv,
170                                       qgetsv, sq)) {
171         com_err(whoami, status, " getting services");
172         leave("query failed");
173     }
174     while (sq_get_data(sq, &service)) {
175         for (p = service; *p; p++)
176           if (isupper(*p))
177             *p = tolower(*p);
178         com_err(whoami, 0, "checking %s...", service);
179         qargv[0] = service;
180         sprintf(dfgen_prog, "%s/%s.gen", BIN_DIR, service);
181         if (!file_exists(dfgen_prog)) {
182             com_err(whoami, 0, "prog %s doesn't exist\n", dfgen_prog);
183             free(service);
184             continue;
185         }
186         sprintf(dfgen_cmd, "exec %s %s/%s.out",
187                 dfgen_prog, DCM_DIR, service);
188         gettimeofday(&tv, &tz);
189         if (status = mr_query_with_retry("get_server_info", 1, qargv,
190                                           getsvinfo, &svc)) {
191             com_err(whoami, status, " getting service %s info, skipping to next service", service);
192             continue;
193         }
194         svc.service = strsave(service);
195         qargv[0] = strsave(service);
196         qargv[1] = itoa(svc.dfgen);
197         qargv[2] = itoa(svc.dfcheck);
198         qargv[3] = strsave("0");
199         qargv[4] = itoa(svc.harderror);
200         qargv[5] = strsave(svc.errmsg);
201         if (svc.interval != 0) {
202             if (svc.interval * 60 + svc.dfcheck < tv.tv_sec) {
203                 lock_fd = maybe_lock_update("@db@", service, 1);
204                 if (lock_fd < 0)
205                   goto free_service;
206                 free(qargv[3]);
207                 free(qargv[4]);
208                 free(qargv[5]);
209                 qargv[3] = strsave("1");
210                 qargv[4] = strsave("0");
211                 qargv[5] = strsave("");
212                 status = mr_query_with_retry("set_server_internal_flags", 6,
213                                               qargv, scream, NULL);
214                 if (status != MR_SUCCESS) {
215                     com_err(whoami, status, " setting server state");
216                     goto free_service;
217                 }
218             
219                 com_err(whoami, status, " running %s", dfgen_prog);
220                 cstat = signal(SIGCHLD, SIG_DFL);
221                 waits.w_status = system(dfgen_cmd);
222                 signal(SIGCHLD, cstat);
223                 if (waits.w_termsig) {
224                     status = MR_COREDUMP;
225                     com_err(whoami, status, " %s exited on signal %d",
226                             dfgen_prog, waits.w_termsig);
227                 } else if (waits.w_retcode) {
228                     /* extract the process's exit value */
229                     status = waits.w_retcode + ERROR_TABLE_BASE_sms;
230                     com_err(whoami, status, " %s exited", dfgen_prog);
231                 }
232                 if (SOFT_FAIL(status)) {
233                     free(qargv[5]);
234                     qargv[5] = strsave(error_message(status));
235                 } else if (status == MR_NO_CHANGE) {
236                     free(qargv[2]);
237                     qargv[2] = itoa(tv.tv_sec);
238                     svc.dfcheck = tv.tv_sec;
239                 } else if (status == MR_SUCCESS) {
240                     free(qargv[1]);
241                     free(qargv[2]);
242                     qargv[1] = itoa(tv.tv_sec);
243                     qargv[2] = strsave(qargv[1]);
244                     svc.dfcheck = svc.dfgen = tv.tv_sec;
245                 } else { /* HARD_FAIL(status) */
246                     free(qargv[2]);
247                     free(qargv[4]);
248                     free(qargv[5]);
249                     qargv[2] = itoa(tv.tv_sec); 
250                     svc.dfcheck = tv.tv_sec;
251                     qargv[4] = itoa(status);
252                     qargv[5] = strsave(error_message(status));
253                     critical_alert("DCM","DCM building config files for %s: %s",
254                                   service, qargv[5]);
255                 }
256             free_service:
257                 free(qargv[3]);
258                 qargv[3] = strsave("0");
259                 status = mr_query_with_retry("set_server_internal_flags", 6,
260                                               qargv, scream, NULL);
261                 if (status)
262                   com_err(whoami, status, " setting service state");
263                 close(lock_fd);
264                 free(qargv[0]);
265                 free(qargv[1]);
266                 free(qargv[2]);
267                 free(qargv[3]);
268                 free(qargv[4]);
269                 free(qargv[5]);
270             }
271             if (!strcmp(svc.type, "REPLICAT"))
272               ex = 1;
273             else
274               ex = 0;
275             lock_fd = maybe_lock_update("@db@", service, ex);
276             if (lock_fd >= 0) {
277                 do_hosts(&svc);
278                 close(lock_fd);
279             }
280         }
281         free(svc.service);
282         free(svc.target);
283         free(svc.script);
284         free(svc.type);
285         free(svc.errmsg);
286         free(service);
287     }
288     sq_destroy(sq);
289 }
290
291
292 /* Used by qualified_get_server_host to make a list of hosts to check */
293
294 qgethost(argc, argv, sq)
295 int argc;
296 char **argv;
297 struct save_queue *sq;
298 {
299     sq_save_data(sq, strsave(argv[1]));
300     return(UPCALL_CONT);
301 }
302
303
304 /* Used by get_server_host_info to store all of the info about a host */
305
306 gethostinfo(argc, argv, shost)
307 int argc;
308 char **argv;
309 struct svrhost *shost;
310 {
311     shost->service = strsave(argv[0]);
312     shost->machine = strsave(argv[1]);
313     shost->enable = atoi(argv[2]);
314     shost->override = atoi(argv[3]);
315     shost->success = atoi(argv[4]);
316     shost->inprogress = atoi(argv[5]);
317     shost->hosterror = atoi(argv[6]);
318     shost->errmsg = strsave(argv[7]);
319     shost->lasttry = atoi(argv[8]);
320     shost->lastsuccess = atoi(argv[9]);
321     shost->value1 = atoi(argv[10]);
322     shost->value2 = atoi(argv[11]);
323     shost->value3 = strsave(argv[12]);
324     return(UPCALL_STOP);
325 }
326
327
328 /* Scans all of the hosts for a particular service, and processes them. */
329
330 do_hosts(svc)
331 struct service *svc;
332 {
333     char *argv[9], *machine;
334     int status, lock_fd;
335     struct save_queue *sq;
336     struct svrhost shost;
337
338     sq = sq_create();
339     argv[0] = svc->service;
340     argv[1] = "TRUE";
341     argv[2] = argv[3] = argv[4] = "DONTCARE";
342     argv[5] = "FALSE";
343     status = mr_query_with_retry("qualified_get_server_host", 6, argv,
344                                   qgethost, sq);
345     if (status == MR_NO_MATCH) {
346         return;
347     } else if (status) {
348         com_err(whoami, status, " getting server_hosts for  %s", svc->service);
349         return;
350     }
351     while (sq_get_data(sq, &machine)) {
352         if (dbg & DBG_TRACE)
353           com_err(whoami, 0, "checking %s...", machine);
354         argv[1] = machine;
355         status = mr_query_with_retry("get_server_host_info", 2, argv,
356                                       gethostinfo, &shost);
357         if (status) {
358             com_err(whoami,status, " getting server_host_info for %s", machine);
359             goto free_mach;
360         }
361         if (!shost.enable || shost.hosterror ||
362             (shost.success && !shost.override &&
363              shost.lastsuccess >= svc->dfgen)) {
364             if (dbg & DBG_TRACE)
365               com_err(whoami, 0, "not updating %s:%s", svc->service, machine);
366             goto free_mach;
367         }
368
369         lock_fd = maybe_lock_update(machine, svc->service, 1);
370         if (lock_fd < 0)
371           goto free_mach;
372         argv[0] = svc->service;
373         argv[1] = machine;
374         argv[2] = argv[3] = argv[5] = "0";
375         argv[4] = "1";
376         argv[6] = strsave("");
377         argv[7] = itoa(tv.tv_sec);
378         argv[8] = itoa(shost.lastsuccess);
379         status = mr_query_with_retry("set_server_host_internal", 9, argv,
380                                       scream, NULL);
381         if (status != MR_SUCCESS) {
382             com_err(whoami,status," while setting internal state for %s:%s",
383                     svc->service, machine);
384             goto free_mach;
385         }
386         status = mr_update_server(svc->service, machine, svc->target,
387                                    svc->script);
388         if (status == MR_SUCCESS) {
389             argv[2] = "0";
390             argv[3] = "1";
391             free(argv[8]);
392             argv[8] = itoa(tv.tv_sec);
393         } else if (SOFT_FAIL(status)) {
394             free(argv[6]);
395             argv[6] = strsave(error_message(status));
396         } else { /* HARD_FAIL */
397             argv[2] = itoa(shost.override);
398             argv[5] = itoa(status);
399             free(argv[6]);
400             argv[6] = strsave(error_message(status));
401             critical_alert("DCM", "DCM updating %s:%s: %s",
402                            machine, svc->service, argv[6]);
403             if (!strcmp(svc->type, "REPLICAT")) {
404                 char *qargv[6];
405
406                 svc->harderror = status;
407                 svc->errmsg = strsave(argv[6]);
408                 qargv[0] = strsave(svc->service);
409                 qargv[1] = itoa(svc->dfgen);
410                 qargv[2] = itoa(svc->dfcheck);
411                 qargv[3] = strsave("0");
412                 qargv[4] = itoa(svc->harderror);
413                 qargv[5] = strsave(svc->errmsg);
414                 status = mr_query_with_retry("set_server_internal_flags",
415                                               6, qargv, scream, NULL);
416                 if (status)
417                   com_err(whoami, status, " setting service state again");
418                 free(qargv[0]);
419                 free(qargv[1]);
420                 free(qargv[2]);
421                 free(qargv[3]);
422                 free(qargv[4]);
423                 free(qargv[5]);
424                 close(lock_fd);
425                 free(argv[2]);
426                 argv[4] = "0";
427                 free(argv[5]);
428                 status = mr_query_with_retry("set_server_host_internal",
429                                               9, argv,scream,NULL);
430                 if (status)
431                   com_err(whoami, status, " setting host state again");
432                 return(-1);
433             }
434             free(argv[2]);
435             free(argv[5]);
436         }
437         argv[4] = "0";
438         close(lock_fd);
439         status = mr_query_with_retry("set_server_host_internal", 9, argv,
440                                       scream, NULL);
441         if (status)
442           com_err(whoami, status, " setting host state again");
443     free_mach:
444         free(machine);
445         close(lock_fd);
446     }
447     return(0);
448 }
This page took 0.082911 seconds and 5 git commands to generate.