]> andersk Git - moira.git/blob - gen/hesiod.pc
only output groups which have the nfsgroup bit set into a user's hesiod
[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       EXEC SQL OPEN u_cursor2;
423       while (1)
424         {
425           EXEC SQL FETCH u_cursor2 INTO :id, :name;
426           if (sqlca.sqlcode)
427             break;
428           u = malloc(sizeof(struct user));
429           strcpy(u->name, strtrim(name));
430           u->lists = NULL;
431           hash_store(users, id, u);
432         }
433       EXEC SQL CLOSE u_cursor2;
434     }
435
436   EXEC SQL DECLARE i_cursor CURSOR FOR
437     SELECT m.list_id, m.member_id
438     FROM imembers m, list l 
439     WHERE m.member_type = 'USER'
440     AND m.list_id = l.list_id AND l.grouplist = 1 AND l.nfsgroup = 1;
441   EXEC SQL OPEN i_cursor;
442   while (1)
443     {
444       EXEC SQL FETCH i_cursor INTO :lid, :id;
445       if (sqlca.sqlcode)
446         break;
447       if ((l = hash_lookup(groups, lid)) && (u = hash_lookup(users, id)))
448         {
449           g = malloc(sizeof(struct grp));
450           g->next = u->lists;
451           u->lists = g;
452           g->lid = l;
453         }
454     }
455   EXEC SQL CLOSE i_cursor;
456
457   EXEC SQL COMMIT;
458
459   for (p = &(users->data[users->size - 1]); p >= users->data; p--)
460     {
461       for (b = *p; b; b = b->next)
462         {
463           if (!(g = ((struct user *)b->data)->lists))
464             continue;
465           fprintf(lout, "%s.grplist\t%s %s \"",
466                   ((struct user *)b->data)->name, HCLASS, HTYPE);
467           len = 0;
468           for (; g; g = g->next)
469             {
470               if (len + strlen(g->lid) + 1 < MAXHESSIZE)
471                 {
472                   fputs(g->lid, lout);
473                   if (g->next)
474                     putc(':', lout);
475                   len += strlen(g->lid) + 1;
476                 }
477               else
478                 {
479                   com_err(whoami, 0, "truncated grp list for user %s",
480                           ((struct user *)b->data)->name);
481                   break;
482                 }
483             }
484           fputs("\"\n", lout);
485         }
486     }
487
488   if (fclose(iout) || fclose(gout) || fclose(lout))
489     {
490       fprintf(stderr, "Unsuccessful close of gid.db, group.db, or grplist.db\n");
491       exit(MR_CCONFIG);
492     }
493   fix_file(ioutf);
494   fix_file(goutf);
495   fix_file(loutf);
496   return 1;
497 sqlerr:
498   db_error(sqlca.sqlcode);
499   return 0;
500 }
501
502
503 int do_filsys(void)
504 {
505   FILE *out;
506   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach, *group;
507   struct stat sb;
508   time_t ftime;
509   struct save_queue *sq, *sq2;
510   EXEC SQL BEGIN DECLARE SECTION;
511   char name[FILESYS_LABEL_SIZE], type[FILESYS_TYPE_SIZE];
512   char loc[FILESYS_NAME_SIZE], access[FILESYS_RWACCESS_SIZE];
513   char mount[FILESYS_MOUNT_SIZE], comments[FILESYS_COMMENTS_SIZE];
514   char key[FSGROUP_KEY_SIZE];
515   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
516   int flag1, flag2, flag3, flag4, id, fid;
517   EXEC SQL END DECLARE SECTION;
518
519   sprintf(outf, "%s/filsys.db", hesiod_dir);
520
521   if (stat(outf, &sb) == 0)
522     {
523       ftime = sb.st_mtime;
524
525       if (ModDiff(&flag1, "filesys", ftime))
526         exit(MR_DATE);
527       if (ModDiff(&flag2, "machine", ftime))
528         exit(MR_DATE);
529       if (ModDiff(&flag3, "alias", ftime))
530         exit(MR_DATE);
531       if (ModDiff(&flag4, "fsgroup", ftime))
532         exit(MR_DATE);
533
534       if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0)
535         {
536           fprintf(stderr, "File filsys.db does not need to be rebuilt.\n");
537           return 0;
538         }
539     }
540
541   sprintf(outft, "%s~", outf);
542   out = fopen(outft, "w");
543   if (!out)
544     {
545       perror("cannot open filsys.db for write");
546       exit(MR_OCONFIG);
547     }
548
549   fprintf(stderr, "Building filsys.db\n");
550   get_mach();
551   sq = sq_create();
552   sq2 = sq_create();
553
554   EXEC SQL DECLARE f_cursor CURSOR FOR
555     SELECT label, type, name, mach_id, rwaccess, mount, comments, filsys_id
556     FROM filesys
557     ORDER BY filsys_id;
558   EXEC SQL OPEN f_cursor;
559   while (1)
560     {
561       EXEC SQL FETCH f_cursor INTO :name, :type, :loc, :id, :access,
562         :mount, :comments, :fid;
563       if (sqlca.sqlcode)
564         break;
565       strtrim(name);
566       if (!valid(name))
567         continue;
568       strtrim(type);
569       if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
570         {
571           if ((mach = hash_lookup(machines, id)))
572             {
573               fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s\"\n",
574                       name, HCLASS, HTYPE, type, strtrim(loc),
575                       mach, strtrim(access), strtrim(mount));
576             }
577         }
578       else if (!strcmp(type, "AFS"))
579         {
580           fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s\"\n",
581                   name, HCLASS, HTYPE, strtrim(loc),
582                   strtrim(access), strtrim(mount));
583         }
584       else if (!strcmp(type, "ERR"))
585         {
586           fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
587                   name, HCLASS, HTYPE, strtrim(comments));
588         }
589       else if (!strcmp(type, "FSGROUP"))
590         {
591           char buf[FILESYS_NAME_SIZE + 10];
592           sprintf(buf, "%s:%d", name, fid);
593           sq_save_data(sq, strdup(buf));
594         }
595       else if (!strcmp(type, "MUL"))
596         {
597           char buf[FILESYS_NAME_SIZE + 10];
598           sprintf(buf, "%s:%d", name, fid);
599           sq_save_data(sq2, strdup(buf));
600         }
601     }
602   EXEC SQL CLOSE f_cursor;
603
604   while (sq_get_data(sq, &group))
605     {
606       fid = atoi(strchr(group, ':') + 1);
607       *strchr(group, ':') = 0;
608
609       EXEC SQL DECLARE f_cursor2 CURSOR FOR
610         SELECT DISTINCT f.type, f.name, f.mach_id, f.rwaccess, f.mount,
611         f.comments, f.label, g.key
612         FROM filesys f, fsgroup g
613         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
614         ORDER BY key, label;
615       EXEC SQL OPEN f_cursor2;
616       for (flag1 = 1; ; flag1++)
617         {
618           EXEC SQL FETCH f_cursor2 INTO :type, :loc, :id, :access, :mount,
619             :comments, :name, :key;
620           if (sqlca.sqlcode)
621             break;
622           strtrim(type);
623           if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
624             {
625               if ((mach = hash_lookup(machines, id)))
626                 {
627                   fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s %d\"\n",
628                           group, HCLASS, HTYPE, type, strtrim(loc), mach,
629                           strtrim(access), strtrim(mount), flag1);
630                 }
631             }
632           else if (!strcmp(type, "AFS"))
633             {
634               fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s %d\"\n",
635                       group, HCLASS, HTYPE, strtrim(loc), strtrim(access),
636                       strtrim(mount), flag1);
637             }
638           else if (!strcmp(type, "ERR"))
639             {
640               fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
641                       group, HCLASS, HTYPE, strtrim(comments));
642             }
643         }
644       EXEC SQL CLOSE f_cursor2;
645       free(group);
646     }
647   sq_destroy(sq);
648
649   while (sq_get_data(sq2, &group))
650     {
651       fid = atoi(strchr(group, ':') + 1);
652       *strchr(group, ':') = 0;
653       fprintf(out, "%s.filsys\t%s %s \"MUL", group, HCLASS, HTYPE);
654       EXEC SQL DECLARE f_cursor3 CURSOR FOR
655         SELECT DISTINCT f.label, g.key
656         FROM filesys f, fsgroup g
657         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
658         ORDER BY key, label;
659       EXEC SQL OPEN f_cursor3;
660       while (1)
661         {
662           EXEC SQL FETCH f_cursor3 INTO :name, :key;
663           if (sqlca.sqlcode)
664             break;
665           fprintf(out, " %s", strtrim(name));
666         }
667       EXEC SQL CLOSE f_cursor3;
668       fprintf(out, "\"\n");
669       free(group);
670     }
671   sq_destroy(sq2);
672
673   EXEC SQL DECLARE a_cursor CURSOR FOR
674     SELECT name, trans
675     FROM alias
676     WHERE type = 'FILESYS';
677   EXEC SQL OPEN a_cursor;
678   while (1)
679     {
680       EXEC SQL FETCH a_cursor INTO :aname, :trans;
681       if (sqlca.sqlcode)
682         break;
683       strtrim(aname);
684       strtrim(trans);
685       if (!valid(aname) || !valid(trans))
686         continue;
687       fprintf(out, "%s.filsys\t%s CNAME %s.filsys\n",
688               aname, HCLASS, trans);
689     }
690   EXEC SQL CLOSE a_cursor;
691
692   EXEC SQL COMMIT;
693
694   if (fclose(out))
695     {
696       fprintf(stderr, "Unsuccessful close of filsys.db\n");
697       exit(MR_CCONFIG);
698     }
699   fix_file(outf);
700   return 1;
701 sqlerr:
702   db_error(sqlca.sqlcode);
703   return 0;
704 }
705
706 int nbitsset(set_mask *set)
707 {
708   int i, ret;
709   ret = 0;
710   for (i = 0; i < setsize * NSETBITS; i++)
711     {
712       if (SET_ISSET(i, set))
713         ret++;
714     }
715   return ret;
716 }
717
718
719 int do_cluster(void)
720 {
721   FILE *out;
722   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
723   char machbuf[MACHINE_NAME_SIZE], clubuf[CLUSTERS_NAME_SIZE], *p;
724   struct stat sb;
725   time_t ftime;
726   EXEC SQL BEGIN DECLARE SECTION;
727   int flag1, flag2, flag3, flag4, maxmach, maxclu, mid, cid, id;
728   char name[CLUSTERS_NAME_SIZE];
729   char label[SVC_SERV_LABEL_SIZE], data[SVC_SERV_CLUSTER_SIZE];
730   EXEC SQL END DECLARE SECTION;
731   set_mask **machs, *ms, *ps;
732
733   sprintf(outf, "%s/cluster.db", hesiod_dir);
734
735   if (stat(outf, &sb) == 0)
736     {
737       ftime = sb.st_mtime;
738       if (ModDiff (&flag1, "clusters", ftime)
739           || ModDiff (&flag2, "machine", ftime)
740           || ModDiff (&flag3, "mcmap", ftime)
741           || ModDiff (&flag4, "svc", ftime))
742         exit(MR_DATE);
743       if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0)
744         {
745           fprintf(stderr, "File cluster.db does not need to be rebuilt.\n");
746           return 0;
747         }
748     }
749
750   sprintf(outft, "%s~", outf);
751   out = fopen(outft, "w");
752   if (!out)
753     {
754       perror("cannot open cluster.db for write");
755       exit(MR_OCONFIG);
756     }
757
758   fprintf(stderr, "Building cluster.db\n");
759   get_mach();
760
761   EXEC SQL SELECT MAX(clu_id) INTO :maxclu FROM clusters;
762   maxclu++;
763   setsize = howmany(maxclu, NSETBITS);
764
765   EXEC SQL SELECT MAX(mach_id) INTO :maxmach FROM machine;
766   maxmach++;
767   machs = malloc((maxmach + 1) * sizeof(set_mask **));
768   memset(machs, 0, (maxmach + 1) * sizeof(int));
769
770   EXEC SQL DECLARE p_cursor CURSOR FOR
771     SELECT mach_id, clu_id
772     FROM mcmap
773     ORDER BY mach_id;
774   EXEC SQL OPEN p_cursor;
775   while (1)
776     {
777       EXEC SQL FETCH p_cursor INTO :mid, :cid;
778       if (sqlca.sqlcode)
779         break;
780       if (!(ms = machs[mid]))
781         {
782           ms = machs[mid] = SET_CREATE();
783           SET_ZERO(ms);
784         }
785       SET_SET(cid, ms);
786     }
787   EXEC SQL CLOSE p_cursor;
788
789   for (mid = 1; mid < maxmach; mid++)
790     {
791       if (!machs[mid])
792         continue;
793       ms = machs[mid];
794       if (nbitsset(ms) > 1)
795         {
796           sprintf(clubuf, "mrinternal-%d", mid);
797           for (cid = 1; cid < maxclu; cid++)
798             {
799               if (SET_ISSET(cid, ms))
800                 {
801                   EXEC SQL DECLARE d_cursor CURSOR FOR
802                     SELECT serv_label, serv_cluster
803                     FROM svc
804                     WHERE clu_id = :cid;
805                   EXEC SQL OPEN d_cursor;
806                   while (1)
807                     {
808                       EXEC SQL FETCH d_cursor INTO :label, :data;
809                       if (sqlca.sqlcode)
810                         break;
811                       strtrim(label);
812                       strtrim(data);
813                       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
814                               clubuf, HCLASS, HTYPE, label, data);
815                     }
816                   EXEC SQL CLOSE d_cursor;
817                 }
818             }
819         }
820       else
821         {
822           for (cid = 1; cid < maxclu; cid++)
823             if (SET_ISSET(cid, ms))
824               break;
825
826           EXEC SQL SELECT name INTO :name FROM clusters WHERE clu_id = :cid;
827           strtrim(name);
828           if (!valid(name))
829             continue;
830           strcpy(clubuf, name);
831         }
832
833       if ((mach = hash_lookup(machines, mid)))
834         {
835           fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
836                   mach, HCLASS, clubuf);
837           for (p = machbuf; *mach && *mach != '.'; mach++)
838             *p++ = *mach;
839           if (!strcasecmp(mach, ".mit.edu"))
840             {
841               *p = '\0';
842               fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
843                       machbuf, HCLASS, clubuf);
844             }
845         }
846       for (id = mid + 1; id < maxmach; id++)
847         {
848           if ((ps = machs[id]) && !SET_CMP(ms, ps))
849             {
850               free(ps);
851               machs[id] = NULL;
852               if ((mach = hash_lookup(machines, id)))
853                 {
854                   fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
855                           mach, HCLASS, clubuf);
856                   for (p = machbuf; *mach && *mach != '.'; mach++)
857                     *p++ = *mach;
858                   if (!strcasecmp(mach, ".mit.edu"))
859                     {
860                       *p = '\0';
861                       fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
862                               machbuf, HCLASS, clubuf);
863                     }
864                 }
865             }
866         }
867       free(ms);
868       machs[mid] = NULL;
869     }
870
871   EXEC SQL DECLARE d_cursor2 CURSOR FOR
872     SELECT c.name, d.serv_label, d.serv_cluster
873     FROM svc d, clusters c
874     WHERE c.clu_id = d.clu_id;
875   EXEC SQL OPEN d_cursor2;
876   while (1)
877     {
878       EXEC SQL FETCH d_cursor2 INTO :name, :label, :data;
879       if (sqlca.sqlcode)
880         break;
881       strtrim(name);
882       if (!valid(name))
883         continue;
884       strtrim(label);
885       strtrim(data);
886       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
887               name, HCLASS, HTYPE, label, data);
888     }
889   free(machs);
890   EXEC SQL COMMIT;
891
892   if (fclose(out))
893     {
894       fprintf(stderr, "Unsuccessful close of cluster.db\n");
895       exit(MR_CCONFIG);
896     }
897   fix_file(outf);
898   return 1;
899 sqlerr:
900   db_error(sqlca.sqlcode);
901   return 0;
902 }
903
904
905 int do_printcap(void)
906 {
907   FILE *out;
908   char outf[MAXPATHLEN], outft[MAXPATHLEN];
909   struct stat sb;
910   time_t ftime;
911   EXEC SQL BEGIN DECLARE SECTION;
912   char name[PRINTERS_NAME_SIZE], duplexname[PRINTERS_DUPLEXNAME_SIZE];
913   char rp[PRINTERS_RP_SIZE], type[PRINTERS_TYPE_SIZE];
914   char duplexrp[PRINTERS_RP_SIZE], pskind[PRINTSERVERS_KIND_SIZE];
915   int flag1, flag2, ka, rm, mc;
916   EXEC SQL END DECLARE SECTION;
917   char *rmname;
918
919   sprintf(outf, "%s/printcap.db", hesiod_dir);
920
921   if (stat(outf, &sb) == 0)
922     {
923       ftime = sb.st_mtime;
924       if (ModDiff (&flag1, "printers", ftime)
925           || ModDiff (&flag2, "printservers", ftime)
926           || ModDiff (&flag2, "machine", ftime))
927         exit(MR_DATE);
928       if (flag1 < 0 && flag2 < 0)
929         {
930           fprintf(stderr, "File printcap.db does not need to be rebuilt.\n");
931           return 0;
932         }
933     }
934
935   sprintf(outft, "%s~", outf);
936   out = fopen(outft, "w");
937   if (!out)
938     {
939       perror("cannot open printcap.db for write");
940       exit(MR_OCONFIG);
941     }
942
943   fprintf(stderr, "Building printcap.db\n");
944   get_mach();
945
946   EXEC SQL DECLARE p_cursor2 CURSOR FOR
947     SELECT p.name, p.duplexname, p.type, p.rp, p.rm, p.ka, p.mc, ps.kind
948     FROM printers p, printservers ps
949     WHERE p.rm = ps.mach_id;
950   EXEC SQL OPEN p_cursor2;
951   while (1)
952     {
953       EXEC SQL FETCH p_cursor2 INTO :name, :duplexname, :type,
954         :rp, :rm, :ka, :mc, :pskind;
955       if (sqlca.sqlcode)
956         break;
957       if (!(rmname = hash_lookup(machines, rm)))
958         continue;
959       strtrim(name);
960       if (!valid(name))
961         continue;
962       strtrim(rp);
963       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
964               name, HCLASS, HTYPE, name, rp, rmname, ka, mc);
965
966       strtrim(pskind);
967       if (!strcmp(pskind, "BSD"))
968         fprintf(out, "auth=none:remote_support=RQM:");
969       else if (!strcmp(pskind, "ATHENA"))
970         {
971           fprintf(out, "auth=%s:az:remote_support=RQM:",
972                   ka ? "kerberos4" : "none");
973         }
974       else if (!strcmp(pskind, "LPRNG"))
975         fprintf(out, "auth=kerberos5:xn:");
976
977       fputs("\"\n", out);
978
979       strtrim(duplexname);
980       if (!valid(duplexname))
981         continue;
982       if (!strcmp(strtrim(type), "ALIAS"))
983         {
984           EXEC SQL SELECT duplexname INTO :duplexrp
985             FROM printers WHERE name = :rp;
986           strtrim(duplexrp);
987         }
988       else
989         strcpy(duplexrp, duplexname);
990       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
991               duplexname, HCLASS, HTYPE, duplexname, duplexrp,
992               rmname, ka, mc);
993
994       if (!strcmp(pskind, "BSD"))
995         fprintf(out, "auth=none:remote_support=RQM:");
996       else if (!strcmp(pskind, "ATHENA"))
997         {
998           fprintf(out, "auth=%s:az:remote_support=RQM:",
999                   ka ? "kerberos4" : "none");
1000         }
1001       else if (!strcmp(pskind, "LPRNG"))
1002         fprintf(out, "auth=kerberos5:xn:");
1003
1004       fputs("\"\n", out);
1005     }
1006   EXEC SQL CLOSE p_cursor2;
1007
1008   EXEC SQL COMMIT;
1009
1010   if (fclose(out))
1011     {
1012       fprintf(stderr, "Unsuccessful close of pcap.db\n");
1013       exit(MR_CCONFIG);
1014     }
1015   fix_file(outf);
1016   return 1;
1017 sqlerr:
1018   db_error(sqlca.sqlcode);
1019   return 0;
1020 }
1021
1022
1023 int do_sloc(void)
1024 {
1025   FILE *out;
1026   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
1027   struct stat sb;
1028   time_t ftime;
1029   EXEC SQL BEGIN DECLARE SECTION;
1030   char service[SERVERHOSTS_SERVICE_SIZE];
1031   int flag1, flag2, id;
1032   EXEC SQL END DECLARE SECTION;
1033
1034   sprintf(outf, "%s/sloc.db", hesiod_dir);
1035
1036   if (stat(outf, &sb) == 0)
1037     {
1038       ftime = sb.st_mtime;
1039       if ((ModDiff (&flag1, "serverhosts", ftime)) ||
1040           (ModDiff (&flag2, "machine", ftime)))
1041         exit(MR_DATE);
1042       if (flag1 < 0 && flag2 < 0)
1043         {
1044           fprintf(stderr, "File sloc.db does not need to be rebuilt.\n");
1045           return 0;
1046         }
1047     }
1048
1049   sprintf(outft, "%s~", outf);
1050   out = fopen(outft, "w");
1051   if (!out)
1052     {
1053       perror("cannot open sloc.db for write");
1054       exit(MR_OCONFIG);
1055     }
1056
1057   fprintf(stderr, "Building sloc.db\n");
1058   get_mach();
1059
1060   EXEC SQL DECLARE s_cursor CURSOR FOR
1061     SELECT DISTINCT service, mach_id
1062     FROM serverhosts
1063     ORDER BY service;
1064   EXEC SQL OPEN s_cursor;
1065   while (1)
1066     {
1067       EXEC SQL FETCH s_cursor INTO :service, :id;
1068       if (sqlca.sqlcode)
1069         break;
1070       strtrim(service);
1071       if (valid(service) && (mach = hash_lookup(machines, id)))
1072         fprintf(out, "%s.sloc\t%s %s %s\n", service, HCLASS, HTYPE, mach);
1073     }
1074   EXEC SQL CLOSE s_cursor;
1075
1076   EXEC SQL COMMIT;
1077
1078   if (fclose(out))
1079     {
1080       fprintf(stderr, "Unsuccessful close of sloc.db\n");
1081       exit(MR_CCONFIG);
1082     }
1083
1084   fix_file(outf);
1085   return 1;
1086 sqlerr:
1087   db_error(sqlca.sqlcode);
1088   return 0;
1089 }
1090
1091 int do_service(void)
1092 {
1093   FILE *out;
1094   char outf[MAXPATHLEN], outft[MAXPATHLEN];
1095   struct stat sb;
1096   time_t ftime;
1097   EXEC SQL BEGIN DECLARE SECTION;
1098   char service[SERVICES_NAME_SIZE], protocol[SERVICES_PROTOCOL_SIZE];
1099   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
1100   int port, flag1;
1101   EXEC SQL END DECLARE SECTION;
1102
1103   sprintf(outf, "%s/service.db", hesiod_dir);
1104
1105   if (stat(outf, &sb) == 0)
1106     {
1107       ftime = sb.st_mtime;
1108       if (ModDiff (&flag1, "services", ftime))
1109         exit(MR_DATE);
1110       if (flag1 < 0)
1111         {
1112           fprintf(stderr, "File service.db does not need to be rebuilt.\n");
1113           return 0;
1114         }
1115     }
1116
1117   sprintf(outft, "%s~", outf);
1118   out = fopen(outft, "w");
1119   if (!out)
1120     {
1121       perror("cannot open service.db for write");
1122       exit(MR_OCONFIG);
1123     }
1124
1125   fprintf(stderr, "Building service.db\n");
1126
1127   EXEC SQL DECLARE s_cursor2 CURSOR FOR
1128     SELECT name, protocol, port
1129     FROM services;
1130   EXEC SQL OPEN s_cursor2;
1131   while (1)
1132     {
1133       EXEC SQL FETCH s_cursor2 INTO :service, :protocol, :port;
1134       if (sqlca.sqlcode)
1135         break;
1136       lowercase(protocol);      /* Convert protocol to lowercase */
1137       strtrim(service);
1138       if (!valid(service))
1139         continue;
1140       strtrim(protocol);
1141       fprintf(out, "%s.service\t%s %s \"%s %s %d\"\n",
1142               service, HCLASS, HTYPE, service, protocol, port);
1143     }
1144   EXEC SQL CLOSE s_cursor2;
1145
1146   EXEC SQL DECLARE a_cursor3 CURSOR FOR
1147     SELECT name, trans
1148     FROM alias
1149     WHERE type = 'SERVICE';
1150   EXEC SQL OPEN a_cursor3;
1151   while (1)
1152     {
1153       EXEC SQL FETCH a_cursor3 INTO :aname, :trans;
1154       if (sqlca.sqlcode)
1155         break;
1156       strtrim(aname);
1157       strtrim(trans);
1158       if (!valid(aname) || !valid(trans))
1159         continue;
1160       fprintf(out, "%s.service\t%s CNAME %s.service\n", aname, HCLASS,
1161               trans);
1162     }
1163   EXEC SQL CLOSE a_cursor3;
1164
1165   EXEC SQL COMMIT;
1166
1167   if (fclose(out))
1168     {
1169       fprintf(stderr, "Unsuccessful close of service.db\n");
1170       exit(MR_CCONFIG);
1171     }
1172   fix_file(outf);
1173   return 1;
1174 sqlerr:
1175   db_error(sqlca.sqlcode);
1176   return 0;
1177 }
This page took 0.148543 seconds and 5 git commands to generate.