/* * 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)); }
/* * 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); }