]> andersk Git - moira.git/blob - gen/hesiod.pc
deal with IMAP poboxes
[moira.git] / gen / hesiod.pc
1 /* $Id$
2  *
3  * This generates the zone files necessary to load a hesiod server.
4  * The following zones are generated: passwd, uid, pobox, group,
5  * grplist, gid, filsys, cluster, pcap, sloc, service.
6  *
7  * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology.
8  * For copying and distribution information, please see the file
9  * <mit-copyright.h>.
10  */
11
12 #include <mit-copyright.h>
13 #include <moira.h>
14 #include <moira_site.h>
15
16 #include <sys/stat.h>
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "util.h"
23
24 EXEC SQL INCLUDE sqlca;
25
26 RCSID("$Header$");
27
28 #ifndef HTYPE
29 #define HTYPE "TXT"
30 #endif
31 #ifndef HCLASS
32 #define HCLASS ""
33 #endif
34
35 #ifndef HESIOD_SUBDIR
36 #define HESIOD_SUBDIR "hesiod"
37 #endif
38
39 /* max number of bytes of a data record that can be returned in a hesiod
40  * query.  This is 512 - overhead (~78) [derived empirically]
41  * (it used to be 446 with older versions of bind)
42  */
43 #define MAXHESSIZE 434
44
45 char hesiod_dir[MAXPATHLEN];
46
47 #define min(x, y)       ((x) < (y) ? (x) : (y))
48 struct hash *machines = NULL;
49 struct hash *users = NULL;
50 char *whoami = "hesiod.gen";
51 char *db = "moira/moira";
52
53 struct grp {
54   struct grp *next;
55   char *lid;
56 };
57 struct user {
58   char name[USERS_LOGIN_SIZE];
59   struct grp *lists;
60 };
61
62 /*
63  * Modified from sys/types.h:
64  */
65 int setsize;    /* = howmany(setbits, NSETBITS) */
66
67 typedef long    set_mask;
68 #define NSETBITS        (sizeof(set_mask) * NBBY)       /* bits per mask */
69 #ifndef howmany
70 #define howmany(x, y)   (((x) + ((y) - 1)) / (y))
71 #endif
72
73 #define SET_SET(n, p)   ((p)[(n)/NSETBITS] |=  (1 << ((n) % NSETBITS)))
74 #define SET_CLR(n, p)   ((p)[(n)/NSETBITS] &= ~(1 << ((n) % NSETBITS)))
75 #define SET_ISSET(n, p) ((p)[(n)/NSETBITS] &   (1 << ((n) % NSETBITS)))
76 #define SET_CREATE()    (malloc(setsize * sizeof(set_mask)))
77 #define SET_ZERO(p)     memset(p, 0, setsize * sizeof(set_mask))
78 #define SET_CMP(p1, p2) (memcmp(p1, p2, setsize * sizeof(set_mask)))
79
80
81 void get_mach(void);
82 int nbitsset(set_mask *set);
83 int valid(char *name);
84
85 int do_passwd(void);
86 int do_groups(void);
87 int do_filsys(void);
88 int do_cluster(void);
89 int do_printcap(void);
90 int do_sloc(void);
91 int do_service(void);
92
93 int main(int argc, char **argv)
94 {
95   char cmd[64];
96   struct stat sb;
97   int changed = 0;
98
99   if (argc > 2)
100     {
101       fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
102       exit(MR_ARGS);
103     }
104
105   initialize_sms_error_table();
106   sprintf(hesiod_dir, "%s/%s", DCM_DIR, HESIOD_SUBDIR);
107
108   EXEC SQL CONNECT :db;
109
110   changed = do_passwd();
111   changed += do_filsys();
112   changed += do_cluster();
113   changed += do_printcap();
114   changed += do_sloc();
115   changed += do_service();
116   changed += do_groups();
117
118   if (!changed)
119     {
120       fprintf(stderr, "No files updated.\n");
121       if (argc == 2 && stat(argv[1], &sb) == 0)
122         exit(MR_NO_CHANGE);
123     }
124
125   if (argc == 2)
126     {
127       fprintf(stderr, "Building tar file.\n");
128       sprintf(cmd, "cd %s; tar cf %s .", hesiod_dir, argv[1]);
129       if (system(cmd))
130         exit(MR_TAR_FAIL);
131     }
132
133   exit(MR_SUCCESS);
134 }
135
136
137 void get_mach(void)
138 {
139   EXEC SQL BEGIN DECLARE SECTION;
140   int id;
141   char name[MACHINE_NAME_SIZE];
142   EXEC SQL END DECLARE SECTION;
143
144   if (machines)
145     return;
146
147   machines = create_hash(1000);
148   EXEC SQL DECLARE m_cursor CURSOR FOR
149     SELECT name, mach_id
150     FROM machine
151     WHERE status = 1 and mach_id != 0
152     ORDER BY mach_id;
153   EXEC SQL OPEN m_cursor;
154   while (1)
155     {
156       EXEC SQL FETCH m_cursor INTO :name, :id;
157       if (sqlca.sqlcode)
158         break;
159       strtrim(name);
160       if (!valid(name))
161         continue;
162       hash_store(machines, id, strdup(name));
163     }
164   if (sqlca.sqlcode < 0)
165     db_error(sqlca.sqlcode);
166   EXEC SQL CLOSE m_cursor;
167   EXEC SQL COMMIT;
168 }
169
170
171 /* Determine whether or not a name is a valid DNS label.
172    (Can't start or end with . or have two .s in a row) */
173 int valid(char *name)
174 {
175   int sawdot;
176
177   for (sawdot = 1; *name; name++)
178     {
179       if (*name == '.')
180         {
181           if (sawdot)
182             return 0;
183           else
184             sawdot = 1;
185         }
186       else
187         sawdot = 0;
188     }
189   return !sawdot;
190 }
191
192
193 int do_passwd(void)
194 {
195   FILE *pout, *uout, *bout;
196   char poutf[MAXPATHLEN], uoutf[MAXPATHLEN], poutft[MAXPATHLEN];
197   char uoutft[MAXPATHLEN], boutf[MAXPATHLEN], boutft[MAXPATHLEN];
198   struct stat psb, usb, bsb;
199   time_t ftime;
200   struct user *u;
201   char *mach;
202   EXEC SQL BEGIN DECLARE SECTION;
203   char login[USERS_LOGIN_SIZE], shell[USERS_SHELL_SIZE];
204   char fullname[USERS_FULLNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE];
205   char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE];
206   char nn[USERS_NICKNAME_SIZE];
207   int uid, flag1, flag2, id, pid, iid, mid, status;
208   EXEC SQL END DECLARE SECTION;
209
210   sprintf(poutf, "%s/passwd.db", hesiod_dir);
211   sprintf(uoutf, "%s/uid.db", hesiod_dir);
212   sprintf(boutf, "%s/pobox.db", hesiod_dir);
213
214   if (stat(poutf, &psb) == 0 && stat(uoutf, &usb) == 0 &&
215       stat(boutf, &bsb) == 0)
216     {
217       ftime = min(min(psb.st_mtime, usb.st_mtime), bsb.st_mtime);
218       if (ModDiff (&flag1, "users", ftime) ||
219           ModDiff (&flag2, "machine", ftime))
220         exit(MR_DATE);
221       if (flag1 < 0 && flag2 < 0)
222         {
223           fprintf(stderr, "Files passwd.db, uid.db, and pobox.db "
224                   "do not need to be rebuilt.\n");
225           return 0;
226         }
227     }
228
229   sprintf(poutft, "%s~", poutf);
230   pout = fopen(poutft, "w");
231   if (!pout)
232     {
233       perror("cannot open passwd.db~ for write");
234       exit(MR_OCONFIG);
235     }
236   sprintf(uoutft, "%s~", uoutf);
237   uout = fopen(uoutft, "w");
238   if (!uout)
239     {
240       perror("cannot open uid.db~ for write");
241       exit(MR_OCONFIG);
242     }
243   sprintf(boutft, "%s~", boutf);
244   bout = fopen(boutft, "w");
245   if (!bout)
246     {
247       perror("cannot open pobox.db for write");
248       exit(MR_OCONFIG);
249     }
250
251   fprintf(stderr, "Building passwd.db, uid.db, and pobox.db\n");
252   get_mach();
253
254   users = create_hash(12001);
255   EXEC SQL DECLARE u_cursor CURSOR FOR
256     SELECT login, unix_uid, shell, fullname, nickname, office_addr,
257     office_phone, home_phone, users_id, pop_id, imap_id, status
258     FROM users
259     WHERE status = 1 OR status = 2 OR status = 5 OR status = 6
260     ORDER BY users_id;
261   EXEC SQL OPEN u_cursor;
262   while (1)
263     {
264       EXEC SQL FETCH u_cursor INTO :login, :uid, :shell, :fullname, :nn,
265         :oa, :op, :hp, :id, :pid, :iid, :status;
266       if (sqlca.sqlcode)
267         break;
268       strtrim(login);
269       dequote(fullname);
270       dequote(nn);
271       dequote(oa);
272       dequote(op);
273       dequote(hp);
274       dequote(shell);
275       u = malloc(sizeof(struct user));
276       strcpy(u->name, login);
277       u->lists = NULL;
278       hash_store(users, id, u);
279       if (status == 1 || status == 2)
280         {
281           fprintf(pout, "%s.passwd\t%s %s \"%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\"\n",
282                   login, HCLASS, HTYPE, login, uid, fullname, nn, oa,
283                   op, hp, login, shell);
284           fprintf(uout, "%d.uid\t%s CNAME %s.passwd\n", uid, HCLASS, login);
285         }
286
287       if (iid != 0)
288         {
289           EXEC SQL SELECT mach_id INTO :mid FROM filesys
290             WHERE filsys_id = :iid AND type = 'IMAP';
291           if (sqlca.sqlcode == 0)
292             pid = mid;
293         }
294
295       if (pid != 0 && (mach = hash_lookup(machines, pid)))
296         {
297           fprintf(bout, "%s.pobox\t%s %s \"POP %s %s\"\n",
298                   login, HCLASS, HTYPE, mach, login);
299         }
300     }
301   if (sqlca.sqlcode < 0)
302     db_error(sqlca.sqlcode);
303   EXEC SQL CLOSE u_cursor;
304   EXEC SQL COMMIT;
305
306   if (fclose(pout) || fclose(uout) || fclose(bout))
307     {
308       fprintf(stderr, "Unsuccessful file close of passwd.db, uid.db, or pobox.db\n");
309       exit(MR_CCONFIG);
310     }
311   fix_file(poutf);
312   fix_file(uoutf);
313   fix_file(boutf);
314   return 1;
315 }
316
317
318 int do_groups(void)
319 {
320   FILE *iout, *gout, *lout;
321   char ioutf[MAXPATHLEN], goutf[MAXPATHLEN], loutf[MAXPATHLEN];
322   char buf[MAXPATHLEN], *l;
323   struct hash *groups;
324   struct bucket *b, **p;
325   struct grp *g;
326   struct user *u;
327   struct stat isb, gsb, lsb;
328   time_t ftime;
329   EXEC SQL BEGIN DECLARE SECTION;
330   char name[LIST_NAME_SIZE];
331   int gid, id, lid, flag1, flag2, flag3, len;
332   EXEC SQL END DECLARE SECTION;
333
334   /* open files */
335   sprintf(ioutf, "%s/gid.db", hesiod_dir);
336   sprintf(goutf, "%s/group.db", hesiod_dir);
337   sprintf(loutf, "%s/grplist.db", hesiod_dir);
338
339   if (stat(ioutf, &isb) == 0 && stat(goutf, &gsb) == 0 &&
340       stat(loutf, &lsb) == 0)
341     {
342       ftime = min(isb.st_mtime, min(gsb.st_mtime, lsb.st_mtime));
343       if (ModDiff (&flag1, "users", ftime) ||
344           ModDiff (&flag2, "list", ftime) ||
345           ModDiff (&flag3, "imembers", ftime))
346         exit(MR_DATE);
347       if (flag1 < 0 && flag2 < 0 && flag3 < 0)
348         {
349           fprintf(stderr, "Files gid.db, group.db and grplist.db "
350                   "do not need to be rebuilt.\n");
351           return 0;
352         }
353     }
354
355   sprintf(buf, "%s~", ioutf);
356   iout = fopen(buf, "w");
357   if (!iout)
358     {
359       perror("cannot open gid.db for write");
360       exit(MR_OCONFIG);
361     }
362   sprintf(buf, "%s~", goutf);
363   gout = fopen(buf, "w");
364   if (!gout)
365     {
366       perror("cannot open group.db for write");
367       exit(MR_OCONFIG);
368     }
369   sprintf(buf, "%s~", loutf);
370   lout = fopen(buf, "w");
371   if (!lout)
372     {
373       perror("cannot open grplist.db for write");
374       exit(MR_OCONFIG);
375     }
376
377   fprintf(stderr, "Building gid.db, group.db, and grplist.db\n");
378
379   /* make space for group list */
380   groups = create_hash(15001);
381
382   /* The following WHENEVER is declarative, not executed,
383    * and applies for the remainder of this file only.
384    */
385   EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
386
387   EXEC SQL DECLARE l_cursor CURSOR FOR
388     SELECT name, gid, list_id
389     FROM list
390     WHERE grouplist != 0 AND active != 0
391     ORDER BY list_id;
392   EXEC SQL OPEN l_cursor;
393   while (1)
394     {
395       char buf[LIST_NAME_SIZE + 10];
396
397       EXEC SQL FETCH l_cursor INTO :name, :gid, :lid;
398       if (sqlca.sqlcode)
399         break;
400       strtrim(name);
401       if (!valid(name))
402         continue;
403       sprintf(buf, "%s:%d", name, gid);
404       hash_store(groups, lid, strdup(buf));
405       fprintf(iout, "%d.gid\t%s CNAME %s.group\n", gid, HCLASS, name);
406       fprintf(gout, "%s.group\t%s %s \"%s:*:%d:\"\n",
407               name, HCLASS, HTYPE, name, gid);
408     }
409   EXEC SQL CLOSE l_cursor;
410
411   fflush(iout);
412   fflush(gout);
413
414   /* now do grplists */
415   if (!users)
416     {
417       users = create_hash(12001);
418       EXEC SQL DECLARE u_cursor2 CURSOR FOR
419         SELECT users_id, login
420         FROM users
421         WHERE status = 1 OR status = 2
422         ORDER BY users_id;
423       EXEC SQL OPEN u_cursor2;
424       while (1)
425         {
426           EXEC SQL FETCH u_cursor2 INTO :id, :name;
427           if (sqlca.sqlcode)
428             break;
429           u = malloc(sizeof(struct user));
430           strcpy(u->name, strtrim(name));
431           u->lists = NULL;
432           hash_store(users, id, u);
433         }
434       EXEC SQL CLOSE u_cursor2;
435     }
436
437   EXEC SQL DECLARE i_cursor CURSOR FOR
438     SELECT list_id, member_id
439     FROM imembers
440     WHERE member_type = 'USER'
441     ORDER BY list_id;
442   EXEC SQL OPEN i_cursor;
443   while (1)
444     {
445       EXEC SQL FETCH i_cursor INTO :lid, :id;
446       if (sqlca.sqlcode)
447         break;
448       if ((l = hash_lookup(groups, lid)) && (u = hash_lookup(users, id)))
449         {
450           g = malloc(sizeof(struct grp));
451           g->next = u->lists;
452           u->lists = g;
453           g->lid = l;
454         }
455     }
456   EXEC SQL CLOSE i_cursor;
457
458   EXEC SQL COMMIT;
459
460   for (p = &(users->data[users->size - 1]); p >= users->data; p--)
461     {
462       for (b = *p; b; b = b->next)
463         {
464           if (!(g = ((struct user *)b->data)->lists))
465             continue;
466           fprintf(lout, "%s.grplist\t%s %s \"",
467                   ((struct user *)b->data)->name, HCLASS, HTYPE);
468           len = 0;
469           for (; g; g = g->next)
470             {
471               if (len + strlen(g->lid) + 1 < MAXHESSIZE)
472                 {
473                   fputs(g->lid, lout);
474                   if (g->next)
475                     putc(':', lout);
476                   len += strlen(g->lid) + 1;
477                 }
478               else
479                 {
480                   com_err(whoami, 0, "truncated grp list for user %s",
481                           ((struct user *)b->data)->name);
482                   break;
483                 }
484             }
485           fputs("\"\n", lout);
486         }
487     }
488
489   if (fclose(iout) || fclose(gout) || fclose(lout))
490     {
491       fprintf(stderr, "Unsuccessful close of gid.db, group.db, or grplist.db\n");
492       exit(MR_CCONFIG);
493     }
494   fix_file(ioutf);
495   fix_file(goutf);
496   fix_file(loutf);
497   return 1;
498 sqlerr:
499   db_error(sqlca.sqlcode);
500   return 0;
501 }
502
503
504 int do_filsys(void)
505 {
506   FILE *out;
507   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach, *group;
508   struct stat sb;
509   time_t ftime;
510   struct save_queue *sq, *sq2;
511   EXEC SQL BEGIN DECLARE SECTION;
512   char name[FILESYS_LABEL_SIZE], type[FILESYS_TYPE_SIZE];
513   char loc[FILESYS_NAME_SIZE], access[FILESYS_RWACCESS_SIZE];
514   char mount[FILESYS_MOUNT_SIZE], comments[FILESYS_COMMENTS_SIZE];
515   char key[FSGROUP_KEY_SIZE];
516   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
517   int flag1, flag2, flag3, flag4, id, fid;
518   EXEC SQL END DECLARE SECTION;
519
520   sprintf(outf, "%s/filsys.db", hesiod_dir);
521
522   if (stat(outf, &sb) == 0)
523     {
524       ftime = sb.st_mtime;
525
526       if (ModDiff(&flag1, "filesys", ftime))
527         exit(MR_DATE);
528       if (ModDiff(&flag2, "machine", ftime))
529         exit(MR_DATE);
530       if (ModDiff(&flag3, "alias", ftime))
531         exit(MR_DATE);
532       if (ModDiff(&flag4, "fsgroup", ftime))
533         exit(MR_DATE);
534
535       if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0)
536         {
537           fprintf(stderr, "File filsys.db does not need to be rebuilt.\n");
538           return 0;
539         }
540     }
541
542   sprintf(outft, "%s~", outf);
543   out = fopen(outft, "w");
544   if (!out)
545     {
546       perror("cannot open filsys.db for write");
547       exit(MR_OCONFIG);
548     }
549
550   fprintf(stderr, "Building filsys.db\n");
551   get_mach();
552   sq = sq_create();
553   sq2 = sq_create();
554
555   EXEC SQL DECLARE f_cursor CURSOR FOR
556     SELECT label, type, name, mach_id, rwaccess, mount, comments, filsys_id
557     FROM filesys
558     ORDER BY filsys_id;
559   EXEC SQL OPEN f_cursor;
560   while (1)
561     {
562       EXEC SQL FETCH f_cursor INTO :name, :type, :loc, :id, :access,
563         :mount, :comments, :fid;
564       if (sqlca.sqlcode)
565         break;
566       strtrim(name);
567       if (!valid(name))
568         continue;
569       strtrim(type);
570       if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
571         {
572           if ((mach = hash_lookup(machines, id)))
573             {
574               fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s\"\n",
575                       name, HCLASS, HTYPE, type, strtrim(loc),
576                       mach, strtrim(access), strtrim(mount));
577             }
578         }
579       else if (!strcmp(type, "AFS"))
580         {
581           fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s\"\n",
582                   name, HCLASS, HTYPE, strtrim(loc),
583                   strtrim(access), strtrim(mount));
584         }
585       else if (!strcmp(type, "ERR"))
586         {
587           fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
588                   name, HCLASS, HTYPE, strtrim(comments));
589         }
590       else if (!strcmp(type, "FSGROUP"))
591         {
592           char buf[FILESYS_NAME_SIZE + 10];
593           sprintf(buf, "%s:%d", name, fid);
594           sq_save_data(sq, strdup(buf));
595         }
596       else if (!strcmp(type, "MUL"))
597         {
598           char buf[FILESYS_NAME_SIZE + 10];
599           sprintf(buf, "%s:%d", name, fid);
600           sq_save_data(sq2, strdup(buf));
601         }
602     }
603   EXEC SQL CLOSE f_cursor;
604
605   while (sq_get_data(sq, &group))
606     {
607       fid = atoi(strchr(group, ':') + 1);
608       *strchr(group, ':') = 0;
609
610       EXEC SQL DECLARE f_cursor2 CURSOR FOR
611         SELECT DISTINCT f.type, f.name, f.mach_id, f.rwaccess, f.mount,
612         f.comments, f.label, g.key
613         FROM filesys f, fsgroup g
614         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
615         ORDER BY key, label;
616       EXEC SQL OPEN f_cursor2;
617       for (flag1 = 1; ; flag1++)
618         {
619           EXEC SQL FETCH f_cursor2 INTO :type, :loc, :id, :access, :mount,
620             :comments, :name, :key;
621           if (sqlca.sqlcode)
622             break;
623           strtrim(type);
624           if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
625             {
626               if ((mach = hash_lookup(machines, id)))
627                 {
628                   fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s %d\"\n",
629                           group, HCLASS, HTYPE, type, strtrim(loc), mach,
630                           strtrim(access), strtrim(mount), flag1);
631                 }
632             }
633           else if (!strcmp(type, "AFS"))
634             {
635               fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s %d\"\n",
636                       group, HCLASS, HTYPE, strtrim(loc), strtrim(access),
637                       strtrim(mount), flag1);
638             }
639           else if (!strcmp(type, "ERR"))
640             {
641               fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
642                       group, HCLASS, HTYPE, strtrim(comments));
643             }
644         }
645       EXEC SQL CLOSE f_cursor2;
646       free(group);
647     }
648   sq_destroy(sq);
649
650   while (sq_get_data(sq2, &group))
651     {
652       fid = atoi(strchr(group, ':') + 1);
653       *strchr(group, ':') = 0;
654       fprintf(out, "%s.filsys\t%s %s \"MUL", group, HCLASS, HTYPE);
655       EXEC SQL DECLARE f_cursor3 CURSOR FOR
656         SELECT DISTINCT f.label, g.key
657         FROM filesys f, fsgroup g
658         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
659         ORDER BY key, label;
660       EXEC SQL OPEN f_cursor3;
661       while (1)
662         {
663           EXEC SQL FETCH f_cursor3 INTO :name, :key;
664           if (sqlca.sqlcode)
665             break;
666           fprintf(out, " %s", strtrim(name));
667         }
668       EXEC SQL CLOSE f_cursor3;
669       fprintf(out, "\"\n");
670       free(group);
671     }
672   sq_destroy(sq2);
673
674   EXEC SQL DECLARE a_cursor CURSOR FOR
675     SELECT name, trans
676     FROM alias
677     WHERE type = 'FILESYS';
678   EXEC SQL OPEN a_cursor;
679   while (1)
680     {
681       EXEC SQL FETCH a_cursor INTO :aname, :trans;
682       if (sqlca.sqlcode)
683         break;
684       strtrim(aname);
685       strtrim(trans);
686       if (!valid(aname) || !valid(trans))
687         continue;
688       fprintf(out, "%s.filsys\t%s CNAME %s.filsys\n",
689               aname, HCLASS, trans);
690     }
691   EXEC SQL CLOSE a_cursor;
692
693   EXEC SQL COMMIT;
694
695   if (fclose(out))
696     {
697       fprintf(stderr, "Unsuccessful close of filsys.db\n");
698       exit(MR_CCONFIG);
699     }
700   fix_file(outf);
701   return 1;
702 sqlerr:
703   db_error(sqlca.sqlcode);
704   return 0;
705 }
706
707 int nbitsset(set_mask *set)
708 {
709   int i, ret;
710   ret = 0;
711   for (i = 0; i < setsize * NSETBITS; i++)
712     {
713       if (SET_ISSET(i, set))
714         ret++;
715     }
716   return ret;
717 }
718
719
720 int do_cluster(void)
721 {
722   FILE *out;
723   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
724   char machbuf[MACHINE_NAME_SIZE], clubuf[CLUSTERS_NAME_SIZE], *p;
725   struct stat sb;
726   time_t ftime;
727   EXEC SQL BEGIN DECLARE SECTION;
728   int flag1, flag2, flag3, flag4, maxmach, maxclu, mid, cid, id;
729   char name[CLUSTERS_NAME_SIZE];
730   char label[SVC_SERV_LABEL_SIZE], data[SVC_SERV_CLUSTER_SIZE];
731   EXEC SQL END DECLARE SECTION;
732   set_mask **machs, *ms, *ps;
733
734   sprintf(outf, "%s/cluster.db", hesiod_dir);
735
736   if (stat(outf, &sb) == 0)
737     {
738       ftime = sb.st_mtime;
739       if (ModDiff (&flag1, "clusters", ftime)
740           || ModDiff (&flag2, "machine", ftime)
741           || ModDiff (&flag3, "mcmap", ftime)
742           || ModDiff (&flag4, "svc", ftime))
743         exit(MR_DATE);
744       if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0)
745         {
746           fprintf(stderr, "File cluster.db does not need to be rebuilt.\n");
747           return 0;
748         }
749     }
750
751   sprintf(outft, "%s~", outf);
752   out = fopen(outft, "w");
753   if (!out)
754     {
755       perror("cannot open cluster.db for write");
756       exit(MR_OCONFIG);
757     }
758
759   fprintf(stderr, "Building cluster.db\n");
760   get_mach();
761
762   EXEC SQL SELECT MAX(clu_id) INTO :maxclu FROM clusters;
763   maxclu++;
764   setsize = howmany(maxclu, NSETBITS);
765
766   EXEC SQL SELECT MAX(mach_id) INTO :maxmach FROM machine;
767   maxmach++;
768   machs = malloc((maxmach + 1) * sizeof(set_mask **));
769   memset(machs, 0, (maxmach + 1) * sizeof(int));
770
771   EXEC SQL DECLARE p_cursor CURSOR FOR
772     SELECT mach_id, clu_id
773     FROM mcmap
774     ORDER BY mach_id;
775   EXEC SQL OPEN p_cursor;
776   while (1)
777     {
778       EXEC SQL FETCH p_cursor INTO :mid, :cid;
779       if (sqlca.sqlcode)
780         break;
781       if (!(ms = machs[mid]))
782         {
783           ms = machs[mid] = SET_CREATE();
784           SET_ZERO(ms);
785         }
786       SET_SET(cid, ms);
787     }
788   EXEC SQL CLOSE p_cursor;
789
790   for (mid = 1; mid < maxmach; mid++)
791     {
792       if (!machs[mid])
793         continue;
794       ms = machs[mid];
795       if (nbitsset(ms) > 1)
796         {
797           sprintf(clubuf, "mrinternal-%d", mid);
798           for (cid = 1; cid < maxclu; cid++)
799             {
800               if (SET_ISSET(cid, ms))
801                 {
802                   EXEC SQL DECLARE d_cursor CURSOR FOR
803                     SELECT serv_label, serv_cluster
804                     FROM svc
805                     WHERE clu_id = :cid;
806                   EXEC SQL OPEN d_cursor;
807                   while (1)
808                     {
809                       EXEC SQL FETCH d_cursor INTO :label, :data;
810                       if (sqlca.sqlcode)
811                         break;
812                       strtrim(label);
813                       strtrim(data);
814                       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
815                               clubuf, HCLASS, HTYPE, label, data);
816                     }
817                   EXEC SQL CLOSE d_cursor;
818                 }
819             }
820         }
821       else
822         {
823           for (cid = 1; cid < maxclu; cid++)
824             if (SET_ISSET(cid, ms))
825               break;
826
827           EXEC SQL SELECT name INTO :name FROM clusters WHERE clu_id = :cid;
828           strtrim(name);
829           if (!valid(name))
830             continue;
831           strcpy(clubuf, name);
832         }
833
834       if ((mach = hash_lookup(machines, mid)))
835         {
836           fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
837                   mach, HCLASS, clubuf);
838           for (p = machbuf; *mach && *mach != '.'; mach++)
839             *p++ = *mach;
840           if (!strcasecmp(mach, ".mit.edu"))
841             {
842               *p = '\0';
843               fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
844                       machbuf, HCLASS, clubuf);
845             }
846         }
847       for (id = mid + 1; id < maxmach; id++)
848         {
849           if ((ps = machs[id]) && !SET_CMP(ms, ps))
850             {
851               free(ps);
852               machs[id] = NULL;
853               if ((mach = hash_lookup(machines, id)))
854                 {
855                   fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
856                           mach, HCLASS, clubuf);
857                   for (p = machbuf; *mach && *mach != '.'; mach++)
858                     *p++ = *mach;
859                   if (!strcasecmp(mach, ".mit.edu"))
860                     {
861                       *p = '\0';
862                       fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
863                               machbuf, HCLASS, clubuf);
864                     }
865                 }
866             }
867         }
868       free(ms);
869       machs[mid] = NULL;
870     }
871
872   EXEC SQL DECLARE d_cursor2 CURSOR FOR
873     SELECT c.name, d.serv_label, d.serv_cluster
874     FROM svc d, clusters c
875     WHERE c.clu_id = d.clu_id;
876   EXEC SQL OPEN d_cursor2;
877   while (1)
878     {
879       EXEC SQL FETCH d_cursor2 INTO :name, :label, :data;
880       if (sqlca.sqlcode)
881         break;
882       strtrim(name);
883       if (!valid(name))
884         continue;
885       strtrim(label);
886       strtrim(data);
887       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
888               name, HCLASS, HTYPE, label, data);
889     }
890   free(machs);
891   EXEC SQL COMMIT;
892
893   if (fclose(out))
894     {
895       fprintf(stderr, "Unsuccessful close of cluster.db\n");
896       exit(MR_CCONFIG);
897     }
898   fix_file(outf);
899   return 1;
900 sqlerr:
901   db_error(sqlca.sqlcode);
902   return 0;
903 }
904
905
906 int do_printcap(void)
907 {
908   FILE *out;
909   char outf[MAXPATHLEN], outft[MAXPATHLEN];
910   struct stat sb;
911   time_t ftime;
912   EXEC SQL BEGIN DECLARE SECTION;
913   char name[PRINTERS_NAME_SIZE], duplexname[PRINTERS_DUPLEXNAME_SIZE];
914   char rp[PRINTERS_RP_SIZE], type[PRINTERS_TYPE_SIZE];
915   char duplexrp[PRINTERS_RP_SIZE], pskind[PRINTSERVERS_KIND_SIZE];
916   int flag1, flag2, ka, rm, mc;
917   EXEC SQL END DECLARE SECTION;
918   char *rmname;
919
920   sprintf(outf, "%s/printcap.db", hesiod_dir);
921
922   if (stat(outf, &sb) == 0)
923     {
924       ftime = sb.st_mtime;
925       if (ModDiff (&flag1, "printers", ftime)
926           || ModDiff (&flag2, "printservers", ftime)
927           || ModDiff (&flag2, "machine", ftime))
928         exit(MR_DATE);
929       if (flag1 < 0 && flag2 < 0)
930         {
931           fprintf(stderr, "File printcap.db does not need to be rebuilt.\n");
932           return 0;
933         }
934     }
935
936   sprintf(outft, "%s~", outf);
937   out = fopen(outft, "w");
938   if (!out)
939     {
940       perror("cannot open printcap.db for write");
941       exit(MR_OCONFIG);
942     }
943
944   fprintf(stderr, "Building printcap.db\n");
945   get_mach();
946
947   EXEC SQL DECLARE p_cursor2 CURSOR FOR
948     SELECT p.name, p.duplexname, p.type, p.rp, p.rm, p.ka, p.mc, ps.kind
949     FROM printers p, printservers ps
950     WHERE p.rm = ps.mach_id;
951   EXEC SQL OPEN p_cursor2;
952   while (1)
953     {
954       EXEC SQL FETCH p_cursor2 INTO :name, :duplexname, :type,
955         :rp, :rm, :ka, :mc, :pskind;
956       if (sqlca.sqlcode)
957         break;
958       if (!(rmname = hash_lookup(machines, rm)))
959         continue;
960       strtrim(name);
961       if (!valid(name))
962         continue;
963       strtrim(rp);
964       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
965               name, HCLASS, HTYPE, name, rp, rmname, ka, mc);
966
967       strtrim(pskind);
968       if (!strcmp(pskind, "BSD"))
969         fprintf(out, "auth=none:remote_support=RQM:");
970       else if (!strcmp(pskind, "ATHENA"))
971         {
972           fprintf(out, "auth=%s:az:remote_support=RQM:",
973                   ka ? "kerberos4" : "none");
974         }
975       else if (!strcmp(pskind, "LPRNG"))
976         fprintf(out, "auth=kerberos5:xn:");
977
978       fputs("\"\n", out);
979
980       strtrim(duplexname);
981       if (!valid(duplexname))
982         continue;
983       if (!strcmp(strtrim(type), "ALIAS"))
984         {
985           EXEC SQL SELECT duplexname INTO :duplexrp
986             FROM printers WHERE name = :rp;
987           strtrim(duplexrp);
988         }
989       else
990         strcpy(duplexrp, duplexname);
991       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
992               duplexname, HCLASS, HTYPE, duplexname, duplexrp,
993               rmname, ka, mc);
994
995       if (!strcmp(pskind, "BSD"))
996         fprintf(out, "auth=none:remote_support=RQM:");
997       else if (!strcmp(pskind, "ATHENA"))
998         {
999           fprintf(out, "auth=%s:az:remote_support=RQM:",
1000                   ka ? "kerberos4" : "none");
1001         }
1002       else if (!strcmp(pskind, "LPRNG"))
1003         fprintf(out, "auth=kerberos5:xn:");
1004
1005       fputs("\"\n", out);
1006     }
1007   EXEC SQL CLOSE p_cursor2;
1008
1009   EXEC SQL COMMIT;
1010
1011   if (fclose(out))
1012     {
1013       fprintf(stderr, "Unsuccessful close of pcap.db\n");
1014       exit(MR_CCONFIG);
1015     }
1016   fix_file(outf);
1017   return 1;
1018 sqlerr:
1019   db_error(sqlca.sqlcode);
1020   return 0;
1021 }
1022
1023
1024 int do_sloc(void)
1025 {
1026   FILE *out;
1027   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
1028   struct stat sb;
1029   time_t ftime;
1030   EXEC SQL BEGIN DECLARE SECTION;
1031   char service[SERVERHOSTS_SERVICE_SIZE];
1032   int flag1, flag2, id;
1033   EXEC SQL END DECLARE SECTION;
1034
1035   sprintf(outf, "%s/sloc.db", hesiod_dir);
1036
1037   if (stat(outf, &sb) == 0)
1038     {
1039       ftime = sb.st_mtime;
1040       if ((ModDiff (&flag1, "serverhosts", ftime)) ||
1041           (ModDiff (&flag2, "machine", ftime)))
1042         exit(MR_DATE);
1043       if (flag1 < 0 && flag2 < 0)
1044         {
1045           fprintf(stderr, "File sloc.db does not need to be rebuilt.\n");
1046           return 0;
1047         }
1048     }
1049
1050   sprintf(outft, "%s~", outf);
1051   out = fopen(outft, "w");
1052   if (!out)
1053     {
1054       perror("cannot open sloc.db for write");
1055       exit(MR_OCONFIG);
1056     }
1057
1058   fprintf(stderr, "Building sloc.db\n");
1059   get_mach();
1060
1061   EXEC SQL DECLARE s_cursor CURSOR FOR
1062     SELECT DISTINCT service, mach_id
1063     FROM serverhosts
1064     ORDER BY service;
1065   EXEC SQL OPEN s_cursor;
1066   while (1)
1067     {
1068       EXEC SQL FETCH s_cursor INTO :service, :id;
1069       if (sqlca.sqlcode)
1070         break;
1071       strtrim(service);
1072       if (valid(service) && (mach = hash_lookup(machines, id)))
1073         fprintf(out, "%s.sloc\t%s %s %s\n", service, HCLASS, HTYPE, mach);
1074     }
1075   EXEC SQL CLOSE s_cursor;
1076
1077   EXEC SQL COMMIT;
1078
1079   if (fclose(out))
1080     {
1081       fprintf(stderr, "Unsuccessful close of sloc.db\n");
1082       exit(MR_CCONFIG);
1083     }
1084
1085   fix_file(outf);
1086   return 1;
1087 sqlerr:
1088   db_error(sqlca.sqlcode);
1089   return 0;
1090 }
1091
1092 int do_service(void)
1093 {
1094   FILE *out;
1095   char outf[MAXPATHLEN], outft[MAXPATHLEN];
1096   struct stat sb;
1097   time_t ftime;
1098   EXEC SQL BEGIN DECLARE SECTION;
1099   char service[SERVICES_NAME_SIZE], protocol[SERVICES_PROTOCOL_SIZE];
1100   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
1101   int port, flag1;
1102   EXEC SQL END DECLARE SECTION;
1103
1104   sprintf(outf, "%s/service.db", hesiod_dir);
1105
1106   if (stat(outf, &sb) == 0)
1107     {
1108       ftime = sb.st_mtime;
1109       if (ModDiff (&flag1, "services", ftime))
1110         exit(MR_DATE);
1111       if (flag1 < 0)
1112         {
1113           fprintf(stderr, "File service.db does not need to be rebuilt.\n");
1114           return 0;
1115         }
1116     }
1117
1118   sprintf(outft, "%s~", outf);
1119   out = fopen(outft, "w");
1120   if (!out)
1121     {
1122       perror("cannot open service.db for write");
1123       exit(MR_OCONFIG);
1124     }
1125
1126   fprintf(stderr, "Building service.db\n");
1127
1128   EXEC SQL DECLARE s_cursor2 CURSOR FOR
1129     SELECT name, protocol, port
1130     FROM services;
1131   EXEC SQL OPEN s_cursor2;
1132   while (1)
1133     {
1134       EXEC SQL FETCH s_cursor2 INTO :service, :protocol, :port;
1135       if (sqlca.sqlcode)
1136         break;
1137       lowercase(protocol);      /* Convert protocol to lowercase */
1138       strtrim(service);
1139       if (!valid(service))
1140         continue;
1141       strtrim(protocol);
1142       fprintf(out, "%s.service\t%s %s \"%s %s %d\"\n",
1143               service, HCLASS, HTYPE, service, protocol, port);
1144     }
1145   EXEC SQL CLOSE s_cursor2;
1146
1147   EXEC SQL DECLARE a_cursor3 CURSOR FOR
1148     SELECT name, trans
1149     FROM alias
1150     WHERE type = 'SERVICE';
1151   EXEC SQL OPEN a_cursor3;
1152   while (1)
1153     {
1154       EXEC SQL FETCH a_cursor3 INTO :aname, :trans;
1155       if (sqlca.sqlcode)
1156         break;
1157       strtrim(aname);
1158       strtrim(trans);
1159       if (!valid(aname) || !valid(trans))
1160         continue;
1161       fprintf(out, "%s.service\t%s CNAME %s.service\n", aname, HCLASS,
1162               trans);
1163     }
1164   EXEC SQL CLOSE a_cursor3;
1165
1166   EXEC SQL COMMIT;
1167
1168   if (fclose(out))
1169     {
1170       fprintf(stderr, "Unsuccessful close of service.db\n");
1171       exit(MR_CCONFIG);
1172     }
1173   fix_file(outf);
1174   return 1;
1175 sqlerr:
1176   db_error(sqlca.sqlcode);
1177   return 0;
1178 }
This page took 0.15811 seconds and 5 git commands to generate.