[comp.sys.ibm.pc.rt] Fix for libc, part 2 of 3, IBM/4.3

brunner@bullhead.uucp (12/05/89)

Subject: Fix for libc (part 2)
Index: /usr/src/lib/libc IBM/4.3

Description:
	The C library name resolver code distributed in the December
	release does not contain all of the routines in the post-4.3
	Berkeley release. Compilation of Tahoe-release versions of
	sendmail (5.61) and named (4.8) fail. This kit adds files to
	and patches existing files in the include and libc source trees.

	When this kit is installed and the library has been rebuilt and
	reinstalled replacement of named and sendmail only requires the
	usual make install sequence. (See /usr/src/Makefile, and
	/usr/src/lib/libc/Makefile)

	Sendmail version 5.61 and named (aka "BIND") version 4.8 are
	available via anonymous ftp at numerous sites on the Internet.
	For the benefit of sites without Internet access, compressed tar
	images of each are available via uucp from ibmsupt, the sizes
	are:

		314397 named4.8.tar.Z
		473205 sendmail5.61.tar.Z

	It is strongly recommended that the versions of sendmail and
	named shipped with the December 88 release be replaced with
	these versions.

	This is part 2 of a 3 part patch installation kit. The contents
	of the kit are:

part 1  patchs to the following files in /usr/src/include:
	netdb.h, resolve and arpa/nameser.h

part 2  shar file containing the following files in /usr/src/lib/libc:
	gen/{setenv.c, strcasecmp.c}
	net/{herror.c, res_query.c}
        
part 3  patchs to the following files in /usr/src/lib/libc:
	gen/{Makefile, getenv.c}
	net/{Makefile, res_comp.c, res_debug.c, res_init.c, res_mkquery.c,
	and res_send.c}

Fix:    Change directories to /usr/src/lib/libc and unpack
	the attached shar file, e.g.,

		sh < this_file

	This will create the new files. Proceede to the next part
	of the kit.


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	gen/setenv.c
#	gen/strcasecmp.c
#	net/herror.c
#	net/res_query.c
#
echo x - gen/setenv.c
sed 's/^X//' >gen/setenv.c << 'END-of-gen/setenv.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)setenv.c	5.2 (Berkeley) 6/27/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <stdio.h>
X
X/*
X * setenv --
X *	Set the value of the environmental variable "name" to be
X *	"value".  If rewrite is set, replace any current value.
X */
Xsetenv(name, value, rewrite)
X	register char *name, *value;
X	int rewrite;
X{
X	extern char **environ;
X	static int alloced;			/* if allocated space before */
X	register char *C;
X	int l_value, offset;
X	char *malloc(), *realloc(), *_findenv();
X
X	if (*value == '=')			/* no `=' in value */
X		++value;
X	l_value = strlen(value);
X	if ((C = _findenv(name, &offset))) {	/* find if already exists */
X		if (!rewrite)
X			return(0);
X		if (strlen(C) >= l_value) {	/* old larger; copy over */
X			while (*C++ = *value++);
X			return(0);
X		}
X	}
X	else {					/* create new slot */
X		register int	cnt;
X		register char	**P;
X
X		for (P = environ, cnt = 0; *P; ++P, ++cnt);
X		if (alloced) {			/* just increase size */
X			environ = (char **)realloc((char *)environ,
X			    (u_int)(sizeof(char *) * (cnt + 2)));
X			if (!environ)
X				return(-1);
X		}
X		else {				/* get new space */
X			alloced = 1;		/* copy old entries into it */
X			P = (char **)malloc((u_int)(sizeof(char *) *
X			    (cnt + 2)));
X			if (!P)
X				return(-1);
X			bcopy(environ, P, cnt * sizeof(char *));
X			environ = P;
X		}
X		environ[cnt + 1] = NULL;
X		offset = cnt;
X	}
X	for (C = name; *C && *C != '='; ++C);	/* no `=' in name */
X	if (!(environ[offset] =			/* name + `=' + value */
X	    malloc((u_int)((int)(C - name) + l_value + 2))))
X		return(-1);
X	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
X	for (*C++ = '='; *C++ = *value++;);
X	return(0);
X}
X
X/*
X * unsetenv(name) --
X *	Delete environmental variable "name".
X */
Xvoid
Xunsetenv(name)
X	char	*name;
X{
X	extern	char	**environ;
X	register char	**P;
X	int	offset;
X
X	while (_findenv(name, &offset))		/* if set multiple times */
X		for (P = &environ[offset];; ++P)
X			if (!(*P = *(P + 1)))
X				break;
X}
END-of-gen/setenv.c
echo x - gen/strcasecmp.c
sed 's/^X//' >gen/strcasecmp.c << 'END-of-gen/strcasecmp.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strcasecmp.c	1.3 (Berkeley) 8/3/87";
X#endif LIBC_SCCS and not lint
X
X/*
X * This array is designed for mapping upper and lower case letter
X * together for a case independent comparison.  The mappings are
X * based upon ascii character sequences.
X */
Xstatic char charmap[] = {
X	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
X	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
X	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
X	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
X	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
X	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
X	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
X	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
X	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
X	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
X	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
X	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
X	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
X	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
X	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
X	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
X	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
X	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
X	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
X	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
X};
X
Xstrcasecmp(s1, s2)
X	register char *s1, *s2;
X{
X	register char *cm = charmap;
X
X	while (cm[*s1] == cm[*s2++])
X		if (*s1++ == '\0')
X			return(0);
X	return(cm[*s1] - cm[*--s2]);
X}
X
Xstrncasecmp(s1, s2, n)
X	register char *s1, *s2;
X	register int n;
X{
X	register char *cm = charmap;
X
X	while (--n >= 0 && cm[*s1] == cm[*s2++])
X		if (*s1++ == '\0')
X			return(0);
X	return(n < 0 ? 0 : cm[*s1] - cm[*--s2]);
X}
END-of-gen/strcasecmp.c
echo x - net/herror.c
sed 's/^X//' >net/herror.c << 'END-of-net/herror.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.  The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)herror.c	6.1 (Berkeley) 12/4/87";
X#endif LIBC_SCCS and not lint
X
X#include <sys/types.h>
X#include <sys/uio.h>
X
Xchar	*h_errlist[] = {
X	"Error 0",
X	"Unknown host",				/* 1 HOST_NOT_FOUND */
X	"Host name lookup failure",		/* 2 TRY_AGAIN */
X	"Unknown server error",			/* 3 NO_RECOVERY */
X	"No address associated with name",	/* 4 NO_ADDRESS */
X};
Xint	h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
X
Xextern int	h_errno;
X
X/*
X * herror --
X *	print the error indicated by the h_errno value.
X */
Xherror(s)
X	char *s;
X{
X	struct iovec iov[4];
X	register struct iovec *v = iov;
X
X	if (s && *s) {
X		v->iov_base = s;
X		v->iov_len = strlen(s);
X		v++;
X		v->iov_base = ": ";
X		v->iov_len = 2;
X		v++;
X	}
X	v->iov_base = h_errno < h_nerr ? h_errlist[h_errno] : "Unknown error";
X	v->iov_len = strlen(v->iov_base);
X	v++;
X	v->iov_base = "\n";
X	v->iov_len = 1;
X	writev(2, iov, (v - iov) + 1);
X}
END-of-net/herror.c
echo x - net/res_query.c
sed 's/^X//' >net/res_query.c << 'END-of-net/res_query.c'
X/*
X * 5799-WZQ (C) COPYRIGHT = NONE
X * LICENSED MATERIALS - PROPERTY OF IBM
X */
X/* $Header:res_query.c 12.0$ */
X/* $ACIS:res_query.c 12.0$ */
X/* $Source: /ibm/acis/usr/src/lib/libc/net/RCS/res_query.c,v $ */
X
X#ifndef lint
Xstatic char *rcsid = "$Header:res_query.c 12.0$";
X#endif
X
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)res_query.c	5.4 (Berkeley) 4/21/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <ctype.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <errno.h>
X#include <strings.h>
X#include <arpa/inet.h>
X#include <arpa/nameser.h>
X#include <resolv.h>
X
X#if PACKETSZ > 1024
X#define MAXPACKET	PACKETSZ
X#else
X#define MAXPACKET	1024
X#endif
X
Xextern int errno;
Xint h_errno;
X
X/*
X * Formulate a normal query, send, and await answer.
X * Returned answer is placed in supplied buffer "answer".
X * Perform preliminary check of answer, returning success only
X * if no error is indicated and the answer count is nonzero.
X * Return the size of the response on success, -1 on error.
X * Error number is left in h_errno.
X * Caller must parse answer and determine whether it answers the question.
X */
Xres_query(name, class, type, answer, anslen)
X	char *name;		/* domain name */
X	int class, type;	/* class and type of query */
X	u_char *answer;		/* buffer to put answer */
X	int anslen;		/* size of answer buffer */
X{
X	char buf[MAXPACKET];
X	HEADER *hp;
X	int n;
X
X	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
X		return (-1);
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG)
X		printf("res_query(%s, %d, %d)\n", name, class, type);
X#endif
X	n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
X	    buf, sizeof(buf));
X
X	if (n <= 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_query: mkquery failed\n");
X#endif
X		h_errno = NO_RECOVERY;
X		return (n);
X	}
X	n = res_send(buf, n, answer, anslen);
X	if (n < 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("res_query: send error\n");
X#endif
X		h_errno = TRY_AGAIN;
X		return(n);
X	}
X
X	hp = (HEADER *) answer;
X	if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
X#ifdef DEBUG
X		if (_res.options & RES_DEBUG)
X			printf("rcode = %d, ancount=%d\n", hp->rcode,
X			    ntohs(hp->ancount));
X#endif
X		switch (hp->rcode) {
X			case NXDOMAIN:
X				h_errno = HOST_NOT_FOUND;
X				break;
X			case SERVFAIL:
X				h_errno = TRY_AGAIN;
X				break;
X			case NOERROR:
X				h_errno = NO_DATA;
X				break;
X			case FORMERR:
X			case NOTIMP:
X			case REFUSED:
X			default:
X				h_errno = NO_RECOVERY;
X				break;
X		}
X		return (-1);
X	}
X	return(n);
X}
X
X/*
X * Formulate a normal query, send, and retrieve answer in supplied buffer.
X * Return the size of the response on success, -1 on error.
X * If enabled, implement search rules until answer or unrecoverable failure
X * is detected.  Error number is left in h_errno.
X * Only useful for queries in the same name hierarchy as the local host
X * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
X */
Xres_search(name, class, type, answer, anslen)
X	char *name;		/* domain name */
X	int class, type;	/* class and type of query */
X	u_char *answer;		/* buffer to put answer */
X	int anslen;		/* size of answer */
X{
X	register char *cp, **domain;
X	int n, ret, got_nodata = 0;
X	char *hostalias();
X
X	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
X		return (-1);
X
X	errno = 0;
X	h_errno = HOST_NOT_FOUND;		/* default, if we never query */
X	for (cp = name, n = 0; *cp; cp++)
X		if (*cp == '.')
X			n++;
X	if (n == 0 && (cp = hostalias(name)))
X		return (res_query(cp, class, type, answer, anslen));
X
X	if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
X	    for (domain = _res.dnsrch; *domain; domain++) {
X		ret = res_querydomain(name, *domain, class, type,
X		    answer, anslen);
X		if (ret > 0)
X			return (ret);
X		/*
X		 * If no server present, give up.
X		 * If name isn't found in this domain,
X		 * keep trying higher domains in the search list
X		 * (if that's enabled).
X		 * On a NO_DATA error, keep trying, otherwise
X		 * a wildcard entry of another type could keep us
X		 * from finding this entry higher in the domain.
X		 * If we get some other error (non-authoritative negative
X		 * answer or server failure), then stop searching up,
X		 * but try the input name below in case it's fully-qualified.
X		 */
X		if (errno == ECONNREFUSED) {
X			h_errno = TRY_AGAIN;
X			return (-1);
X		}
X		if (h_errno == NO_DATA)
X			got_nodata++;
X		if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
X		    (_res.options & RES_DNSRCH) == 0)
X			break;
X	}
X	/*
X	 * If the search/default failed, try the name as fully-qualified,
X	 * but only if it contained at least one dot (even trailing).
X	 */
X	if (n)
X		return (res_querydomain(name, (char *)NULL, class, type,
X		    answer, anslen));
X	if (got_nodata)
X		h_errno = NO_DATA;
X	return (-1);
X}
X
X/*
X * Perform a call on res_query on the concatenation of name and domain,
X * removing a trailing dot from name if domain is NULL.
X */
Xres_querydomain(name, domain, class, type, answer, anslen)
X	char *name, *domain;
X	int class, type;	/* class and type of query */
X	u_char *answer;		/* buffer to put answer */
X	int anslen;		/* size of answer */
X{
X	char nbuf[2*MAXDNAME+2];
X	char *longname = nbuf;
X	int n;
X
X#ifdef DEBUG
X	if (_res.options & RES_DEBUG)
X		printf("res_querydomain(%s, %s, %d, %d)\n",
X		    name, domain, class, type);
X#endif
X	if (domain == NULL) {
X		/*
X		 * Check for trailing '.';
X		 * copy without '.' if present.
X		 */
X		n = strlen(name) - 1;
X		if (name[n] == '.' && n < sizeof(nbuf) - 1) {
X			bcopy(name, nbuf, n);
X			nbuf[n] = '\0';
X		} else
X			longname = name;
X	} else
X		(void)sprintf(nbuf, "%.*s.%.*s",
X		    MAXDNAME, name, MAXDNAME, domain);
X
X	return (res_query(longname, class, type, answer, anslen));
X}
X
Xchar *
Xhostalias(name)
X	register char *name;
X{
X	register char *C1, *C2;
X	FILE *fp;
X	char *file, *getenv(), *strcpy(), *strncpy();
X	char buf[BUFSIZ];
X	static char abuf[MAXDNAME];
X
X	file = getenv("HOSTALIASES");
X	if (file == NULL || (fp = fopen(file, "r")) == NULL)
X		return (NULL);
X	buf[sizeof(buf) - 1] = '\0';
X	while (fgets(buf, sizeof(buf), fp)) {
X		for (C1 = buf; *C1 && !isspace(*C1); ++C1);
X		if (!*C1)
X			break;
X		*C1 = '\0';
X		if (!strcasecmp(buf, name)) {
X			while (isspace(*++C1));
X			if (!*C1)
X				break;
X			for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
X			abuf[sizeof(abuf) - 1] = *C2 = '\0';
X			(void)strncpy(abuf, C1, sizeof(abuf) - 1);
X			fclose(fp);
X			return (abuf);
X		}
X	}
X	fclose(fp);
X	return (NULL);
X}
END-of-net/res_query.c
exit


Eric Brunner, Consultant, IBM AWD Palo Alto	(415) 855-4486
inet: brunner@monet.berkeley.edu
uucp: uunet!ibmsupt!brunner