]> andersk Git - moira.git/blob - gen/hesiod.pc
Revised EXCHANGE behavior.
[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 256
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         return 0;
181       if (*name == '.')
182         {
183           if (sawdot)
184             return 0;
185           else
186             sawdot = 1;
187         }
188       else
189         sawdot = 0;
190     }
191   return !sawdot;
192 }
193
194
195 int do_passwd(void)
196 {
197   FILE *pout, *uout, *bout;
198   char poutf[MAXPATHLEN], uoutf[MAXPATHLEN], poutft[MAXPATHLEN];
199   char uoutft[MAXPATHLEN], boutf[MAXPATHLEN], boutft[MAXPATHLEN];
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], potype[USERS_POTYPE_SIZE];
207   int uid, id, pid, iid, eid, 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   sprintf(poutft, "%s~", poutf);
215   pout = fopen(poutft, "w");
216   if (!pout)
217     {
218       perror("cannot open passwd.db~ for write");
219       exit(MR_OCONFIG);
220     }
221   sprintf(uoutft, "%s~", uoutf);
222   uout = fopen(uoutft, "w");
223   if (!uout)
224     {
225       perror("cannot open uid.db~ for write");
226       exit(MR_OCONFIG);
227     }
228   sprintf(boutft, "%s~", boutf);
229   bout = fopen(boutft, "w");
230   if (!bout)
231     {
232       perror("cannot open pobox.db for write");
233       exit(MR_OCONFIG);
234     }
235
236   fprintf(stderr, "Building passwd.db, uid.db, and pobox.db\n");
237   get_mach();
238
239   users = create_hash(12001);
240   EXEC SQL DECLARE u_cursor CURSOR FOR
241     SELECT login, unix_uid, shell, fullname, nickname, office_addr,
242     office_phone, home_phone, users_id, potype, pop_id, imap_id, exchange_id,
243     status
244     FROM users
245     WHERE status = 1 OR status = 2 OR status = 5 OR status = 6
246     ORDER BY users_id;
247   EXEC SQL OPEN u_cursor;
248   while (1)
249     {
250       EXEC SQL FETCH u_cursor INTO :login, :uid, :shell, :fullname, :nn,
251         :oa, :op, :hp, :id, :potype, :pid, :iid, :eid, :status;
252       if (sqlca.sqlcode)
253         break;
254       strtrim(login);
255       dequote(fullname);
256       dequote(nn);
257       dequote(oa);
258       dequote(op);
259       dequote(hp);
260       dequote(shell);
261       dequote(potype);
262       u = malloc(sizeof(struct user));
263       strcpy(u->name, login);
264       u->lists = NULL;
265       hash_store(users, id, u);
266       if (status == 1 || status == 2)
267         {
268           fprintf(pout, "%s.passwd\t%s %s \"%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\"\n",
269                   login, HCLASS, HTYPE, login, uid, fullname, nn, oa,
270                   op, hp, login, shell);
271           fprintf(uout, "%d.uid\t%s CNAME %s.passwd\n", uid, HCLASS, login);
272         }
273
274       if (eid != 0)
275         {
276           /* Check for IMAP.  Can't use iid because it should be zero. */
277           EXEC SQL SELECT mach_id INTO :mid FROM filesys
278             WHERE label = :login || '.po' AND type = 'IMAP';
279           if (sqlca.sqlcode == 0)
280             pid = mid;
281           else
282             {
283               /* EXCHANGE user with no IMAP filesystem.  Give them
284                * IMAP.EXCHANGE.MIT.EDU instead of EXCHANGE.MIT.EDU.
285                */
286               EXEC SQL SELECT mach_id INTO :eid FROM machine
287                 WHERE name = 'IMAP.EXCHANGE.MIT.EDU';
288               if (sqlca.sqlcode == 0)
289                 pid = eid;
290             }
291         }
292
293       if (iid != 0)
294         {
295           EXEC SQL SELECT mach_id INTO :mid FROM filesys
296             WHERE filsys_id = :iid AND type = 'IMAP';
297           if (sqlca.sqlcode == 0)
298             pid = mid;
299         }
300
301       if ((strcmp(potype, "NONE") != 0) &&  pid != 0 &&
302           (mach = hash_lookup(machines, pid)))
303         {
304           fprintf(bout, "%s.pobox\t%s %s \"POP %s %s\"\n",
305                   login, HCLASS, HTYPE, mach, login);
306         }
307     }
308   if (sqlca.sqlcode < 0)
309     db_error(sqlca.sqlcode);
310   EXEC SQL CLOSE u_cursor;
311   EXEC SQL COMMIT;
312
313   if (fclose(pout) || fclose(uout) || fclose(bout))
314     {
315       fprintf(stderr, "Unsuccessful file close of passwd.db, uid.db, or pobox.db\n");
316       exit(MR_CCONFIG);
317     }
318   fix_file(poutf);
319   fix_file(uoutf);
320   fix_file(boutf);
321   return 1;
322 }
323
324
325 int do_groups(void)
326 {
327   FILE *iout, *gout, *lout;
328   char ioutf[MAXPATHLEN], goutf[MAXPATHLEN], loutf[MAXPATHLEN];
329   char buf[MAXPATHLEN], *l;
330   struct hash *groups;
331   struct bucket *b, **p;
332   struct grp *g;
333   struct user *u;
334   EXEC SQL BEGIN DECLARE SECTION;
335   char name[LIST_NAME_SIZE];
336   int gid, id, lid, len;
337   EXEC SQL END DECLARE SECTION;
338
339   /* open files */
340   sprintf(ioutf, "%s/gid.db", hesiod_dir);
341   sprintf(goutf, "%s/group.db", hesiod_dir);
342   sprintf(loutf, "%s/grplist.db", hesiod_dir);
343
344   sprintf(buf, "%s~", ioutf);
345   iout = fopen(buf, "w");
346   if (!iout)
347     {
348       perror("cannot open gid.db for write");
349       exit(MR_OCONFIG);
350     }
351   sprintf(buf, "%s~", goutf);
352   gout = fopen(buf, "w");
353   if (!gout)
354     {
355       perror("cannot open group.db for write");
356       exit(MR_OCONFIG);
357     }
358   sprintf(buf, "%s~", loutf);
359   lout = fopen(buf, "w");
360   if (!lout)
361     {
362       perror("cannot open grplist.db for write");
363       exit(MR_OCONFIG);
364     }
365
366   fprintf(stderr, "Building gid.db, group.db, and grplist.db\n");
367
368   /* make space for group list */
369   groups = create_hash(15001);
370
371   /* The following WHENEVER is declarative, not executed,
372    * and applies for the remainder of this file only.
373    */
374   EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
375
376   EXEC SQL DECLARE l_cursor CURSOR FOR
377     SELECT name, gid, list_id
378     FROM list
379     WHERE grouplist != 0 AND active != 0
380     ORDER BY list_id;
381   EXEC SQL OPEN l_cursor;
382   while (1)
383     {
384       char buf[LIST_NAME_SIZE + 10];
385
386       EXEC SQL FETCH l_cursor INTO :name, :gid, :lid;
387       if (sqlca.sqlcode)
388         break;
389       strtrim(name);
390       if (!valid(name))
391         continue;
392       sprintf(buf, "%s:%d", name, gid);
393       hash_store(groups, lid, strdup(buf));
394       fprintf(iout, "%d.gid\t%s CNAME %s.group\n", gid, HCLASS, name);
395       fprintf(gout, "%s.group\t%s %s \"%s:*:%d:\"\n",
396               name, HCLASS, HTYPE, name, gid);
397     }
398   EXEC SQL CLOSE l_cursor;
399
400   fflush(iout);
401   fflush(gout);
402
403   /* now do grplists */
404   if (!users)
405     {
406       users = create_hash(12001);
407       EXEC SQL DECLARE u_cursor2 CURSOR FOR
408         SELECT users_id, login
409         FROM users
410         WHERE status = 1 OR status = 2;
411       EXEC SQL OPEN u_cursor2;
412       while (1)
413         {
414           EXEC SQL FETCH u_cursor2 INTO :id, :name;
415           if (sqlca.sqlcode)
416             break;
417           u = malloc(sizeof(struct user));
418           strcpy(u->name, strtrim(name));
419           u->lists = NULL;
420           hash_store(users, id, u);
421         }
422       EXEC SQL CLOSE u_cursor2;
423     }
424
425   EXEC SQL DECLARE i_cursor CURSOR FOR
426     SELECT m.list_id, m.member_id
427     FROM imembers m, list l 
428     WHERE m.member_type = 'USER'
429     AND m.list_id = l.list_id AND l.grouplist = 1 AND l.nfsgroup = 1;
430   EXEC SQL OPEN i_cursor;
431   while (1)
432     {
433       EXEC SQL FETCH i_cursor INTO :lid, :id;
434       if (sqlca.sqlcode)
435         break;
436       if ((l = hash_lookup(groups, lid)) && (u = hash_lookup(users, id)))
437         {
438           g = malloc(sizeof(struct grp));
439           g->next = u->lists;
440           u->lists = g;
441           g->lid = l;
442         }
443     }
444   EXEC SQL CLOSE i_cursor;
445
446   EXEC SQL COMMIT;
447
448   for (p = &(users->data[users->size - 1]); p >= users->data; p--)
449     {
450       for (b = *p; b; b = b->next)
451         {
452           if (!(g = ((struct user *)b->data)->lists))
453             continue;
454           fprintf(lout, "%s.grplist\t%s %s \"",
455                   ((struct user *)b->data)->name, HCLASS, HTYPE);
456           len = 0;
457           for (; g; g = g->next)
458             {
459               if (len + strlen(g->lid) + 1 < MAXHESSIZE)
460                 {
461                   fputs(g->lid, lout);
462                   if (g->next)
463                     putc(':', lout);
464                   len += strlen(g->lid) + 1;
465                 }
466               else
467                 {
468                   com_err(whoami, 0, "truncated grp list for user %s",
469                           ((struct user *)b->data)->name);
470                   break;
471                 }
472             }
473           fputs("\"\n", lout);
474         }
475     }
476
477   if (fclose(iout) || fclose(gout) || fclose(lout))
478     {
479       fprintf(stderr, "Unsuccessful close of gid.db, group.db, or grplist.db\n");
480       exit(MR_CCONFIG);
481     }
482   fix_file(ioutf);
483   fix_file(goutf);
484   fix_file(loutf);
485   return 1;
486 sqlerr:
487   db_error(sqlca.sqlcode);
488   return 0;
489 }
490
491
492 int do_filsys(void)
493 {
494   FILE *out;
495   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach, *group;
496   struct save_queue *sq, *sq2;
497   EXEC SQL BEGIN DECLARE SECTION;
498   char name[FILESYS_LABEL_SIZE], type[FILESYS_TYPE_SIZE];
499   char loc[FILESYS_NAME_SIZE], access[FILESYS_RWACCESS_SIZE];
500   char mount[FILESYS_MOUNT_SIZE], comments[FILESYS_COMMENTS_SIZE];
501   char key[FSGROUP_KEY_SIZE];
502   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
503   int flag, id, fid;
504   EXEC SQL END DECLARE SECTION;
505
506   sprintf(outf, "%s/filsys.db", hesiod_dir);
507
508   sprintf(outft, "%s~", outf);
509   out = fopen(outft, "w");
510   if (!out)
511     {
512       perror("cannot open filsys.db for write");
513       exit(MR_OCONFIG);
514     }
515
516   fprintf(stderr, "Building filsys.db\n");
517   get_mach();
518   sq = sq_create();
519   sq2 = sq_create();
520
521   EXEC SQL DECLARE f_cursor CURSOR FOR
522     SELECT label, type, name, mach_id, rwaccess, mount, comments, filsys_id
523     FROM filesys
524     ORDER BY filsys_id;
525   EXEC SQL OPEN f_cursor;
526   while (1)
527     {
528       EXEC SQL FETCH f_cursor INTO :name, :type, :loc, :id, :access,
529         :mount, :comments, :fid;
530       if (sqlca.sqlcode)
531         break;
532       strtrim(name);
533       if (!valid(name))
534         continue;
535       strtrim(type);
536       if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
537         {
538           if ((mach = hash_lookup(machines, id)))
539             {
540               fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s\"\n",
541                       name, HCLASS, HTYPE, type, strtrim(loc),
542                       mach, strtrim(access), strtrim(mount));
543             }
544         }
545       else if (!strcmp(type, "AFS"))
546         {
547           fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s\"\n",
548                   name, HCLASS, HTYPE, strtrim(loc),
549                   strtrim(access), strtrim(mount));
550         }
551       else if (!strcmp(type, "ERR"))
552         {
553           fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
554                   name, HCLASS, HTYPE, strtrim(comments));
555         }
556       else if (!strcmp(type, "FSGROUP"))
557         {
558           char buf[FILESYS_NAME_SIZE + 10];
559           sprintf(buf, "%s:%d", name, fid);
560           sq_save_data(sq, strdup(buf));
561         }
562       else if (!strcmp(type, "MUL"))
563         {
564           char buf[FILESYS_NAME_SIZE + 10];
565           sprintf(buf, "%s:%d", name, fid);
566           sq_save_data(sq2, strdup(buf));
567         }
568     }
569   EXEC SQL CLOSE f_cursor;
570
571   while (sq_get_data(sq, &group))
572     {
573       fid = atoi(strchr(group, ':') + 1);
574       *strchr(group, ':') = 0;
575
576       EXEC SQL DECLARE f_cursor2 CURSOR FOR
577         SELECT DISTINCT f.type, f.name, f.mach_id, f.rwaccess, f.mount,
578         f.comments, f.label, g.key
579         FROM filesys f, fsgroup g
580         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
581         ORDER BY key, label;
582       EXEC SQL OPEN f_cursor2;
583       for (flag = 1; ; flag++)
584         {
585           EXEC SQL FETCH f_cursor2 INTO :type, :loc, :id, :access, :mount,
586             :comments, :name, :key;
587           if (sqlca.sqlcode)
588             break;
589           strtrim(type);
590           if (!strcmp(type, "NFS") || !strcmp(type, "RVD"))
591             {
592               if ((mach = hash_lookup(machines, id)))
593                 {
594                   fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s %d\"\n",
595                           group, HCLASS, HTYPE, type, strtrim(loc), mach,
596                           strtrim(access), strtrim(mount), flag);
597                 }
598             }
599           else if (!strcmp(type, "AFS"))
600             {
601               fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s %d\"\n",
602                       group, HCLASS, HTYPE, strtrim(loc), strtrim(access),
603                       strtrim(mount), flag);
604             }
605           else if (!strcmp(type, "ERR"))
606             {
607               fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n",
608                       group, HCLASS, HTYPE, strtrim(comments));
609             }
610         }
611       EXEC SQL CLOSE f_cursor2;
612       free(group);
613     }
614   sq_destroy(sq);
615
616   while (sq_get_data(sq2, &group))
617     {
618       fid = atoi(strchr(group, ':') + 1);
619       *strchr(group, ':') = 0;
620       fprintf(out, "%s.filsys\t%s %s \"MUL", group, HCLASS, HTYPE);
621       EXEC SQL DECLARE f_cursor3 CURSOR FOR
622         SELECT DISTINCT f.label, g.key
623         FROM filesys f, fsgroup g
624         WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid
625         ORDER BY key, label;
626       EXEC SQL OPEN f_cursor3;
627       while (1)
628         {
629           EXEC SQL FETCH f_cursor3 INTO :name, :key;
630           if (sqlca.sqlcode)
631             break;
632           fprintf(out, " %s", strtrim(name));
633         }
634       EXEC SQL CLOSE f_cursor3;
635       fprintf(out, "\"\n");
636       free(group);
637     }
638   sq_destroy(sq2);
639
640   EXEC SQL DECLARE a_cursor CURSOR FOR
641     SELECT name, trans
642     FROM alias
643     WHERE type = 'FILESYS';
644   EXEC SQL OPEN a_cursor;
645   while (1)
646     {
647       EXEC SQL FETCH a_cursor INTO :aname, :trans;
648       if (sqlca.sqlcode)
649         break;
650       strtrim(aname);
651       strtrim(trans);
652       if (!valid(aname) || !valid(trans))
653         continue;
654       fprintf(out, "%s.filsys\t%s CNAME %s.filsys\n",
655               aname, HCLASS, trans);
656     }
657   EXEC SQL CLOSE a_cursor;
658
659   EXEC SQL COMMIT;
660
661   if (fclose(out))
662     {
663       fprintf(stderr, "Unsuccessful close of filsys.db\n");
664       exit(MR_CCONFIG);
665     }
666   fix_file(outf);
667   return 1;
668 sqlerr:
669   db_error(sqlca.sqlcode);
670   return 0;
671 }
672
673 int nbitsset(set_mask *set)
674 {
675   int i, ret;
676   ret = 0;
677   for (i = 0; i < setsize * NSETBITS; i++)
678     {
679       if (SET_ISSET(i, set))
680         ret++;
681     }
682   return ret;
683 }
684
685
686 int do_cluster(void)
687 {
688   FILE *out;
689   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
690   char machbuf[MACHINE_NAME_SIZE], clubuf[CLUSTERS_NAME_SIZE], *p;
691   EXEC SQL BEGIN DECLARE SECTION;
692   int maxmach, maxclu, mid, cid, id;
693   char name[CLUSTERS_NAME_SIZE];
694   char label[SVC_SERV_LABEL_SIZE], data[SVC_SERV_CLUSTER_SIZE];
695   EXEC SQL END DECLARE SECTION;
696   set_mask **machs, *ms, *ps;
697
698   sprintf(outf, "%s/cluster.db", hesiod_dir);
699
700   sprintf(outft, "%s~", outf);
701   out = fopen(outft, "w");
702   if (!out)
703     {
704       perror("cannot open cluster.db for write");
705       exit(MR_OCONFIG);
706     }
707
708   fprintf(stderr, "Building cluster.db\n");
709   get_mach();
710
711   EXEC SQL SELECT MAX(clu_id) INTO :maxclu FROM clusters;
712   maxclu++;
713   setsize = howmany(maxclu, NSETBITS);
714
715   EXEC SQL SELECT MAX(mach_id) INTO :maxmach FROM machine;
716   maxmach++;
717   machs = malloc((maxmach + 1) * sizeof(set_mask **));
718   memset(machs, 0, (maxmach + 1) * sizeof(int));
719
720   EXEC SQL DECLARE p_cursor CURSOR FOR
721     SELECT mach_id, clu_id
722     FROM mcmap
723     ORDER BY mach_id;
724   EXEC SQL OPEN p_cursor;
725   while (1)
726     {
727       EXEC SQL FETCH p_cursor INTO :mid, :cid;
728       if (sqlca.sqlcode)
729         break;
730       if (!(ms = machs[mid]))
731         {
732           ms = machs[mid] = SET_CREATE();
733           SET_ZERO(ms);
734         }
735       SET_SET(cid, ms);
736     }
737   EXEC SQL CLOSE p_cursor;
738
739   for (mid = 1; mid < maxmach; mid++)
740     {
741       if (!machs[mid])
742         continue;
743       ms = machs[mid];
744       if (nbitsset(ms) > 1)
745         {
746           sprintf(clubuf, "mrinternal-%d", mid);
747           for (cid = 1; cid < maxclu; cid++)
748             {
749               if (SET_ISSET(cid, ms))
750                 {
751                   EXEC SQL DECLARE d_cursor CURSOR FOR
752                     SELECT serv_label, serv_cluster
753                     FROM svc
754                     WHERE clu_id = :cid;
755                   EXEC SQL OPEN d_cursor;
756                   while (1)
757                     {
758                       EXEC SQL FETCH d_cursor INTO :label, :data;
759                       if (sqlca.sqlcode)
760                         break;
761                       strtrim(label);
762                       strtrim(data);
763                       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
764                               clubuf, HCLASS, HTYPE, label, data);
765                     }
766                   EXEC SQL CLOSE d_cursor;
767                 }
768             }
769         }
770       else
771         {
772           for (cid = 1; cid < maxclu; cid++)
773             if (SET_ISSET(cid, ms))
774               break;
775
776           EXEC SQL SELECT name INTO :name FROM clusters WHERE clu_id = :cid;
777           strtrim(name);
778           if (!valid(name))
779             continue;
780           strcpy(clubuf, name);
781         }
782
783       if ((mach = hash_lookup(machines, mid)))
784         {
785           fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
786                   mach, HCLASS, clubuf);
787           for (p = machbuf; *mach && *mach != '.'; mach++)
788             *p++ = *mach;
789           if (!strcasecmp(mach, ".mit.edu"))
790             {
791               *p = '\0';
792               fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
793                       machbuf, HCLASS, clubuf);
794             }
795         }
796       for (id = mid + 1; id < maxmach; id++)
797         {
798           if ((ps = machs[id]) && !SET_CMP(ms, ps))
799             {
800               free(ps);
801               machs[id] = NULL;
802               if ((mach = hash_lookup(machines, id)))
803                 {
804                   fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
805                           mach, HCLASS, clubuf);
806                   for (p = machbuf; *mach && *mach != '.'; mach++)
807                     *p++ = *mach;
808                   if (!strcasecmp(mach, ".mit.edu"))
809                     {
810                       *p = '\0';
811                       fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n",
812                               machbuf, HCLASS, clubuf);
813                     }
814                 }
815             }
816         }
817       free(ms);
818       machs[mid] = NULL;
819     }
820
821   EXEC SQL DECLARE d_cursor2 CURSOR FOR
822     SELECT c.name, d.serv_label, d.serv_cluster
823     FROM svc d, clusters c
824     WHERE c.clu_id = d.clu_id;
825   EXEC SQL OPEN d_cursor2;
826   while (1)
827     {
828       EXEC SQL FETCH d_cursor2 INTO :name, :label, :data;
829       if (sqlca.sqlcode)
830         break;
831       strtrim(name);
832       if (!valid(name))
833         continue;
834       strtrim(label);
835       strtrim(data);
836       fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n",
837               name, HCLASS, HTYPE, label, data);
838     }
839   free(machs);
840   EXEC SQL COMMIT;
841
842   if (fclose(out))
843     {
844       fprintf(stderr, "Unsuccessful close of cluster.db\n");
845       exit(MR_CCONFIG);
846     }
847   fix_file(outf);
848   return 1;
849 sqlerr:
850   db_error(sqlca.sqlcode);
851   return 0;
852 }
853
854
855 int do_printcap(void)
856 {
857   FILE *out;
858   char outf[MAXPATHLEN], outft[MAXPATHLEN];
859   EXEC SQL BEGIN DECLARE SECTION;
860   char name[PRINTERS_NAME_SIZE], duplexname[PRINTERS_DUPLEXNAME_SIZE];
861   char rp[PRINTERS_RP_SIZE], type[PRINTERS_TYPE_SIZE];
862   char duplexrp[PRINTERS_RP_SIZE], pskind[PRINTSERVERS_KIND_SIZE];
863   int ka, rm, mc;
864   EXEC SQL END DECLARE SECTION;
865   char *rmname;
866
867   sprintf(outf, "%s/printcap.db", hesiod_dir);
868
869   sprintf(outft, "%s~", outf);
870   out = fopen(outft, "w");
871   if (!out)
872     {
873       perror("cannot open printcap.db for write");
874       exit(MR_OCONFIG);
875     }
876
877   fprintf(stderr, "Building printcap.db\n");
878   get_mach();
879
880   EXEC SQL DECLARE p_cursor2 CURSOR FOR
881     SELECT p.name, p.duplexname, p.type, p.rp, p.rm, p.ka, p.mc, ps.kind
882     FROM printers p, printservers ps
883     WHERE p.rm = ps.mach_id;
884   EXEC SQL OPEN p_cursor2;
885   while (1)
886     {
887       EXEC SQL FETCH p_cursor2 INTO :name, :duplexname, :type,
888         :rp, :rm, :ka, :mc, :pskind;
889       if (sqlca.sqlcode)
890         break;
891       if (!(rmname = hash_lookup(machines, rm)))
892         continue;
893       strtrim(name);
894       if (!valid(name))
895         continue;
896       strtrim(rp);
897       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
898               name, HCLASS, HTYPE, name, rp, rmname, ka, mc);
899
900       strtrim(pskind);
901       if (!strcmp(pskind, "BSD"))
902         fprintf(out, "auth=none:remote_support=RQM:");
903       else if (!strcmp(pskind, "ATHENA"))
904         {
905           fprintf(out, "auth=%s:az:remote_support=RQM:",
906                   ka ? "kerberos4" : "none");
907         }
908       else if (!strcmp(pskind, "LPRNG"))
909         fprintf(out, "auth=kerberos5:xn:");
910
911       fputs("\"\n", out);
912
913       strtrim(duplexname);
914       if (!valid(duplexname))
915         continue;
916       if (!strcmp(strtrim(type), "ALIAS"))
917         {
918           EXEC SQL SELECT duplexname INTO :duplexrp
919             FROM printers WHERE name = :rp;
920           strtrim(duplexrp);
921         }
922       else
923         strcpy(duplexrp, duplexname);
924       fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:",
925               duplexname, HCLASS, HTYPE, duplexname, duplexrp,
926               rmname, ka, mc);
927
928       if (!strcmp(pskind, "BSD"))
929         fprintf(out, "auth=none:remote_support=RQM:");
930       else if (!strcmp(pskind, "ATHENA"))
931         {
932           fprintf(out, "auth=%s:az:remote_support=RQM:",
933                   ka ? "kerberos4" : "none");
934         }
935       else if (!strcmp(pskind, "LPRNG"))
936         fprintf(out, "auth=kerberos5:xn:");
937
938       fputs("\"\n", out);
939     }
940   EXEC SQL CLOSE p_cursor2;
941
942   EXEC SQL COMMIT;
943
944   if (fclose(out))
945     {
946       fprintf(stderr, "Unsuccessful close of pcap.db\n");
947       exit(MR_CCONFIG);
948     }
949   fix_file(outf);
950   return 1;
951 sqlerr:
952   db_error(sqlca.sqlcode);
953   return 0;
954 }
955
956
957 int do_sloc(void)
958 {
959   FILE *out;
960   char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach;
961   EXEC SQL BEGIN DECLARE SECTION;
962   char service[SERVERHOSTS_SERVICE_SIZE];
963   int id;
964   EXEC SQL END DECLARE SECTION;
965
966   sprintf(outf, "%s/sloc.db", hesiod_dir);
967
968   sprintf(outft, "%s~", outf);
969   out = fopen(outft, "w");
970   if (!out)
971     {
972       perror("cannot open sloc.db for write");
973       exit(MR_OCONFIG);
974     }
975
976   fprintf(stderr, "Building sloc.db\n");
977   get_mach();
978
979   EXEC SQL DECLARE s_cursor CURSOR FOR
980     SELECT DISTINCT service, mach_id
981     FROM serverhosts
982     ORDER BY service;
983   EXEC SQL OPEN s_cursor;
984   while (1)
985     {
986       EXEC SQL FETCH s_cursor INTO :service, :id;
987       if (sqlca.sqlcode)
988         break;
989       strtrim(service);
990       if (valid(service) && (mach = hash_lookup(machines, id)))
991         fprintf(out, "%s.sloc\t%s %s %s\n", service, HCLASS, HTYPE, mach);
992     }
993   EXEC SQL CLOSE s_cursor;
994
995   EXEC SQL COMMIT;
996
997   if (fclose(out))
998     {
999       fprintf(stderr, "Unsuccessful close of sloc.db\n");
1000       exit(MR_CCONFIG);
1001     }
1002
1003   fix_file(outf);
1004   return 1;
1005 sqlerr:
1006   db_error(sqlca.sqlcode);
1007   return 0;
1008 }
1009
1010 int do_service(void)
1011 {
1012   FILE *out;
1013   char outf[MAXPATHLEN], outft[MAXPATHLEN];
1014   EXEC SQL BEGIN DECLARE SECTION;
1015   char service[SERVICES_NAME_SIZE], protocol[SERVICES_PROTOCOL_SIZE];
1016   char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE];
1017   int port;
1018   EXEC SQL END DECLARE SECTION;
1019
1020   sprintf(outf, "%s/service.db", hesiod_dir);
1021
1022   sprintf(outft, "%s~", outf);
1023   out = fopen(outft, "w");
1024   if (!out)
1025     {
1026       perror("cannot open service.db for write");
1027       exit(MR_OCONFIG);
1028     }
1029
1030   fprintf(stderr, "Building service.db\n");
1031
1032   EXEC SQL DECLARE s_cursor2 CURSOR FOR
1033     SELECT name, protocol, port
1034     FROM services;
1035   EXEC SQL OPEN s_cursor2;
1036   while (1)
1037     {
1038       EXEC SQL FETCH s_cursor2 INTO :service, :protocol, :port;
1039       if (sqlca.sqlcode)
1040         break;
1041       lowercase(protocol);      /* Convert protocol to lowercase */
1042       strtrim(service);
1043       if (!valid(service))
1044         continue;
1045       strtrim(protocol);
1046       fprintf(out, "%s.service\t%s %s \"%s %s %d\"\n",
1047               service, HCLASS, HTYPE, service, protocol, port);
1048     }
1049   EXEC SQL CLOSE s_cursor2;
1050
1051   EXEC SQL DECLARE a_cursor3 CURSOR FOR
1052     SELECT name, trans
1053     FROM alias
1054     WHERE type = 'SERVICE';
1055   EXEC SQL OPEN a_cursor3;
1056   while (1)
1057     {
1058       EXEC SQL FETCH a_cursor3 INTO :aname, :trans;
1059       if (sqlca.sqlcode)
1060         break;
1061       strtrim(aname);
1062       strtrim(trans);
1063       if (!valid(aname) || !valid(trans))
1064         continue;
1065       fprintf(out, "%s.service\t%s CNAME %s.service\n", aname, HCLASS,
1066               trans);
1067     }
1068   EXEC SQL CLOSE a_cursor3;
1069
1070   EXEC SQL COMMIT;
1071
1072   if (fclose(out))
1073     {
1074       fprintf(stderr, "Unsuccessful close of service.db\n");
1075       exit(MR_CCONFIG);
1076     }
1077   fix_file(outf);
1078   return 1;
1079 sqlerr:
1080   db_error(sqlca.sqlcode);
1081   return 0;
1082 }
This page took 0.149843 seconds and 5 git commands to generate.