source: trunk/third/moira/gen/hesiod.pc @ 26024

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