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