ncohafmuta-1.4.2/bot/
ncohafmuta-1.4.2/helpfiles/
ncohafmuta-1.4.2/lib/emailver/
ncohafmuta-1.4.2/tzinfo/Atlantic/
ncohafmuta-1.4.2/tzinfo/Brazil/
ncohafmuta-1.4.2/tzinfo/Chile/
ncohafmuta-1.4.2/tzinfo/Indian/
ncohafmuta-1.4.2/tzinfo/Mexico/
ncohafmuta-1.4.2/tzinfo/Mideast/
ncohafmuta-1.4.2/tzinfo/SystemV/
ncohafmuta-1.4.2/utils/
ncohafmuta-1.4.2/utils/code_fragments/new_config/
/* Some of the utility functions are straight from the Bind source */

#if defined(HAVE_CONFIG_H)
#include "../hdrfiles/config.h"
#endif

#include "../hdrfiles/includes.h"

#if defined(HAVE_NAMESER_H)
#include <nameser.h>
#elif defined(HAVE_ARPA_NAMESER_H)
#include <arpa/nameser.h>
#else
#include "../hdrfiles/nameser.h"
#endif

#if defined(HAVE_RESOLV_H)
#include <resolv.h>
#elif defined(HAVE_ARPA_RESOLV_H)
#include <arpa/resolv.h>
#else
#include "../hdrfiles/resolv.h"
#endif

/* LOGFILE should be the only thing you have to set, if deviating from */
/* the normal directory structure */
#define LOGFILE		"logfiles/resolve.log"

#define FCLOSE(file) if (file) fclose(file)

#define RESOLVELOG	1
#define YESTIME	1
#define NOTIME	0
#define FILE_NAME_LEN 256

#if !defined(NS_INT32SZ)
#define NS_INT32SZ      4       /* #/bytes of data in a u_int32_t */
#endif
#if !defined(MAXCDNAME)
#define MAXCDNAME	255
#endif
#if !defined(NS_MAXCDNAME)
#define NS_MAXCDNAME MAXCDNAME
#endif
#if !defined(NS_CMPRSFLGS)
#define NS_CMPRSFLGS    0xc0    /* Flag bits indicating name compression. */
#endif

#define _DEFINING_OSDEFS
#include "../hdrfiles/osdefs.h"
#include "../hdrfiles/resolver_clipon.h"
/* #define _DEFINING_CONSTANTS */
/* #include "../hdrfiles/constants.h" */

RETSIGTYPE handle_sig(int sig);
handler_t setsignal(int sig, handler_t handler);
/* RETSIGTYPE (*setsignal(int, RETSIGTYPE (*)(int)))(int); */

#if defined(OPENBSD_SYS)
/* our own ctime because the one in OpenBSD behaves badly */
char *ctime(const time_t *mytm);
#endif

int SHUTDOWN(int sock, int how);

#define MAXALIASES		35
#define MAXADDRS		35
#define MSGSIZ			512
#define NS_INT16SZ      2       /* #/bytes of data in a u_int16_t */

#define HAVE_GET16
#define HAVE_GET32
#define HAVE_PUT16
#define HAVE_PUT32

u_int my_ns_get16(u_char *src);
#if !defined(NS_GET16)
#define NS_GET16(s, cp) do { \
        register u_char *t_cp = (u_char *)(cp); \
        (s) = ((unsigned short)t_cp[0] << 8) \
            | ((unsigned short)t_cp[1]) \
            ; \
        (cp) += NS_INT16SZ; \
} while (0)
#undef HAVE_GET16
#endif

u_long my_ns_get32(u_char *src);
#if !defined(NS_GET32)
#define NS_GET32(l, cp) do { \
        register u_char *t_cp = (u_char *)(cp); \
        (l) = ((u_int32_t)t_cp[0] << 24) \
            | ((u_int32_t)t_cp[1] << 16) \
            | ((u_int32_t)t_cp[2] << 8) \
            | ((u_int32_t)t_cp[3]) \
            ; \
        (cp) += NS_INT32SZ; \
} while (0)
#undef HAVE_GET32
#endif

void my_putshort(unsigned short src, u_char *dst);
void my_ns_put16(u_int src, u_char *dst);
#if !defined(NS_PUT16)
#define NS_PUT16(s, cp) do { \
        register unsigned short t_s = (unsigned short)(s); \
        register u_char *t_cp = (u_char *)(cp); \
        *t_cp++ = t_s >> 8; \
        *t_cp   = t_s; \
        (cp) += NS_INT16SZ; \
} while (0)
#undef HAVE_PUT16
#endif

#if !defined(NS_PUT32)
#define NS_PUT32(l, cp) do { \
        register u_int32_t t_l = (u_int32_t)(l); \
        register u_char *t_cp = (u_char *)(cp); \
        *t_cp++ = t_l >> 24; \
        *t_cp++ = t_l >> 16; \
        *t_cp++ = t_l >> 8; \
        *t_cp   = t_l; \
        (cp) += NS_INT32SZ; \
} while (0)
void putlong(u_int32_t src, u_char *dst);
void ns_put32(u_long src, u_char *dst);
#undef HAVE_PUT32
#endif

#if !defined(BOUNDS_CHECK)
#define BOUNDS_CHECK(ptr, count) \
        do { \
                if ((ptr) + (count) > eom) { \
                        write_log(RESOLVELOG,NOTIME,"(form error.)\n"); \
                        return (NULL); \
                } \
        } while (0)
#endif

#define MATCH(line, name) \
        (!strncmp(line, name, sizeof(name) - 1) && \
        (line[sizeof(name) - 1] == ' ' || \
         line[sizeof(name) - 1] == '\t'))

void write_log(int type, int wanttime, char *str, ...);
void remove_first(char *inpstr);
void handle_sig(int sig);
void init_structs(int slot);
void process_result(int slot);
void my_print_query(u_char *msg, u_char *eom);
void midcpy(char *strf, char *strt, int fr, int to);
int write_stdout(char *msg);
int get_slot(int fd);
int find_free_ns_slot(void);
int find_user_slot(int user, char *site);
int read_result(int slot);
int start_query(int slot, char *ipaddy);
int restart_query(int slot);
char *Calloc(register int num, register int size);
char *Malloc(int size);
char *get_time(time_t ref,int mode);
char *get_error(void);
char *my_p_type(int mytype);
char *my_p_class(int myclass);
char *my_p_rcode(int myrcode);
char *get_ip(unsigned long addr);

const char *_res_opcodes[] = {
        "QUERY",
        "IQUERY",
        "CQUERYM",
        "CQUERYU",      /* experimental */
        "NOTIFY",       /* experimental */
        "UPDATE",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12",
        "13",
        "ZONEINIT",
        "ZONEREF",
};

#if !defined(HAVE_RES_NMKQUERY) && defined(CYGWIN_SYS)
 struct __res_state _res;
#else
#if !(defined(BSD) && (BSD >= 199103)) && !defined(OSF_SYS) && !defined(HPUX_SYS)
# if (!defined(__RES)) || (__RES < 19940415)
#  ifdef SCOR5
        extern struct __res_state       _res;
#  else
        extern struct state         _res;
#  endif
# endif
#endif
#endif
/*
struct __res_state _res;
*/
#if defined(WHICH_RES_STATE)
#define _my_res WHICH_RES_STATE()
#else
# if !defined(HAVE_RES_NMKQUERY)
#  define _my_res _res
# else
#  define _my_res &_res
# endif
#endif

int res_mkquery(int op,                     /* opcode of query */
            const char *dname,          /* domain name */
            int class, int type,        /* class and type of query */
            const u_char *data,         /* resource record data */
            int datalen,                /* length of data */
            const u_char *newrr_in,     /* new rr for modify or append */
            u_char *buf,                /* buffer to put query */
            int buflen);                 /* size of buffer */
#if !defined(HAVE_RES_NMKQUERY)
int res_nmkquery(struct __res_state statp,
             int op,                    /* opcode of query */
             const char *dname,         /* domain name */
             int class, int type,       /* class and type of query */
             const u_char *data,        /* resource record data */
             int datalen,               /* length of data */
             const u_char *newrr_in,    /* new rr for modify or append */
             u_char *buf,               /* buffer to put query */
             int buflen);               /* size of buffer */
#endif
static int dn_find(const u_char *domain, const u_char *msg,
        const u_char * const *dnptrs,
        const u_char * const *lastdnptr);
int dn_comp(const char *src, u_char *dst, int dstsiz,
 	u_char **dnptrs, u_char **lastdnptr);
int dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
          char *dst, int dstsiz);
int dn_skipname(const u_char *ptr, const u_char *eom);
int ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
                 const u_char **dnptrs, const u_char **lastdnptr);
int ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
                   char *dst, size_t dstsiz);
int ns_name_skip(const u_char **ptrptr, const u_char *eom);
int ns_name_pton(const char *src, u_char *dst, size_t dstsiz);
int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz);
int ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
             const u_char **dnptrs, const u_char **lastdnptr);
int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
               u_char *dst, size_t dstsiz);
u_char *Print_cdname(const u_char *cp, const u_char *msg, const u_char *eom);
u_char *Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom);

static int special(int ch);
static int printable(int ch);
static int mklower(int ch);
void __h_errno_set(struct __res_state *res, int err);
#define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x)

typedef int Boolean;
unsigned short nsport = NAMESERVER_PORT;

unsigned long naddy        = 0;
unsigned long second_naddy = 0;
unsigned long third_naddy  = 0;
unsigned long ftemp        = 0;
int number_of_servers      = 0;
static const char digits[] = "0123456789";
static u_char  hostbuf[MAXDNAME];

/*    u_char qb2[64*1024]; */
typedef union {
    HEADER qb1;
    u_char qb2[256];
} querybuf;

struct {
	int fd;
	int user;
	int status;
	int result;
	int buflen;
	int tries;
	unsigned long nameserver;
	char site[21];
	char hostname[64];
	char badlookup[64];
	querybuf buf;
	querybuf answer;
	time_t starttime;
} resolves[MAX_RESOLVES_IN_PROGRESS];

typedef union {
    int32_t al;
    char ac;
} align;

#define GetShort(cp)    my_ns_get16(cp); cp += INT16SZ;
#define GetLong(cp)     my_ns_get32(cp); cp += INT32SZ;

/*
 * Modified struct hostent from <netdb.h>
 *
 * "Structures returned by network data base library.  All addresses
 * are supplied in host order, and returned in network order (suitable
 * for use in system calls)."
 */

int             queryType = T_PTR;
int             queryClass = C_IN;
char		mess[256];
char nameserver[21];
char second_nameserver[21];
char third_nameserver[21];
char temp_nameserver[21];

int main(void) {
int ret=0, slot=-1, i=0, suspended=0, user;
static int nfds;
long len;
char action[5];
char site[21];
char buffer[BUFSIZ];
char s[BUFSIZ];
fd_set fds_read;
fd_set fds_write;
struct timeval timeout;  /* how much time to give select() */
FILE *fp;

/* 066 will make permissions -rw------- This is the default */
/* 006 will make permissions -rw-rw---- Use this is you need the group
   to have the same permissions as the user. i.e. on talker.com */
#if defined(HAVE_UMASK)
umask(066);
#endif

	/* tell talker we are alive! */
        write_stdout(RESOLVER_SERVER_CONNECT_MSG);

	/* set up signals */
        (void)setsignal(SIGTERM, handle_sig);
        (void)setsignal(SIGSEGV, handle_sig);
	(void)setsignal(SIGBUS, handle_sig);
	(void)setsignal(SIGILL, handle_sig);
	(void)setsignal(SIGABRT, handle_sig);
	(void)setsignal(SIGSTOP, handle_sig);
	(void)setsignal(SIGINT, handle_sig);
        (void)setsignal(SIGPIPE, handle_sig);
        (void)setsignal(SIGCHLD, handle_sig);

/* get name server addys */
if (USE_FALLBACK_AS_DEFAULT > 0) {
                strcpy(nameserver,FALLBACK_DNS_SERVER);
                if((naddy = inet_addr(nameserver)) == -1L) { nameserver[0]=0; }
		else number_of_servers++;
}

        if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
            /* read the config file */
            while (fgets(buffer, sizeof(buffer), fp) != NULL) {
		buffer[strlen(buffer)-1]=0; /* strip newline */
                /* skip comments */
                if (*buffer == ';' || *buffer == '#')
                        continue;
                /* read default domain name */
                if (MATCH(buffer, "nameserver") && number_of_servers != 3) {
			for (i=10;i<strlen(buffer);++i) {
				if (isalnum((int)buffer[i])) break;
			}
			midcpy(buffer,temp_nameserver,i,i+20);

			  ftemp=0;
			  ftemp = inet_addr(temp_nameserver);
			  if (ftemp == -1L) {
			   ftemp=0;
			  }
			  else {
			   if (number_of_servers==0) {
			    naddy = ftemp;
			    strcpy(nameserver,temp_nameserver);
			    number_of_servers++;
			   } /* if 0 */
			   else if (number_of_servers==1) {
			    second_naddy = ftemp;
			    strcpy(second_nameserver,temp_nameserver);
			    number_of_servers++;
			   } /* if 1 */
			   else if (number_of_servers==2) {
			    third_naddy = ftemp;
			    strcpy(third_nameserver,temp_nameserver);
			    number_of_servers++;
			   } /* if 2 */
			  } /* else */
		} /* if match */
	} /* end of while */
	FCLOSE(fp);
	}
	else {
		strcpy(nameserver,FALLBACK_DNS_SERVER);
		if((naddy = inet_addr(nameserver)) == -1L) return 0;
		else number_of_servers=1;
	}

	/* set up structure */
        for (i = 0 ; i < MAX_RESOLVES_IN_PROGRESS ; i++) init_structs(i);

if (naddy)
 write_log(RESOLVELOG,YESTIME,"CLIPON: Ready to answer queries with nameserver %s of %d\n",nameserver,number_of_servers);
if (second_naddy)
 write_log(RESOLVELOG,YESTIME,"CLIPON: Ready to answer queries with nameserver2 %s of %d\n",second_nameserver,number_of_servers);
if (third_naddy)
 write_log(RESOLVELOG,YESTIME,"CLIPON: Ready to answer queries with nameserver3 %s of %d\n",third_nameserver,number_of_servers);

/* start forever loop */
while (1) {

		/* under normal circumstances, we would probably want	*/
		/* to check for this, to see if our parent abandoned us	*/
		/* but the talker does soft-boots which would make us	*/
		/* lost the parent pid here. We do checkpoints instead	*/
		/* to make sure we're not orphaned			*/

/* CODE KEPT HERE IN CASE NEEDED
		ret = getppid();
                if (ret==1)
                {
			write_log(RESOLVELOG,YESTIME,"CLIPON: init has us! exiting!\n");
                        exit(0);
                }
*/

		/* These are for connection being established */
                FD_ZERO(&fds_write);
		/* These are for a reply being ready */
                FD_ZERO(&fds_read);

		/* standard input */
                FD_SET(0, &fds_read);
		if (0 >= nfds) nfds = 1;
		/* standard output */
                /* FD_SET(1, &fds_write);
		if (1 >= nfds) nfds = 2; */
		/* pending resolves */
		for (i=0;i<MAX_RESOLVES_IN_PROGRESS;++i) {
		if (resolves[i].fd != -1) {
		sprintf(mess,"CLIPON: Setting active fd %d to FD_SET!\n",resolves[i].fd);
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,mess);
#endif
			FD_SET(resolves[i].fd,&fds_read);
			if (resolves[i].fd >= nfds)
			nfds = resolves[i].fd + 1;
			}
		} /* end of for */

                timeout.tv_sec = RESOLVE_SELECT_TIMEOUT;
                timeout.tv_usec = 0;
		
		ret = select(nfds, (void *) &fds_read, (void *) &fds_write, (void *) 0, &timeout);

		if (ret == SOCKET_ERROR) {
		if (errno != EINTR) {
		write_log(RESOLVELOG,YESTIME,"CLIPON: SELECT error %s!\n",get_error());
		exit(0);
		}
		else continue;
		} /* end of if bad select */
		else if (!ret) {
		/* select timeout */
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: Select timed out\n");
#endif
		}

if (write_stdout(RESOLVER_SERVER_SEND_CHECKPOINT) <= 0) {
        write_log(RESOLVELOG,YESTIME,"CLIPON: Can't checkpoint with talker! %s\n",get_error());
        if (!suspended) {
        write_log(RESOLVELOG,YESTIME,"CLIPON: Exiting!\n");
        exit(1);
        }
}


/* out of select */
                  for (i = 0 ; i < MAX_RESOLVES_IN_PROGRESS ; i++)
                  {
			if (resolves[i].status == STA_PENDING &&
			    !FD_ISSET(resolves[i].fd, &fds_read) &&
			    ((time(0)-resolves[i].starttime) >= RESOLVE_SELECT_TIMEOUT)) {
			write_log(RESOLVELOG,YESTIME,"CLIPON: Timing out pending fd %d (%d seconds)\n",resolves[i].fd,(int)(time(0)-resolves[i].starttime));
			SHUTDOWN(resolves[i].fd, 2);
			CLOSE(resolves[i].fd);
			restart_query(i);
			}
		  } /* end of for */

                if (FD_ISSET(0,&fds_read)) {
		/* request coming in from talker */
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: Incoming request\n");
#endif
		len = S_READ(0, s, 1000);
		  /* Check for error */
		  if (len <= 0) {
			sprintf(mess,"CLIPON: Bad read len %ld error %s\n",len,get_error());
			write_log(RESOLVELOG,YESTIME,mess);
			/* Should we really exit here?  The theorey is, that if  */
			/* the talker is gonna reboot, suspends us, and then     */
			/* fails to reboot, we might get stuck, checkpoints      */
			/* failing to no end and stdin being readble but no data */
			/* sooner or later we'll hog cpu and fill up logspace    */
			exit(1);
			/* continue; */
		  }
		s[len]=0;
		if (!strlen(s)) continue;
		  if ((slot = find_free_ns_slot()) == -1) continue;
			/* parse request */
		/* s[strlen(s)-1]=0; */
                sscanf(s,"%s ",action);
                remove_first(s);
                if (!strcmp(action,RESOLVER_CLIENT_SEND_SUSPEND)) {
                suspended=1;
                write_log(RESOLVELOG,YESTIME,"Got suspend message\n");
                continue;  
                }
                else if (!strcmp(action,RESOLVER_CLIENT_SEND_RESUME)) {
                suspended=0;
                write_log(RESOLVELOG,YESTIME,"Got resume message\n");
                continue;
                }
                else if (!strcmp(action,RESOLVER_CLIENT_SEND_REQUEST)) {
                        sscanf(s,"%d",&resolves[slot].user);
                        remove_first(s);
                        sscanf(s,"%s ",resolves[slot].site);
                        remove_first(s);
                        strcpy(resolves[slot].badlookup,s);
			if (naddy) resolves[slot].nameserver=naddy;
			else if (second_naddy) resolves[slot].nameserver=second_naddy;
			else if (third_naddy) resolves[slot].nameserver=third_naddy;
write_log(RESOLVELOG,YESTIME,"CLIPON: Starting query for ip %s user %d nameserver %s\n",
resolves[slot].site,resolves[slot].user,get_ip(resolves[slot].nameserver));
                        if (!start_query(slot, resolves[slot].site)) {
                                resolves[slot].status = STA_DONE;
                                resolves[slot].result = RES_NONAUTH;
				process_result(slot);
                                }
                        else continue;
                  }
                else if (!strcmp(action,RESOLVER_CLIENT_CANCEL_REQUEST)) {
                        /* find what slot this user request is in */
                        /* by matching up user number and site */
                        sscanf(s,"%d",&user);
                        remove_first(s);   
                        sscanf(s,"%s",site);
                        remove_first(s);
                        if ((slot = find_user_slot(user,site)) != -1) {
				SHUTDOWN(resolves[slot].fd, 2);
                                CLOSE(resolves[slot].fd);
                                resolves[slot].status = STA_DONE;
                                resolves[slot].result = RES_NONAUTH;
				process_result(slot);
                                }
                        continue;
                  }
		} /* end if FD_ISSET */

		for (i=1;i<nfds;++i) {
		  if (FD_ISSET(i,&fds_read)) {
#if defined(RESOLVER_DEBUG)
			write_log(RESOLVELOG,YESTIME,"CLIPON: Gonna read result from remote fd now\n");
#endif
			/* i is the fd, not the slot! */
			slot = get_slot(i);
			/* printf("%s",""); */
			resolves[slot].result = read_result(slot);
#if defined(RESOLVER_DEBUG)
			write_log(RESOLVELOG,YESTIME,"CLIPON: Result read\n");
#endif
			if (resolves[slot].result == RES_ERROR) restart_query(slot);
			else resolves[slot].status = STA_DONE;
		  } /* end of if FD_ISSET */
		} /* end of for */

		/* stdout ready for writing? */

                  for (i = 0 ; i < MAX_RESOLVES_IN_PROGRESS ; i++)
                  {
			if (resolves[i].status == STA_DONE)
				process_result(i);
		  } /* end of for */

} /* end of while forever */

} /* end of main */


int start_query(int slot, char *ipaddy) {
int             ip[4];
char            qbuf[256];
struct sockaddr_in sin2;

memset((char *)&sin2, 0, sizeof(struct sockaddr_in));

        sin2.sin_family  = AF_INET;
        sin2.sin_port    = htons(nsport);

                (void)bcopy((char *)&resolves[slot].nameserver,(char *)&sin2.sin_addr,sizeof(resolves[slot].nameserver));

/* Make query */
if (sscanf(ipaddy, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) {
            sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa.",
                ip[3], ip[2], ip[1], ip[0]);
}
else {
return 0;
}

resolves[slot].buflen = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, 
		resolves[slot].buf.qb2, sizeof resolves[slot].buf);
if (resolves[slot].buflen < 0) {
        return 0;
}
#if defined(HAVE_RES_NMKQUERY)
/* because we are not using our own function, we have to set */
/* flags here */
resolves[slot].buf.qb1.rd = 1;
#endif

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"    ----- START QUERY DEBUG INFO -----\n");
my_print_query((u_char *)&resolves[slot].buf, (u_char *)&resolves[slot].buf + resolves[slot].buflen);
write_log(RESOLVELOG,YESTIME,"    ----- END QUERY DEBUG INFO   -----\n");
#endif

/* Use datagrams - UDP */
resolves[slot].fd = socket(AF_INET, SOCK_DGRAM, 0);
/* resolves[slot].fd = socket(AF_INET, SOCK_STREAM, 0); */
if (resolves[slot].fd < 0) {
	return 0;
}

resolves[slot].status		= STA_PENDING;
resolves[slot].starttime	= time(0);

#if RES_BSD >= 43

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: connecting to nameserver\n");
#endif

if (connect(resolves[slot].fd, (struct sockaddr *)&sin2, sizeof sin2) < 0) {
#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: connect failed!\n");
#endif
	return 0;
}

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: sending to nameserver with send\n");
#endif

if (S_WRITE(resolves[slot].fd, (char *)&resolves[slot].buf, resolves[slot].buflen) != resolves[slot].buflen) {
	SHUTDOWN(resolves[slot].fd, 2);
	CLOSE(resolves[slot].fd);
#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: write failed!\n");
#endif
	return 0;
}
#else

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: sending to nameserver with sendto\n");
#endif

if (sendto(resolves[slot].fd, (const char *)&resolves[slot].buf, resolves[slot].buflen, 0, 
	(struct sockaddr *) &sin2, sizeof sin2) != resolves[slot].buflen) {
	SHUTDOWN(resolves[slot].fd, 2);
	CLOSE(resolves[slot].fd);
#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: sendto failed!\n");
#endif
	return 0;
}
#endif

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"CLIPON: sent\n");
#endif
return 1;
/* sent query, now wait for select in main loop to return a reply */
} /* end of function */


int restart_query(int slot) {

			resolves[slot].tries++;
			 if (resolves[slot].tries==number_of_servers) {
			  resolves[slot].status = STA_DONE;
			  resolves[slot].result = RES_NONAUTH;
			  process_result(slot);
			 }
			 else {
			  if (resolves[slot].tries==1) {
				resolves[slot].nameserver=second_naddy;
				write_log(RESOLVELOG,YESTIME,"CLIPON: Try 2 for %s with nameserver %s\n",
				resolves[slot].site,get_ip(resolves[slot].nameserver));
	                        if (!start_query(slot, resolves[slot].site)) {
                                 resolves[slot].status = STA_DONE;
                                 resolves[slot].result = RES_NONAUTH;
				 process_result(slot);
                                }
			  } /* if 1 */
			  else if (resolves[slot].tries==2) {
				resolves[slot].nameserver=third_naddy;
				write_log(RESOLVELOG,YESTIME,"CLIPON: Try 3 for %s with nameserver %s\n",
				resolves[slot].site,get_ip(resolves[slot].nameserver));
	                        if (!start_query(slot, resolves[slot].site)) {
                                 resolves[slot].status = STA_DONE;
                                 resolves[slot].result = RES_NONAUTH;
				 process_result(slot);
                                }
			  } /* if 2 */
			 } /* else */
return 1;
}


int read_result(int slot) {
int		n, type, origClass, class, qdcount, ancount, arcount, nscount, dlen;
int		buflen, resplen, anslen, trueLenPtr;
NET_SIZE_T salen;
Boolean		haveAnswer;
Boolean		printedAnswers;
u_char		*eom, *bp;
register HEADER	*headerPtr;
register u_char	*cp;
size_t		s;
struct sockaddr_in	sa;

printedAnswers = FALSE;
origClass = C_IN;

salen = sizeof sa;
anslen = sizeof(resolves[slot].answer);
resplen = recvfrom(resolves[slot].fd,
		   (u_char *)&resolves[slot].answer, 
                   anslen, 0, (struct sockaddr *)&sa, &salen);
if (resplen <= 0) {
SHUTDOWN(resolves[slot].fd, 2);
CLOSE(resolves[slot].fd);
write_log(RESOLVELOG,YESTIME,"CLIPON: Bad result read from nameserver %s\n",get_ip(resolves[slot].nameserver));
return(RES_ERROR);
}

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"    ----- START ANSWER DEBUG INFO -----\n");
write_log(RESOLVELOG,YESTIME,"Got answer (%d bytes):\n",resplen);
my_print_query((u_char *) &resolves[slot].answer, (u_char *) &resolves[slot].answer + resplen);
write_log(RESOLVELOG,YESTIME,"    ----- END ANSWER DEBUG INFO   -----\n");
#endif

		SHUTDOWN(resolves[slot].fd, 2);
                CLOSE(resolves[slot].fd);
                s = -1;
                trueLenPtr = resplen;
                /*  *trueLenPtr = resplen; */

/* process answer */
    eom = (u_char *) &resolves[slot].answer + trueLenPtr;

    headerPtr = (HEADER *) &resolves[slot].answer;

/*
 * Currently defined response codes
 */
/* NOERROR         0               no error */
/* FORMERR         1               format error */
/* SERVFAIL        2               server failure */
/* NXDOMAIN        3               non existent domain */
/* NOTIMP          4               not implemented */
/* REFUSED         5               query refused */
    if (headerPtr->rcode != NOERROR) {
        return (headerPtr->rcode);
    }

/* qdcount - number of question entries */
/* ancount - number of answer entries */
/* nscount - number of authority entries */
/* arcount - number of resource entries */

    qdcount = ntohs(headerPtr->qdcount);
    ancount = ntohs(headerPtr->ancount);
    arcount = ntohs(headerPtr->arcount);
    nscount = ntohs(headerPtr->nscount);

#if defined(RESOLVER_DEBUG)
write_log(RESOLVELOG,YESTIME,"QDCOUNT: %d\n",qdcount);
write_log(RESOLVELOG,YESTIME,"ANCOUNT: %d\n",ancount);
write_log(RESOLVELOG,YESTIME,"NSCOUNT: %d\n",nscount);
write_log(RESOLVELOG,YESTIME,"ARCOUNT: %d\n",arcount);
#endif


    /*
     * If there are no answer, n.s. or additional records
     * then return with an error.
     */
      if (!ancount) {
        return (RES_NO_INFO);
	}

    bp     = hostbuf;
    buflen = sizeof(hostbuf);
    cp     = (u_char *) &resolves[slot].answer + HFIXEDSZ;
    /* Skip over question section. */

    while (qdcount-- > 0) {
            n = dn_skipname(cp, eom);
            if (n < 0) {
                    return (RES_ERROR);
                }
            cp += n + QFIXEDSZ;
            if (cp > eom) {
                      return (RES_ERROR);
                }
    }
    haveAnswer  = FALSE;

    /*
     * Scan through the answer resource records.
     * Answers for address query types are saved.
     * Other query type answers are just printed.
     */

            while (--ancount >= 0 && cp < eom) {
                n = dn_expand(resolves[slot].answer.qb2, eom, cp, (char *)bp, buflen);
                if (n < 0) {
#if defined(RESOLVER_DEBUG)
                write_log(RESOLVELOG,YESTIME,"CLIPON: Returning error in dn_expand n: %d h_errno: %d\n",n,h_errno);
#endif
                    return(RES_ERROR);
                }
                cp += n;
                if (cp + 3 * INT16SZ + INT32SZ > eom)
                        return (RES_ERROR);
                type  = GetShort(cp);
                class = GetShort(cp);
                cp   += INT32SZ;        /* skip TTL */
                dlen  = GetShort(cp);
                if (cp + dlen > eom)
                        return (RES_ERROR);
                if (type == T_CNAME) {
                    /*
                     * Found an alias.
                     */
#if defined(RESOLVER_DEBUG)
                write_log(RESOLVELOG,YESTIME,"CLIPON: Found a CNAME type %d/%d\n",class,type);
#endif
		cp += dlen;
		continue;
                } else if (type == T_PTR) {
                    /*
                     *  Found a "pointer" to the real name.
                     */
#if defined(RESOLVER_DEBUG)
                write_log(RESOLVELOG,YESTIME,"CLIPON: Found a PTR type %d/%d\n",class,type);
#endif
                    n = dn_expand(resolves[slot].answer.qb2, eom, cp, (char *)bp, buflen);
			strcpy(resolves[slot].hostname,(char *)bp);
                    if (n < 0) {
                        cp += n;
                        continue;
                    }
                    cp += n;
                    s = strlen((char *)bp) + 1;
                    haveAnswer = TRUE;
                    break;
                } else if (type != T_A) {
#if defined(RESOLVER_DEBUG)
                write_log(RESOLVELOG,YESTIME,"CLIPON: Found an A type %d/%d\n",class,type);
#endif
                    cp += dlen;
                    continue;
                }
		else {
#if defined(RESOLVER_DEBUG)
                write_log(RESOLVELOG,YESTIME,"CLIPON: Found an UNKNOWN type %d/%d\n",class,type);
#endif
		}
                    /*
                     * If we've already got 1 address, we aren't interested
                     * in addresses with a different length or class.
                     */

                    /*
                     * First address: record its length and class so we
                     * only save additonal ones with the same attributes.
                     */
            } /* end of while */

return (RES_SUCCESS);

}


void init_structs(int slot) {

resolves[slot].fd		= -1;
resolves[slot].user		= -1;
resolves[slot].tries		= 0;
resolves[slot].nameserver	= 0;
resolves[slot].status		= STA_WAITING;
resolves[slot].result		= RES_SUCCESS;
resolves[slot].buflen		= 0;
resolves[slot].site[0]		= 0;
resolves[slot].hostname[0]	= 0;
resolves[slot].badlookup[0]	= 0;
resolves[slot].buf.qb2[0]	= 0;
resolves[slot].answer.qb2[0]	= 0;
resolves[slot].starttime	= 0;
}


int find_free_ns_slot(void) {
int a;

for (a=0;a<MAX_RESOLVES_IN_PROGRESS;++a) {
if (resolves[a].fd == -1) return a;
}
return -1;

}

int find_user_slot(int user, char *site) {
int a;

for (a=0;a<MAX_RESOLVES_IN_PROGRESS;++a) {
if ((resolves[a].user == user) && (!strcmp(resolves[a].site,site))) return a;
}
return -1;
}

int get_slot(int fd) {
int b=0;

for (b=0;b<MAX_RESOLVES_IN_PROGRESS;++b) {
if (resolves[b].fd==fd) return b;
}
return -1;
}


char *Calloc(register int num, register int size)
{
    char *ptr;

    ptr = Malloc(num*size);
if (ptr == NULL) { return NULL; }
    memset(ptr, 0, num*size);
    return(ptr);
}


char *Malloc(int size)
{
    char        *ptr;

      ptr = malloc((unsigned) size);

    if (ptr == NULL) {
			write_log(RESOLVELOG,YESTIME,"CLIPON: bad malloc\n");
	exit(0);
	}
    return (ptr);
}

u_int my_ns_get16(u_char *src) {
        u_int dst;
        NS_GET16(dst, src);
        return (dst);
}

u_long my_ns_get32(u_char *src) {
        u_long dst;
        NS_GET32(dst, src);
        return (dst);
}


RETSIGTYPE handle_sig(int sig) {

/* write_log(RESOLVELOG,YESTIME,"CLIPON: Caught signal %d!\n",sig); */
switch(sig) {
	case SIGTERM:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigterm!\n");
			exit(1);
	case SIGBUS:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigbus!\n");
			exit(1);
	case SIGSEGV:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigsegv!\n");
			exit(1);
	case SIGILL:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigill!\n");
			exit(1);
	case SIGABRT:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigabrt!\n");
			exit(1);
	case SIGINT:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigint!\n");
			exit(1);
	case SIGCHLD:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigchld!\n");
			exit(1);
	case SIGSTOP:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigstop!\n"); break;
			exit(1);
	case SIGPIPE:	write_log(RESOLVELOG,YESTIME,"CLIPON: Got sigpipe!\n"); break;
	default: write_log(RESOLVELOG,YESTIME,"CLIPON: Got unknown signal!\n"); break;
	}

}

int write_stdout(char *msg) {
int n;

n = write(1,msg,strlen(msg));
return n;
}

/*** removes first word at front of string and moves rest down ***/
void remove_first(char *inpstr)
{
int newpos,oldpos;

newpos=0;  oldpos=0;
/* find first word */
while(inpstr[oldpos]==' ') {
        if (!inpstr[oldpos]) { inpstr[0]=0;  return; }
        oldpos++;
        }
/* find end of first word */
while(inpstr[oldpos]!=' ') {
        if (!inpstr[oldpos]) { inpstr[0]=0;  return; }
        oldpos++;
        }
/* find second word */
while(inpstr[oldpos]==' ') {
        if (!inpstr[oldpos]) { inpstr[0]=0;  return; }
        oldpos++;
        }
while(inpstr[oldpos]!=0)
        inpstr[newpos++]=inpstr[oldpos++];
inpstr[newpos]='\0';
}

/* Write string and arguments to a specific logging facility */
void write_log(int type, int wanttime, char *str, ...)
{
char z_mess[256*2];
char logfile[FILE_NAME_LEN];
va_list args;
FILE *fp;
/* if (!syslog_on) return; */

z_mess[0]=0;
strcpy(z_mess,LOGFILE);
strncpy(logfile,z_mess,FILE_NAME_LEN);
 if (!(fp=fopen(logfile,"a")))
   {
/*
    sprintf(z_mess,"%s LOGGING: Couldn't open file(a) \"%s\"! %s",STAFF_PREFIX,logfile,get_error());
    writeall_str(z_mess, WIZ_ONLY, -1, 0, -1, BOLD, NONE, 0);
*/
    return;
   }
 else {
    va_start(args,str);
    if (wanttime) {
    sprintf(z_mess,"%s: ",get_time(0,0));
    vsprintf(z_mess+strlen(z_mess),str,args);
    }
    else
    vsprintf(z_mess,str,args);
    va_end(args);
    fputs(z_mess,fp);
    FCLOSE(fp);
   }
}

/* Get time in a certain way and return it as a string */
/* mode 0 is to get rid of the year string and the carriage return */
/* mode 1 is to get rid of just the carriage return */
char *get_time(time_t ref,int mode)
{
time_t tm;
static char mrtime[30];
if ((int)ref==0) {
   time(&tm);
   strcpy(mrtime,ctime(&tm));
  }
else {
   strcpy(mrtime,ctime(&ref));
  }
if (mode==0)
   mrtime[strlen(mrtime)-6]=0; /* get rid of newline and year */
else if (mode==1)
   mrtime[strlen(mrtime)-1]=0; /* get rid of newline */
   return mrtime;
}


char *get_error(void)
{
static char errstr[256];
sprintf(errstr,"(%d:%s)",errno,strerror(errno));
return errstr;
}


void process_result(int slot) {

switch (resolves[slot].result) {
        case RES_SUCCESS:
            /*
             *  If the query was for an address, then the &curHostInfo
             *  variable can be used by Finger.
             *  There's no need to print anything for other query types
             *  because the info has already been printed.
             */
            break;
        /*
         * No Authoritative answer was available but we got names
         * of servers who know about the host.
         */
        case RES_NONAUTH:
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: RESULT: No auth answers!\n");
#endif
		strcpy(resolves[slot].hostname,resolves[slot].badlookup);
		break;
        case RES_NO_INFO:
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: RESULT: No records available!\n");
#endif
		strcpy(resolves[slot].hostname,resolves[slot].badlookup);
		break;
        case RES_TIME_OUT:
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: RESULT: Request timed out!\n");
#endif
		strcpy(resolves[slot].hostname,resolves[slot].badlookup);
		break;
        default:
#if defined(RESOLVER_DEBUG)
		write_log(RESOLVELOG,YESTIME,"CLIPON: RESULT: Can't find host!\n");
#endif
		strcpy(resolves[slot].hostname,resolves[slot].badlookup);
		break;
    } /* end of switch */
#if defined(HAVE_SNPRINTF)
snprintf(mess,256,"%d %s %s ",resolves[slot].user,resolves[slot].site,resolves[slot].hostname);
#else
sprintf(mess,"%d %s %s ",resolves[slot].user,resolves[slot].site,resolves[slot].hostname);
#endif
write_stdout(mess);
write_log(RESOLVELOG,YESTIME,"CLIPON: RESULT: Wrote results \"%s\" from fd %d to talker (total time %d secs)\n",mess,resolves[slot].fd,(int)(time(0)-resolves[slot].starttime));
init_structs(slot);
}


/* LIB STUFF */
/*
 * Expand compressed domain name 'comp_dn' to full domain name.
 * 'msg' is a pointer to the begining of the message,
 * 'eomorig' points to the first location after the message,
 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
 * Return size of compressed name or -1 if there was an error.
 */
int dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
          char *dst, int dstsiz)
{
        int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
        if (n > 0 && dst[0] == '.')
                dst[0] = '\0';
        return (n);
}

/*
 * Skip over a compressed domain name. Return the size or -1.
 */
int dn_skipname(const u_char *ptr, const u_char *eom) {
        const u_char *saveptr = ptr;
        if (ns_name_skip(&ptr, eom) == -1)
                return (-1);
        return (ptr - saveptr);
}

/*
 * ns_name_uncompress(msg, eom, src, dst, dstsiz)
 *      Expand compressed domain name to presentation format.
 * return:
 *      Number of bytes read out of `src', or -1 (with errno set).
 * note:
 *      Root domain returns as "." not "".
 */
int ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
                   char *dst, size_t dstsiz)
{
        u_char tmp[NS_MAXCDNAME];
        int n;
        if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
                return (-1);
        if (ns_name_ntop(tmp, dst, dstsiz) == -1)
                return (-1);
        return (n);
}

/*
 * ns_name_skip(ptrptr, eom)
 *      Advance *ptrptr to skip over the compressed name it points at.
 * return:
 *      0 on success, -1 (with errno set) on failure.
 */
int ns_name_skip(const u_char **ptrptr, const u_char *eom) {
        const u_char *cp;
        u_int n;
        cp = *ptrptr;
        while (cp < eom && (n = *cp++) != 0) {
                /* Check for indirection. */
                switch (n & NS_CMPRSFLGS) {
                case 0:                 /* normal case, n == len */
                        cp += n;
                        continue;
                case NS_CMPRSFLGS:      /* indirection */
                        cp++;
                        break;
                default:                /* illegal type */
                        errno = EMSGSIZE;
                        return (-1);
                }
                break;
        }
        if (cp > eom) {
                errno = EMSGSIZE;
                return (-1);
        }
        *ptrptr = cp;
        return (0);
}


/*
 * ns_name_ntop(src, dst, dstsiz)
 *      Convert an encoded domain name to printable ascii as per RFC1035.
 * return:
 *      Number of bytes written to buffer, or -1 (with errno set)
 * notes:
 *      The root is returned as "."
 *      All other domains are returned in non absolute form
 */
int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
        const u_char *cp;
        char *dn, *eom;
        u_char c;
        u_int n;
        cp = src;
        dn = dst;
        eom = dst + dstsiz;
        while ((n = *cp++) != 0) {
                if ((n & NS_CMPRSFLGS) != 0) {
                        /* Some kind of compression pointer. */
                        errno = EMSGSIZE;
                        return (-1);
                }
                if (dn != dst) {
                        if (dn >= eom) {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        *dn++ = '.';
                }
                if (dn + n >= eom) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                for ((void)NULL; n > 0; n--) {
                        c = *cp++;
                        if (special(c)) {
                                if (dn + 1 >= eom) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                *dn++ = '\\';
                                *dn++ = (char)c;
                        } else if (!printable(c)) {
                                if (dn + 3 >= eom) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                *dn++ = '\\';
                                *dn++ = digits[c / 100];
                                *dn++ = digits[(c % 100) / 10];
                                *dn++ = digits[c % 10];
                        } else {
                                if (dn >= eom) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                *dn++ = (char)c;
                        }
                }
        }
        if (dn == dst) {
                if (dn >= eom) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                *dn++ = '.';
        }
        if (dn >= eom) {
                errno = EMSGSIZE;
                return (-1);
        }
        *dn++ = '\0';
        return (dn - dst);
}

/*
 * ns_name_unpack(msg, eom, src, dst, dstsiz)
 *      Unpack a domain name from a message, source may be compressed.
 * return:
 *      -1 if it fails, or consumed octets if it succeeds.
 */
int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
               u_char *dst, size_t dstsiz)
{
        const u_char *srcp, *dstlim;
        u_char *dstp;
        int n, len, checked;
        len = -1;
        checked = 0;
        dstp = dst;
        srcp = src;
        dstlim = dst + dstsiz;
        if (srcp < msg || srcp >= eom) {
                errno = EMSGSIZE;
                return (-1);
        }
        /* Fetch next label in domain name. */
        while ((n = *srcp++) != 0) {
                /* Check for indirection. */
                switch (n & NS_CMPRSFLGS) {
                case 0:
                        /* Limit checks. */
                        if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        checked += n + 1;
                        *dstp++ = n;
                        memcpy(dstp, srcp, n);
                        dstp += n;
                        srcp += n;
                        break;
                case NS_CMPRSFLGS:
                        if (srcp >= eom) {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        if (len < 0)
                                len = srcp - src + 1;
                        srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
                        if (srcp < msg || srcp >= eom) {  /* Out of range. */
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        checked += 2;
                        /*
                         * Check for loops in the compressed name;
                         * if we've looked at the whole message,
                         * there must be a loop.
                         */
                        if (checked >= eom - msg) {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        break;
                default:
                        errno = EMSGSIZE;
                        return (-1);                    /* flag error */
                }
        }
        *dstp = '\0';
        if (len < 0)
                len = srcp - src;
        return (len);
}

/*
 * special(ch)
 *      Thinking in noninternationalized USASCII (per the DNS spec),
 *      is this characted special ("in need of quoting") ?
 * return:
 *      boolean.
 */
static int special(int ch) {
        switch (ch) {
        case 0x22: /* '"' */
        case 0x2E: /* '.' */
        case 0x3B: /* ';' */
        case 0x5C: /* '\\' */
        /* Special modifiers in zone files. */
        case 0x40: /* '@' */
        case 0x24: /* '$' */
                return (1);
        default:
                return (0);
        }
}

/*
 * printable(ch)
 *      Thinking in noninternationalized USASCII (per the DNS spec),
 *      is this character visible and not a space when printed ?
 * return:
 *      boolean.
 */
static int printable(int ch) {
        return (ch > 0x20 && ch < 0x7f);
}


int res_mkquery(int op,                     /* opcode of query */
            const char *dname,          /* domain name */
            int class, int type,        /* class and type of query */
            const u_char *data,         /* resource record data */
            int datalen,                /* length of data */
            const u_char *newrr_in,     /* new rr for modify or append */
            u_char *buf,                /* buffer to put query */
            int buflen)                 /* size of buffer */
{
/*
        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
                RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
                return (-1);
        }
*/

        return (res_nmkquery(_my_res, op, dname, class, type,
                             data, datalen,
                             newrr_in, buf, buflen));
}

#if !defined(HAVE_RES_NMKQUERY)
/*
 * Form all types of queries.
 * Returns the size of the result or -1.
 */
int res_nmkquery(struct __res_state statp,
	     int op,			/* opcode of query */
	     const char *dname,		/* domain name */
	     int class, int type,	/* class and type of query */
	     const u_char *data,	/* resource record data */
	     int datalen,		/* length of data */
	     const u_char *newrr_in,	/* new rr for modify or append */
	     u_char *buf,		/* buffer to put query */
	     int buflen)		/* size of buffer */
{
	register HEADER *hp;
	register u_char *cp;
	register int n;
	u_char *dnptrs[20], **dpp, **lastdnptr;

	/*
	 * Initialize header fields.
	 */
	if ((buf == NULL) || (buflen < HFIXEDSZ))
		return (-1);
	memset(buf, 0, HFIXEDSZ);
	hp = (HEADER *) buf;
	hp->id = htons(++statp.id);
	hp->opcode = op;
	hp->rd = 1;
/*	hp->rd = (statp.options & RES_RECURSE) != 0; */
	hp->rcode = NOERROR;
	cp = buf + HFIXEDSZ;
	buflen -= HFIXEDSZ;
	dpp = dnptrs;
	*dpp++ = buf;
	*dpp++ = NULL;
	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
	/*
	 * perform opcode specific processing
	 */
	switch (op) {
	case QUERY:	/*FALLTHROUGH*/
	case NS_NOTIFY_OP:
		if ((buflen -= QFIXEDSZ) < 0)
			return (-1);
		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
			return (-1);
		cp += n;
		buflen -= n;
		my_putshort(type, cp);
		cp += INT16SZ;
		my_putshort(class, cp);
		cp += INT16SZ;
		hp->qdcount = htons(1);
		if (op == QUERY || data == NULL)
			break;
		/*
		 * Make an additional record for completion domain.
		 */
		buflen -= RRFIXEDSZ;
/* 		n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); */
 		n = dn_comp((const char *)data, cp, buflen, dnptrs, lastdnptr);
		if (n < 0)
			return (-1);
		cp += n;
		buflen -= n;
		my_putshort(T_NULL, cp);
		cp += INT16SZ;
		my_putshort(class, cp);
		cp += INT16SZ;
		NS_PUT32(0, cp);
		cp += INT32SZ;
		my_putshort(0, cp);
		cp += INT16SZ;
		hp->arcount = htons(1);
		break;

	case IQUERY:
		/*
		 * Initialize answer section
		 */
		if (buflen < 1 + RRFIXEDSZ + datalen)
			return (-1);
		*cp++ = '\0';	/* no domain name */
		my_putshort(type, cp);
		cp += INT16SZ;
		my_putshort(class, cp);
		cp += INT16SZ;
		NS_PUT32(0, cp);
		cp += INT32SZ;
		my_putshort(datalen, cp);
		cp += INT16SZ;
		if (datalen) {
			memcpy(cp, data, datalen);
			cp += datalen;
		}
		hp->ancount = htons(1);
		break;

	default:
		return (-1);
	}
	return (cp - buf);
}
#endif

int dn_comp(const char *src, u_char *dst, int dstsiz,
        u_char **dnptrs, u_char **lastdnptr)
{
        return (ns_name_compress(src, dst, (size_t)dstsiz,
                                 (const u_char **)dnptrs,
                                 (const u_char **)lastdnptr));
}

/*
 * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
 *      Compress a domain name into wire format, using compression pointers.
 * return:
 *      Number of bytes consumed in `dst' or -1 (with errno set).
 * notes:
 *      'dnptrs' is an array of pointers to previous compressed names.
 *      dnptrs[0] is a pointer to the beginning of the message.
 *      The list ends with NULL.  'lastdnptr' is a pointer to the end of the
 *      array pointed to by 'dnptrs'. Side effect is to update the list of
 *      pointers for labels inserted into the message as we compress the name.
 *      If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
 *      is NULL, we don't update the list.
 */
int ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
                 const u_char **dnptrs, const u_char **lastdnptr)
{
        u_char tmp[NS_MAXCDNAME];
        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
                return (-1);
        return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
}

/*
 * ns_name_pton(src, dst, dstsiz)
 *      Convert a ascii string into an encoded domain name as per RFC1035.
 * return:
 *      -1 if it fails
 *      1 if string was fully qualified
 *      0 is string was not fully qualified
 * notes:
 *      Enforces label and domain length limits.
 */
int ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
        u_char *label, *bp, *eom;
        int c, n, escaped;
        char *cp;
        escaped = 0;
        bp = dst;
        eom = dst + dstsiz;
        label = bp++;
        while ((c = *src++) != 0) {
                if (escaped) {
                        if ((cp = strchr(digits, c)) != NULL) {
                                n = (cp - digits) * 100;
                                if ((c = *src++) == 0 ||
                                    (cp = strchr(digits, c)) == NULL) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                n += (cp - digits) * 10;
                                if ((c = *src++) == 0 ||
                                    (cp = strchr(digits, c)) == NULL) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                n += (cp - digits);
                                if (n > 255) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                c = n;
                        }
                        escaped = 0;
                } else if (c == '\\') {
                        escaped = 1;
                        continue;
                } else if (c == '.') {
                        c = (bp - label - 1);
                        if ((c & NS_CMPRSFLGS) != 0) {  /* Label too big. */
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        if (label >= eom) {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        *label = c;
                        /* Fully qualified ? */
                        if (*src == '\0') {
                                if (c != 0) {
                                        if (bp >= eom) {
                                                errno = EMSGSIZE;
                                                return (-1);
                                        }
                                        *bp++ = '\0';
                                }
                                if ((bp - dst) > MAXCDNAME) {
                                        errno = EMSGSIZE;
                                        return (-1);
                                }
                                return (1);
                        }
                        if (c == 0 || *src == '.') {
                                errno = EMSGSIZE;
                                return (-1);
                        }
                        label = bp++;
                        continue;
                }
                if (bp >= eom) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                *bp++ = (u_char)c;
        }
        c = (bp - label - 1);
        if ((c & NS_CMPRSFLGS) != 0) {          /* Label too big. */
                errno = EMSGSIZE;
                return (-1);
        }
        if (label >= eom) {
                errno = EMSGSIZE;
                return (-1);
        }
        *label = c;
        if (c != 0) {
                if (bp >= eom) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                *bp++ = 0;
        }
        if ((bp - dst) > MAXCDNAME) {   /* src too big */
                errno = EMSGSIZE;
                return (-1);
        }
        return (0);
}

/*
 * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
 *      Pack domain name 'domain' into 'comp_dn'.
 * return:
 *      Size of the compressed name, or -1.
 * notes:
 *      'dnptrs' is an array of pointers to previous compressed names.
 *      dnptrs[0] is a pointer to the beginning of the message. The array
 *      ends with NULL.
 *      'lastdnptr' is a pointer to the end of the array pointed to
 *      by 'dnptrs'.
 * Side effects:
 *      The list of pointers in dnptrs is updated for labels inserted into
 *      the message as we compress the name.  If 'dnptr' is NULL, we don't
 *      try to compress names. If 'lastdnptr' is NULL, we don't update the
 *      list.
 */
int ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
             const u_char **dnptrs, const u_char **lastdnptr)
{
        u_char *dstp;
        const u_char **cpp, **lpp, *eob, *msg;
        const u_char *srcp;
        int n, l;
        srcp = src;
        dstp = dst;
        eob = dstp + dstsiz;
        lpp = cpp = NULL;
        if (dnptrs != NULL) {
                if ((msg = *dnptrs++) != NULL) {
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
                                (void)NULL;
                        lpp = cpp;      /* end of list to search */
                }
        } else
                msg = NULL;
        /* make sure the domain we are about to add is legal */
        l = 0;
        do {
                n = *srcp;
                if ((n & NS_CMPRSFLGS) != 0) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                l += n + 1;
                if (l > MAXCDNAME) {
                        errno = EMSGSIZE;
                        return (-1);
                }
                srcp += n + 1;
        } while (n != 0);
        /* from here on we need to reset compression pointer array on error */
        srcp = src;
        do {
                /* Look to see if we can use pointers. */
                n = *srcp;
                if (n != 0 && msg != NULL) {
                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
                                    (const u_char * const *)lpp);
                        if (l >= 0) {
                                if (dstp + 1 >= eob) {
                                        goto cleanup;
                                }
                                *dstp++ = (l >> 8) | NS_CMPRSFLGS;
                                *dstp++ = l % 256;
                                return (dstp - dst);
                        }
                        /* Not found, save it. */
                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
                            (dstp - msg) < 0x4000) {
                                *cpp++ = dstp;
                                *cpp = NULL;
                        }
                }
                /* copy label to buffer */
                if (n & NS_CMPRSFLGS) {         /* Should not happen. */
                        goto cleanup;
                }
                if (dstp + 1 + n >= eob) {
                        goto cleanup;
                }
                memcpy(dstp, srcp, n + 1);
                srcp += n + 1;
                dstp += n + 1;
        } while (n != 0);
        if (dstp > eob) {
cleanup:
                if (msg != NULL)
                        *lpp = NULL;
                errno = EMSGSIZE;
                return (-1);
        }
        return (dstp - dst);
}

/*
 * dn_find(domain, msg, dnptrs, lastdnptr)
 *      Search for the counted-label name in an array of compressed names.
 * return:
 *      offset from msg if found, or -1.
 * notes:
 *      dnptrs is the pointer to the first name on the list,
 *      not the pointer to the start of the message.
 */
static int dn_find(const u_char *domain, const u_char *msg,
        const u_char * const *dnptrs,
        const u_char * const *lastdnptr)
{
        const u_char *dn, *cp, *sp;
        const u_char * const *cpp;
        u_int n;
        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
                dn = domain;
                sp = cp = *cpp;
                while ((n = *cp++) != 0) {
                        /*
                         * check for indirection
                         */
                        switch (n & NS_CMPRSFLGS) {
                        case 0:                 /* normal case, n == len */
                                if (n != *dn++)
                                        goto next;
                                for ((void)NULL; n > 0; n--)
                                        if (mklower(*dn++) != mklower(*cp++))
                                                goto next;
                                /* Is next root for both ? */
                                if (*dn == '\0' && *cp == '\0')
                                        return (sp - msg);
                                if (*dn)
                                        continue;
                                goto next;
                        case NS_CMPRSFLGS:      /* indirection */
                                cp = msg + (((n & 0x3f) << 8) | *cp);
                                break;
                        default:        /* illegal type */
                                errno = EMSGSIZE;
                                return (-1);
                        }
                }
 next: ;
        }
        errno = ENOENT;
        return (-1);
}

static int mklower(int ch) {
        if (ch >= 0x41 && ch <= 0x5A)
                return (ch + 0x20);
        return (ch);
}

void my_putshort(unsigned short src, u_char *dst) { my_ns_put16(src, dst); }

void my_ns_put16(u_int src, u_char *dst) {
        NS_PUT16(src, dst);
}

#if !defined(HAVE_PUT32)
void putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
void ns_put32(u_long src, u_char *dst) {
        NS_PUT32(src, dst);
}
#endif


void my_print_query(u_char *msg, u_char *eom)
{
        register HEADER *hp;
        register u_char *cp;
        int n;
        u_int class=queryClass, type=queryType;
        /*
         * Print header fields.
         */
        hp = (HEADER *)msg;
        cp = (u_char *)msg + HFIXEDSZ;

                write_log(RESOLVELOG,YESTIME,"     HEADER:\n");
                write_log(RESOLVELOG,YESTIME,"\topcode = %s", _res_opcodes[hp->opcode]);
                write_log(RESOLVELOG,NOTIME,", id = %d", ntohs(hp->id));
                write_log(RESOLVELOG,NOTIME,", rcode = %s\n", my_p_rcode(hp->rcode));
                write_log(RESOLVELOG,YESTIME,"\theader flags: ");
                if (hp->qr) {
                        write_log(RESOLVELOG,NOTIME," response");
                } else {
                        write_log(RESOLVELOG,NOTIME," query");
                }
                if (hp->aa)
                        write_log(RESOLVELOG,NOTIME,", auth. answer");
                if (hp->tc)
                        write_log(RESOLVELOG,NOTIME,", truncation");
                if (hp->rd)
                        write_log(RESOLVELOG,NOTIME,", want recursion");
                if (hp->ra)
                        write_log(RESOLVELOG,NOTIME,", recursion avail.");
                if (hp->unused)
                        write_log(RESOLVELOG,NOTIME,", UNUSED-QUERY_BIT");
/* 
               if (hp->ad)
                        write_log(RESOLVELOG,NOTIME,", authentic data");
                if (hp->cd)
                        write_log(RESOLVELOG,NOTIME,", checking disabled");
*/
                write_log(RESOLVELOG,NOTIME,"\n");
		write_log(RESOLVELOG,YESTIME,"\tquestions = %d", ntohs(hp->qdcount));
                write_log(RESOLVELOG,NOTIME,",  answers = %d", ntohs(hp->ancount));
                write_log(RESOLVELOG,NOTIME,",  authority records = %d", ntohs(hp->nscount));
                write_log(RESOLVELOG,NOTIME,",  additional = %d\n\n", ntohs(hp->arcount));

        /*
         * Print question records.
         */
        n = ntohs(hp->qdcount);
        if (n > 0) {
                write_log(RESOLVELOG,YESTIME,"    QUESTIONS:\n");
                while (--n >= 0) {
                        write_log(RESOLVELOG,YESTIME,"\t");
                        cp = Print_cdname((const u_char *)cp, (const u_char *)msg, (const u_char *)eom);
                        if (cp == NULL)
                                return;
                	type  = GetShort(cp);
                	class = GetShort(cp);
                        write_log(RESOLVELOG,NOTIME,", type = %s", my_p_type(type));
                        write_log(RESOLVELOG,NOTIME,", class = %s\n", my_p_class(class));
                }
        }
        /*
         * Print authoritative answer records
         */
        n = ntohs(hp->ancount);
        if (n > 0) {
                write_log(RESOLVELOG,YESTIME,"    ANSWERS:\n");
                if (type == T_A && n > MAXADDRS) {
                        write_log(RESOLVELOG,YESTIME,"Limiting response to MAX Addrs = %d \n",
                               MAXADDRS);
                        n = MAXADDRS;
                }
                while (--n >= 0) {
                        write_log(RESOLVELOG,YESTIME,"    ->  ");
                        cp = Print_rr((const u_char *)cp, (const u_char *)msg, (const u_char *)eom);
                        if (cp == NULL)
                                return;
                }
        }
        /*
         * print name server records
         */
        n = ntohs(hp->nscount);
        if (n > 0) {
                write_log(RESOLVELOG,YESTIME,"    AUTHORITY RECORDS:\n");
                while (--n >= 0) {
                        write_log(RESOLVELOG,YESTIME,"    ->  ");
                        cp = Print_rr((const u_char *)cp, (const u_char *)msg, (const u_char *)eom);
                        if (cp == NULL)
                                return;
                }
        }
        /*
         * print additional records
         */
        n = ntohs(hp->arcount);
        if (n > 0) {
                write_log(RESOLVELOG,YESTIME,"    ADDITIONAL RECORDS:\n");
                while (--n >= 0) {
                        write_log(RESOLVELOG,YESTIME,"    ->  ");
                        cp = Print_rr((const u_char *)cp, (const u_char *)msg, (const u_char *)eom);
                        if (cp == NULL)
                                return;
                }
        }

write_log(RESOLVELOG,NOTIME,"\n");
}

u_char *Print_cdname(const u_char *cp, const u_char *msg, const u_char *eom)
{
        char name[MAXDNAME];
        int n;

        n = dn_expand(msg, eom, cp, name, sizeof name);
        if (n < 0)
                return (NULL);
        if (name[0] == '\0')
                strcpy(name, "(root)");

#if defined(RESOLVER_DEBUG)
	write_log(RESOLVELOG,NOTIME,"%s",name);
#endif
        return (cp + n);
}

u_char *Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom) {
        u_int type, class;
        int dlen;
        u_long rrttl;
        register u_char *cp, *cp1;

        if ((cp = Print_cdname(ocp, msg, eom)) == NULL) {
                write_log(RESOLVELOG,NOTIME,"(name truncated?)\n");
                return (NULL);                  /* compression error */
        }
        BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
        NS_GET16(type, cp);
        NS_GET16(class, cp);
        NS_GET32(rrttl, cp);
        NS_GET16(dlen, cp);
        BOUNDS_CHECK(cp, dlen);

	write_log(RESOLVELOG,NOTIME,"\n");
        write_log(RESOLVELOG,YESTIME,"\ttype = %s, class = %s, dlen = %d\n",
                                my_p_type(type), my_p_class(class), dlen);
        cp1 = cp;
        /*
         * Print type specific data, if appropriate
         */
        switch (type) {
        case T_NS:
                write_log(RESOLVELOG,YESTIME,"\tnameserver = ");
                goto doname;
        case T_PTR:
                write_log(RESOLVELOG,YESTIME,"\tname = ");
 doname:
                cp = Print_cdname(cp, msg, eom);
                if (cp == NULL) {
                        write_log(RESOLVELOG,NOTIME,"(name truncated?)\n");
                        return (NULL);                  /* compression error */
                }
                write_log(RESOLVELOG,NOTIME,"\n");
                break;
        case T_CNAME:
                write_log(RESOLVELOG,YESTIME,"\tname = ");
                cp = Print_cdname(cp, msg, eom);
                if (cp == NULL) {
                        write_log(RESOLVELOG,NOTIME,"(name truncated?)\n");
                        return (NULL);                  /* compression error */
                }
                write_log(RESOLVELOG,NOTIME,"\n");
                break;
	} /* end of switch */
/*
        if (cp != cp1 + dlen) {
                write_log(RESOLVELOG,NOTIME,"\n");
                write_log(RESOLVELOG,YESTIME,"*** Error: record size incorrect (%d != %d)\n\n",
                        cp - cp1, dlen);
                cp = NULL;
        }
*/
	write_log(RESOLVELOG,NOTIME,"\n");
        return (cp);
}


char *my_p_type(int mytype) {

switch(mytype) {
case T_PTR:	return "PTR";
case T_CNAME:	return "CNAME";
case T_A:	return "A";
case T_NS:	return "NS";
case T_ANY:	return "ANY";
default: return "UNKNOWN";
}
return NULL;

}

char *my_p_class(int myclass) {

switch(myclass) {
case C_IN:	return "IN";
case C_ANY:	return "ANY";
default: return "UNKNOWN";
}
return NULL;

}

char *my_p_rcode(int myrcode) {

switch(myrcode) {
case NOERROR:	return "NOERROR";
case FORMERR:	return "FORMERR";
case SERVFAIL:	return "SERVFAIL";
case NXDOMAIN:	return "NXDOMAIN";
case NOTIMP:		return "NOTIMP";
case REFUSED:	return "REFUSED";
default:	return "UNKNOWN";
}
return NULL;

}


/*
 * An os independent signal() with BSD semantics, e.g. the signal
 * catcher is restored following service of the signal.
 *
 * When sigset() is available, signal() has SYSV semantics and sigset()
 * has BSD semantics and call interface. Unfortunately, Linux does not
 * have sigset() so we use the more complicated sigaction() interface
 * there.
 *
 * Did I mention that signals suck?
 */
/* (*setsignal (int sig, RETSIGTYPE (*func)(int)))(int) */
handler_t
setsignal(int sig, handler_t handler)
{
#if defined(HAVE_SIGACTION)
        struct sigaction old, new;
#elif defined(HAVE_SIGMASK)
	struct sigvec nsv,osv;
#endif
	handler_t oldh;

#if defined(HAVE_SIGACTION)
        memset(&new, 0, sizeof(new));
        new.sa_handler = handler;
#if defined(SA_RESTART)
        new.sa_flags |= SA_RESTART;
#endif
        if (sigaction(sig, &new, &old) < 0)
                return ((handler_t)SIG_ERR);
        oldh = old.sa_handler;

#elif defined(HAVE_SIGMASK)
        memset(&nsv, 0, sizeof(nsv));
    nsv.sv_handler = handler;
    nsv.sv_mask = 0;                    /* punt */
    nsv.sv_flags = SV_INTERRUPT;        /* punt */
    sigvec(sig, &nsv, &osv);
    oldh = osv.sv_handler;
#elif defined(HAVE_SIGSET)
        oldh = (handler_t)sigset(sig, handler);
#else
        oldh = signal(sig, handler);
#endif
	return oldh;
}



#if defined(OPENBSD_SYS)
char *ctime(const time_t *mytm)   
{
struct tm *clocker;
static char buf1[32];

clocker=localtime(mytm);
#if defined(HAVE_STRFTIME)
strftime(buf1,sizeof(buf1),"%a %b %d %H:%M:%S %Y\n",clocker);
#else
#if defined(HAVE_SNPRINTF)
snprintf(buf1,sizeof(buf1),"%s %s %d %.2d:%.2d:%.2d %d\n",
clocker_daylist[clocker->tm_wday],clocker_monthlist[clocker->tm_mon],
clocker->tm_mday,clocker->tm_hour,clocker->tm_min,clocker->tm_sec,
1900+clocker->tm_year);
#else
sprintf(buf1,"%s %s %d %.2d:%.2d:%.2d %d\n",
clocker_daylist[clocker->tm_wday],clocker_monthlist[clocker->tm_mon],
clocker->tm_mday,clocker->tm_hour,clocker->tm_min,clocker->tm_sec,
1900+clocker->tm_year);
#endif
#endif

return buf1;
}
#endif

int SHUTDOWN(int sock, int how) {

#if defined(CYGWIN_SYS)
        return shutdown(sock, how);
#endif

return 1;
}

/* mid copy copies chunk from string strf to string strt */
void midcpy(char *strf, char *strt, int fr, int to)
{
int f;
for (f=fr;f<=to;++f)
  {          
   if (!strf[f])
     {
      strt[f-fr]='\0';
      return;
     }
   strt[f-fr]=strf[f];
  }
strt[f-fr]='\0';
}

char *get_ip(unsigned long addr) {
static char buf[21];

addr=ntohl(addr);
 buf[0]=0;
 sprintf(buf,"%ld.%ld.%ld.%ld", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
         (addr >> 8) & 0xff, addr & 0xff);

return buf;
}