/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2001 by Sun Microsystems, Inc. * All rights reserved. */ #include "sun_msgfmt.h" static const char *mandatory_fields[] = { "Project-Id-Version", "PO-Revision-Date", "Last-Translator", "Language-Team", "Content-Type", "Content-Transfer-Encoding", NULL }; static const char *mandatory_fields_new[] = { "POT-Creation-Date", "Plural-Forms", NULL }; extern int verbose; extern void invoke_gnu_msgfmt(void); static size_t get_one_line(char **bufhead, char **mbuf, size_t *fsize) { size_t len; char *p = *mbuf; char *q, *tmp; if (*bufhead) { free(*bufhead); *bufhead = NULL; } if (*fsize == 0) { /* eof */ return (0); } q = p; while (((*fsize) != 0) && (*p++ != '\n')) { (*fsize)--; } len = p - q; if (len == 0) { return (0); } tmp = (char *)Xmalloc(len + 1); (void) memcpy(tmp, q, len); tmp[len] = '\0'; *bufhead = tmp; *mbuf = p; return (len); } void check_gnu(char *addr, size_t fsize) { int i; char c, mc; char *linebuf; char *mbuf, *p, *buf; unsigned int n; size_t ln_size; size_t bufsize, index; size_t size = fsize; int quotefound = 0; const char *field; buf = NULL; linebuf = NULL; mbuf = addr; loop: ln_size = get_one_line(&linebuf, &mbuf, &size); if ((ln_size == (size_t)-1) || (ln_size == 0)) { goto no_gnu; } p = linebuf; while ((*p == '#') || (*p == '\n')) { ln_size = get_one_line(&linebuf, &mbuf, &size); if ((ln_size == (size_t)-1) || (ln_size == 0)) { goto no_gnu; } p = linebuf; } if (strncmp(p, "domain", 6) == 0) goto loop; if (strncmp(p, "msgid", 5) != 0) { /* error */ goto no_gnu; } p += 5; if ((*p != ' ') && (*p != '\t') && (*p != '\n') && (*p != '\0')) { /* no space after msgid */ goto no_gnu; } /* skip spaces */ while ((*p == ' ') || (*p == '\t')) p++; /* check if this entry is an empty string */ if ((*p != '\"') || (*(p + 1) != '\"')) { /* this is not an empty string */ goto no_gnu; } p += 2; while (*p && ((*p == ' ') || (*p == '\t'))) { p++; } if ((*p != '\n') && (*p != '\0')) { /* other characters than '\n' and '\0' found */ goto no_gnu; } for (; ; ) { ln_size = get_one_line(&linebuf, &mbuf, &size); if ((ln_size == (size_t)-1) || (ln_size == 0)) { goto no_gnu; } p = linebuf; /* skip leading spaces */ while ((*p == ' ') || (*p == '\t')) p++; if (*p != '\"') { if (strncmp(p, "msgstr", 6) == 0) { break; } /* not a valid entry */ goto no_gnu; } if (*(p + 1) != '\"') { /* not an empty string */ goto no_gnu; } p += 2; while ((*p == ' ') || (*p == '\t')) p++; if ((*p != '\n') && (*p != '\0')) { /* other characters than '\n' and '\0' found */ goto no_gnu; } } /* * msgid for the header entry found * Now p points to "msgstr" */ p += 6; if ((*p != ' ') && (*p != '\t') && (*p != '\n') && (*p != '\0')) { /* no space after msgid */ goto no_gnu; } /* skip spaces */ while ((*p == ' ') || (*p == '\t')) p++; if (*p != '\"') { /* no quote */ goto no_gnu; } bufsize = ln_size + 1; index = 0; buf = (char *)Xmalloc(bufsize); for (; ; ) { if (*p != '\"') { /* msgstr entry ends */ buf[index] = '\0'; break; } if (*p++ != '\"') { /* no beginning quote */ goto no_gnu; } while (*p) { switch (mc = *p++) { case '\n': if (!quotefound) { /* error */ goto no_gnu; } break; case '\"': quotefound = 1; break; case '\\': if (!*p) break; switch (c = *p++) { case 'b': buf[index++] = '\b'; break; case 'f': buf[index++] = '\f'; break; case 'n': buf[index++] = '\n'; break; case 'r': buf[index++] = '\r'; break; case 't': buf[index++] = '\t'; break; case 'v': buf[index++] = '\v'; break; case 'a': buf[index++] = '\a'; break; case '\"': case '\\': case '\'': case '?': buf[index++] = c; break; default: if (isdigit((unsigned char)c)) { unsigned int x; unsigned char *up = (unsigned char *)p; n = c - '0'; if (isdigit(*up)) { x = *up++ - '0'; n = 8 * n + x; if (isdigit(*up)) { x = *up++ - '0'; n = 8 * n + x; } } p = (char *)up; buf[index++] = n; } break; } break; default: buf[index++] = mc; break; } if (quotefound) { while (*p && ((*p == ' ') || (*p == '\t'))) { p++; } if ((*p != '\n') && (*p != '\0')) { goto no_gnu; } quotefound = 0; break; } } ln_size = get_one_line(&linebuf, &mbuf, &size); if ((ln_size == (size_t)-1) || (ln_size == 0)) { goto no_gnu; } p = linebuf; /* skip spaces */ while ((*p == ' ') || (*p == '\t')) p++; bufsize += ln_size; buf = (char *)Xrealloc(buf, bufsize); } for (i = 0; (field = mandatory_fields[i]) != NULL; i++) { if (strstr(buf, field) == NULL) continue; /* one of mandatory fields found */ free(linebuf); free(buf); (void) munmap(addr, fsize); if (verbose) diag(gettext(DIAG_GNU_FOUND)); invoke_gnu_msgfmt(); /* NOTREACHED */ } for (i = 0; (field = mandatory_fields_new[i]) != NULL; i++) { if (strstr(buf, field) == NULL) continue; /* one of mandatory fields found */ free(linebuf); free(buf); (void) munmap(addr, fsize); if (verbose) diag(gettext(DIAG_GNU_FOUND)); invoke_gnu_msgfmt(); /* NOTREACHED */ } no_gnu: free(linebuf); if (buf) free(buf); }