/*
 * dnsutl - utilities to make DNS easier to configure
 * Copyright (C) 1991-1993, 1995, 1996, 1999, 2006, 2007 Peter Miller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include <ac/stdio.h>
#include <ac/string.h>

#include <arglex.h>
#include <error.h>
#include <hosts.h>
#include <mem.h>
#include <srrf/reader.h>
#include <symtab.h>

int             verbose;
int             delete_foreign_names;


static string_ty *
first_part(string_ty *s)
{
    char            *dot;

    dot = strchr(s->str_text, '.');
    if (!dot)
        return str_from_c("");
    return str_n_from_c(s->str_text, dot - s->str_text);
}


static string_ty *
no_trailing_dot(string_ty *s)
{
    if (s->str_length < 2 || s->str_text[s->str_length - 1] != '.')
        return str_copy(s);
    return str_n_from_c(s->str_text, s->str_length - 1);
}


static void
cname_reap(void *p)
{
    strlist_ty      *slp;

    slp = p;
    strlist_free(p);
    mem_free(p);
}


void
hosts(const char *infile, const char *outfile)
{
    FILE            *fp;
    srrf_t          *rp;
    srrf_list_ty    *rlp;
    size_t          j, k;
    srrf_t          *kp;
    string_ty       *tmp;
    string_ty       *tmp2;
    srrf_class_ty   *in_class;
    srrf_type_ty    *in_hinfo_type;
    srrf_type_ty    *in_cname_type;
    srrf_type_ty    *in_a_type;
    symtab_ty       *hinfo_stp;
    symtab_ty       *cname_stp;
    strlist_ty      *slp;

    /*
     * find the magic stuff
     */
    in_class = srrf_class_by_name("in");
    assert(in_class);
    in_hinfo_type = srrf_type_by_name(in_class, "hinfo");
    assert(in_hinfo_type);
    in_cname_type = srrf_type_by_name(in_class, "cname");
    assert(in_cname_type);
    in_a_type = srrf_type_by_name(in_class, "a");
    assert(in_a_type);

    /*
     * read the input file
     */
    rlp = srrf_reader(infile, verbose, delete_foreign_names);

    /*
     * remember cname and hinfo records
     */
    hinfo_stp = symtab_alloc(5);
    cname_stp = symtab_alloc(5);
    cname_stp->reap = cname_reap;
    for (j = 0; j < rlp->nrecords; ++j)
    {
        rp = rlp->record[j];

        if (rp->type == in_hinfo_type)
            symtab_assign(hinfo_stp, rp->name, rp);
        if (rp->type == in_cname_type)
        {
            slp = symtab_query(cname_stp, rp->arg.string[0]);
            if (!slp)
            {
                slp = mem_alloc(sizeof(strlist_ty));
                strlist_zero(slp);
                symtab_assign(cname_stp, rp->arg.string[0], slp);
            }
            strlist_append_unique(slp, rp->name);
        }
    }

    /*
     * open the output file
     */
    if (outfile)
    {
        fp = fopen(outfile, "w");
        if (!fp)
            nfatal("creat \"%s\"", outfile);
    }
    else
    {
        outfile = "(stdout)";
        fp = stdout;
    }

    /*
     * warning comment at the top of the file
     */
    fprintf(fp, "# Do not edit this file.  It is generated\n");
    fprintf
    (
        fp,
        "# using a '%s %s %s' command.\n",
        progname,
        (infile ? infile : "-"),
        (fp == stdout ? "-" : outfile)
    );

    /*
     * scan the resources looking for hosts
     */
    for (j = 0; j < rlp->nrecords; ++j)
    {
        rp = rlp->record[j];
        if (rp->type != in_a_type)
            continue;

        /*
         * Print the address and the name.
         * Given the fully qualified domain name as an alias.
         */
        tmp = first_part(rp->name);
        fprintf(fp, "%s %s", rp->arg.string[0]->str_text, tmp->str_text);
        tmp2 = no_trailing_dot(rp->name);
        if (!str_equal(tmp, tmp2))
        {
            fprintf(fp, " %s", tmp2->str_text);
        }
        str_free(tmp);
        str_free(tmp2);

        /*
         * search for aliases
         */
        slp = symtab_query(cname_stp, rp->name);
        if (slp)
        {
            for (k = 0; k < slp->nstrings; ++k)
            {
                string_ty       *name;

                name = slp->string[k];
                tmp = first_part(name);
                    fprintf(fp, " ");
                fprintf(fp, "%s", tmp->str_text);
                tmp2 = no_trailing_dot(name);
                if (!str_equal(tmp, tmp2))
                    fprintf(fp, " %s", tmp2->str_text);
                str_free(tmp);
                str_free(tmp2);
            }
        }

        /*
         * search for host info
         */
        kp = symtab_query(hinfo_stp, rp->name);
        if (kp)
        {
            fprintf
            (
                fp,
                " # %s, %s",
                kp->arg.string[0]->str_text,
                kp->arg.string[1]->str_text
            );
        }

        fprintf(fp, "\n");
    }
    symtab_free(hinfo_stp);
    symtab_free(cname_stp);
    srrf_list_free(rlp);

    /*
     * close the output file
     */
    if (fflush(fp))
        nfatal("write \"%s\"", outfile);
    if (fp != stdout && fclose(fp))
        nfatal("close \"%s\"", outfile);
}


syntax highlighted by Code2HTML, v. 0.9.1