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

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