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); }
int main(int argc, char **argv) { int ret; static struct flags flag; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); oargv = argv; ret = parse_option(&argc, &argv, &flag); if (ret == -1) { usage(); /* NOTREACHED */ } if (flag.sun_p) { /* never invoke gnu msgfmt */ if (flag.gnu_p) { error(gettext(ERR_GNU_ON_SUN)); /* NOTREACHED */ } sun_p = flag.sun_p; } if (flag.idir) { inputdir = flag.idir; } if (flag.ofile) { oflag = 1; outfile = flag.ofile; } if (flag.verbose) { verbose = 1; } if (flag.version) { printf("illumos msgfmt version 5.11 (GNU compatible)\n"); return (0); } if (flag.gnu_p) { /* invoke /usr/lib/gmsgfmt */ invoke_gnu_msgfmt(); /* NOTREACHED */ } if (argc == 0) { usage(); /* NOTREACHED */ } /* * read all portable object files specified in command arguments. * Allocate initial size for msgid and msgstr. If it needs more * spaces, realloc later. */ gmsgid = (char *)Xmalloc(MAX_VALUE_LEN); gmsgstr = (char *)Xmalloc(MAX_VALUE_LEN); gmsgid_size = gmsgstr_size = MAX_VALUE_LEN; (void) memset(gmsgid, 0, gmsgid_size); (void) memset(gmsgstr, 0, gmsgstr_size); mbcurmax = MB_CUR_MAX; while (argc-- > 0) { if (verbose) { diag(gettext(DIAG_START_PROC), *argv); } read_psffm(*argv++); } output_all_mo_files(); #ifdef DEBUG printlist(); #endif return (0); } /* main */