/* Functions that emulate UNIX catgets */ /* Kitten version 2021 by Tom Ehlert, */ /* This software is free software; free to use, modify, pass to others, whatever use it at your own risk */ /* Minor modifications to use internal static buffer to keep API compatible * with regular kitten. */ #ifndef NO_KITTEN #include /* sprintf */ #include /* getenv */ #include /* sprintf */ #include /* sprintf */ #include /* sprintf */ #include "kitten.h" #include "kittenc.h" /* Globals */ static char global_nls_buffer[4096] = {0}; /* Functions */ /** * On success, catgets() returns a pointer to an internal * buffer area containing the null-terminated message string. * On failure, catgets() returns the value 'message'. */ const char * _kittengets (int msgID, const char *message) { struct message_header *message_header; // if this is != 0 then init was done if (global_nls_buffer[0] == 0) return message; message_header = (struct message_header *)global_nls_buffer; for ( ; message_header->len != 0; message_header = (struct message_header *)((char*)message_header + message_header->len)) { if (message_header->id== msgID) { return (const char*)message_header + sizeof(struct message_header); } } return message; } /** * Initialize kitten for program (name). */ #define _toupper(c) (c & ~0x20) nl_catd kittenopen (const char *name) { int fd; struct message_end message_end; struct content content[KITTEN_MAX_RESOURCES]; char *language; int i; long len; char exename[_MAX_PATH]; long fileendnow, seekoffset; //printf("kittenopen %s\n", name); if ((fd = open(name, _O_RDONLY | _O_BINARY)) < 0) { sprintf(exename, "%s.exe", name); if ((fd = open(exename, _O_RDONLY | _O_BINARY)) < 0) { printf("can't open %s\n", name); // should never happen return 0; } } fileendnow = lseek(fd, 0, SEEK_END); lseek(fd, - (int)sizeof(struct message_end), SEEK_END); read(fd, &message_end, sizeof(struct message_end)); if (memcmp(message_end.ID, "KITTENC", 8) != 0) { //printf("no KITTENC record found\n"); return 0; } if (message_end.resource_count > KITTEN_MAX_RESOURCES) { printf("resource > %d\n", KITTEN_MAX_RESOURCES); return 0; } seekoffset = fileendnow - message_end.fileend_orig; if (lseek(fd, message_end.filepos+seekoffset, SEEK_SET) != message_end.filepos+seekoffset) { printf("can't seek 1\n"); return 0; } read(fd, &content, sizeof(content[0]) * message_end.resource_count); language = getenv("LANG"); // printf("using language %s\n", language); if (message_end.resource_count == 1) { if (language && _toupper(language[0]) == 'E' && _toupper(language[0]) == 'N') { // set LANG=EN switches to internal strings close(fd); return 0; } // otherwise use the only compiled language i = 0; goto found_my_language; } if (language == NULL) // language not found { // use internal strings close(fd); return 0; } // see if we find our language in the existing resources for (i = 0; i < message_end.resource_count; i++) { if(_toupper(content[i].language[0]) == _toupper(language[0]) && _toupper(content[i].language[1]) == _toupper(language[1])) { goto found_my_language; } } // language not found close(fd); return 0; found_my_language: // found our language // printf(" language %s found between %lx and %lx\n", language, content[i].filepos_start, content[i].filepos_end); // printf("seek %lu --> %lu\n", content[i].filepos_start, content[i].filepos_start+seekoffset); lseek(fd, content[i].filepos_start+seekoffset, SEEK_SET); len = content[i].filepos_end - content[i].filepos_start; if (len > sizeof(global_nls_buffer)) { printf("nls_buffer too small(%d). we need at least %l\n", sizeof(global_nls_buffer), len); close(fd); return 1; } read(fd, global_nls_buffer, (int)len); close(fd); return 0; } #endif /*NO_KITTEN */