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