Exemplo n.º 1
0
static char *
handle_type_mo(Msg_node *mnp, struct msg_pack *mp)
{
	char	*result;

	switch (mnp->type) {
	case T_ILL_MO:
		/* invalid MO */
		return (NULL);
	case T_SUN_MO:
		/* Sun MO found */
		mp->status |= ST_SUN_MO_FOUND;

		if (mp->plural) {
			/*
			 * *ngettext is called against
			 * Sun MO file
			 */
			int	exp = (mp->n == 1);
			result = (char *)mp->msgid1;
			if (!exp)
				result = (char *)mp->msgid2;
			return (result);
		}
		result = key_2_text(mnp->msg.sunmsg, mp->msgid1);
		if (!mnp->trusted) {
			result = check_format(mp->msgid1, result, 0);
		}
		return (result);
	case T_GNU_MO:
		/* GNU MO found */
		mp->status |= ST_GNU_MO_FOUND;

		result = gnu_key_2_text(mnp->msg.gnumsg,
		    get_codeset(mp->domain), mp);

		if (result == mp->msgid1 || result == mp->msgid2) {
			/* no valid msg found */
			return (result);
		}

		/* valid msg found */
		mp->status |= ST_GNU_MSG_FOUND;

		if (!mnp->trusted) {
			result = check_format(mp->msgid1, result, 0);
			if (result == mp->msgid1) {
				DFLTMSG(result, mp->msgid1, mp->msgid2,
				    mp->n, mp->plural);
			}
		}
		return (result);
	default:
		/* this should never happen */
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}
	/* NOTREACHED */
}
Exemplo n.º 2
0
static char *
handle_gnu_mo(struct cache_pack *cp, struct msg_pack *mp,
	Gettext_t *gt)
{
	char	*result;
	char	*codeset = get_codeset(mp->domain);

	result = gnu_key_2_text(cp->mnp->msg.gnumsg, codeset, mp);
	if (mp->plural) {
		if (((result == mp->msgid1) && (mp->n == 1)) ||
			((result == mp->msgid2) && (mp->n != 1))) {
			return (NULL);
		}
	} else {
		if (result == mp->msgid1) {
			return (NULL);
		}
	}
	gt->c_m_node = cp->mnp;
	if (!cp->mnp->trusted) {
		result = check_format(mp->msgid1, result, 0);
		if (result == mp->msgid1) {
			DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
				mp->plural);
		}
	}
	return (result);
}
Exemplo n.º 3
0
/*
 * dfltmsgstr
 *
 * choose an appropriate message by evaluating the plural expression,
 * and return it.
 */
static char *
dfltmsgstr(Msg_g_node *gmnp, const char *msgstr, size_t msgstr_len,
	struct msg_pack *mp)
{
	unsigned int	pindex;
	size_t	len;
	const char	*p;

#ifdef GETTEXT_DEBUG
	(void) printf("*************** dfltmsgstr(0x%p, \"%s\", %d, 0x%p)\n",
		(void *)gmnp,
		msgstr ? msgstr : "(null)", msgstr_len, (void *)mp);
	printgnumsg(gmnp, 0);
	printmp(mp, 0);
#endif

	if (mp->plural) {
		if (gmnp->plural) {
			pindex = plural_eval(gmnp->plural, mp->n);
		} else {
			/*
			 * This mo does not have plural information.
			 * Using the English form.
			 */
			if (mp->n == 1)
				pindex = 0;
			else
				pindex = 1;
		}
#ifdef GETTEXT_DEBUG
		(void) printf("plural_eval returned: %d\n", pindex);
#endif
		if (pindex >= gmnp->nplurals) {
			/* should never happen */
			pindex = 0;
		}
		p = msgstr;
		for (; pindex != 0; pindex--) {
			len = msgstr_len - (p - msgstr);
			p = memchr(p, '\0', len);
			if (!p) {
				/*
				 * null byte not found
				 * this should never happen
				 */
				char	*result;
				DFLTMSG(result, mp->msgid1, mp->msgid2,
					mp->n, mp->plural);
				return (result);
			}
			p++;		/* skip */
		}
		return ((char *)p);
	}

	return ((char *)msgstr);
}
Exemplo n.º 4
0
char *
_real_gettext_u(const char *domain, const char *msgid1, const char *msgid2,
    unsigned long int ln, int category, int plural)
{
	char	msgfile[MAXPATHLEN]; 	/* 1024 */
	char	mydomain[TEXTDOMAINMAX + 1]; /* 256 + 1 */
	char	*cur_binding;	/* points to current binding in list */
	char	*cur_locale, *cur_domain, *result, *nlspath;
	char	*msgloc, *cb, *cur_domain_binding;
	char	*language;
	unsigned int	n = (unsigned int)ln;	/* we don't need long for n */
	uint32_t	cur_domain_len, cblen;
	uint32_t	hash_domain;
	struct msg_pack	*mp, omp;

#ifdef GETTEXT_DEBUG
	gprintf(0, "*************** _real_gettext_u(\"%s\", \"%s\", "
	    "\"%s\", %d, %d, %d)\n",
	    domain ? domain : "NULL", msgid1 ? msgid1 : "NULL",
	    msgid2 ? msgid2 : "NULL", n, category, plural);
	gprintf(0, "***************** global_gt: 0x%p\n", global_gt);
	printgt(global_gt, 1);
#endif

	if (msgid1 == NULL)
		return (NULL);

	mp = memset(&omp, 0, sizeof (omp));	/* msg pack */

	/*
	 * category may be LC_MESSAGES or LC_TIME
	 * locale contains the value of 'category'
	 */
	cur_locale = setlocale(category, NULL);

	language = getenv("LANGUAGE"); /* for GNU */
	if (language) {
		if (!*language || strchr(language, '/') != NULL) {
			/*
			 * LANGUAGE is an empty string or
			 * LANGUAGE contains '/'.
			 * Ignore it.
			 */
			language = NULL;
		}
	}

	/*
	 * Query the current domain if domain argument is NULL pointer
	 */
	mydomain[0] = '\0';
	if (domain == NULL) {
		/*
		 * if NULL is specified for domainname,
		 * use the currently bound domain.
		 */
		cur_domain = _textdomain_u(NULL, mydomain);
	} else if (!*domain) {
		/*
		 * if an empty string is specified
		 */
		cur_domain = DEFAULT_DOMAIN;
	} else {
		cur_domain = (char *)domain;
	}

	hash_domain = get_hashid(cur_domain, &cur_domain_len);
	if (cur_domain_len > TEXTDOMAINMAX) {
		/* domain is invalid, return msg_id */
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	nlspath = getenv("NLSPATH"); /* get the content of NLSPATH */
	if (nlspath == NULL || !*nlspath) {
		/* no NLSPATH is defined in the environ */
		if ((*cur_locale == 'C') && (*(cur_locale + 1) == '\0')) {
			/*
			 * If C locale,
			 * return the original msgid immediately.
			 */
			DFLTMSG(result, msgid1, msgid2, n, plural);
			return (result);
		}
		nlspath = NULL;
	} else {
		/* NLSPATH is set */
		int	ret;

		msgloc = setlocale(LC_MESSAGES, NULL);

		ret = process_nlspath(cur_domain, msgloc,
		    (const char *)nlspath, &cur_binding);
		if (ret == -1) {
			/* error occurred */
			DFLTMSG(result, msgid1, msgid2, n, plural);
			return (result);
		} else if (ret == 0) {
			nlspath = NULL;
		}
	}

	cur_domain_binding = _real_bindtextdomain_u(cur_domain,
	    NULL, TP_BINDING);
	if (cur_domain_binding == NULL) {
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	mp->msgid1 = msgid1;
	mp->msgid2 = msgid2;
	mp->msgfile = msgfile;
	mp->domain = cur_domain;
	mp->binding = cur_domain_binding;
	mp->locale = cur_locale;
	mp->language = language;
	mp->domain_len = cur_domain_len;
	mp->n = n;
	mp->category = category;
	mp->plural = plural;
	mp->hash_domain = hash_domain;

	/*
	 * Spec1170 requires that we use NLSPATH if it's defined, to
	 * override any system default variables.  If NLSPATH is not
	 * defined or if a message catalog is not found in any of the
	 * components (bindings) specified by NLSPATH, dcgettext_u() will
	 * search for the message catalog in either a) the binding path set
	 * by any previous application calls to bindtextdomain() or
	 * b) the default binding path (/usr/lib/locale).  Save the original
	 * binding path so that we can search it if the message catalog
	 * is not found via NLSPATH.  The original binding is restored before
	 * returning from this routine because the gettext routines should
	 * not change the binding set by the application.  This allows
	 * bindtextdomain() to be called once for all gettext() calls in the
	 * application.
	 */

	/*
	 * First, examine NLSPATH
	 */
	if (nlspath) {
		/*
		 * NLSPATH binding has been successfully built
		 */
#ifdef GETTEXT_DEBUG
		gprintf(0, "************************** examining NLSPATH\n");
		gprintf(0, "       cur_binding: \"%s\"\n",
		    cur_binding ? cur_binding : "(null)");
#endif

		mp->nlsp = 1;
		/*
		 * cur_binding always ends with ':' before a null
		 * termination.
		 */
		while (*cur_binding) {
			cb = cur_binding;
			while (*cur_binding != ':')
				cur_binding++;
			cblen = cur_binding - cb;
			cur_binding++;
			if (cblen >= MAXPATHLEN) {
				/* cur_binding too long */
				DFLTMSG(result, msgid1, msgid2, n, plural);
				return (result);
			}

			(void) memcpy(mp->msgfile, cb, cblen);
			*(mp->msgfile + cblen) = '\0';

#ifdef GETTEXT_DEBUG
			gprintf(0, "*******************"
			    "********************* \n");
			gprintf(0, "       msgfile: \"%s\"\n",
			    msgfile ? msgfile : "(null)");
			gprintf(0, "*******************"
			    "********************* \n");
#endif
			result = handle_mo(mp);
			if (result) {
				return (result);
			}
		}
	}

	mp->nlsp = 0;
	mp->binding = cur_domain_binding;
	/*
	 * Next, examine LANGUAGE
	 */
	if (language) {
		char	*ret_msg;
		ret_msg = handle_lang(mp);
		if (ret_msg != NULL) {
			/* valid msg found in GNU MO */
			return (ret_msg);
		}
		/*
		 * handle_lang() may have overridden locale
		 */
		mp->locale = cur_locale;
		mp->status = 0;
	}

	/*
	 * Finally, handle a single binding
	 */
#ifdef GETTEXT_DEBUG
	*mp->msgfile = '\0';
#endif
	if (mk_msgfile(mp) == NULL) {
		DFLTMSG(result, msgid1, msgid2, n, plural);
		return (result);
	}

	result = handle_mo(mp);
	if (result) {
		return (result);
	}
	DFLTMSG(result, msgid1, msgid2, n, plural);
	return (result);
} /* _real_gettext_u */
Exemplo n.º 5
0
/*
 * handle_mo() returns NULL if invalid MO found.
 */
char *
handle_mo(struct msg_pack *mp)
{
	int	fd;
	char	*result;
	struct stat64	statbuf;
	Msg_node	*mnp;
	Gettext_t	*gt = global_gt;

#define	CONNECT_ENTRY	\
	mnp->next = gt->m_node; \
	gt->m_node = mnp; \
	gt->c_m_node = mnp

#ifdef GETTEXT_DEBUG
	gprintf(0, "*************** handle_mo(0x%p)\n", (void *)mp);
	printmp(mp, 1);
#endif

	mnp = check_cache(mp);

	if (mnp != NULL) {
		/* cache found */
		return (handle_type_mo(mnp, mp));
	}

	/*
	 * Valid entry not found in the cache
	 */
	mnp = calloc(1, sizeof (Msg_node));
	if (mnp == NULL) {
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}
	mnp->hashid = mp->hash_domain;
	mnp->path = strdup(mp->msgfile);
	if (mnp->path == NULL) {
		free(mnp);
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}

	fd = nls_safe_open(mp->msgfile, &statbuf, &mp->trusted, !mp->nlsp);
	if ((fd == -1) || (statbuf.st_size > LONG_MAX)) {
		if (fd != -1)
			(void) close(fd);
		mnp->type = T_ILL_MO;
		CONNECT_ENTRY;
		return (NULL);
	}
	mp->fsz = (size_t)statbuf.st_size;
	mp->addr = mmap(NULL, mp->fsz, PROT_READ, MAP_SHARED, fd, 0);
	(void) close(fd);

	if (mp->addr == MAP_FAILED) {
		free(mnp->path);
		free(mnp);
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}

	if (setmsg(mnp, (char *)mp->addr, mp->fsz) == -1) {
		free(mnp->path);
		free(mnp);
		(void) munmap(mp->addr, mp->fsz);
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}
	mnp->trusted = mp->trusted;
	CONNECT_ENTRY;

	return (handle_type_mo(mnp, mp));
}
Exemplo n.º 6
0
/*
 * gnu_key_2_text
 *
 * Extracts msgstr from the GNU MO file
 */
char *
gnu_key_2_text(Msg_g_node *gmnp, const char *codeset,
	struct msg_pack *mp)
{
	char	*result, *msgstr;
	size_t	msgstr_len;
	unsigned int	midx;
	int	ret;
	char	*conv_msgstr, *conv_dst;
	size_t	*p;
	size_t	conv_msgstr_len, buflen;
	iconv_t	fd;
	int	conversion, new_encoding;
	unsigned int	num_of_str;

#ifdef GETTEXT_DEBUG
	(void) printf("*************** gnu_key_2_text("
		"0x%p, \"%s\", 0x%p)\n",
		(void *)gmnp, codeset ? codeset : "(null)", (void *)mp);
	printgnumsg(gmnp, 0);
	printmp(mp, 0);
#endif

	/* first checks if header entry has been processed */
	if (!(gmnp->flag & ST_CHK)) {
		char	*msg_header;

		msg_header = gnu_msgsearch(gmnp, "", NULL, NULL);
		ret = parse_header((const char *)msg_header, gmnp);
		if (ret == -1) {
			/* fatal error */
			DFLTMSG(result, mp->msgid1, mp->msgid2,
				mp->n, mp->plural);
			return (result);
		}
		gmnp->flag |= ST_CHK;
	}
	msgstr = gnu_msgsearch(gmnp, mp->msgid1, &msgstr_len, &midx);
	if (msgstr == mp->msgid1) {
		/* not found */
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		return (result);
	}

#ifdef GETTEXT_DEBUG
	printgnumsg(gmnp, 0);
#endif
	if (!gmnp->dst_encoding) {
		/*
		 * destination encoding has not been set.
		 */
		char	*dupcodeset = strdup(codeset);
		if (!dupcodeset) {
			/* strdup failed */
			result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
			return (result);
		}
		gmnp->dst_encoding = dupcodeset;

		if (strcmp(gmnp->dst_encoding, gmnp->src_encoding) == 0) {
			/*
			 * target encoding and src encoding
			 * are the same.
			 * No conversion required.
			 */
			conversion = 0;
		} else {
			/*
			 * target encoding is different from
			 * src encoding.
			 * New conversion required.
			 */
			/* sanity check */
			if (gmnp->fd && (gmnp->fd != (iconv_t)-1)) {
				(void) iconv_close(gmnp->fd);
				gmnp->fd = (iconv_t)-1;
			}
			if (gmnp->conv_msgstr)
				free_conv_msgstr(gmnp);
			conversion = 1;
			new_encoding = 1;
		}
	} else {
		/*
		 * dst encoding has been already set.
		 */
		if (strcmp(gmnp->dst_encoding, codeset) == 0) {
			/*
			 * dst encoding and target encoding are the same.
			 */
			if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
				== 0) {
				/*
				 * dst encoding and src encoding are the same.
				 * No conversion required.
				 */
				conversion = 0;
			} else {
				/*
				 * dst encoding is different from src encoding.
				 * current conversion is valid.
				 */
				conversion = 1;
				new_encoding = 0;
				/* checks if iconv_open has succeeded before */
				if (gmnp->fd == (iconv_t)-1) {
					/*
					 * iconv_open should have failed before
					 * Assume this conversion is invalid
					 */
					conversion = 0;
				} else {
					if (!gmnp->conv_msgstr) {
						/*
						 * memory allocation for
						 * conv_msgstr should
						 * have failed before.
						 */
						new_encoding = 1;
						if (gmnp->fd)
							(void) iconv_close(
								gmnp->fd);
						gmnp->fd = (iconv_t)-1;
					}
				}
			}
		} else {
			/*
			 * dst encoding is different from target encoding.
			 * It has changed since before.
			 */
			char	*dupcodeset = strdup(codeset);
			if (!dupcodeset) {
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			free(gmnp->dst_encoding);
			gmnp->dst_encoding = dupcodeset;
			if (strcmp(gmnp->dst_encoding, gmnp->src_encoding)
				== 0) {
				/*
				 * dst encoding and src encoding are the same.
				 * now, no conversion required.
				 */
				conversion = 0;
			} else {
				/*
				 * dst encoding is different from src encoding.
				 * new conversion required.
				 */
				conversion = 1;
				new_encoding = 1;
			}

			if (gmnp->fd && (gmnp->fd != (iconv_t)-1)) {
				(void) iconv_close(gmnp->fd);
			}
			if (gmnp->fd != (iconv_t)-1) {
				gmnp->fd = (iconv_t)-1;
			}
			if (gmnp->conv_msgstr)
				free_conv_msgstr(gmnp);
		}
	}

	if (conversion == 0) {
		/* no conversion */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	/* conversion required */

	if (new_encoding == 0) {
		/* dst codeset hasn't been changed since before */
		if (!gmnp->conv_msgstr[midx]) {
			/* this msgstr hasn't been converted yet */
			conv_msgstr_len = do_conv(gmnp->fd,
				&conv_dst, (const char *)msgstr, msgstr_len);
			if (conv_msgstr_len == (size_t)-1) {
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			buflen = (conv_msgstr_len + sizeof (size_t));
			/* allign to sizeof (size_t) */
			if (buflen % sizeof (size_t))
				buflen += (sizeof (size_t) -
					(buflen % sizeof (size_t)));
			p = (size_t *)malloc(buflen);
			if (!p) {
				free(conv_dst);
				result = dfltmsgstr(gmnp, msgstr,
					msgstr_len, mp);
				return (result);
			}
			*p = conv_msgstr_len;
			(void) memcpy(p + 1, conv_dst, conv_msgstr_len);
			free(conv_dst);
			gmnp->conv_msgstr[midx] = (char *)p;
			conv_msgstr = (char *)(p + 1);
		} else {
			/* this msgstr is in the conversion cache */
			/* LINTED */
			size_t	*cmsg = (size_t *)gmnp->conv_msgstr[midx];
			conv_msgstr_len = *cmsg;
			conv_msgstr = (char *)(cmsg + 1);
		}
		result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
		return (result);
	}
	/* new conversion */
#ifdef GETTEXT_DEBUG
	(void) printf("******* calling iconv_open()\n");
	(void) printf("      dst: \"%s\", src: \"%s\"\n",
		gmnp->dst_encoding, gmnp->src_encoding);
#endif
	fd = iconv_open(gmnp->dst_encoding, gmnp->src_encoding);
	gmnp->fd = fd;
	if (fd == (iconv_t)-1) {
		/*
		 * iconv_open() failed.
		 * no conversion
		 */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	num_of_str = SWAP(gmnp, gmnp->msg_file_info->num_of_str);
	gmnp->conv_msgstr = (char **)calloc((size_t)num_of_str,
		sizeof (char *));
	if (!gmnp->conv_msgstr) {
		/* malloc failed */
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	conv_msgstr_len = do_conv(gmnp->fd, &conv_dst,
		(const char *)msgstr, msgstr_len);
	if (conv_msgstr_len == (size_t)-1) {
		free_conv_msgstr(gmnp);
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	buflen = (conv_msgstr_len + sizeof (size_t));
	/* allign to sizeof (size_t) */
	if (buflen % sizeof (size_t))
		buflen += (sizeof (size_t) - (buflen % sizeof (size_t)));
	p = (size_t *)malloc(buflen);
	if (!p) {
		free(conv_dst);
		free_conv_msgstr(gmnp);
		result = dfltmsgstr(gmnp, msgstr, msgstr_len, mp);
		return (result);
	}
	*p = conv_msgstr_len;
	(void) memcpy(p + 1, conv_dst, conv_msgstr_len);
	free(conv_dst);
	gmnp->conv_msgstr[midx] = (char *)p;
	conv_msgstr = (char *)(p + 1);
	result = dfltmsgstr(gmnp, conv_msgstr, conv_msgstr_len, mp);
	return (result);
}
Exemplo n.º 7
0
/*
 * handle_lang
 *
 * take care of the LANGUAGE specification
 */
char *
handle_lang(struct cache_pack *cp, struct msg_pack *mp)
{
	Gettext_t *gt = global_gt;
	struct stat64	statbuf;
	const char	*p, *op, *q;
	char	*locale = NULL, *olocale, *result;
	unsigned int	hash_locale;
	size_t	locale_len, olocale_len = 0;
	int	gnu_mo_found = 0;
	int	fd;
	int	ret;

#ifdef GETTEXT_DEBUG
	(void) printf("*************** handle_lang(0x%p, 0x%p)\n",
		(void *)cp, (void *)mp);
	printcp(cp, 0);
	printmp(mp, 0);
#endif

	p = mp->language;

	while (*p) {
		op = p;
		q = strchr(p, ':');
		if (!q) {
			locale_len = strlen(p);
			p += locale_len;
		} else {
			locale_len = q - p;
			p += locale_len + 1;
		}
		if ((locale_len >= MAXPATHLEN) ||
			(locale_len == 0)) {
			/* illegal locale name */
			continue;
		}
		if (olocale_len < locale_len) {
			olocale = locale;
			locale = (char *)realloc(locale, locale_len + 1);
			if (!locale) {
				if (olocale)
					free(olocale);
				DFLTMSG(result, mp->msgid1, mp->msgid2,
					mp->n, mp->plural);
				return (result);
			}
			olocale_len = locale_len;
		}
		(void) memcpy(locale, op, locale_len);
		locale[locale_len] = '\0';
		hash_locale = get_hashid(locale, NULL);
		mp->locale = locale;
		mp->hash_locale = hash_locale;
		mp->locale_len = locale_len;
#ifdef GETTEXT_DEBUG
		*mp->msgfile = '\0';
#endif
		if (mk_msgfile(mp) == NULL) {
			/* illegal locale name */
			continue;
		}

		cp->node_hash = NULL;

		ret = check_cache(cp, mp);
		if (ret) {
			/*
			 * found in cache
			 */
			switch (cp->mnp->type) {
			case T_ILL_MO:
				/* invalid MO */
				continue;
			case T_SUN_MO:
				/* Solaris MO */
				goto out_loop;
			case T_GNU_MO:
				/* GNU MO */
				gnu_mo_found = 1;
				result = handle_gnu_mo(cp, mp, gt);
				if (result) {
					free(locale);
					return (result);
				}
				continue;
			}
			/* NOTREACHED */
		}
		/*
		 * not found in cache
		 */
		fd = nls_safe_open(mp->msgfile, &statbuf, &mp->trusted, 1);
		if ((fd == -1) || (statbuf.st_size > LONG_MAX)) {
			if (connect_invalid_entry(cp, mp) == -1) {
				DFLTMSG(result, mp->msgid1, mp->msgid2,
					mp->n, mp->plural);
				free(locale);
				return (result);
			}
			continue;
		}
		mp->fsz = (size_t)statbuf.st_size;
		mp->addr = mmap(0, mp->fsz, PROT_READ, MAP_SHARED, fd, 0);
		(void) close(fd);

		if (mp->addr == (caddr_t)-1) {
			if (connect_invalid_entry(cp, mp) == -1) {
				DFLTMSG(result, mp->msgid1, mp->msgid2,
					mp->n, mp->plural);
				free(locale);
				return (result);
			}
			continue;
		}

		cp->mnp = create_mnp(mp);
		if (!cp->mnp) {
			free(locale);
			free_mnp_mp(cp->mnp, mp);
			DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
				mp->plural);
			return (result);
		}

		if (setmsg(cp->mnp, (char *)mp->addr, mp->fsz) == -1) {
			free(locale);
			free_mnp_mp(cp->mnp, mp);
			DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n,
				mp->plural);
			return (result);
		}
		if (!cp->cacheline) {
			cp->cnp = create_cnp(cp->mnp, mp);
			if (!cp->cnp) {
				free(locale);
				free_mnp_mp(cp->mnp, mp);
				DFLTMSG(result, mp->msgid1, mp->msgid2,
					mp->n, mp->plural);
				return (result);
			}
		}
		cp->mnp->trusted = mp->trusted;
		connect_entry(cp);

		switch (cp->mnp->type) {
		case T_ILL_MO:
			/* invalid MO */
			continue;
		case T_SUN_MO:
			/* Solaris MO */
			goto out_loop;
		case T_GNU_MO:
			/* GNU MO */
			gnu_mo_found = 1;

			result = handle_gnu_mo(cp, mp, gt);
			if (result) {
				free(locale);
				return (result);
			}
			continue;
		}
		/* NOTREACHED */
	}

out_loop:
	if (gnu_mo_found) {
		DFLTMSG(result, mp->msgid1, mp->msgid2, mp->n, mp->plural);
		free(locale);
		return (result);
	}
	if (locale)
		free(locale);
	return (NULL);
}