home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / ns2tab / part03 / list.c
Encoding:
C/C++ Source or Header  |  1993-04-04  |  31.9 KB  |  1,552 lines

  1. /*
  2.  *******************************************************************************
  3.  *
  4.  *  list.c --
  5.  *
  6.  *    Routines to obtain info from name and finger servers.
  7.  *
  8.  *    Adapted from 4.3BSD BIND ns_init.c and from finger.c.
  9.  *
  10.  *******************************************************************************
  11.  */
  12.  
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <netinet/in.h>
  16. #include <netdb.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <errno.h>
  21. #include <arpa/nameser.h>
  22. #ifndef T_TXT
  23. #define T_TXT 16
  24. #endif
  25. #include <arpa/inet.h>
  26. #include <resolv.h>
  27. #include "res.h"
  28. #include "vtable.h"
  29.  
  30. #ifndef __STDC__
  31. extern char *malloc();
  32. #else
  33. #include <stdlib.h>
  34. #endif
  35.  
  36. extern void *htab_find();
  37.  
  38. #define NOID -8472874   /* Something very unlikely */
  39. /*
  40.  *  Imported from res_debug.c
  41.  */
  42. extern char *_res_resultcodes[];
  43.  
  44. extern int errno;
  45. static int lelmstyle;
  46. static int recursegroup;
  47.  
  48. typedef union {
  49.     HEADER qb1;
  50.     char qb2[PACKETSZ];
  51. } querybuf;
  52.  
  53. extern HostInfo    *defaultPtr;
  54. extern HostInfo    curHostInfo;
  55. extern char *vdomain;
  56. extern int    queryType;
  57. extern int    queryClass;
  58.  
  59. static int sockFD = -1;
  60. static int ListSubr();
  61.  
  62. static void AddAlias();
  63. static void ChangeMailList();
  64. static void ChangeAddr();
  65. static void ChangeMailBox();
  66. static void AddMailListMember();
  67. static void ChangeUGID();
  68. static void ChangeHInfo();
  69. #ifdef EMULATE_HESIOD
  70. static void ChangeText();
  71. #endif /* EMULATE_HESIOD */
  72. /*
  73.  *  During a listing to a file, hash marks are printed
  74.  *  every HASH_SIZE records.
  75.  */
  76.  
  77. #define HASH_SIZE 50
  78.  
  79.  
  80. /*
  81.  *******************************************************************************
  82.  *
  83.  *  LoadHosts --
  84.  *
  85.  *    Requests the name server to do a zone transfer so we
  86.  *    find out what hosts it knows about.
  87.  *
  88.  *    For LoadHosts, there are five types of output:
  89.  *
  90.  *    To see all types of information sorted by name, do the following:
  91.  *      ls -d domain.edu > file
  92.  *      view file
  93.  *
  94.  *  Results:
  95.  *    SUCCESS        the listing was successful.
  96.  *    ERROR        the server could not be contacted because
  97.  *            a socket could not be obtained or an error
  98.  *            occured while receiving, or the output file
  99.  *            could not be opened.
  100.  *
  101.  *******************************************************************************
  102.  */
  103.  
  104. void
  105. LoadHosts(domain)
  106.     char *domain;
  107. {
  108.     int result;
  109.  
  110.     if (domain && *domain)
  111.     {
  112.         result = ListSubr(domain);
  113.         if (result != SUCCESS)
  114.         fprintf(stderr, "*** Can't list domain %s: %s\n", 
  115.             domain, DecodeError(result));
  116.     }
  117.     else
  118.     {
  119.         fprintf(stderr, "*** ns2tab: empty domain\n");
  120.     }
  121.         return;
  122. }
  123.  
  124. struct minfo_ent {
  125.     char name[32];
  126.     char request[32];
  127.     char errors[32];
  128.     vtable table; /* Table for the members */
  129. };
  130. struct mg_ent {
  131.     char member[32];
  132. };
  133.  
  134. struct mb_ent {
  135.     char name[32];
  136.     char mailbox[32];
  137.     int qtype;
  138.     char *gecos;
  139.     int gid;
  140.     int uid;
  141. };
  142.  
  143. struct host_ent {
  144.     char name[32];
  145.     char *machtype;
  146.     char *ostype;
  147.     vtable aliases;
  148.     vtable ipaddr;
  149. };
  150. struct host_ali {
  151.     char name[32];
  152. };
  153. struct host_ip {
  154.     int addr;
  155.     int used;
  156. };
  157.  
  158. struct txt_ent {
  159.     char name[32];
  160.     char *txt;
  161. };
  162.  
  163. struct ns_ent {
  164.     char name[32];
  165.     int is_explicit;
  166. };
  167. vtable subdomains; /* Table to hold subdomain list */
  168.  
  169. void *mailtab; /* The global hash table for maillists */
  170. void *mb_tab; /* The hash table for mailboxes */
  171. void *host_tab;
  172. #ifdef EMULATE_HESIOD
  173. void *txt_tab;
  174. #endif /* EMULATE_HESIOD */
  175.  
  176. int
  177. ns_cmp(n1,n2)
  178.     struct ns_ent *n1,*n2;
  179. {
  180.     return strncmp(n1->name,n2->name,sizeof(n1->name));
  181. }
  182.  
  183. ns_add(name,is_explicit)
  184.     char *name;
  185.     int is_explicit;
  186. {
  187.     struct ns_ent nb;
  188.  
  189.     memcpy(nb.name,name,sizeof(nb.name));
  190.     nb.is_explicit = is_explicit;
  191.     if(!VTableLookup(&subdomains,&nb))
  192.     VTableAppend(&subdomains,(char*)&nb);
  193. }
  194.  
  195. int
  196. InitTables()
  197. {
  198.     mailtab = htab_init(17,NULL,NULL,NULL);
  199.     mb_tab = htab_init(231,NULL,NULL,NULL);
  200.     host_tab = htab_init(231,NULL,NULL,NULL);
  201.     VTableSet(&subdomains,sizeof(struct ns_ent));
  202.     VTableSetCmp(&subdomains,ns_cmp);
  203. #ifdef EMULATE_HESIOD
  204.     txt_tab = htab_init(17,NULL,NULL,NULL);
  205. #endif /* EMULATE_HESIOD */
  206. }
  207.  
  208. static int
  209. ListSubr(domain)
  210.     char *domain;
  211. {
  212.     querybuf        buf;
  213.     struct sockaddr_in    sin;
  214.     HEADER            *headerPtr;
  215.     int            msglen;
  216.     int            amtToRead;
  217.     int            numRead;
  218.     int            numAnswers = 0;
  219.     int            result;
  220.     int            soacnt = 0;
  221.     u_short            len;
  222.     char            *cp, *nmp;
  223.     char            dname[2][NAME_LEN];
  224.     char            file[NAME_LEN];
  225.     static char        *answer = NULL;
  226.     static int        answerLen = 0;
  227.     enum {
  228.         NO_ERRORS,
  229.         ERR_READING_LEN,
  230.         ERR_READING_MSG,
  231.         ERR_PRINTING,
  232.     } error = NO_ERRORS;
  233.  
  234.     /*
  235.      *  Create a query packet for the requested domain name.
  236.      */
  237.     msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR,
  238.                 (char *)0, 0, (char *)0,
  239.                 (char *) &buf, sizeof(buf));
  240.     if (msglen < 0) {
  241.         if (_res.options & RES_DEBUG) {
  242.         fprintf(stderr, "*** ls: res_mkquery failed\n");
  243.         }
  244.         return (ERROR);
  245.     }
  246.  
  247.     bzero((char *)&sin, sizeof(sin));
  248.     sin.sin_family    = AF_INET;
  249.     sin.sin_port    = htons(nsport);
  250.  
  251.     /*
  252.      *  Check to see if we have the address of the server or the
  253.      *  address of a server who knows about this domain.
  254.      *
  255.      *  For now, just use the first address in the list.
  256.      */
  257.  
  258.     if (defaultPtr->addrList != NULL) {
  259.       sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0];
  260.     } else {
  261.       sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0];
  262.     }
  263.  
  264.     /*
  265.      *  Set up a virtual circuit to the server.
  266.      */
  267.     if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  268.         perror("ls: socket");
  269.         return(ERROR);
  270.     }
  271.     if (connect(sockFD, &sin, sizeof(sin)) < 0) {
  272.         int e;
  273.         if (errno == ECONNREFUSED) {
  274.         e = NO_RESPONSE;
  275.         } else {
  276.         perror("ls: connect");
  277.         e = ERROR;
  278.         }
  279.         (void) close(sockFD);
  280.         sockFD = -1;
  281.         return e;
  282.     }
  283.  
  284.     /*
  285.      * Send length & message for zone transfer
  286.      */
  287.  
  288.         len = htons(msglen);
  289.  
  290.         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
  291.             write(sockFD, (char *) &buf, msglen) != msglen) {
  292.         perror("ls: write");
  293.         (void) close(sockFD);
  294.         sockFD = -1;
  295.         return(ERROR);
  296.     }
  297.  
  298.     dname[0][0] = '\0';
  299.     while (1) {
  300.         unsigned short tmp;
  301.  
  302.         /*
  303.          * Read the length of the response.
  304.          */
  305.  
  306.         cp = (char *) &tmp;
  307.         amtToRead = sizeof(u_short);
  308.         while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
  309.         cp      += numRead;
  310.         amtToRead -= numRead;
  311.         }
  312.         if (numRead <= 0) {
  313.         error = ERR_READING_LEN;
  314.         break;
  315.         }
  316.  
  317.         if ((len = htons(tmp)) == 0) {
  318.         break;    /* nothing left to read */
  319.         }
  320.  
  321.         /*
  322.          * The server sent too much data to fit the existing buffer --
  323.          * allocate a new one.
  324.          */
  325.         if (len > answerLen) {
  326.         if (answerLen != 0) {
  327.             free(answer);
  328.         }
  329.         answerLen = len;
  330.         answer = malloc(answerLen);
  331.         }
  332.  
  333.         /*
  334.          * Read the response.
  335.          */
  336.  
  337.         amtToRead = len;
  338.         cp = answer;
  339.         while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) {
  340.         cp += numRead;
  341.         amtToRead -= numRead;
  342.         }
  343.         if (numRead <= 0) {
  344.         error = ERR_READING_MSG;
  345.         break;
  346.         }
  347.  
  348.         result = PrintListInfo(filePtr, answer, cp, dname[0]);
  349.         if (result != SUCCESS) {
  350.         error = ERR_PRINTING;
  351.         break;
  352.         }
  353.  
  354.         numAnswers++;
  355.         cp = answer + sizeof(HEADER);
  356.         if (ntohs(((HEADER* )answer)->qdcount) > 0)
  357.         cp += dn_skipname(cp, answer + len) + QFIXEDSZ;
  358.         nmp = cp;
  359.         cp += dn_skipname(cp, (u_char *)answer + len);
  360.         if ((_getshort(cp) == T_SOA)) {
  361.         dn_expand(answer, answer + len, nmp, dname[soacnt],
  362.             sizeof(dname[0]));
  363.             if (soacnt) {
  364.             if (strcmp(dname[0], dname[1]) == 0)
  365.             break;
  366.         } else
  367.             soacnt++;
  368.         }
  369.     } /* while */
  370.  
  371.     (void) close(sockFD);
  372.     sockFD = -1;
  373.     switch (error) {
  374.         case NO_ERRORS:
  375.         return (SUCCESS);
  376.  
  377.         case ERR_READING_LEN:
  378.         return(ERROR);
  379.  
  380.         case ERR_PRINTING:
  381.         return(result);
  382.  
  383.         case ERR_READING_MSG:
  384.         headerPtr = (HEADER *) answer;
  385.         fprintf(stderr,"*** ls: error receiving zone transfer:\n");
  386.         fprintf(stderr,
  387.            "  result: %s, answers = %d, authority = %d, additional = %d\n",
  388.             _res_resultcodes[headerPtr->rcode],
  389.             ntohs(headerPtr->ancount), ntohs(headerPtr->nscount),
  390.             ntohs(headerPtr->arcount));
  391.         return(ERROR);
  392.         default:
  393.         return(ERROR);
  394.     }
  395. }
  396.  
  397.  
  398. /*
  399.  *******************************************************************************
  400.  *
  401.  *  PrintListInfo --
  402.  *
  403.  *    Used by the ListInfo routine to print the answer
  404.  *    received from the name server. Only the desired
  405.  *    information is printed.
  406.  *
  407.  *  Results:
  408.  *    SUCCESS        the answer was printed without a problem.
  409.  *    NO_INFO        the answer packet did not contain an answer.
  410.  *    ERROR        the answer was malformed.
  411.  *      Misc. errors    returned in the packet header.
  412.  *
  413.  *******************************************************************************
  414.  */
  415.  
  416. #define NAME_FORMAT "%s"
  417.  
  418. static Boolean
  419. strip_domain(string, domain)
  420.     char *string, *domain;
  421. {
  422.     register char *dot;
  423.  
  424.     if (*domain != '\0') {
  425.     dot = string;
  426.     while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot))
  427.         ;
  428.     if (dot != NULL) {
  429.         dot[-1] = '\0';
  430.         return TRUE;
  431.     }
  432.     }
  433.     return FALSE;
  434. }
  435.  
  436. static char *
  437. domain_start(string, domain)
  438.     char *string, *domain;
  439. {
  440.     register char *dot;
  441.  
  442.     if (*domain != '\0') {
  443.     dot = string;
  444.     while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot))
  445.         ;
  446.     return dot;
  447.     }
  448.     return NULL;
  449. }
  450.  
  451. static char *
  452. domain_child(string, domain)
  453.     char *string, *domain;
  454. {
  455.     register char *dot;
  456.  
  457.     if (*domain != '\0') {
  458.     dot = string;
  459.     if((dot = strchr(dot, '.')) != NULL && !strcasecmp(domain, ++dot))
  460.         return dot;
  461.     }
  462.     return NULL;
  463. }
  464.  
  465. PrintListInfo(file, msg, eom, domain)
  466.     FILE    *file;
  467.     char    *msg, *eom;
  468.     char    *domain;
  469. {
  470.     register char    *cp;
  471.     HEADER        *headerPtr;
  472.     int            type, qclass, dlen, nameLen;
  473.     u_long        ttl;
  474.     int            n, pref;
  475.     struct in_addr    inaddr;
  476.     char        name[NAME_LEN];
  477.     char        name2[NAME_LEN];
  478.     Boolean        stripped;
  479.  
  480.     /*
  481.      * Read the header fields.
  482.      */
  483.     headerPtr = (HEADER *)msg;
  484.     cp = msg + sizeof(HEADER);
  485.     if (headerPtr->rcode != NOERROR) {
  486.     return(headerPtr->rcode);
  487.     }
  488.  
  489.     /*
  490.      *  We are looking for info from answer resource records.
  491.      *  If there aren't any, return with an error. We assume
  492.      *  there aren't any question records.
  493.      */
  494.  
  495.     if (ntohs(headerPtr->ancount) == 0) {
  496.     return(NO_INFO);
  497.     } else {
  498.     if (ntohs(headerPtr->qdcount) > 0) {
  499.         nameLen = dn_skipname(cp, eom);
  500.         if (nameLen < 0)
  501.         return (ERROR);
  502.         cp += nameLen + QFIXEDSZ;
  503.     }
  504.     if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0)
  505.         return (ERROR);
  506.     cp += nameLen;
  507.  
  508.     type = _getshort(cp);
  509.     cp += sizeof(u_short);
  510.  
  511.     qclass = _getshort(cp);
  512.     cp += sizeof(u_short);
  513.     ttl = _getlong(cp);
  514.     cp += sizeof(u_long);
  515.     dlen = _getshort(cp);
  516.     cp += sizeof(u_short);
  517.  
  518.     if (name[0] == 0)
  519.         strcpy(name, ".");
  520.  
  521.     /* Strip the domain name from the data, if desired. */
  522.     stripped = FALSE;
  523.     if (type != T_A && type != T_HINFO && type != T_CNAME)
  524.     {
  525.         char *y;
  526.  
  527.         stripped = strip_domain(name, vdomain);
  528.         if ((y = strrchr(name,'.')) != 0)
  529.         {
  530.         if(stripped)
  531.         {
  532.             *y++ = '\0';
  533.             ns_add(y,0); /* Adding implicit domain */
  534.         }
  535.         return(SUCCESS);
  536.         }
  537.     }
  538.     else
  539.     {
  540.         char *y,*ds;
  541.  
  542.         ds = domain_start(name,vdomain);
  543.         if(!ds)  return(SUCCESS);
  544.         ds[-1] = '\0';
  545.         if(( y = strrchr(name,'.')) != 0)
  546.         {
  547.         *y++ = '\0';
  548.         ns_add(y,0); /* Adding implicit domain */
  549.         return (SUCCESS);
  550.         }
  551.         ds[-1] = '.';
  552.     }
  553.     if(strlen(name) == 0)
  554.         return(SUCCESS); /* Ignore this record */
  555.  
  556. /*
  557.  * The wildcard is a special case.
  558.  */
  559.     if(!strcmp(name,"*")) return(SUCCESS);
  560.  
  561.     switch (type)
  562.     {
  563.         case T_NS:
  564.         if ((nameLen =
  565.             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  566.             return (ERROR);
  567.         }
  568.         strip_domain(name2, vdomain);
  569.         ns_add(name,1); /* Add explicit domain */
  570.         break;
  571.         case T_MR:
  572.         {
  573.         char mailbox[64];
  574.  
  575.         if ((nameLen =
  576.             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  577.             return (ERROR);
  578.         }
  579.         strip_domain(name2, domain);
  580.         if(use_quotes(name2))
  581.         {
  582.             sprintf(mailbox,"\"%s\"",name2);
  583.             ChangeMailBox(name,mailbox,NULL,type);
  584.             /* fprintf(file, "%s:\"%s\"\n",name,name2); */
  585.         }
  586.         else
  587.         {
  588.             ChangeMailBox(name,name2,NULL,type);
  589.             /* fprintf(file, "%s:%s\n",name,name2); */
  590.         }
  591.         break;
  592.         }
  593.         case T_MB:
  594.         {
  595.         char mailbox[64];
  596.  
  597.         if ((nameLen =
  598.             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) {
  599.             return (ERROR);
  600.         }
  601. /*        strip_domain(name2, vdomain); */
  602.         if(use_quotes(name2))
  603.         {
  604.             fprintf(stderr,"Error in hostname: %s\n",name2);
  605.             break;
  606.         }
  607.         sprintf(mailbox,"%s@%s",name,name2);
  608.         ChangeMailBox(name,mailbox,NULL,type);
  609.         /* fprintf(file, "%s:%s@%s\n",name,name, name2); */
  610.         break;
  611.         }
  612.         case T_MG:
  613.         if ((nameLen =
  614.             dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0)
  615.             return (ERROR);
  616.         strip_domain(name2, domain);
  617.         AddMailListMember(name,name2);
  618.         break;
  619.         case T_CNAME:
  620.         if ((nameLen = dn_expand(msg, eom, cp, name2,
  621.         sizeof(name2))) < 0)
  622.             return (ERROR);
  623.         strip_domain(name2, vdomain);
  624.         AddAlias(name2,name);
  625.         break;
  626.  
  627.         case T_MINFO:
  628.         {
  629.         char req_name[32],err_name[32];
  630.         int n;
  631.  
  632.         if((n = dn_expand(msg,eom,cp,req_name,sizeof(req_name))) < 0)
  633.             return(ERROR);
  634.         cp += n;
  635.         strip_domain(req_name, domain);
  636.         if((n = dn_expand(msg,eom,cp,err_name,sizeof(err_name))) < 0)
  637.             return(ERROR);
  638.         cp += n;
  639.         strip_domain(err_name, domain);
  640.         ChangeMailList(name,req_name,err_name);
  641.         }
  642.         break;
  643.         case T_UINFO:
  644.         ChangeMailBox(name,NULL,cp,0);
  645.         /* fprintf(file, "# %s -- %s\n",name, cp); */
  646.         break;
  647.         case T_HINFO:
  648.         {
  649.         char mach_name[128],os_name[128];
  650.         int n;
  651.  
  652.         *mach_name = '\0'; /* Reset machine_name */
  653.         if(n = *cp++) {
  654.             (void)sprintf(mach_name,"%.*s",n, cp);
  655.             cp += n;
  656.         } 
  657.         *os_name = '\0'; /* Reset os_name */
  658.         if(n = *cp++) {
  659.             (void)sprintf(os_name,"%.*s",n, cp);
  660.             cp += n;
  661.         } 
  662.         ChangeHInfo(name,mach_name,os_name);
  663.         }
  664.         break;
  665.         case T_GID:
  666.         ChangeUGID(name,NOID,_getlong(cp));
  667.         break;
  668.         case T_UID:
  669.         ChangeUGID(name,_getlong(cp),NOID);
  670.         break;
  671.         case T_A:
  672.         ChangeAddr(name,_getlong(cp));
  673.         break;
  674. #ifdef EMULATE_HESIOD
  675.         case T_TXT:
  676.         {
  677.             int n;
  678.             n = *cp++;
  679.             ChangeText(name,cp,n);
  680.             /* fprintf(file, "%s|%s\n",name,name2); */
  681.         }
  682.         break;
  683. #endif /* EMULATE_HESIOD */
  684.         default:
  685.         break;
  686.     } /* switch */
  687.     }
  688.     return(SUCCESS);
  689. }
  690.  
  691. static int
  692. use_quotes(name)
  693.     char *name;
  694. {
  695.     char *wildp;
  696.     int noquotes = 1;
  697.  
  698.     while(*name && noquotes)
  699.     {
  700.     for(wildp = " \t\n|/"; *wildp && noquotes; )
  701.         if(*wildp++ == *name)
  702.         noquotes=0;
  703.     name++;
  704.     }
  705.     return !noquotes;
  706. }
  707.  
  708. ListHost_close()
  709. {
  710.     if (sockFD != -1) {
  711.     (void) close(sockFD);
  712.     sockFD = -1;
  713.     }
  714. }
  715.  
  716. struct mb_ent *
  717. CreateMailBox(name)
  718.    char *name;
  719. {
  720.     struct mb_ent *me;
  721.  
  722.     me = (struct mb_ent*)malloc(sizeof(struct mb_ent));
  723.     bzero(me,sizeof(struct mb_ent));
  724.     me->gid = NOID;
  725.     me->uid = NOID;
  726.     strncpy(me->name,name,32);
  727.     htab_enter(mb_tab,me,me);
  728.     return me;
  729. }
  730.  
  731. static void
  732. ChangeMailBox(name,box,gecos,qtype)
  733.    char *name,*box,*gecos;
  734.    int qtype;
  735. {
  736.     struct mb_ent *me;
  737.     
  738.     me = (struct mb_ent*)htab_find(mb_tab,name);
  739.     if(!me) 
  740.     me = CreateMailBox(name);
  741.     if(qtype)
  742.     me->qtype = qtype;
  743.     if(box)
  744.     {
  745.     strncpy(me->mailbox,box,32);
  746.         if(!strncmp(name,box,32))
  747.         *me->mailbox = '\0'; /* Zeroing it. */
  748.     }
  749. /*
  750.  * This can have some size, and is probaly infrequent, so I malloc the space
  751.  */
  752.     if(gecos)
  753.     {
  754.     if(me->gecos) free(me->gecos); /* Previos stuff */
  755.     me->gecos = malloc(strlen(gecos) +1 );
  756.     strcpy(me->gecos,gecos);
  757.     }
  758. }
  759.  
  760. #ifdef EMULATE_HESIOD
  761. static void
  762. ChangeText(name,text,n)
  763.     char *name,*text;
  764.     int n;
  765. {
  766.     struct txt_ent *te;
  767.  
  768.     te = (struct txt_ent*)htab_find(txt_tab,name);
  769.     if(!te) 
  770.     {
  771.     te = (struct txt_ent*)malloc(sizeof(struct txt_ent));
  772.     strncpy(te->name,name,32);
  773.     htab_enter(txt_tab,te,te);
  774.     }
  775.     else
  776.     free(te->txt);
  777.     te->txt = malloc(n+1);
  778.     strncpy(te->txt,text,n);
  779.     te->txt[n] = '\0';
  780. }
  781. #endif /* EMULATE_HESIOD */
  782.  
  783. static void
  784. ChangeUGID(name,uid,gid)
  785.     char *name;
  786.     int uid,gid;
  787. {
  788.     struct mb_ent *me;
  789.     
  790.     me = (struct mb_ent*)htab_find(mb_tab,name);
  791.     if(!me) 
  792.     me = CreateMailBox(name);
  793.     if(gid != NOID) me->gid = gid;
  794.     if(uid != NOID) me->uid = uid;
  795. }
  796.  
  797. struct host_ent *
  798. CreateAddr(name)
  799.     char *name;
  800. {
  801.     struct host_ent *me;
  802.  
  803.     me = (struct host_ent *)malloc(sizeof(struct host_ent));
  804.     bzero(me,sizeof(struct host_ent));
  805.     strncpy(me->name,name,32);
  806.     VTableSet(&me->ipaddr,sizeof(struct host_ip));
  807.     VTableSet(&me->aliases,sizeof(struct host_ali));
  808.     htab_enter(host_tab,me,me);
  809.     return me;
  810. }
  811.  
  812. static void
  813. ChangeAddr(name,addr)
  814.     char *name;
  815.     int addr;
  816. {
  817.     struct host_ent *me;
  818.     struct host_ip ip,*hi;
  819.     int ix=0;
  820.  
  821. #if 0
  822. fprintf(stderr,"In ChangeAddr with %s\n",name);
  823. #endif
  824.     me = (struct host_ent*)htab_find(host_tab,name);
  825.     if(!me)
  826.        me = CreateAddr(name);
  827.     while(hi = (struct host_ip*)VTableNext(&me->ipaddr,&ix,1))
  828.     {
  829.        if(hi->addr == addr) return; /* Do not add same IP address twice */
  830.     }
  831.     ip.used = 0;
  832.     ip.addr = addr;
  833.     VTableAppend(&me->ipaddr,(char*)&ip);
  834. }
  835.  
  836. static void
  837. AddAlias(name,alias)
  838.     char *name;
  839.     char *alias;
  840. {
  841.     struct host_ent *me;
  842.     struct host_ali ali;
  843.  
  844. #if 0
  845. fprintf(stderr,"In AddAlias with %s\n",name);
  846. #endif
  847.     me = (struct host_ent*)htab_find(host_tab,name);
  848.     if(!me)
  849.        me = CreateAddr(name);
  850.     strncpy(ali.name,alias,32);
  851.     VTableAppend(&me->aliases,(char*)&ali);
  852. }
  853.  
  854. static void
  855. ChangeHInfo(name,mach,os)
  856.     char *name;
  857.     char *mach;
  858.     char *os;
  859. {
  860.     struct host_ent *me;
  861.     char *mmach;
  862.     char *mos;
  863.  
  864.     me = (struct host_ent*)htab_find(host_tab,name);
  865.     if(!me)
  866.     me = CreateAddr(name);
  867.     mmach = malloc(strlen(mach)+1);
  868.     mos = malloc(strlen(os)+1);
  869.     strcpy(mmach,mach);
  870.     strcpy(mos,os);
  871.  
  872.     me->ostype = mos;
  873.     me->machtype = mmach;
  874. }
  875.  
  876. struct minfo_ent *
  877. CreateMailList(name)
  878.    char *name;
  879. {
  880.     struct minfo_ent *me;
  881.  
  882.     me = (struct minfo_ent*)malloc(sizeof(struct minfo_ent));
  883.     bzero(me,sizeof(struct minfo_ent));
  884.     strncpy(me->name,name,32);
  885.     VTableSet(&me->table,sizeof(struct mg_ent));
  886.     htab_enter(mailtab,me,me);
  887.     return me;
  888. }
  889.  
  890. static void
  891. ChangeMailList(name,request,errors)
  892.    char *name,*request,*errors;
  893. {
  894.     struct minfo_ent *me;
  895.     
  896.     me = (struct minfo_ent*)htab_find(mailtab,name);
  897.     if(!me) 
  898.     me = CreateMailList(name);
  899.     if(request)
  900.     strncpy(me->request,request,32);
  901.     if(errors)
  902.     strncpy(me->errors,errors,32);
  903. }
  904.  
  905. static void
  906. AddMailListMember(name,member)
  907.     char *name,*member;
  908. {
  909.     struct minfo_ent *me;
  910.     struct mg_ent mg;
  911.     
  912.     me = (struct minfo_ent*)htab_find(mailtab,name);
  913.     if(!me) 
  914.     me = CreateMailList(name);
  915.     strncpy(mg.member,member,32);
  916.     VTableAppend(&me->table,(char*)&mg);
  917. }
  918.  
  919. PrintMailLists(file)
  920.     FILE    *file;
  921. {
  922.     int starting= TRUE;
  923.     int pos,first,mlen;
  924.     struct minfo_ent *me,*key;
  925.     struct mg_ent *mg;
  926.  
  927.     fprintf(file,"#\n# Maillists created by ns2tab\n#\n");
  928.     while(htab_list(mailtab,starting,&me,&key))
  929.     {
  930.     int ix=0;
  931.     int l,dnr;
  932.     struct mb_ent *mb;
  933.  
  934.     starting = FALSE;
  935.     if(VTableSize(&me->table) == 0)
  936.         continue;
  937.     fprintf(file,"\n"); /* Start each list with a newline */
  938.     if((mb = htab_find(mb_tab,me->name)) && mb->gecos)
  939.        fprintf(file,"# %s\n",mb->gecos); /* Get comment */
  940.     dnr =0;
  941.     if(*me->request)
  942.         fprintf(file,"%s-request: %s\n",me->name,me->request);
  943.     if(*me->errors)
  944.         fprintf(file,"owner-%s: %s\n",me->name,me->errors);
  945.     fprintf(file,"%s: ",me->name);
  946.     pos = strlen(me->name) +1;
  947.     mlen = pos;
  948.     first = TRUE;
  949.         while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
  950.     {
  951. /*
  952.  * Do not include a listmember with the same name as the list it self
  953.  */
  954.         if(!strcmp(me->name,mg->member)) continue;
  955.  
  956.         l = strlen(mg->member) + 2;
  957. /* I am told that because of restrictions in dbm an alias cannot contain
  958.    more than approximately 1000 bytes of information. So I create
  959.    dummy aliases.
  960. */
  961.         mlen += l;
  962.         if(mlen > 970)
  963.         {
  964.         if(!first) putc(',',file);
  965.         dnr++;
  966.         fprintf(file,"%s_%d,\n",me->name,dnr);
  967.         fprintf(file,
  968.     "# Dummy alias necesary because of restrictions in dbm(3x).\n");
  969.         fprintf(file,"%s_%d: %s",me->name,dnr,mg->member);
  970.         pos = strlen(me->name) + 4;
  971.         mlen = pos + l;
  972.         first = FALSE;
  973.         }
  974.         if((pos + l) > 76)
  975.         {
  976.         pos = l;
  977.         fprintf(file,",\n\t%s",mg->member);
  978.         }
  979.         else
  980.         {
  981.         pos += l;
  982.         if(!first) fprintf(file,", ");
  983.         first = FALSE;
  984.         fprintf(file,"%s",mg->member);
  985.         }
  986.     }
  987.     fprintf(file,"\n");
  988.     }
  989. }
  990.  
  991. PrintMailBoxes(file)
  992.     FILE    *file;
  993. {
  994.     int starting= TRUE;
  995.     struct mb_ent *me,*key;
  996.  
  997.     fprintf(file,"#\n# Mailboxes created by ns2tab\n#\n");
  998.     while(htab_list(mb_tab,starting,&me,&key))
  999.     {
  1000.     starting = FALSE;
  1001.     if(*me->mailbox)
  1002.     {
  1003.         if(me->gecos)
  1004.         fprintf(file,"# %s +- %s\n",me->name,me->gecos);
  1005.         fprintf(file,"%s: %s\n",me->name,me->mailbox);
  1006.     }
  1007.     }
  1008. }
  1009.  
  1010. PrintMail(file)
  1011.     FILE    *file;
  1012. {
  1013.     fprintf(file,"# Aliases created from [%s] nameserver.\n",
  1014.         (defaultPtr->addrList != NULL) ? defaultPtr->name :
  1015.          defaultPtr->servers[0]->name);
  1016.     PrintMailBoxes(file);
  1017.     PrintMailLists(file);
  1018.     return 0;
  1019. }
  1020.  
  1021.  
  1022. PrintElmLists(file)
  1023.     FILE    *file;
  1024. {
  1025.     int starting= TRUE;
  1026.     int pos,first,mlen;
  1027.     struct minfo_ent *me,*key;
  1028.     struct mg_ent *mg;
  1029.  
  1030.     fprintf(file,"#\n# Maillists created by ns2tab (ELM) Style\n#\n");
  1031.     while(htab_list(mailtab,starting,&me,&key))
  1032.     {
  1033.     int ix=0;
  1034.     int l,dnr;
  1035.     struct mb_ent *mb;
  1036.  
  1037.     starting = FALSE;
  1038.     if(VTableSize(&me->table) == 0)
  1039.         continue;
  1040.     fprintf(file,"\n"); /* Start each list with a newline */
  1041.     mb = htab_find(mb_tab,me->name); /* Get Comment */
  1042.     dnr =0;
  1043.     if(*me->request)
  1044.         if(lelmstyle)
  1045.         fprintf(file,"%s-request = %s Request = %s-request\n",
  1046.              me->name,me->name,me->name);
  1047.         else
  1048.         fprintf(file,"%s-request = %s Request = %s\n",
  1049.              me->name,me->name,me->request);
  1050.     if(*me->errors)
  1051.         if(lelmstyle)
  1052.         fprintf(file,"owner-%s = %s Errors = owner-%s\n",
  1053.              me->name,me->name,me->name);
  1054.         else
  1055.         fprintf(file,"owner-%s = %s Errors = %s\n",
  1056.              me->name,me->name,me->errors);
  1057.     if(mb && mb->gecos)
  1058.         fprintf(file,"%s = %s = ",me->name,mb->gecos);
  1059.     else
  1060.         fprintf(file,"%s = = ",me->name);
  1061. /*
  1062.  * Local elm doesn't define the members in a maillist, but lets
  1063.  * /usr/lib/aliases handle that part.
  1064.  */
  1065.     if(lelmstyle)
  1066.     {
  1067.         fprintf(file,"%s\n",me->name);
  1068.         continue;
  1069.     }
  1070.     pos = strlen(me->name) +1;
  1071.     mlen = pos;
  1072.     first = TRUE;
  1073.         while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
  1074.     {
  1075. /*
  1076.  * Do not include a listmember with the same name as the list itself
  1077.  */
  1078.         if(!strcmp(me->name,mg->member)) continue;
  1079.  
  1080.         l = strlen(mg->member) + 2;
  1081. #if 0
  1082. /* I am told that because of restrictions in dbm an alias cannot contain
  1083.    more than approximately 1000 bytes of information. So I create
  1084.    dummy aliases.
  1085. */
  1086.         mlen += l;
  1087.         if(mlen > 970)
  1088.         {
  1089.         if(!first) putc(',',file);
  1090.         dnr++;
  1091.         fprintf(file,"%s_%d\n",me->name,dnr);
  1092.         fprintf(file,
  1093.     "# Dummy alias necesary because of restrictions in dbm(3x).\n");
  1094.         fprintf(file,"%s_%d = = %s",me->name,dnr,mg->member);
  1095.         pos = strlen(me->name) + 4;
  1096.         mlen = pos + l;
  1097.         first = FALSE;
  1098.         }
  1099. #endif
  1100.         if((pos + l) > 76)
  1101.         {
  1102.         pos = l;
  1103.         fprintf(file,",\n   %s",mg->member);
  1104.         }
  1105.         else
  1106.         {
  1107.         pos += l;
  1108.         if(!first) fprintf(file,", ");
  1109.         first = FALSE;
  1110.         fprintf(file,"%s",mg->member);
  1111.         }
  1112.     } /* while */
  1113.     fprintf(file,"\n");
  1114.     } /* while */
  1115. }
  1116.  
  1117. PrintElmBoxes(file)
  1118.     FILE    *file;
  1119. {
  1120.     int starting= TRUE;
  1121.     struct mb_ent *me,*key;
  1122.  
  1123.     fprintf(file,"#\n# Mailboxes created by ns2tab (ELM style)\n#\n");
  1124.     while(htab_list(mb_tab,starting,&me,&key))
  1125.     {
  1126.     starting = FALSE;
  1127.     if(*me->mailbox)
  1128.     {
  1129.         if(lelmstyle)
  1130.         {
  1131.         if(me->qtype == T_MR)
  1132.             fprintf(file,"%s = = %s\n",me->name,me->mailbox);
  1133.         else
  1134.             if(me->gecos)
  1135.             fprintf(file,"%s = %s = %s\n"
  1136.             ,me->name,me->gecos,me->name);
  1137.         }
  1138.         else /* Elm style with no /usr/lib/aliases */
  1139.         {
  1140.         fprintf(file,"%s = %s = %s\n",me->name,
  1141.             (me->gecos)?me->gecos:"",me->mailbox);
  1142.         }
  1143.     }
  1144.     } /* while */
  1145. }
  1146.  
  1147. PrintElmish(file)
  1148.     FILE    *file;
  1149. {
  1150.     fprintf(file,"# Aliases created from [%s] nameserver.\n",
  1151.         (defaultPtr->addrList != NULL) ? defaultPtr->name :
  1152.          defaultPtr->servers[0]->name);
  1153.     PrintElmBoxes(file);
  1154.     PrintElmLists(file);
  1155.     return 0;
  1156. }
  1157.  
  1158. static void ExpandMember();
  1159.  
  1160. PrintGroupish(file)
  1161.     FILE    *file;
  1162. {
  1163.     int starting= TRUE;
  1164.     int first;
  1165.     struct minfo_ent *me,*key;
  1166.     struct mg_ent *mg;
  1167.  
  1168.     while(htab_list(mailtab,starting,&me,&key))
  1169.     {
  1170.     int ix=0;
  1171.     struct mb_ent *mb;
  1172.  
  1173.     starting = FALSE;
  1174.     if(!(mb = htab_find(mb_tab,me->name)))
  1175.        continue;  /* Ignore everything that doesn't have a MB */
  1176.     if(mb->gid == NOID)
  1177.        continue;  /* Ignore everything that doesn't have a GID */
  1178.     fprintf(file,"%s:*:%d:",me->name,mb->gid);
  1179.     first = TRUE;
  1180.     ExpandMember(file,me);
  1181.     fprintf(file,"\n");
  1182.     } /* while */
  1183. }
  1184.  
  1185. static void
  1186. ExpandMember(file,me)
  1187.     FILE *file;
  1188.     struct minfo_ent *me;
  1189. {
  1190.     struct mg_ent *mg;
  1191.  
  1192.     int first=TRUE;
  1193.     int ix=0;
  1194.     while(mg = (struct mg_ent*)VTableNext(&me->table,&ix,1))
  1195.     {
  1196.     int doprint = 1;
  1197.  
  1198.     if(!first) fprintf(file,",");
  1199.     first = FALSE;
  1200. /*
  1201.  * If we expand members, we must check them out. If a member has a UID
  1202.  * It should not be expanded.
  1203.  * Also, as an added security, if a member of a group has same
  1204.  * name the group it is not expanded.
  1205.  */
  1206.     if(recursegroup && strcmp(me->name,mg->member))
  1207.     {
  1208.         struct minfo_ent *mm;
  1209.         struct mb_ent *member;
  1210.  
  1211. /* Check too see if this is a MINFO */
  1212.         if(mm = htab_find(mailtab,mg->member))
  1213.         {
  1214.         member = htab_find(mb_tab,mg->member);
  1215.         if ((member && member->uid == NOID) || !member)
  1216.             if(VTableSize(&mm->table) != 0)
  1217.             {
  1218.             ExpandMember(file,mm);
  1219.             doprint = 0;
  1220.             }
  1221.         }
  1222.     }
  1223.     if(doprint)
  1224.         fprintf(file,"%s",mg->member);
  1225.     }
  1226. }
  1227.  
  1228. PrintHosts(file,domain)
  1229.     FILE    *file;
  1230.     char *domain;
  1231. {
  1232.     int starting= TRUE;
  1233.     int first;
  1234.     struct host_ent *host,*key;
  1235.  
  1236.     fprintf(file,"#\n# Hosttable - derived from ns2tab. Do not change\n#\n");
  1237. /*
  1238.  * Run through all the canonical names.
  1239.  */
  1240.     while(htab_list(host_tab,starting,&host,&key))
  1241.     {
  1242.     int aix,ix=0;
  1243.     struct host_ali *ha;
  1244.     struct host_ip *hi;
  1245.     char *punkt;
  1246.  
  1247.     starting = FALSE;
  1248.         while(hi = (struct host_ip*)VTableNext(&host->ipaddr,&ix,1))
  1249.     {
  1250.         aix=0;
  1251. #if 0
  1252.         fprintf(file,"%-15s %s.%s %s",inet_ntoa(ntohl(hi->addr)),
  1253.           host->name,vdomain,host->name);
  1254. #else
  1255.         fprintf(file,"%-15s %s",inet_ntoa(ntohl(hi->addr)),
  1256.           host->name);
  1257.         if(punkt = strchr(host->name,'.'))
  1258.         {
  1259.         *punkt = '\0';
  1260.         fprintf(file," %s",host->name);
  1261.         *punkt = '.';
  1262.         }
  1263. #endif
  1264.         while(ha = (struct host_ali*)VTableNext(&host->aliases,&aix,1))
  1265.         fprintf(file," %s",ha->name);
  1266.         if(host->machtype || host->ostype)
  1267.         fprintf(file,"\t#");
  1268.         if(host->machtype)
  1269.         fprintf(file," %s",host->machtype);
  1270.         if(host->ostype)
  1271.         fprintf(file," %s",host->ostype);
  1272.         fprintf(file,"\n");
  1273.     }
  1274.     }
  1275. }
  1276.  
  1277. #include <pwd.h>
  1278. PWUpd(file)
  1279.     FILE    *file;
  1280. {
  1281.     struct passwd *pw;
  1282.     struct mb_ent *mb;
  1283.     char *gecostmp;
  1284.  
  1285.     while(pw = getpwent())
  1286.     {
  1287.     gecostmp = pw->pw_gecos;
  1288.     if((mb = htab_find(mb_tab,pw->pw_name)) && mb->gecos)
  1289.         pw->pw_gecos = mb->gecos;
  1290.     putpwent(pw,file);
  1291.     pw->pw_gecos = gecostmp;
  1292.     }
  1293.     endpwent();
  1294. }
  1295.  
  1296. static
  1297. PrintElm(file)
  1298.     FILE    *file;
  1299. {
  1300.     lelmstyle=0;
  1301.     PrintElmish(file);
  1302. }
  1303.  
  1304. static
  1305. PrintLElm(file)
  1306.     FILE    *file;
  1307. {
  1308.     lelmstyle=1;
  1309.     PrintElmish(file);
  1310. }
  1311.  
  1312. static
  1313. PrintGroup(file)
  1314.     FILE    *file;
  1315. {
  1316.     recursegroup=1;
  1317.     PrintGroupish(file);
  1318. }
  1319.  
  1320. static
  1321. PrintNrGroup(file)
  1322.     FILE    *file;
  1323. {
  1324.     recursegroup=0;
  1325.     PrintGroupish(file);
  1326. }
  1327.  
  1328. static
  1329. PrintSubdomains(file)
  1330.     FILE    *file;
  1331. {
  1332.     struct ns_ent *ns;
  1333.     int ix = 0;
  1334.  
  1335.     while(ns = (struct ns_ent*)VTableNext(&subdomains,&ix,1))
  1336.     {
  1337.     printf("%-32s %s\n",ns->name,(ns->is_explicit)?"explicit":"implicit");
  1338.     }
  1339. }
  1340.  
  1341. #ifdef EMULATE_HESIOD
  1342. PrintPrintcap(file)
  1343.     FILE *file;
  1344. {
  1345.     int starting= TRUE;
  1346.     int first;
  1347.     struct txt_ent *name,*key;
  1348.  
  1349.     fprintf(file,"#\n# Printcap - derived from ns2tab. Do not change\n#\n");
  1350. /*
  1351.  * Run through all the canonical names.
  1352.  */
  1353.     while(htab_list(txt_tab,starting,&name,&key))
  1354.     {
  1355.     register char *p;
  1356.  
  1357.     starting = FALSE;
  1358. /*    fprintf(file,"%s",name->txt); */
  1359.     p = name->txt;
  1360.     while(*p)
  1361.     {
  1362.        putc(*p,file);
  1363.        if(*p == ':' && p[1] ) fprintf(file,"\\\n\t:");
  1364.        p++;
  1365.     }
  1366.     }
  1367.     return 0;
  1368. }
  1369.  
  1370. void (*printfunc)();
  1371.  
  1372. FilesysEngine(file)
  1373.     FILE *file;
  1374. {
  1375.     int starting= TRUE;
  1376.     int first;
  1377.     struct txt_ent *name,*key;
  1378. /*
  1379.  * Run through all the canonical names.
  1380.  */
  1381.     while(htab_list(txt_tab,starting,&name,&key))
  1382.     {
  1383.     int x;
  1384.     char fs_type[8];
  1385.     char name_on_server[128], server_hostname[128];
  1386.     char mount_mode[2],mount_point[128];
  1387.  
  1388.     starting = FALSE;
  1389.     x = sscanf(name->txt,"%s %s %s %s %s",
  1390.         fs_type,name_on_server,
  1391.         server_hostname,mount_mode,mount_point);
  1392.     if(x != 5) continue;
  1393.     (*printfunc)(file,fs_type,name_on_server,server_hostname,
  1394.           mount_mode,mount_point);
  1395.     }
  1396.     return 0;
  1397. }
  1398.  
  1399. void
  1400. FstabEntry(file,fs_type,name_on_server,server_hostname,mount_mode,mount_point)
  1401.     FILE *file;
  1402.     char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
  1403. {
  1404.     char *p;
  1405.     for(p = fs_type; *p; p++) *p = tolower(*p);
  1406.     fprintf(file,"%s@%s:%s:r%s:0:0:%s:hard,intr:\n",
  1407.     name_on_server,server_hostname,mount_point,
  1408.     mount_mode,fs_type);
  1409. }
  1410.  
  1411. PrintFstab(file)
  1412.     FILE *file;
  1413. {
  1414.     printfunc = FstabEntry;
  1415.     FilesysEngine(file);
  1416. }
  1417.  
  1418. /*
  1419.  * /etc/default/filesys format as seen on SCO unix.
  1420.  */
  1421. void
  1422. FilesysEntry(file,fs_type,name_on_server,server_hostname,mount_mode,mount_point)
  1423.     FILE *file;
  1424.     char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
  1425. {
  1426.     fprintf(file,"bdev=%s:%s mountdir=%s fsck=no rcfsck=no \\\n",
  1427.        server_hostname,name_on_server,mount_point);
  1428.     fprintf(file,"rcmount=yes mount=yes fstyp=%s nfsopts=\"hard,intr\"\n\n",
  1429.        fs_type);
  1430. }
  1431.  
  1432. PrintFilesys(file)
  1433.     FILE *file;
  1434. {
  1435.     printfunc = FilesysEntry;
  1436.     FilesysEngine(file);
  1437. }
  1438.  
  1439. void
  1440. ChecklistEntry(file,fs_type,
  1441.   name_on_server,server_hostname,mount_mode,mount_point)
  1442.     FILE *file;
  1443.     char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
  1444. {
  1445.     char *p;
  1446.     for(p = fs_type; *p; p++) *p = tolower(*p);
  1447.     fprintf(file,"%s:%s %s %s r%s,hard,intr 0 0 # loaded from ns2tab\n",
  1448.     server_hostname,name_on_server,mount_point,fs_type,mount_mode);
  1449. }
  1450.  
  1451. PrintChecklist(file)
  1452. {
  1453.     printfunc = ChecklistEntry;
  1454.     FilesysEngine(file);
  1455. }
  1456.  
  1457. void
  1458. VfstabEntry(file,fs_type,
  1459.   name_on_server,server_hostname,mount_mode,mount_point)
  1460.     FILE *file;
  1461.     char *fs_type,*name_on_server,*server_hostname,*mount_mode,*mount_point;
  1462. {
  1463.     char *p;
  1464.     for(p = fs_type; *p; p++) *p = tolower(*p);
  1465.     fprintf(file,"%s:%s - %s %s - yes r%s,hard,intr\n",
  1466.     server_hostname,name_on_server,mount_point,fs_type,mount_mode);
  1467. }
  1468.  
  1469. PrintVfstab(file)
  1470. {
  1471.     printfunc = VfstabEntry;
  1472.     FilesysEngine(file);
  1473. }
  1474.  
  1475. void
  1476. PrintPasswd(file)
  1477.     FILE *file;
  1478. {
  1479.     int starting= TRUE;
  1480.     int first;
  1481.     struct txt_ent *name,*key;
  1482.  
  1483.     while(htab_list(txt_tab,starting,&name,&key))
  1484.     {
  1485.     starting = FALSE;
  1486.     fprintf(file,"%s\n",name->txt);
  1487.     }
  1488. }
  1489. #endif /* EMULATE_HESIOD */
  1490.  
  1491. typedef int (*intfunc)();
  1492.  
  1493. struct stylerec {
  1494.      char *name;
  1495.      int  parselen;
  1496.      intfunc func;
  1497.      char *infix;
  1498. } Styles[] = {
  1499.     { "lelm",4,PrintLElm ,""},
  1500.     { "elm",3, PrintElm ,""},
  1501.     { "aliases",3, PrintMail ,""},
  1502.     { "group",3, PrintGroup ,""},
  1503.     { "nrgroup",3, PrintNrGroup ,""},
  1504.     { "pwupd",5, PWUpd ,""},
  1505.     { "hosts",5, PrintHosts ,""},
  1506.     { "subdomain",4,PrintSubdomains,""},
  1507. #ifdef EMULATE_HESIOD
  1508.     { "printcap",8,PrintPrintcap,"pcap"},
  1509.     { "fstab",5,PrintFstab,"filsys"},
  1510.     { "vfstab",5,PrintVfstab,"filsys"},
  1511.     { "filesys",7,PrintFilesys,"filsys"},
  1512.     { "checklist",6,PrintChecklist,"filsys"},
  1513.     { "passwd",7,PrintPasswd,"passwd"},
  1514. #endif /* EMULATE_HESIOD */
  1515. };
  1516.  
  1517. static intfunc stylefunc = PrintMail;
  1518.  
  1519. int
  1520. SetStyle(style)
  1521.     char *style;
  1522. {
  1523.     int x;
  1524.  
  1525.     for(x = 0; x < (sizeof(Styles)/sizeof(Styles[0])); x++)
  1526.     if(!strncmp(Styles[x].name,style,Styles[x].parselen))
  1527.     {
  1528.         stylefunc = Styles[x].func;
  1529. #ifdef EMULATE_HESIOD
  1530.         if(*Styles[x].infix)
  1531.         {
  1532.         char *v;
  1533.         v = malloc(strlen(vdomain) + strlen(Styles[x].infix) + 4);
  1534.         sprintf(v,"%s.%s",Styles[x].infix,vdomain);
  1535.         vdomain = v;
  1536.         }
  1537. #endif /* EMULATE_HESIOD */
  1538.         return 0;
  1539.     }
  1540.     fprintf(stderr,"Unimplemented style: %s\n",style);
  1541.     return -1;
  1542. }
  1543.  
  1544. extern int hasprinted;
  1545.  
  1546. PrintStyle(file)
  1547.     FILE *file;
  1548. {
  1549.     hasprinted = 1;
  1550.     (*stylefunc)(file);
  1551. }
  1552.