/*
* dnsutl - utilities to make DNS easier to configure
* Copyright (C) 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/ctype.h>
#include <ac/string.h>
#include <error.h>
#include <mem.h>
#include <srrf.h>
#include <srrf/origin.h>
static int
needs_quoting(string_ty *sp)
{
char *s;
s = sp->str_text;
while (*s)
{
if (!isprint(*s) || isspace(*s) || strchr("\"\\();", *s))
return 1;
++s;
}
return 0;
}
static string_ty *
quote(string_ty *sp)
{
static char *buffer;
static size_t max;
static size_t pos;
char *bp;
char *s;
pos = sp->str_length * 4 + 2;
if (max < pos)
{
max = pos;
buffer = mem_change_size(buffer, max);
}
bp = buffer;
*bp++ = '"';
s = sp->str_text;
while (*s)
{
int c = (unsigned char)*s++;
if (isprint(c))
{
if (strchr("\"\\", c))
*bp++ = '\\';
*bp++ = c;
}
else
{
/* Sigh. rfc1035 says decimal */
sprintf(bp, "\\%03d", c);
bp += 4;
}
}
*bp++ = '"';
return str_n_from_c(buffer, bp - buffer);
}
static int
srrf_print_generic(srrf_t *rp, FILE *fp)
{
int col;
string_ty *tmp;
const char *tmp2;
size_t j;
int nlines;
int pos;
int single_line;
/*
* print the name
*/
nlines = 1;
col = 0;
if (rp->name)
{
fprintf(fp, "%s", rp->name->str_text);
col += rp->name->str_length;
}
/*
* print the time to live
*/
if (rp->ttl)
{
char ttl[30];
if (col < 8)
{
while (col < 8)
{
putc(' ', fp);
++col;
}
}
else
{
fprintf(fp, " ");
col++;
}
sprintf(ttl, "%ld", rp->ttl);
fprintf(fp, "%s", ttl);
col += strlen(ttl);
}
/*
* print the class
*/
tmp2 = rp->class->name;
if (col >= 16)
{
fprintf(fp, " ");
col++;
}
else
{
while (col < 16)
{
putc(' ', fp);
++col;
}
}
fprintf(fp, "%s", tmp2);
col += strlen(tmp2);
/*
* print the type
*/
tmp2 = rp->type->name;
if (col >= 24)
{
fprintf(fp, " ");
col++;
}
else
{
while (col < 24)
{
putc(' ', fp);
++col;
}
}
fprintf(fp, "%s", tmp2);
col += strlen(tmp2);
/*
* print the other stuff
*/
if (rp->arg.nstrings)
{
if (col >= 32)
{
fprintf(fp, " ");
col++;
}
else
{
while (col < 32)
{
putc(' ', fp);
++col;
}
}
/*
* see if we need separate line for each entry
*/
pos = col;
for (j = 0; j < rp->arg.nstrings; ++j)
{
if (j)
++pos;
tmp = rp->arg.string[j];
if (needs_quoting(tmp))
tmp = quote(tmp);
else
tmp = str_copy(tmp);
pos += tmp->str_length;
str_free(tmp);
}
single_line = (rp->arg.nstrings < 2) || (pos <= 80);
if (!single_line)
fprintf(fp, "("/*)*/);
for (j = 0; j < rp->arg.nstrings; ++j)
{
if (single_line)
{
if (j)
{
fprintf(fp, " ");
col++;
}
}
else
{
if (!j)
fprintf(fp, " ");
else
{
putc('\n', fp);
col = 0;
++nlines;
while (col < 32)
{
putc(' ', fp);
++col;
}
}
}
tmp = rp->arg.string[j];
if (needs_quoting(tmp))
tmp = quote(tmp);
else
tmp = str_copy(tmp);
fprintf(fp, "%s", tmp->str_text);
col += tmp->str_length;
str_free(tmp);
}
if (!single_line)
fprintf(fp, " )");
}
/*
* done
*/
fprintf(fp, "\n");
return nlines;
}
int
srrf_print(FILE *fp, srrf_t *rp)
{
srrf_t *relative;
int nlines;
size_t j;
static string_ty *prev_name;
/*
* create a bogus relative row
*/
relative = srrf_alloc();
if (rp->name)
relative->name = srrf_absolute_to_relative(rp->name);
relative->ttl = rp->ttl;
assert(rp->class);
relative->class = rp->class;
assert(rp->type);
relative->type = rp->type;
for (j = 0; j < rp->arg.nstrings; ++j)
strlist_append(&relative->arg, rp->arg.string[j]);
if (rp->file_name)
relative->file_name = str_copy(rp->file_name);
relative->line_number = rp->line_number;
if (relative->type->abs_to_rel)
relative->type->abs_to_rel(relative);
if (prev_name && str_equal(relative->name, prev_name))
{
str_free(relative->name);
relative->name = 0;
}
/*
* print the row in a special way, if specified
*/
if (relative->type->print)
nlines = relative->type->print(relative, fp);
else
nlines = srrf_print_generic(relative, fp);
/*
* clean up and go home
*/
if (relative->name)
{
if (prev_name)
str_free(prev_name);
prev_name = str_copy(relative->name);
}
srrf_free(relative);
return nlines;
}
syntax highlighted by Code2HTML, v. 0.9.1