Ejemplo n.º 1
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));
}
Ejemplo n.º 2
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);
}