#include <stdio.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <ctype.h>

#define NOTOK -1
#define LINESIZE 256
#define FALSE 0
#define TRUE 1
#define MAXLINEARG 40

typedef struct 
    {
	char *domain;
	char *type;
	char *value;
    } DNSREC;

char				       /* character conversion table   */
	chrcnv[] =                     /*   lower to upper case letters */
{
    '\0', '\1', '\2', '\3', '\4', '\5', '\6', '\7',
    '\10', '\t', '\n', '\13', '\14', '\r', '\16', '\17',
    '\20', '\21', '\22', '\23', '\24', '\25', '\26', '\27',
    '\30', '\31', '\32', '\33', '\34', '\35', '\36', '\37',
    ' ', '!', '"', '#', '$', '%', '&', '\47',
    '(', ')', '*', '+', ',', '-', '.', '/',
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
    '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
    '\0', '\1', '\2', '\3', '\4', '\5', '\6', '\7',
    '\10', '\t', '\n', '\13', '\14', '\r', '\16', '\17',
    '\20', '\21', '\22', '\23', '\24', '\25', '\26', '\27',
    '\30', '\31', '\32', '\33', '\34', '\35', '\36', '\37',
    ' ', '!', '"', '#', '$', '%', '&', '\47',
    '(', ')', '*', '+', ',', '-', '.', '/',
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
    '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '{', '|', '}', '~', '\177'
};

DNSREC * parse_line();
char * dotted();
char * revdot();
char * appenddomain();
char * strdup();
char * normalize();


main (argc,argv)
int  argc;
char *argv[];
{ 
     
     DNSREC *rec;
     char input[LINESIZE];
     char defdom[LINESIZE];
     char *zone, *network;

     if (argc != 3) {
	printf("Usage: %s domain network\n",argv[0]);
	printf("Example: %s maine.edu 130.111\n",argv[0]);
	exit(1);
     }

     zone=appenddomain((argv[1]),"", (char *) 0); /* append dot and prime
						     default domain value */

     network=revdot(argv[2]);       /* flip the net number */

     while (fgets(input,LINESIZE,stdin) != NULL) {
	 if ((rec=parse_line(zone,input,defdom)) != (DNSREC *) 0)
	    print_ptr(rec->domain, network, rec->value);
     }
}


char *
revdot(instr)
char *instr;
{
    char *incopy;
    char *outstr;
    char *inargv[6];
    int inargc;

    incopy = strdup(instr);
    outstr = strdup(instr);  /* just allocate the right sized string */

    if ((inargc = cstr2arg(incopy, 6, inargv, '.')) == -1 ) {
        printf("Parse error in address specification: %s\n", instr);
	exit(1);
    }

    outstr[0]='\0'; /* empty the output string */
    for (;inargc > 0; inargc--) {
	strcat(outstr,inargv[inargc-1]);
	if (inargc > 1) strcat(outstr,".");
    }

    (void) free(incopy);

    return(outstr);
}


DNSREC
*parse_line(zone,line,defdom)
char *zone;
char *line;
char *defdom;
{

    static DNSREC rec;
    int lineargc;
    char linecopy[LINESIZE];
    char *lineargv[MAXLINEARG];
    int i,family;

    normalize(line,linecopy);  /* clean up line; strip comments */

    if ((lineargc = cstr2arg (linecopy, MAXLINEARG, lineargv, ' ')) == -1) {
        printf("Parse error on input line: %s", line);
        exit(1);
    }

    family = -1;
    for (i = 0; i < lineargc; i++) {
       if (!strcmp(lineargv[i],"IN") ||
	   !strcmp(lineargv[i],"in")) {
           family=i;
	   break;
       }
    }
    if (family == -1)
	return((DNSREC *) 0);

    switch (family) {
        case 0: rec.domain = zone;
		break;
	case 1: if (isdigit(*lineargv[0]))
		    rec.domain = defdom;
		else
		    rec.domain = appenddomain(lineargv[0],zone,defdom);
		break;
	case 2: rec.domain = appenddomain(lineargv[0],zone,defdom);
		break;
    }
    if (strcmp(lineargv[family+1],"A") &&
	strcmp(lineargv[family+1],"a"))
	return ((DNSREC *) 0);

    rec.value = lineargv[family+2];
 
    return(&rec);    
}

char *
appenddomain(pre,post,def)
char *pre;
char *post;
char *def;
{
    char str[LINESIZE];
    char *newstr;

    if (*pre == '@')
	newstr=dotted(post);  /* use current zone */
    else if (*pre == '.')
	if (def)                /* use current default */
	    newstr = dotted(def);
	else
	    newstr = (char *) 0;
    else {
        (void) sprintf(str,"%s.%s",pre,post);
        newstr = dotted(str);
    }
    if (def)
        (void) strcpy(def,newstr);  /* save new default */
    return (newstr);
}

char *
       dotted(ptr)
register char *ptr;
{
     extern char *malloc();
     register char *newptr,
	           *newstr;

     if (*(ptr+strlen(ptr)-1) == '.')
	return(strdup(ptr));
     else {
	if ((newstr = malloc ((unsigned) (strlen (ptr) + 2))) == 0)
	    return ( (char *) 0);

	for (newptr = newstr; *newptr++ = *ptr++; );
	
	*(newptr-1) = '.';
	*newptr = '\0';

	return (newstr);
    }
}

print_ptr(dom,net,val)
char *dom;
char *net;
char *val;
{
    char *tmp;
    int col;

    tmp=revdot(val);

    /* print if the right network */
    if ((col = strindex(net,tmp)) > 0 ) { 
         tmp[col-1] = '\0';  /* truncate at the dot before the net num */
         printf ("%s\tin\tptr\t%s\n", tmp, dom);
    }

    (void) free(tmp);     
}

/*  convert string into argument list
 *
 *  stash a pointer to each field into the passed array.
 *  any common seperators split the words.  extra white-space
 *  between fields is ignored.
 *
 *  if the separator is '=', then the current argument position in
 *  the array points to "=", the next the one is the key and the
 *  value follows it.  This permits detecting variable assignment,
 *  in addition to positional arguments.
 *      i.e.,  key=value ->  = key value
 *
 *  specially-interpreted characters:
 *      space, tab, double-quote, backslash, comma, equal, slash, period,
 *      semi-colon, colon, carriage return, and line-feed (newline).
 *      preceding a special char with a backslash removes its
 *      interpretation.  a backslash not followed by a special is used
 *      to preface an octal specification for one character
 *
 *      a string begun with double-quote has only double-quote and
 *      backslash as special characters.
 *
 *  a field which begins with semi-colon is interpreted as marking the
 *  rest of the line as a comment and it is skipped, as are blank lines
 */


/* Steve Kille
 * Modified version, which splits a string given a specific
 * separator
 */

extern int errno;

cstr2arg (srcptr, max, argv, dlmchar)/* convert srcptr to argument list */
	register char *srcptr;  /* source data */
	int max;                /* maximum number of permitted fields */
	char *argv[];           /* where to put the pointers */
	char dlmchar;           /* Delimiting character */
{
    char gotquote;      /* currently parsing quoted string */
    register int ind;
    register char *destptr;

    if (srcptr == 0)
    {
	errno = EINVAL;     /* emulate system-call failure */
	return (NOTOK);
    }

    for (ind = 0, max -= 2;; ind++)
    {
	if (ind >= max)
	{
	    errno = E2BIG;      /* emulate system-call failure */
	    return (NOTOK);
	}

	argv [ind] = srcptr;
	destptr = srcptr;

/**/

	for (gotquote = FALSE; ; )
	{
	    if (*srcptr == dlmchar)
	    {
		if (gotquote)
		{           /* don't interpret the char */
		    *destptr++ = *srcptr++;
		    continue;
		}

		srcptr++;
		*destptr = '\0';
		goto nextarg;
	    }
	    else
	    {
		switch (*srcptr)
		{
		    default:        /* just copy it                     */
			*destptr++ = *srcptr++;
			break;

		    case '\"':      /* beginning or end of string       */
			gotquote = (gotquote) ? FALSE : TRUE;
			srcptr++;   /* just toggle */
			break;

		    case '\\':      /* quote next character             */
			srcptr++;   /* just skip the back-slash         */
			if (*srcptr >= '0' && *srcptr <= '7')
			{
				*destptr = '\0';
				do
				    *destptr = (*destptr << 3) | (*srcptr++ - '0');
				while (*srcptr >= '0' && *srcptr <= '7');
				destptr++;
				break;
			}    /* otherwise DROP ON THROUGH */
			else
			     *destptr++ = *srcptr++;
			break;


		    case '\0':
			*destptr = '\0';
			ind++;
			argv[ind] = (char *) 0;
			return (ind);
		}
	    }
	}
    nextarg:
	continue;
    }
}

    
strindex (str, target)           /* return column str starts in target */
register char   *str,
		*target;
{
    char *otarget;
    register short slen;

    for (otarget = target, slen = strlen (str); ; target++)
    {
	if (*target == '\0')
	    return (-1);

	if (equal (str, target, slen))
	    return (target - otarget);
    }
}

/*
 * equal(s1, s2, n)-- compare two strings to see if they're equiv, but
 *			constrain ourselves to equal length strings.
 *
 * If both strings end at the same position and were equivalent for all
 * previous characters, then return TRUE.
 *
 * If both strings are equivalent for their first n characters,
 * then return TRUE.
 *
 * ELSE
 *
 * return FALSE.
 *
 * If n <= 0 then ignore the second condition above.
 *
 * IMPROVEMENT: sanity checks arguments to see if they're good strings.
 *		stops at the end of either string
 *		the n <= 0 thing is an added flexibility
 */
equal(str1, str2, n)
register char *str1, *str2;
int n;
{
	register	int	cnt;

	if (str1 == 0 || str2 == 0)
		return(str1 == str2);

	for (cnt = 1; chrcnv[*str1] == chrcnv[*str2]; str1++, str2++) {

		/*** A string ended. ***/
		if ((*str1 == 0)||(*str2 == 0)) {
			if ((*str1 == 0)&&(*str2 == 0))
				return(TRUE);
			else
				return(FALSE);
		}

		/*** Are they equiv for the first n(n>0)characters? ***/
		cnt++;
		if ((n > 0) && (cnt > n))
			return(TRUE);
	}

	return(FALSE);
}

/*                                                                      */
/*      Create a duplicate copy of the given string.                    */
/*      Modified for V7 Unix by Jim lieb SRI International Aug 80       */

char *
	strdup (str)
register char   *str;
{
    extern char *malloc ();
    register char  *newptr,
		   *newstr;

    if ((newstr = malloc ((unsigned) (strlen (str) + 1))) == 0)
	return ((char *) 0);

    for (newptr = newstr; *newptr++ = *str++; );

    return (newstr);
}

/* compress-out redundant linear white space & strip trailing lwsp */
/* and convert remaining white space to spaces */

char *
	normalize (fromptr, toptr)
register char *fromptr,
	      *toptr;
{
    register char   chr;

    chr = ' ';                    /* init to skip leading spaces  */
    while ((*toptr = *fromptr++) != '\0')
    {                           
	if (isspace (*toptr))
	    if (chr == ' ')
	       continue;
	    else
   	       *toptr = ' ';         /* save only first wsp (as a space) */

	if (*toptr == ';') {         /* stop at beginning of comment */
	    *toptr = '\0';
	    break;
	}
	chr = *toptr++;
    }

    if (chr == ' ')               /* remove trailing space if any */
	*--toptr = '\0';
    return (toptr);
}
