1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "sun_msgfmt.h" 30 31 static const char *mandatory_fields[] = { 32 "Project-Id-Version", 33 "PO-Revision-Date", 34 "Last-Translator", 35 "Language-Team", 36 "Content-Type", 37 "Content-Transfer-Encoding", 38 NULL 39 }; 40 41 static const char *mandatory_fields_new[] = { 42 "POT-Creation-Date", 43 "Plural-Forms", 44 NULL 45 }; 46 47 extern int verbose; 48 49 extern void invoke_gnu_msgfmt(void); 50 51 static size_t 52 get_one_line(char **bufhead, char **mbuf, size_t *fsize) 53 { 54 size_t len; 55 char *p = *mbuf; 56 char *q, *tmp; 57 58 if (*bufhead) { 59 free(*bufhead); 60 *bufhead = NULL; 61 } 62 63 if (*fsize == 0) { 64 /* eof */ 65 return (0); 66 } 67 68 q = p; 69 while (((*fsize) != 0) && (*p++ != '\n')) { 70 (*fsize)--; 71 } 72 len = p - q; 73 if (len == 0) { 74 return (0); 75 } 76 tmp = (char *)Xmalloc(len + 1); 77 (void) memcpy(tmp, q, len); 78 tmp[len] = '\0'; 79 *bufhead = tmp; 80 *mbuf = p; 81 return (len); 82 } 83 84 void 85 check_gnu(char *addr, size_t fsize) 86 { 87 int i; 88 char c, mc; 89 char *linebuf; 90 char *mbuf, *p, *buf; 91 unsigned int n; 92 size_t ln_size; 93 size_t bufsize, index; 94 size_t size = fsize; 95 int quotefound = 0; 96 const char *field; 97 98 buf = NULL; 99 linebuf = NULL; 100 mbuf = addr; 101 102 loop: 103 ln_size = get_one_line(&linebuf, &mbuf, &size); 104 if ((ln_size == (size_t)-1) || 105 (ln_size == 0)) { 106 goto no_gnu; 107 } 108 p = linebuf; 109 110 while ((*p == '#') || (*p == '\n')) { 111 ln_size = get_one_line(&linebuf, &mbuf, &size); 112 if ((ln_size == (size_t)-1) || 113 (ln_size == 0)) { 114 goto no_gnu; 115 } 116 p = linebuf; 117 } 118 119 if (strncmp(p, "domain", 6) == 0) 120 goto loop; 121 122 if (strncmp(p, "msgid", 5) != 0) { 123 /* error */ 124 goto no_gnu; 125 } 126 127 p += 5; 128 if ((*p != ' ') && (*p != '\t') && 129 (*p != '\n') && (*p != '\0')) { 130 /* no space after msgid */ 131 goto no_gnu; 132 } 133 /* skip spaces */ 134 while ((*p == ' ') || (*p == '\t')) 135 p++; 136 137 /* check if this entry is an empty string */ 138 if ((*p != '\"') || (*(p + 1) != '\"')) { 139 /* this is not an empty string */ 140 goto no_gnu; 141 } 142 p += 2; 143 while (*p && ((*p == ' ') || (*p == '\t'))) { 144 p++; 145 } 146 if ((*p != '\n') && (*p != '\0')) { 147 /* other characters than '\n' and '\0' found */ 148 goto no_gnu; 149 } 150 151 for (; ; ) { 152 ln_size = get_one_line(&linebuf, &mbuf, &size); 153 if ((ln_size == (size_t)-1) || 154 (ln_size == 0)) { 155 goto no_gnu; 156 } 157 p = linebuf; 158 /* skip leading spaces */ 159 while ((*p == ' ') || (*p == '\t')) 160 p++; 161 162 if (*p != '\"') { 163 if (strncmp(p, "msgstr", 6) == 0) { 164 break; 165 } 166 /* not a valid entry */ 167 goto no_gnu; 168 } 169 if (*(p + 1) != '\"') { 170 /* not an empty string */ 171 goto no_gnu; 172 } 173 p += 2; 174 while ((*p == ' ') || (*p == '\t')) 175 p++; 176 177 if ((*p != '\n') && (*p != '\0')) { 178 /* other characters than '\n' and '\0' found */ 179 goto no_gnu; 180 } 181 } 182 183 /* 184 * msgid for the header entry found 185 * Now p points to "msgstr" 186 */ 187 p += 6; 188 if ((*p != ' ') && (*p != '\t') && 189 (*p != '\n') && (*p != '\0')) { 190 /* no space after msgid */ 191 goto no_gnu; 192 } 193 194 /* skip spaces */ 195 while ((*p == ' ') || (*p == '\t')) 196 p++; 197 198 if (*p != '\"') { 199 /* no quote */ 200 goto no_gnu; 201 } 202 203 bufsize = ln_size + 1; 204 index = 0; 205 buf = (char *)Xmalloc(bufsize); 206 207 for (; ; ) { 208 if (*p != '\"') { 209 /* msgstr entry ends */ 210 buf[index] = '\0'; 211 break; 212 } 213 214 if (*p++ != '\"') { 215 /* no beginning quote */ 216 goto no_gnu; 217 } 218 while (*p) { 219 switch (mc = *p++) { 220 case '\n': 221 if (!quotefound) { 222 /* error */ 223 goto no_gnu; 224 } 225 break; 226 case '\"': 227 quotefound = 1; 228 break; 229 case '\\': 230 if (!*p) 231 break; 232 switch (c = *p++) { 233 case 'b': 234 buf[index++] = '\b'; 235 break; 236 case 'f': 237 buf[index++] = '\f'; 238 break; 239 case 'n': 240 buf[index++] = '\n'; 241 break; 242 case 'r': 243 buf[index++] = '\r'; 244 break; 245 case 't': 246 buf[index++] = '\t'; 247 break; 248 case 'v': 249 buf[index++] = '\v'; 250 break; 251 case 'a': 252 buf[index++] = '\a'; 253 break; 254 case '\"': 255 case '\\': 256 case '\'': 257 case '?': 258 buf[index++] = c; 259 break; 260 default: 261 if (isdigit((unsigned char)c)) { 262 unsigned int x; 263 unsigned char *up = 264 (unsigned char *)p; 265 n = c - '0'; 266 if (isdigit(*up)) { 267 x = *up++ - '0'; 268 n = 8 * n + x; 269 if (isdigit(*up)) { 270 x = *up++ - '0'; 271 n = 8 * n + x; 272 } 273 } 274 p = (char *)up; 275 buf[index++] = n; 276 } 277 break; 278 } 279 break; 280 default: 281 buf[index++] = mc; 282 break; 283 } 284 if (quotefound) { 285 while (*p && ((*p == ' ') || (*p == '\t'))) { 286 p++; 287 } 288 if ((*p != '\n') && (*p != '\0')) { 289 goto no_gnu; 290 } 291 quotefound = 0; 292 break; 293 } 294 } 295 ln_size = get_one_line(&linebuf, &mbuf, &size); 296 if ((ln_size == (size_t)-1) || 297 (ln_size == 0)) { 298 goto no_gnu; 299 } 300 p = linebuf; 301 /* skip spaces */ 302 while ((*p == ' ') || (*p == '\t')) 303 p++; 304 bufsize += ln_size; 305 buf = (char *)Xrealloc(buf, bufsize); 306 } 307 308 for (i = 0; (field = mandatory_fields[i]) != NULL; i++) { 309 if (strstr(buf, field) == NULL) 310 continue; 311 /* one of mandatory fields found */ 312 free(linebuf); 313 free(buf); 314 (void) munmap(addr, fsize); 315 if (verbose) 316 diag(gettext(DIAG_GNU_FOUND)); 317 invoke_gnu_msgfmt(); 318 /* NOTREACHED */ 319 } 320 for (i = 0; (field = mandatory_fields_new[i]) != NULL; i++) { 321 if (strstr(buf, field) == NULL) 322 continue; 323 /* one of mandatory fields found */ 324 free(linebuf); 325 free(buf); 326 (void) munmap(addr, fsize); 327 if (verbose) 328 diag(gettext(DIAG_GNU_FOUND)); 329 invoke_gnu_msgfmt(); 330 /* NOTREACHED */ 331 } 332 333 no_gnu: 334 free(linebuf); 335 if (buf) 336 free(buf); 337 } 338