home *** CD-ROM | disk | FTP | other *** search
- /*
- *******************************************************************************
- *
- * list.c --
- *
- * Routines to obtain info from name and finger servers.
- *
- * Adapted from 4.3BSD BIND ns_init.c and from finger.c.
- *
- *******************************************************************************
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #include <arpa/nameser.h>
- #ifndef T_TXT
- #define T_TXT 16
- #endif
- #include <arpa/inet.h>
- #include <resolv.h>
- #include "res.h"
- #include "vtable.h"
-
- #ifndef __STDC__
- extern char *malloc();
- #else
- #include <stdlib.h>
- #endif
-
- extern void *htab_find();
-
- #define NOID -8472874 /* Something very unlikely */
- /*
- * Imported from res_debug.c
- */
- extern char *_res_resultcodes[];
-
- extern int errno;
- static int lelmstyle;
- static int recursegroup;
-
- typedef union {
- HEADER qb1;
- char qb2[PACKETSZ];
- } querybuf;
-
- extern HostInfo *defaultPtr;
- extern HostInfo curHostInfo;
- extern char *vdomain;
- extern int queryType;
- extern int queryClass;
-
- static int sockFD = -1;
- static int ListSubr();
-
- static void AddAlias();
- static void ChangeMailList();
- static void ChangeAddr();
- static void ChangeMailBox();
- static void AddMailListMember();
- static void ChangeUGID();
- static void ChangeHInfo();
- #ifdef EMULATE_HESIOD
- static void ChangeText();
- #endif /* EMULATE_HESIOD */
- /*
- * During a listing to a file, hash marks are printed
- * every HASH_SIZE records.
- */
-
- #define HASH_SIZE 50
-
-
- /*
- *******************************************************************************
- *
- * LoadHosts --
- *
- * Requests the name server to do a zone transfer so we
- * find out what hosts it knows about.
- *
- * For LoadHosts, there are five types of output:
- *
- * To see all types of information sorted by name, do the following:
- * ls -d domain.edu > file
- * view file
- *
- * Results:
- * SUCCESS the listing was successful.
- * ERROR the server could not be contacted because
- * a socket could not be obtained or an error
- * occured while receiving, or the output file
- * could not be opened.
- *
- *******************************************************************************
- */
-
- void
- LoadHosts(domain)
- char *domain;
- {
- int result;
-
- if (domain && *domain)
- {
- result = ListSubr(domain);
- if (result != SUCCESS)
- fprintf(stderr, "*** Can't list domain %s: %s\n",
- domain, DecodeError(result));
- }
- else
- {
- fprintf(stderr, "*** ns2tab: empty domain\n");
- }
- return;
- }
-
- struct minfo_ent {
- char name[32];
- char request[32];
- char errors[32];
- vtable table; /* Table for the members */
- };
- struct mg_ent {
- char member[32];
- };
-
- struct mb_ent {
- char name[32];
- char mailbox[32];
- int qtype;
- char *gecos;
- int gid;
- int uid;
- };
-
- struct host_ent {
- char name[32];
- char *machtype;
- char *ostype;
- vtable aliases;
- vtable ipaddr;
- };
- struct host_ali {
- char name[32];
- };
- struct host_ip {
- int addr;
- int used;
- };
-
- struct txt_ent {
- char name[32];
- char *txt;
- };
-
- struct ns_ent {
- char name[32];
- int is_explicit;
- };
- vtable subdomains; /* Table to hold subdomain list */
-
- void *mailtab; /* The global hash table for maillists */
- void *mb_tab; /* The hash table for mailboxes */
- void *host_tab;
- #ifdef EMULATE_HESIOD
- void *txt_tab;
- #endif /* EMULATE_HESIOD */
-
- int
- ns_cmp(n1,n2)
- struct ns_ent *n1,*n2;
- {
- return strncmp(n1->name,n2->name,sizeof(n1->name));
- }
-
- ns_add(name,is_explicit)
- char *name;
- int is_explicit;
- {
- struct ns_ent nb;
-
- memcpy(nb.name,name,sizeof(nb.name));
- nb.is_explicit = is_explicit;
- if(!VTableLookup(&subdomains,&nb))
- VTableAppend(&subdomains,(char*)&nb);
- }
-
- int
- InitTables()
- {
- mailtab = htab_init(17,NULL,NULL,NULL);
- mb_tab = htab_init(231,NULL,NULL,NULL);
- host_tab = htab_init(231,NULL,NULL,NULL);
- VTableSet(&subdomains,sizeof(struct ns_ent));
- VTableSetCmp(&subdomains,ns_cmp);
- #ifdef EMULATE_HESIOD
- txt_tab = htab_init(17,NULL,NULL,NULL);
- #endif /* EMULATE_HESIOD */
- }
-
- static int
- ListSubr(domain)
- char *domain;
- {
- querybuf buf;
- struct sockaddr_in sin;
- HEADER *headerPtr;
- int msglen;
- int amtToRead;
- int numRead;
- int numAnswers = 0;
- int result;
- int soacnt = 0;
- u_short len;
- char *cp, *nmp;
- char dname[2][NAME_LEN];
- char file[NAME_LEN];
- static char *answer = NULL;
- static int answerLen = 0;
- enum {
- NO_ERRORS,
- ERR_READING_LEN,
- ERR_READING_MSG,
- ERR_PRINTING,
- } error = NO_ERRORS;
-
- /*
- * Create a query packet for the requested domain name.
- */
- msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR,
- (char *)0, 0, (char *)0,
- (char *) &buf, sizeof(buf));
- if (msglen < 0) {
- if (_res.options & RES_DEBUG) {
- fprintf(stderr, "*** ls: res_mkquery failed\n");
- }
- return (ERROR);
- }
-
- bzero((char *)&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(nsport);
-
- /*
- * Check to see if we have the address of the server or the
- * address of a server who knows about this domain.
- *
- * For now, just use the first address in the list.
- */
-
- if (defaultPtr->addrList != NULL) {
- sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
- } else {
- sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
- }
-
- /*
- * Set up a virtual circuit to the server.
- */
- if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("ls: socket");
- return(ERROR);
- }
- if (connect(sockFD, &sin, sizeof(sin)) < 0) {
- int e;
- if (errno == ECONNREFUSED) {
- e = NO_RESPONSE;
- } else {
- perror("ls: connect");
- e = ERROR;
- }
- (void) close(sockFD);
- sockFD = -1;
- return e;
- }
-
- /*
- * Send length & message for zone transfer
- */
-
- len = htons(msglen);
-
- if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
- write(sockFD, (char *) &buf, msglen) != msglen) {
- perror("ls: write");
- (void) close(sockFD);
- sockFD = -1;
- return(ERROR);
- }
-
- dname[0][0] = '\0';
- while (1) {
- unsigned short tmp;
-
- /*
- * Read the length of the response.
- */
-
- cp = (char *) &tmp;
- amtToRead = sizeof(u_short);
- while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
- cp += numRead;
- amtToRead -= numRead;
- }
- if (numRead <= 0) {
- error = ERR_READING_LEN;
- break;
- }
-
- if ((len = htons(tmp)) == 0) {
- break; /* nothing left to read */
- }
-
- /*
- * The server sent too much data to fit the existing buffer --
- * allocate a new one.
- */
- if (len > answerLen) {
- if (answerLen != 0) {
- free(answer);
- }
- answerLen = len;
- answer = malloc(answerLen);
- }
-
- /*
- * Read the response.
- */
-
- amtToRead = len;
- cp = answer;
- while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
- cp += numRead;
- amtToRead -= numRead;
- }
- if (numRead <= 0) {
- error = ERR_READING_MSG;
- break;
- }
-
- result = PrintListInfo(filePtr, answer, cp, dname[0]);
- if (result != SUCCESS) {
- error = ERR_PRINTING;
- break;
- }
-
- numAnswers++;
- cp = answer + sizeof(HEADER);
- if (ntohs(((HEADER* )answer)->qdcount) > 0)
- cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
- nmp = cp;
- cp += dn_skipname(cp, (u_char *)answer + len);
- if ((_getshort(cp) == T_SOA)) {
- dn_expand(answer, answer + len, nmp, dname[soacnt],
- sizeof(dname[0]));
- if (soacnt) {
- if (strcmp(dname[0], dname[1]) == 0)
- break;
- } else
- soacnt++;
- }
- } /* while */
-
- (void) close(sockFD);
- sockFD = -1;
- switch (error) {
- case NO_ERRORS:
- return (SUCCESS);
-
- case ERR_READING_LEN:
- return(ERROR);
-
- case ERR_PRINTING:
- return(result);
-
- case ERR_READING_MSG:
- headerPtr = (HEADER *) answer;
- fprintf(stderr,"*** ls: error receiving zone transfer:\n");
- fprintf(stderr,
- " result: %s, answers = %d, authority = %d, additional = %d\n",
- _res_resultcodes[headerPtr->rcode],
- ntohs(headerPtr->ancount), ntohs(headerPtr->nscount),
- ntohs(headerPtr->arcount));
- return(ERROR);
- default:
- return(ERROR);
- }
- }
-
-
- /*
- *******************************************************************************
- *
- * PrintListInfo --
- *
- * Used by the ListInfo routine to print the answer
- * received from the name server. Only the desired
- * information is printed.
- *
- * Results:
- * SUCCESS the answer was printed without a problem.
- * NO_INFO the answer packet did not contain an answer.
- * ERROR the answer was malformed.
- * Misc. errors returned in the packet header.
- *
- *******************************************************************************
- */
-
- #define NAME_FORMAT "%s"
-
- static Boolean
- strip_domain(string, domain)
- char *string, *domain;
- {
- register char *dot;
-
- if (*domain != '\0') {
- dot = string;
- while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot))
- ;
- if (dot != NULL) {
- dot[-1] = '\0';
- return TRUE;
- }
- }
- return FALSE;
- }
-
- static char *
- domain_start(string, domain)
- char *string, *domain;
- {
- register char *dot;
-
- if (*domain != '\0') {
- dot = string;
- while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot))
- ;
- return dot;
- }
- return NULL;
- }
-
- static char *
- domain_child(string, domain)
- char *string, *domain;
- {
- register char *dot;
-
- if (*domain != '\0') {
- dot = string;
- if((dot = strchr(dot, '.')) != NULL && !strcasecmp(domain, ++dot))
- return dot;
- }
- return NULL;
- }
-
- PrintListInfo(file, msg, eom, domain)
- FILE *file;
- char *msg, *eom;
- char *domain;
- {
- register char *cp;
- HEADER *headerPtr;
- int type, qclass, dlen, nameLen;
- u_long ttl;
- int n, pref;
- struct in_addr inaddr;
- char name[NAME_LEN];
- char name2[NAME_LEN];
- Boolean stripped;
-
- /*
- * Read the header fields.
- */
- headerPtr = (HEADER *)msg;
- cp = msg + sizeof(HEADER);
- if (headerPtr->rcode != NOERROR) {
- return(headerPtr->rcode);
- }
-
- /*
- * We are looking for info from answer resource records.
- * If there aren't any, return with an error. We assume
- * there aren't any question records.
- */
-
- if (ntohs(headerPtr->ancount) == 0) {
- return(NO_INFO);
- } else {
- if (ntohs(headerPtr->qdcount) > 0) {
- nameLen = dn_skipname(cp, eom);
- if (nameLen < 0)
- return (ERROR);
- cp += nameLen + QFIXEDSZ;
- }
- if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0)
- return (ERROR);
- cp += nameLen;
-
- type = _getshort(cp);
- cp += sizeof(u_short);
-
- qclass = _getshort(cp);
- cp += sizeof(u_short);
- ttl = _getlong(cp);
- cp += sizeof(u_long);
- dlen = _getshort(cp);
- cp += sizeof(u_short);
-
- if (name[0] == 0)
- strcpy(name, ".");
-
- /* Strip the domain name from the data, if desired. */
- stripped = FALSE;
- if (type != T_A && type != T_HINFO && type != T_CNAME)
- {
- char *y;
-
- stripped = strip_domain(name, vdomain);
- if ((y = strrchr(name,'.')) != 0)
- {
- if(stripped)
- {
- *y++ = '\0';
- ns_add(y,0); /* Adding implicit domain */
- }
- return(SUCCESS);
- }
- }
- else
- {
- char *y,*ds;
-
- ds = domain_start(name,vdomain);
- if(!ds) return(SUCCESS);
- ds[-1] = '\0';
- if(( y = strrchr(name,'.')) != 0)
- {
- *y++ = '\0';
- ns_add(y,0); /* Adding implicit domain */
- return (SUCCESS);
- }
- ds[-1] = '.';
- }
- if(strlen(name) == 0)
- return(SUCCESS); /* Ignore this record */
-
- /*
- * The wildcard is a special case.
- */
- if(!strcmp(name,"*")) return(SUCCESS);
-
- switch (type)
- {
- case T_NS:
- if ((nameLen =
- dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
- return (ERROR);
- }
- strip_domain(name2, vdomain);
- ns_add(name,1); /* Add explicit domain */
- break;
- case T_MR:
- {
- char mailbox[64];
-
- if ((nameLen =
- dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
- return (ERROR);
- }
- strip_domain(name2, domain);
- if(use_quotes(name2))
- {
- sprintf(mailbox,"\"%s\"",name2);
- ChangeMailBox(name,mailbox,NULL,type);
- /* fprintf(file, "%s:\"%s\"\n",name,name2); */
- }
- else
- {
- ChangeMailBox(name,name2,NULL,type);
- /* fprintf(file, "%s:%s\n",name,name2); */
- }
- break;
- }
- case T_MB:
- {
- char mailbox[64];
-
- if ((nameLen =
- dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
- return (ERROR);
- }
- /* strip_domain(name2, vdomain); */
- if(use_quotes(name2))
- {
- fprintf(stderr,"Error in hostname: %s\n",name2);
- break;
- }
- sprintf(mailbox,"%s@%s",name,name2);
- ChangeMailBox(name,mailbox,NULL,type);
- /* fprintf(file, "%s:%s@%s\n",name,name, name2); */
- break;
- }
- case T_MG:
- if ((nameLen =
- dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0)
- return (ERROR);
- strip_domain(name2, domain);
- AddMailListMember(name,name2);
- break;
- case T_CNAME:
- if ((nameLen = dn_expand(msg, eom, cp, name2,
- sizeof(name2))) < 0)
- return (ERROR);
- strip_domain(name2, vdomain);
- AddAlias(name2,name);
- break;
-
- case T_MINFO:
- {
- char req_name[32],err_name[32];
- int n;
-
- if((n = dn_expand(msg,eom,cp,req_name,sizeof(req_name))) < 0)
- return(ERROR);
- cp += n;
- strip_domain(req_name, domain);
- if((n = dn_expand(msg,eom,cp,err_name,sizeof(err_name))) < 0)
- return(ERROR);
- cp += n;
- strip_domain(err_name, domain);
- ChangeMailList(name,req_name,err_name);
- }
- break;
- case T_UINFO:
- ChangeMailBox(name,NULL,cp,0);
- /* fprintf(file, "# %s -- %s\n",name, cp); */
- break;
- case T_HINFO:
- {
- char mach_name[128],os_name[128];
- int n;
-
- *mach_name = '\0'; /* Reset machine_name */
- if(n = *cp++) {
- (void)sprintf(mach_name,"%.*s",n, cp);
- cp += n;
- }
- *os_name = '\0'; /* Reset os_name */
- if(n = *cp++) {
- (void)sprintf(os_name,"%.*s",n, cp);
- cp += n;
- }
- ChangeHInfo(name,mach_name,os_name);
- }
- break;
- case T_GID:
- ChangeUGID(name,NOID,_getlong(cp));
- break;
- case T_UID:
- ChangeUGID(name,_getlong(cp),NOID);
- break;
- case T_A:
- ChangeAddr(name,_getlong(cp));
- break;
- #ifdef EMULATE_HESIOD
- case T_TXT:
- {
- int n;
- n = *cp++;
- ChangeText(name,cp,n);
- /* fprintf(file, "%s|%s\n",name,name2); */
- }
- break;
- #endif /* EMULATE_HESIOD */
- default:
- break;
- } /* switch */
- }
- return(SUCCESS);
- }
-
- static int
- use_quotes(name)
- char *name;
- {
- char *wildp;
- int noquotes = 1;
-
- while(*name && noquotes)
- {
- for(wildp = " \t\n|/"; *wildp && noquotes; )
- if(*wildp++ == *name)
- noquotes=0;
- name++;
- }
- return !noquotes;
- }
-
- ListHost_close()
- {
- if (sockFD != -1) {
- (void) close(sockFD);
- sockFD = -1;
- }
- }
-
- struct mb_ent *
- CreateMailBox(name)
- char *name;
- {
- struct mb_ent *me;
-
- me = (struct mb_ent*)malloc(sizeof(struct mb_ent));
- bzero(me,sizeof(struct mb_ent));
- me->gid = NOID;
- me->uid = NOID;
- strncpy(me->name,name,32);
- htab_enter(mb_tab,me,me);
- return me;
- }
-
- static void
- ChangeMailBox(name,box,gecos,qtype)
- char *name,*box,*gecos;
- int qtype;
- {
- struct mb_ent *me;
-
- me = (struct mb_ent*)htab_find(mb_tab,name);
- if(!me)
- me = CreateMailBox(name);
- if(qtype)
- me->qtype = qtype;
- if(box)
- {
- strncpy(me->mailbox,box,32);
- if(!strncmp(name,box,32))
- *me->mailbox = '\0'; /* Zeroing it. */
- }
- /*
- * This can have some size, and is probaly infrequent, so I malloc the space
- */
- if(gecos)
- {
- if(me->gecos) free(me->gecos); /* Previos stuff */
- me->gecos = malloc(strlen(gecos) +1 );
- strcpy(me->gecos,gecos);
- }
- }
-
- #ifdef EMULATE_HESIOD
- static void
- ChangeText(name,text,n)
- char *name,*text;
- int n;
- {
- struct txt_ent *te;
-
- te = (struct txt_ent*)htab_find(txt_tab,name);
- if(!te)
- {
- te = (struct txt_ent*)malloc(sizeof(struct txt_ent));
- strncpy(te->name,name,32);
- htab_enter(txt_tab,te,te);
- }
- else
- free(te->txt);
- te->txt = malloc(n+1);
- strncpy(te->txt,text,n);
- te->txt[n] = '\0';
- }
- #endif /* EMULATE_HESIOD */
-
- static void
- ChangeUGID(name,uid,gid)
- char *name;
- int uid,gid;
- {
- struct mb_ent *me;
-
- me = (struct mb_ent*)htab_find(mb_tab,name);
- if(!me)
- me = CreateMailBox(name);
- if(gid != NOID) me->gid = gid;
- if(uid != NOID) me->uid = uid;
- }
-
- struct host_ent *
- CreateAddr(name)
- char *name;
- {
- struct host_ent *me;
-
- me = (struct host_ent *)malloc(sizeof(struct host_ent));
- bzero(me,sizeof(struct host_ent));
- strncpy(me->name,name,32);
- VTableSet(&me->ipaddr,sizeof(struct host_ip));
- VTableSet(&me->aliases,sizeof(struct host_ali));
- htab_enter(host_tab,me,me);
- return me;
- }
-
- static void
- ChangeAddr(name,addr)
- char *name;
- int addr;
- {
- struct host_ent *me;
- struct host_ip ip,*hi;
- int ix=0;
-
- #if 0
- fprintf(stderr,"In ChangeAddr with %s\n",name);
- #endif
- me = (struct host_ent*)htab_find(host_tab,name);
- if(!me)
- me = CreateAddr(name);
- while(hi = (struct host_ip*)VTableNext(&me->ipaddr,&ix,1))
- {
- if(hi->addr == addr) return; /* Do not add same IP address twice */
- }
- ip.used = 0;
- ip.addr = addr;
- VTableAppend(&me->ipaddr,(char*)&ip);
- }
-
- static void
- AddAlias(name,alias)
- char *name;
- char *alias;
- {
- struct host_ent *me;
- struct host_ali ali;
-
- #if 0
- fprintf(stderr,"In AddAlias with %s\n",name);
- #endif
- me = (struct host_ent*)htab_find(host_tab,name);
- if(!me)
- me = CreateAddr(name);
- strncpy(ali.name,alias,32);
- VTableAppend(&me->aliases,(char*)&ali);
- }
-
- static void
- ChangeHInfo(name,mach,os)
- char *name;
- char *mach;
- char *os;
- {
- struct host_ent *me;
- char *mmach;
- char *mos;
-
- me = (struct host_ent*)htab_find(host_tab,name);
- if(!me)
- me = CreateAddr(name);
- mmach = malloc(strlen(mach)+1);
- mos = malloc(strlen(os)+1);
- strcpy(mmach,mach);
- strcpy(mos,os);
-
- me->ostype = mos;
- me->machtype = mmach;
- }
-
- struct minfo_ent *
- CreateMailList(name)
- char *name;
- {
- struct minfo_ent *me;
-
- me = (struct minfo_ent*)malloc(sizeof(struct minfo_ent));
- bzero(me,sizeof(struct minfo_ent));
- strncpy(me->name,name,32);
- VTableSet(&me->table,sizeof(struct mg_ent));
- htab_enter(mailtab,me,me);
- return me;
- }
-
- static void
- ChangeMailList(name,request,errors)
- char *name,*request,*errors;
- {
- struct minfo_ent *me;
-
- me = (struct minfo_ent*)htab_find(mailtab,name);
- if(!me)
- me = CreateMailList(name);
- if(request)
- strncpy(me->request,request,32);
- if(errors)
- strncpy(me->errors,errors,32);
- }
-
- static void
- AddMailListMember(name,member)
- char *name,*member;
- {
- struct minfo_ent *me;
- struct mg_ent mg;
-
- me = (struct minfo_ent*)htab_find(mailtab,name);
- if(!me)
- me = CreateMailList(name);
- strncpy(mg.member,member,32);
- VTableAppend(&me->table,(char*)&mg);
- }
-
- PrintMailLists(file)
- FILE *file;
- {
- int starting= TRUE;
- int pos,first,mlen;
- struct minfo_ent *me,*key;
- struct mg_ent *mg;
-
- fprintf(file,"#\n# Maillists created by ns2tab\n#\n");
- while(htab_list(mailtab,starting,&me,&key))
- {
- int ix=0;
- int l,dnr;
- struct mb_ent *mb;
-
- starting = FALSE;
- if(VTableSize(&me->table) == 0)
- continue;
- fprintf(file,"\n"); /* Start each list with a newline */
- if((mb = htab_find(mb_tab,me->name)) && mb->gecos)
- fprintf(file,"# %s\n",mb->gecos); /* Get comment */
- dnr =0;
- if(*me->request)
- fprintf(file,"%s-request: %s\n",me->name,me->request);
- if(*me->errors)
- fprintf(file,"owner-%s: %s\n",me->name,me->errors);
- fprintf(file,"%s: ",me->name);
- pos = strlen(me->name) +1;
- mlen = pos;
- first = TRUE;
- while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
- {
- /*
- * Do not include a listmember with the same name as the list it self
- */
- if(!strcmp(me->name,mg->member)) continue;
-
- l = strlen(mg->member) + 2;
- /* I am told that because of restrictions in dbm an alias cannot contain
- more than approximately 1000 bytes of information. So I create
- dummy aliases.
- */
- mlen += l;
- if(mlen > 970)
- {
- if(!first) putc(',',file);
- dnr++;
- fprintf(file,"%s_%d,\n",me->name,dnr);
- fprintf(file,
- "# Dummy alias necesary because of restrictions in dbm(3x).\n");
- fprintf(file,"%s_%d: %s",me->name,dnr,mg->member);
- pos = strlen(me->name) + 4;
- mlen = pos + l;
- first = FALSE;
- }
- if((pos + l) > 76)
- {
- pos = l;
- fprintf(file,",\n\t%s",mg->member);
- }
- else
- {
- pos += l;
- if(!first) fprintf(file,", ");
- first = FALSE;
- fprintf(file,"%s",mg->member);
- }
- }
- fprintf(file,"\n");
- }
- }
-
- PrintMailBoxes(file)
- FILE *file;
- {
- int starting= TRUE;
- struct mb_ent *me,*key;
-
- fprintf(file,"#\n# Mailboxes created by ns2tab\n#\n");
- while(htab_list(mb_tab,starting,&me,&key))
- {
- starting = FALSE;
- if(*me->mailbox)
- {
- if(me->gecos)
- fprintf(file,"# %s +- %s\n",me->name,me->gecos);
- fprintf(file,"%s: %s\n",me->name,me->mailbox);
- }
- }
- }
-
- PrintMail(file)
- FILE *file;
- {
- fprintf(file,"# Aliases created from [%s] nameserver.\n",
- (defaultPtr->addrList != NULL) ? defaultPtr->name :
- defaultPtr->servers[0]->name);
- PrintMailBoxes(file);
- PrintMailLists(file);
- return 0;
- }
-
-
- PrintElmLists(file)
- FILE *file;
- {
- int starting= TRUE;
- int pos,first,mlen;
- struct minfo_ent *me,*key;
- struct mg_ent *mg;
-
- fprintf(file,"#\n# Maillists created by ns2tab (ELM) Style\n#\n");
- while(htab_list(mailtab,starting,&me,&key))
- {
- int ix=0;
- int l,dnr;
- struct mb_ent *mb;
-
- starting = FALSE;
- if(VTableSize(&me->table) == 0)
- continue;
- fprintf(file,"\n"); /* Start each list with a newline */
- mb = htab_find(mb_tab,me->name); /* Get Comment */
- dnr =0;
- if(*me->request)
- if(lelmstyle)
- fprintf(file,"%s-request = %s Request = %s-request\n",
- me->name,me->name,me->name);
- else
- fprintf(file,"%s-request = %s Request = %s\n",
- me->name,me->name,me->request);
- if(*me->errors)
- if(lelmstyle)
- fprintf(file,"owner-%s = %s Errors = owner-%s\n",
- me->name,me->name,me->name);
- else
- fprintf(file,"owner-%s = %s Errors = %s\n",
- me->name,me->name,me->errors);
- if(mb && mb->gecos)
- fprintf(file,"%s = %s = ",me->name,mb->gecos);
- else
- fprintf(file,"%s = = ",me->name);
- /*
- * Local elm doesn't define the members in a maillist, but lets
- * /usr/lib/aliases handle that part.
- */
- if(lelmstyle)
- {
- fprintf(file,"%s\n",me->name);
- continue;
- }
- pos = strlen(me->name) +1;
- mlen = pos;
- first = TRUE;
- while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
- {
- /*
- * Do not include a listmember with the same name as the list itself
- */
- if(!strcmp(me->name,mg->member)) continue;
-
- l = strlen(mg->member) + 2;
- #if 0
- /* I am told that because of restrictions in dbm an alias cannot contain
- more than approximately 1000 bytes of information. So I create
- dummy aliases.
- */
- mlen += l;
- if(mlen > 970)
- {
- if(!first) putc(',',file);
- dnr++;
- fprintf(file,"%s_%d\n",me->name,dnr);
- fprintf(file,
- "# Dummy alias necesary because of restrictions in dbm(3x).\n");
- fprintf(file,"%s_%d = = %s",me->name,dnr,mg->member);
- pos = strlen(me->name) + 4;
- mlen = pos + l;
- first = FALSE;
- }
- #endif
- if((pos + l) > 76)
- {
- pos = l;
- fprintf(file,",\n %s",mg->member);
- }
- else
- {
- pos += l;
- if(!first) fprintf(file,", ");
- first = FALSE;
- fprintf(file,"%s",mg->member);
- }
- } /* while */
- fprintf(file,"\n");
- } /* while */
- }
-
- PrintElmBoxes(file)
- FILE *file;
- {
- int starting= TRUE;
- struct mb_ent *me,*key;
-
- fprintf(file,"#\n# Mailboxes created by ns2tab (ELM style)\n#\n");
- while(htab_list(mb_tab,starting,&me,&key))
- {
- starting = FALSE;
- if(*me->mailbox)
- {
- if(lelmstyle)
- {
- if(me->qtype == T_MR)
- fprintf(file,"%s = = %s\n",me->name,me->mailbox);
- else
- if(me->gecos)
- fprintf(file,"%s = %s = %s\n"
- ,me->name,me->gecos,me->name);
- }
- else /* Elm style with no /usr/lib/aliases */
- {
- fprintf(file,"%s = %s = %s\n",me->name,
- (me->gecos)?me->gecos:"",me->mailbox);
- }
- }
- } /* while */
- }
-
- PrintElmish(file)
- FILE *file;
- {
- fprintf(file,"# Aliases created from [%s] nameserver.\n",
- (defaultPtr->addrList != NULL) ? defaultPtr->name :
- defaultPtr->servers[0]->name);
- PrintElmBoxes(file);
- PrintElmLists(file);
- return 0;
- }
-
- static void ExpandMember();
-
- PrintGroupish(file)
- FILE *file;
- {
- int starting= TRUE;
- int first;
- struct minfo_ent *me,*key;
- struct mg_ent *mg;
-
- while(htab_list(mailtab,starting,&me,&key))
- {
- int ix=0;
- struct mb_ent *mb;
-
- starting = FALSE;
- if(!(mb = htab_find(mb_tab,me->name)))
- continue; /* Ignore everything that doesn't have a MB */
- if(mb->gid == NOID)
- continue; /* Ignore everything that doesn't have a GID */
- fprintf(file,"%s:*:%d:",me->name,mb->gid);
- first = TRUE;
- ExpandMember(file,me);
- fprintf(file,"\n");
- } /* while */
- }
-
- static void
- ExpandMember(file,me)
- FILE *file;
- struct minfo_ent *me;
- {
- struct mg_ent *mg;
-
- int first=TRUE;
- int ix=0;
- while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
- {
- int doprint = 1;
-
- if(!first) fprintf(file,",");
- first = FALSE;
- /*
- * If we expand members, we must check them out. If a member has a UID
- * It should not be expanded.
- * Also, as an added security, if a member of a group has same
- * name the group it is not expanded.
- */
- if(recursegroup && strcmp(me->name,mg->member))
- {
- struct minfo_ent *mm;
- struct mb_ent *member;
-
- /* Check too see if this is a MINFO */
- if(mm = htab_find(mailtab,mg->member))
- {
- member = htab_find(mb_tab,mg->member);
- if ((member && member->uid == NOID) || !member)
- if(VTableSize(&mm->table) != 0)
- {
- ExpandMember(file,mm);
- doprint = 0;
- }
- }
- }
- if(doprint)
- fprintf(file,"%s",mg->member);
- }
- }
-
- PrintHosts(file,domain)
- FILE *file;
- char *domain;
- {
- int starting= TRUE;
- int first;
- struct host_ent *host,*key;
-
- fprintf(file,"#\n# Hosttable - derived from ns2tab. Do not change\n#\n");
- /*
- * Run through all the canonical names.
- */
- while(htab_list(host_tab,starting,&host,&key))
- {
- int aix,ix=0;
- struct host_ali *ha;
- struct host_ip *hi;
- char *punkt;
-
- starting = FALSE;
- while(hi = (struct host_ip*)VTableNext(&host->ipaddr,&ix,1))
- {
- aix=0;
- #if 0
- fprintf(file,"%-15s %s.%s %s",inet_ntoa(ntohl(hi->addr)),
- host->name,vdomain,host->name);
- #else
- fprintf(file,"%-15s %s",inet_ntoa(ntohl(hi->addr)),
- host->name);
- if(punkt = strchr(host->name,'.'))
- {
- *punkt = '\0';
- fprintf(file," %s",host->name);
- *punkt = '.';
- }
- #endif
- while(ha = (struct host_ali*)VTableNext(&host->aliases,&aix,1))
- fprintf(file," %s",ha->name);
- if(host->machtype || host->ostype)
- fprintf(file,"\t#");
- if(host->machtype)
- fprintf(file," %s",host->machtype);
- if(host->ostype)
- fprintf(file," %s",host->ostype);
- fprintf(file,"\n");
- }
- }
- }
-
- #include <pwd.h>
- PWUpd(file)
- FILE *file;
- {
- struct passwd *pw;
- struct mb_ent *mb;
- char *gecostmp;
-
- while(pw = getpwent())
- {
- gecostmp = pw->pw_gecos;
- if((mb = htab_find(mb_tab,pw->pw_name)) && mb->gecos)
- pw->pw_gecos = mb->gecos;
- putpwent(pw,file);
- pw->pw_gecos = gecostmp;
- }
- endpwent();
- }
-
- static
- PrintElm(file)
- FILE *file;
- {
- lelmstyle=0;
- PrintElmish(file);
- }
-
- static
- PrintLElm(file)
- FILE *file;
- {
- lelmstyle=1;
- PrintElmish(file);
- }
-
- static
- PrintGroup(file)
- FILE *file;
- {
- recursegroup=1;
- PrintGroupish(file);
- }
-
- static
- PrintNrGroup(file)
- FILE *file;
- {
- recursegroup=0;
- PrintGroupish(file);
- }
-
- static
- PrintSubdomains(file)
- FILE *file;
- {
- struct ns_ent *ns;
- int ix = 0;
-
- while(ns = (struct ns_ent*)VTableNext(&subdomains,&ix,1))
- {
- printf("%-32s %s\n",ns->name,(ns->is_explicit)?"explicit":"implicit");
- }
- }
-
- #ifdef EMULATE_HESIOD
- PrintPrintcap(file)
- FILE *file;
- {
- int starting= TRUE;
- int first;
- struct txt_ent *name,*key;
-
- fprintf(file,"#\n# Printcap - derived from ns2tab. Do not change\n#\n");
- /*
- * Run through all the canonical names.
- */
- while(htab_list(txt_tab,starting,&name,&key))
- {
- register char *p;
-
- starting = FALSE;
- /* fprintf(file,"%s",name->txt); */
- p = name->txt;
- while(*p)
- {
- putc(*p,file);
- if(*p == ':' && p[1] ) fprintf(file,"\\\n\t:");
- p++;
- }
- }
- return 0;
- }
-
- void (*printfunc)();
-
- FilesysEngine(file)
- FILE *file;
- {
- int starting= TRUE;
- int first;
- struct txt_ent *name,*key;
- /*
- * Run through all the canonical names.
- */
- while(htab_list(txt_tab,starting,&name,&key))
- {
- int x;
- char fs_type[8];
- char name_on_server[128], server_hostname[128];
- char mount_mode[2],mount_point[128];
-
- starting = FALSE;
- x = sscanf(name->txt,"%s %s %s %s %s",
- fs_type,name_on_server,
- server_hostname,mount_mode,mount_point);
- if(x != 5) continue;
- (*printfunc)(file,fs_type,name_on_server,server_hostname,
- mount_mode,mount_point);
- }
- return 0;
- }
-
- void
- FstabEntry(file,fs_type,name_on_server,server_hostname,mount_mode,mount_point)
- FILE *file;
- char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
- {
- char *p;
- for(p = fs_type; *p; p++) *p = tolower(*p);
- fprintf(file,"%s@%s:%s:r%s:0:0:%s:hard,intr:\n",
- name_on_server,server_hostname,mount_point,
- mount_mode,fs_type);
- }
-
- PrintFstab(file)
- FILE *file;
- {
- printfunc = FstabEntry;
- FilesysEngine(file);
- }
-
- /*
- * /etc/default/filesys format as seen on SCO unix.
- */
- void
- FilesysEntry(file,fs_type,name_on_server,server_hostname,mount_mode,mount_point)
- FILE *file;
- char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
- {
- fprintf(file,"bdev=%s:%s mountdir=%s fsck=no rcfsck=no \\\n",
- server_hostname,name_on_server,mount_point);
- fprintf(file,"rcmount=yes mount=yes fstyp=%s nfsopts=\"hard,intr\"\n\n",
- fs_type);
- }
-
- PrintFilesys(file)
- FILE *file;
- {
- printfunc = FilesysEntry;
- FilesysEngine(file);
- }
-
- void
- ChecklistEntry(file,fs_type,
- name_on_server,server_hostname,mount_mode,mount_point)
- FILE *file;
- char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
- {
- char *p;
- for(p = fs_type; *p; p++) *p = tolower(*p);
- fprintf(file,"%s:%s %s %s r%s,hard,intr 0 0 # loaded from ns2tab\n",
- server_hostname,name_on_server,mount_point,fs_type,mount_mode);
- }
-
- PrintChecklist(file)
- {
- printfunc = ChecklistEntry;
- FilesysEngine(file);
- }
-
- void
- VfstabEntry(file,fs_type,
- name_on_server,server_hostname,mount_mode,mount_point)
- FILE *file;
- char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
- {
- char *p;
- for(p = fs_type; *p; p++) *p = tolower(*p);
- fprintf(file,"%s:%s - %s %s - yes r%s,hard,intr\n",
- server_hostname,name_on_server,mount_point,fs_type,mount_mode);
- }
-
- PrintVfstab(file)
- {
- printfunc = VfstabEntry;
- FilesysEngine(file);
- }
-
- void
- PrintPasswd(file)
- FILE *file;
- {
- int starting= TRUE;
- int first;
- struct txt_ent *name,*key;
-
- while(htab_list(txt_tab,starting,&name,&key))
- {
- starting = FALSE;
- fprintf(file,"%s\n",name->txt);
- }
- }
- #endif /* EMULATE_HESIOD */
-
- typedef int (*intfunc)();
-
- struct stylerec {
- char *name;
- int parselen;
- intfunc func;
- char *infix;
- } Styles[] = {
- { "lelm",4,PrintLElm ,""},
- { "elm",3, PrintElm ,""},
- { "aliases",3, PrintMail ,""},
- { "group",3, PrintGroup ,""},
- { "nrgroup",3, PrintNrGroup ,""},
- { "pwupd",5, PWUpd ,""},
- { "hosts",5, PrintHosts ,""},
- { "subdomain",4,PrintSubdomains,""},
- #ifdef EMULATE_HESIOD
- { "printcap",8,PrintPrintcap,"pcap"},
- { "fstab",5,PrintFstab,"filsys"},
- { "vfstab",5,PrintVfstab,"filsys"},
- { "filesys",7,PrintFilesys,"filsys"},
- { "checklist",6,PrintChecklist,"filsys"},
- { "passwd",7,PrintPasswd,"passwd"},
- #endif /* EMULATE_HESIOD */
- };
-
- static intfunc stylefunc = PrintMail;
-
- int
- SetStyle(style)
- char *style;
- {
- int x;
-
- for(x = 0; x < (sizeof(Styles)/sizeof(Styles[0])); x++)
- if(!strncmp(Styles[x].name,style,Styles[x].parselen))
- {
- stylefunc = Styles[x].func;
- #ifdef EMULATE_HESIOD
- if(*Styles[x].infix)
- {
- char *v;
- v = malloc(strlen(vdomain) + strlen(Styles[x].infix) + 4);
- sprintf(v,"%s.%s",Styles[x].infix,vdomain);
- vdomain = v;
- }
- #endif /* EMULATE_HESIOD */
- return 0;
- }
- fprintf(stderr,"Unimplemented style: %s\n",style);
- return -1;
- }
-
- extern int hasprinted;
-
- PrintStyle(file)
- FILE *file;
- {
- hasprinted = 1;
- (*stylefunc)(file);
- }
-