/* $Id$ * * This generates the zone files necessary to load a hesiod server. * The following zones are generated: passwd, uid, pobox, group, * grplist, gid, filsys, cluster, pcap, sloc, service. * * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include #include #include #include #include "util.h" EXEC SQL INCLUDE sqlca; RCSID("$Header$"); #ifndef HTYPE #define HTYPE "TXT" #endif #ifndef HCLASS #define HCLASS "" #endif #ifndef HESIOD_SUBDIR #define HESIOD_SUBDIR "hesiod" #endif /* max number of bytes of a data record that can be returned in a hesiod * query. This is 512 - overhead (~78) [derived empirically] * (it used to be 446 with older versions of bind) */ #define MAXHESSIZE 256 char hesiod_dir[MAXPATHLEN]; #define min(x, y) ((x) < (y) ? (x) : (y)) struct hash *machines = NULL; struct hash *users = NULL; char *whoami = "hesiod.gen"; char *db = "moira/moira"; struct grp { struct grp *next; char *lid; }; struct user { char name[USERS_LOGIN_SIZE]; struct grp *lists; }; /* * Modified from sys/types.h: */ int setsize; /* = howmany(setbits, NSETBITS) */ typedef long set_mask; #define NSETBITS (sizeof(set_mask) * NBBY) /* bits per mask */ #ifndef howmany #define howmany(x, y) (((x) + ((y) - 1)) / (y)) #endif #define SET_SET(n, p) ((p)[(n)/NSETBITS] |= (1 << ((n) % NSETBITS))) #define SET_CLR(n, p) ((p)[(n)/NSETBITS] &= ~(1 << ((n) % NSETBITS))) #define SET_ISSET(n, p) ((p)[(n)/NSETBITS] & (1 << ((n) % NSETBITS))) #define SET_CREATE() (malloc(setsize * sizeof(set_mask))) #define SET_ZERO(p) memset(p, 0, setsize * sizeof(set_mask)) #define SET_CMP(p1, p2) (memcmp(p1, p2, setsize * sizeof(set_mask))) void get_mach(void); int nbitsset(set_mask *set); int valid(char *name); int do_passwd(void); int do_groups(void); int do_filsys(void); int do_cluster(void); int do_printcap(void); int do_sloc(void); int do_service(void); int main(int argc, char **argv) { char cmd[64]; struct stat sb; int changed = 0; if (argc > 2) { fprintf(stderr, "usage: %s [outfile]\n", argv[0]); exit(MR_ARGS); } initialize_sms_error_table(); sprintf(hesiod_dir, "%s/%s", DCM_DIR, HESIOD_SUBDIR); EXEC SQL CONNECT :db; changed = do_passwd(); changed += do_filsys(); changed += do_cluster(); changed += do_printcap(); changed += do_sloc(); changed += do_service(); changed += do_groups(); if (!changed) { fprintf(stderr, "No files updated.\n"); if (argc == 2 && stat(argv[1], &sb) == 0) exit(MR_NO_CHANGE); } if (argc == 2) { fprintf(stderr, "Building tar file.\n"); sprintf(cmd, "cd %s; tar cf %s .", hesiod_dir, argv[1]); if (system(cmd)) exit(MR_TAR_FAIL); } exit(MR_SUCCESS); } void get_mach(void) { EXEC SQL BEGIN DECLARE SECTION; int id; char name[MACHINE_NAME_SIZE]; EXEC SQL END DECLARE SECTION; if (machines) return; machines = create_hash(1000); EXEC SQL DECLARE m_cursor CURSOR FOR SELECT name, mach_id FROM machine WHERE status = 1 and mach_id != 0 ORDER BY mach_id; EXEC SQL OPEN m_cursor; while (1) { EXEC SQL FETCH m_cursor INTO :name, :id; if (sqlca.sqlcode) break; strtrim(name); if (!valid(name)) continue; hash_store(machines, id, strdup(name)); } if (sqlca.sqlcode < 0) db_error(sqlca.sqlcode); EXEC SQL CLOSE m_cursor; EXEC SQL COMMIT; } /* Determine whether or not a name is a valid DNS label. (Can't start or end with . or have two .s in a row) */ int valid(char *name) { int sawdot; for (sawdot = 1; *name; name++) { if (*name == '$') return 0; if (*name == '.') { if (sawdot) return 0; else sawdot = 1; } else sawdot = 0; } return !sawdot; } int do_passwd(void) { FILE *pout, *uout, *bout; char poutf[MAXPATHLEN], uoutf[MAXPATHLEN], poutft[MAXPATHLEN]; char uoutft[MAXPATHLEN], boutf[MAXPATHLEN], boutft[MAXPATHLEN]; struct user *u; char *mach; EXEC SQL BEGIN DECLARE SECTION; char login[USERS_LOGIN_SIZE], shell[USERS_SHELL_SIZE]; char fullname[USERS_FULLNAME_SIZE], oa[USERS_OFFICE_ADDR_SIZE]; char op[USERS_OFFICE_PHONE_SIZE], hp[USERS_HOME_PHONE_SIZE]; char nn[USERS_NICKNAME_SIZE], potype[USERS_POTYPE_SIZE]; int uid, id, pid, iid, eid, mid, status; EXEC SQL END DECLARE SECTION; sprintf(poutf, "%s/passwd.db", hesiod_dir); sprintf(uoutf, "%s/uid.db", hesiod_dir); sprintf(boutf, "%s/pobox.db", hesiod_dir); sprintf(poutft, "%s~", poutf); pout = fopen(poutft, "w"); if (!pout) { perror("cannot open passwd.db~ for write"); exit(MR_OCONFIG); } sprintf(uoutft, "%s~", uoutf); uout = fopen(uoutft, "w"); if (!uout) { perror("cannot open uid.db~ for write"); exit(MR_OCONFIG); } sprintf(boutft, "%s~", boutf); bout = fopen(boutft, "w"); if (!bout) { perror("cannot open pobox.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building passwd.db, uid.db, and pobox.db\n"); get_mach(); users = create_hash(12001); EXEC SQL DECLARE u_cursor CURSOR FOR SELECT login, unix_uid, shell, fullname, nickname, office_addr, office_phone, home_phone, users_id, potype, pop_id, imap_id, exchange_id, status FROM users WHERE status = 1 OR status = 2 OR status = 5 OR status = 6 ORDER BY users_id; EXEC SQL OPEN u_cursor; while (1) { EXEC SQL FETCH u_cursor INTO :login, :uid, :shell, :fullname, :nn, :oa, :op, :hp, :id, :potype, :pid, :iid, :eid, :status; if (sqlca.sqlcode) break; strtrim(login); dequote(fullname); dequote(nn); dequote(oa); dequote(op); dequote(hp); dequote(shell); dequote(potype); u = malloc(sizeof(struct user)); strcpy(u->name, login); u->lists = NULL; hash_store(users, id, u); if (status == 1 || status == 2) { fprintf(pout, "%s.passwd\t%s %s \"%s:*:%d:101:%s,%s,%s,%s,%s:/mit/%s:%s\"\n", login, HCLASS, HTYPE, login, uid, fullname, nn, oa, op, hp, login, shell); fprintf(uout, "%d.uid\t%s CNAME %s.passwd\n", uid, HCLASS, login); } if (eid != 0) { /* Check for IMAP. Can't use iid because it should be zero. */ EXEC SQL SELECT mach_id INTO :mid FROM filesys WHERE label = :login || '.po' AND type = 'IMAP'; if (sqlca.sqlcode == 0) pid = mid; else { /* EXCHANGE user with no IMAP filesystem. Give them * IMAP.EXCHANGE.MIT.EDU instead of EXCHANGE.MIT.EDU. */ EXEC SQL SELECT mach_id INTO :eid FROM machine WHERE name = 'IMAP.EXCHANGE.MIT.EDU'; if (sqlca.sqlcode == 0) pid = eid; } } if (iid != 0) { EXEC SQL SELECT mach_id INTO :mid FROM filesys WHERE filsys_id = :iid AND type = 'IMAP'; if (sqlca.sqlcode == 0) pid = mid; } if ((strcmp(potype, "NONE") != 0) && pid != 0 && (mach = hash_lookup(machines, pid))) { fprintf(bout, "%s.pobox\t%s %s \"POP %s %s\"\n", login, HCLASS, HTYPE, mach, login); } } if (sqlca.sqlcode < 0) db_error(sqlca.sqlcode); EXEC SQL CLOSE u_cursor; EXEC SQL COMMIT; if (fclose(pout) || fclose(uout) || fclose(bout)) { fprintf(stderr, "Unsuccessful file close of passwd.db, uid.db, or pobox.db\n"); exit(MR_CCONFIG); } fix_file(poutf); fix_file(uoutf); fix_file(boutf); return 1; } int do_groups(void) { FILE *iout, *gout, *lout; char ioutf[MAXPATHLEN], goutf[MAXPATHLEN], loutf[MAXPATHLEN]; char buf[MAXPATHLEN], *l; struct hash *groups; struct bucket *b, **p; struct grp *g; struct user *u; EXEC SQL BEGIN DECLARE SECTION; char name[LIST_NAME_SIZE]; int gid, id, lid, len; EXEC SQL END DECLARE SECTION; /* open files */ sprintf(ioutf, "%s/gid.db", hesiod_dir); sprintf(goutf, "%s/group.db", hesiod_dir); sprintf(loutf, "%s/grplist.db", hesiod_dir); sprintf(buf, "%s~", ioutf); iout = fopen(buf, "w"); if (!iout) { perror("cannot open gid.db for write"); exit(MR_OCONFIG); } sprintf(buf, "%s~", goutf); gout = fopen(buf, "w"); if (!gout) { perror("cannot open group.db for write"); exit(MR_OCONFIG); } sprintf(buf, "%s~", loutf); lout = fopen(buf, "w"); if (!lout) { perror("cannot open grplist.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building gid.db, group.db, and grplist.db\n"); /* make space for group list */ groups = create_hash(15001); /* The following WHENEVER is declarative, not executed, * and applies for the remainder of this file only. */ EXEC SQL WHENEVER SQLERROR GOTO sqlerr; EXEC SQL DECLARE l_cursor CURSOR FOR SELECT name, gid, list_id FROM list WHERE grouplist != 0 AND active != 0 ORDER BY list_id; EXEC SQL OPEN l_cursor; while (1) { char buf[LIST_NAME_SIZE + 10]; EXEC SQL FETCH l_cursor INTO :name, :gid, :lid; if (sqlca.sqlcode) break; strtrim(name); if (!valid(name)) continue; sprintf(buf, "%s:%d", name, gid); hash_store(groups, lid, strdup(buf)); fprintf(iout, "%d.gid\t%s CNAME %s.group\n", gid, HCLASS, name); fprintf(gout, "%s.group\t%s %s \"%s:*:%d:\"\n", name, HCLASS, HTYPE, name, gid); } EXEC SQL CLOSE l_cursor; fflush(iout); fflush(gout); /* now do grplists */ if (!users) { users = create_hash(12001); EXEC SQL DECLARE u_cursor2 CURSOR FOR SELECT users_id, login FROM users WHERE status = 1 OR status = 2; EXEC SQL OPEN u_cursor2; while (1) { EXEC SQL FETCH u_cursor2 INTO :id, :name; if (sqlca.sqlcode) break; u = malloc(sizeof(struct user)); strcpy(u->name, strtrim(name)); u->lists = NULL; hash_store(users, id, u); } EXEC SQL CLOSE u_cursor2; } EXEC SQL DECLARE i_cursor CURSOR FOR SELECT m.list_id, m.member_id FROM imembers m, list l WHERE m.member_type = 'USER' AND m.list_id = l.list_id AND l.grouplist = 1 AND l.nfsgroup = 1; EXEC SQL OPEN i_cursor; while (1) { EXEC SQL FETCH i_cursor INTO :lid, :id; if (sqlca.sqlcode) break; if ((l = hash_lookup(groups, lid)) && (u = hash_lookup(users, id))) { g = malloc(sizeof(struct grp)); g->next = u->lists; u->lists = g; g->lid = l; } } EXEC SQL CLOSE i_cursor; EXEC SQL COMMIT; for (p = &(users->data[users->size - 1]); p >= users->data; p--) { for (b = *p; b; b = b->next) { if (!(g = ((struct user *)b->data)->lists)) continue; fprintf(lout, "%s.grplist\t%s %s \"", ((struct user *)b->data)->name, HCLASS, HTYPE); len = 0; for (; g; g = g->next) { if (len + strlen(g->lid) + 1 < MAXHESSIZE) { fputs(g->lid, lout); if (g->next) putc(':', lout); len += strlen(g->lid) + 1; } else { com_err(whoami, 0, "truncated grp list for user %s", ((struct user *)b->data)->name); break; } } fputs("\"\n", lout); } } if (fclose(iout) || fclose(gout) || fclose(lout)) { fprintf(stderr, "Unsuccessful close of gid.db, group.db, or grplist.db\n"); exit(MR_CCONFIG); } fix_file(ioutf); fix_file(goutf); fix_file(loutf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; } int do_filsys(void) { FILE *out; char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach, *group; struct save_queue *sq, *sq2; EXEC SQL BEGIN DECLARE SECTION; char name[FILESYS_LABEL_SIZE], type[FILESYS_TYPE_SIZE]; char loc[FILESYS_NAME_SIZE], access[FILESYS_RWACCESS_SIZE]; char mount[FILESYS_MOUNT_SIZE], comments[FILESYS_COMMENTS_SIZE]; char key[FSGROUP_KEY_SIZE]; char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE]; int flag, id, fid; EXEC SQL END DECLARE SECTION; sprintf(outf, "%s/filsys.db", hesiod_dir); sprintf(outft, "%s~", outf); out = fopen(outft, "w"); if (!out) { perror("cannot open filsys.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building filsys.db\n"); get_mach(); sq = sq_create(); sq2 = sq_create(); EXEC SQL DECLARE f_cursor CURSOR FOR SELECT label, type, name, mach_id, rwaccess, mount, comments, filsys_id FROM filesys ORDER BY filsys_id; EXEC SQL OPEN f_cursor; while (1) { EXEC SQL FETCH f_cursor INTO :name, :type, :loc, :id, :access, :mount, :comments, :fid; if (sqlca.sqlcode) break; strtrim(name); if (!valid(name)) continue; strtrim(type); if (!strcmp(type, "NFS") || !strcmp(type, "RVD")) { if ((mach = hash_lookup(machines, id))) { fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s\"\n", name, HCLASS, HTYPE, type, strtrim(loc), mach, strtrim(access), strtrim(mount)); } } else if (!strcmp(type, "AFS")) { fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s\"\n", name, HCLASS, HTYPE, strtrim(loc), strtrim(access), strtrim(mount)); } else if (!strcmp(type, "ERR")) { fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n", name, HCLASS, HTYPE, strtrim(comments)); } else if (!strcmp(type, "FSGROUP")) { char buf[FILESYS_NAME_SIZE + 10]; sprintf(buf, "%s:%d", name, fid); sq_save_data(sq, strdup(buf)); } else if (!strcmp(type, "MUL")) { char buf[FILESYS_NAME_SIZE + 10]; sprintf(buf, "%s:%d", name, fid); sq_save_data(sq2, strdup(buf)); } } EXEC SQL CLOSE f_cursor; while (sq_get_data(sq, &group)) { fid = atoi(strchr(group, ':') + 1); *strchr(group, ':') = 0; EXEC SQL DECLARE f_cursor2 CURSOR FOR SELECT DISTINCT f.type, f.name, f.mach_id, f.rwaccess, f.mount, f.comments, f.label, g.key FROM filesys f, fsgroup g WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid ORDER BY key, label; EXEC SQL OPEN f_cursor2; for (flag = 1; ; flag++) { EXEC SQL FETCH f_cursor2 INTO :type, :loc, :id, :access, :mount, :comments, :name, :key; if (sqlca.sqlcode) break; strtrim(type); if (!strcmp(type, "NFS") || !strcmp(type, "RVD")) { if ((mach = hash_lookup(machines, id))) { fprintf(out, "%s.filsys\t%s %s \"%s %s %s %s %s %d\"\n", group, HCLASS, HTYPE, type, strtrim(loc), mach, strtrim(access), strtrim(mount), flag); } } else if (!strcmp(type, "AFS")) { fprintf(out, "%s.filsys\t%s %s \"AFS %s %s %s %d\"\n", group, HCLASS, HTYPE, strtrim(loc), strtrim(access), strtrim(mount), flag); } else if (!strcmp(type, "ERR")) { fprintf(out, "%s.filsys\t%s %s \"ERR %s\"\n", group, HCLASS, HTYPE, strtrim(comments)); } } EXEC SQL CLOSE f_cursor2; free(group); } sq_destroy(sq); while (sq_get_data(sq2, &group)) { fid = atoi(strchr(group, ':') + 1); *strchr(group, ':') = 0; fprintf(out, "%s.filsys\t%s %s \"MUL", group, HCLASS, HTYPE); EXEC SQL DECLARE f_cursor3 CURSOR FOR SELECT DISTINCT f.label, g.key FROM filesys f, fsgroup g WHERE f.filsys_id = g.filsys_id AND g.group_id = :fid ORDER BY key, label; EXEC SQL OPEN f_cursor3; while (1) { EXEC SQL FETCH f_cursor3 INTO :name, :key; if (sqlca.sqlcode) break; fprintf(out, " %s", strtrim(name)); } EXEC SQL CLOSE f_cursor3; fprintf(out, "\"\n"); free(group); } sq_destroy(sq2); EXEC SQL DECLARE a_cursor CURSOR FOR SELECT name, trans FROM alias WHERE type = 'FILESYS'; EXEC SQL OPEN a_cursor; while (1) { EXEC SQL FETCH a_cursor INTO :aname, :trans; if (sqlca.sqlcode) break; strtrim(aname); strtrim(trans); if (!valid(aname) || !valid(trans)) continue; fprintf(out, "%s.filsys\t%s CNAME %s.filsys\n", aname, HCLASS, trans); } EXEC SQL CLOSE a_cursor; EXEC SQL COMMIT; if (fclose(out)) { fprintf(stderr, "Unsuccessful close of filsys.db\n"); exit(MR_CCONFIG); } fix_file(outf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; } int nbitsset(set_mask *set) { int i, ret; ret = 0; for (i = 0; i < setsize * NSETBITS; i++) { if (SET_ISSET(i, set)) ret++; } return ret; } int do_cluster(void) { FILE *out; char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach; char machbuf[MACHINE_NAME_SIZE], clubuf[CLUSTERS_NAME_SIZE], *p; EXEC SQL BEGIN DECLARE SECTION; int maxmach, maxclu, mid, cid, id; char name[CLUSTERS_NAME_SIZE]; char label[SVC_SERV_LABEL_SIZE], data[SVC_SERV_CLUSTER_SIZE]; EXEC SQL END DECLARE SECTION; set_mask **machs, *ms, *ps; sprintf(outf, "%s/cluster.db", hesiod_dir); sprintf(outft, "%s~", outf); out = fopen(outft, "w"); if (!out) { perror("cannot open cluster.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building cluster.db\n"); get_mach(); EXEC SQL SELECT MAX(clu_id) INTO :maxclu FROM clusters; maxclu++; setsize = howmany(maxclu, NSETBITS); EXEC SQL SELECT MAX(mach_id) INTO :maxmach FROM machine; maxmach++; machs = malloc((maxmach + 1) * sizeof(set_mask **)); memset(machs, 0, (maxmach + 1) * sizeof(int)); EXEC SQL DECLARE p_cursor CURSOR FOR SELECT mach_id, clu_id FROM mcmap ORDER BY mach_id; EXEC SQL OPEN p_cursor; while (1) { EXEC SQL FETCH p_cursor INTO :mid, :cid; if (sqlca.sqlcode) break; if (!(ms = machs[mid])) { ms = machs[mid] = SET_CREATE(); SET_ZERO(ms); } SET_SET(cid, ms); } EXEC SQL CLOSE p_cursor; for (mid = 1; mid < maxmach; mid++) { if (!machs[mid]) continue; ms = machs[mid]; if (nbitsset(ms) > 1) { sprintf(clubuf, "mrinternal-%d", mid); for (cid = 1; cid < maxclu; cid++) { if (SET_ISSET(cid, ms)) { EXEC SQL DECLARE d_cursor CURSOR FOR SELECT serv_label, serv_cluster FROM svc WHERE clu_id = :cid; EXEC SQL OPEN d_cursor; while (1) { EXEC SQL FETCH d_cursor INTO :label, :data; if (sqlca.sqlcode) break; strtrim(label); strtrim(data); fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n", clubuf, HCLASS, HTYPE, label, data); } EXEC SQL CLOSE d_cursor; } } } else { for (cid = 1; cid < maxclu; cid++) if (SET_ISSET(cid, ms)) break; EXEC SQL SELECT name INTO :name FROM clusters WHERE clu_id = :cid; strtrim(name); if (!valid(name)) continue; strcpy(clubuf, name); } if ((mach = hash_lookup(machines, mid))) { fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n", mach, HCLASS, clubuf); for (p = machbuf; *mach && *mach != '.'; mach++) *p++ = *mach; if (!strcasecmp(mach, ".mit.edu")) { *p = '\0'; fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n", machbuf, HCLASS, clubuf); } } for (id = mid + 1; id < maxmach; id++) { if ((ps = machs[id]) && !SET_CMP(ms, ps)) { free(ps); machs[id] = NULL; if ((mach = hash_lookup(machines, id))) { fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n", mach, HCLASS, clubuf); for (p = machbuf; *mach && *mach != '.'; mach++) *p++ = *mach; if (!strcasecmp(mach, ".mit.edu")) { *p = '\0'; fprintf(out, "%s.cluster\t%s CNAME %s.cluster\n", machbuf, HCLASS, clubuf); } } } } free(ms); machs[mid] = NULL; } EXEC SQL DECLARE d_cursor2 CURSOR FOR SELECT c.name, d.serv_label, d.serv_cluster FROM svc d, clusters c WHERE c.clu_id = d.clu_id; EXEC SQL OPEN d_cursor2; while (1) { EXEC SQL FETCH d_cursor2 INTO :name, :label, :data; if (sqlca.sqlcode) break; strtrim(name); if (!valid(name)) continue; strtrim(label); strtrim(data); fprintf(out, "%s.cluster\t%s %s \"%s %s\"\n", name, HCLASS, HTYPE, label, data); } free(machs); EXEC SQL COMMIT; if (fclose(out)) { fprintf(stderr, "Unsuccessful close of cluster.db\n"); exit(MR_CCONFIG); } fix_file(outf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; } int do_printcap(void) { FILE *out; char outf[MAXPATHLEN], outft[MAXPATHLEN]; EXEC SQL BEGIN DECLARE SECTION; char name[PRINTERS_NAME_SIZE], duplexname[PRINTERS_DUPLEXNAME_SIZE]; char rp[PRINTERS_RP_SIZE], type[PRINTERS_TYPE_SIZE]; char duplexrp[PRINTERS_RP_SIZE], pskind[PRINTSERVERS_KIND_SIZE]; int ka, rm, mc; EXEC SQL END DECLARE SECTION; char *rmname; sprintf(outf, "%s/printcap.db", hesiod_dir); sprintf(outft, "%s~", outf); out = fopen(outft, "w"); if (!out) { perror("cannot open printcap.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building printcap.db\n"); get_mach(); EXEC SQL DECLARE p_cursor2 CURSOR FOR SELECT p.name, p.duplexname, p.type, p.rp, p.rm, p.ka, p.mc, ps.kind FROM printers p, printservers ps WHERE p.rm = ps.mach_id; EXEC SQL OPEN p_cursor2; while (1) { EXEC SQL FETCH p_cursor2 INTO :name, :duplexname, :type, :rp, :rm, :ka, :mc, :pskind; if (sqlca.sqlcode) break; if (!(rmname = hash_lookup(machines, rm))) continue; strtrim(name); if (!valid(name)) continue; strtrim(rp); fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:", name, HCLASS, HTYPE, name, rp, rmname, ka, mc); strtrim(pskind); if (!strcmp(pskind, "BSD")) fprintf(out, "auth=none:remote_support=RQM:"); else if (!strcmp(pskind, "ATHENA")) { fprintf(out, "auth=%s:az:remote_support=RQM:", ka ? "kerberos4" : "none"); } else if (!strcmp(pskind, "LPRNG")) fprintf(out, "auth=kerberos5:xn:"); fputs("\"\n", out); strtrim(duplexname); if (!valid(duplexname)) continue; if (!strcmp(strtrim(type), "ALIAS")) { EXEC SQL SELECT duplexname INTO :duplexrp FROM printers WHERE name = :rp; strtrim(duplexrp); } else strcpy(duplexrp, duplexname); fprintf(out, "%s.pcap\t%s %s \"%s:rp=%s:rm=%s:ka#%d:mc#%d:", duplexname, HCLASS, HTYPE, duplexname, duplexrp, rmname, ka, mc); if (!strcmp(pskind, "BSD")) fprintf(out, "auth=none:remote_support=RQM:"); else if (!strcmp(pskind, "ATHENA")) { fprintf(out, "auth=%s:az:remote_support=RQM:", ka ? "kerberos4" : "none"); } else if (!strcmp(pskind, "LPRNG")) fprintf(out, "auth=kerberos5:xn:"); fputs("\"\n", out); } EXEC SQL CLOSE p_cursor2; EXEC SQL COMMIT; if (fclose(out)) { fprintf(stderr, "Unsuccessful close of pcap.db\n"); exit(MR_CCONFIG); } fix_file(outf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; } int do_sloc(void) { FILE *out; char outf[MAXPATHLEN], outft[MAXPATHLEN], *mach; EXEC SQL BEGIN DECLARE SECTION; char service[SERVERHOSTS_SERVICE_SIZE]; int id; EXEC SQL END DECLARE SECTION; sprintf(outf, "%s/sloc.db", hesiod_dir); sprintf(outft, "%s~", outf); out = fopen(outft, "w"); if (!out) { perror("cannot open sloc.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building sloc.db\n"); get_mach(); EXEC SQL DECLARE s_cursor CURSOR FOR SELECT DISTINCT service, mach_id FROM serverhosts ORDER BY service; EXEC SQL OPEN s_cursor; while (1) { EXEC SQL FETCH s_cursor INTO :service, :id; if (sqlca.sqlcode) break; strtrim(service); if (valid(service) && (mach = hash_lookup(machines, id))) fprintf(out, "%s.sloc\t%s %s %s\n", service, HCLASS, HTYPE, mach); } EXEC SQL CLOSE s_cursor; EXEC SQL COMMIT; if (fclose(out)) { fprintf(stderr, "Unsuccessful close of sloc.db\n"); exit(MR_CCONFIG); } fix_file(outf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; } int do_service(void) { FILE *out; char outf[MAXPATHLEN], outft[MAXPATHLEN]; EXEC SQL BEGIN DECLARE SECTION; char service[SERVICES_NAME_SIZE], protocol[SERVICES_PROTOCOL_SIZE]; char aname[ALIAS_NAME_SIZE], trans[ALIAS_TRANS_SIZE]; int port; EXEC SQL END DECLARE SECTION; sprintf(outf, "%s/service.db", hesiod_dir); sprintf(outft, "%s~", outf); out = fopen(outft, "w"); if (!out) { perror("cannot open service.db for write"); exit(MR_OCONFIG); } fprintf(stderr, "Building service.db\n"); EXEC SQL DECLARE s_cursor2 CURSOR FOR SELECT name, protocol, port FROM services; EXEC SQL OPEN s_cursor2; while (1) { EXEC SQL FETCH s_cursor2 INTO :service, :protocol, :port; if (sqlca.sqlcode) break; lowercase(protocol); /* Convert protocol to lowercase */ strtrim(service); if (!valid(service)) continue; strtrim(protocol); fprintf(out, "%s.service\t%s %s \"%s %s %d\"\n", service, HCLASS, HTYPE, service, protocol, port); } EXEC SQL CLOSE s_cursor2; EXEC SQL DECLARE a_cursor3 CURSOR FOR SELECT name, trans FROM alias WHERE type = 'SERVICE'; EXEC SQL OPEN a_cursor3; while (1) { EXEC SQL FETCH a_cursor3 INTO :aname, :trans; if (sqlca.sqlcode) break; strtrim(aname); strtrim(trans); if (!valid(aname) || !valid(trans)) continue; fprintf(out, "%s.service\t%s CNAME %s.service\n", aname, HCLASS, trans); } EXEC SQL CLOSE a_cursor3; EXEC SQL COMMIT; if (fclose(out)) { fprintf(stderr, "Unsuccessful close of service.db\n"); exit(MR_CCONFIG); } fix_file(outf); return 1; sqlerr: db_error(sqlca.sqlcode); return 0; }