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

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