[BACK]Return to gencat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / gencat

Annotation of src/usr.bin/gencat/gencat.c, Revision 1.11

1.11    ! ray         1: /*     $OpenBSD: gencat.c,v 1.10 2005/10/17 19:04:20 otto Exp $        */
1.6       danh        2: /*     $NetBSD: gencat.c,v 1.9 1998/10/09 17:00:56 itohy Exp $ */
1.4       deraadt     3:
1.3       deraadt     4: /*-
                      5:  * Copyright (c) 1996 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by J.T. Conklin.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.6       danh       23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1.3       deraadt    25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
1.1       deraadt    32:
1.6       danh       33: #include <sys/cdefs.h>
                     34: #ifndef lint
1.9       mickey     35: static const char rcsid[] =
1.11    ! ray        36:     "$OpenBSD: gencat.c,v 1.10 2005/10/17 19:04:20 otto Exp $";
1.6       danh       37: #endif /* not lint */
                     38:
1.1       deraadt    39: /***********************************************************
                     40: Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
                     41:
                     42:                         All Rights Reserved
                     43:
                     44: Permission to use, copy, modify, and distribute this software and its
                     45: documentation for any purpose and without fee is hereby granted,
                     46: provided that the above copyright notice appear in all copies and that
                     47: both that copyright notice and this permission notice appear in
                     48: supporting documentation, and that Alfalfa's name not be used in
                     49: advertising or publicity pertaining to distribution of the software
                     50: without specific, written prior permission.
                     51:
                     52: ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     53: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     54: ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     55: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     56: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     57: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     58: SOFTWARE.
                     59:
                     60: If you make any modifications, bugfixes or other changes to this software
                     61: we'd appreciate it if you could send a copy to us so we can keep things
                     62: up-to-date.  Many thanks.
                     63:                                Kee Hinckley
                     64:                                Alfalfa Software, Inc.
                     65:                                267 Allston St., #3
                     66:                                Cambridge, MA 02139  USA
                     67:                                nazgul@alfalfa.com
1.3       deraadt    68:
1.1       deraadt    69: ******************************************************************/
                     70:
1.3       deraadt    71: #define _NLS_PRIVATE
1.1       deraadt    72:
1.5       jdm        73: /* ensure 8-bit cleanliness */
1.6       danh       74: #define ISSPACE(c) \
                     75:     (isascii((unsigned char)c) && isspace((unsigned char)c))
1.5       jdm        76:
1.3       deraadt    77: #include <sys/queue.h>
                     78: #include <ctype.h>
1.6       danh       79: #include <err.h>
                     80: #include <fcntl.h>
                     81: #include <nl_types.h>
1.1       deraadt    82: #include <stdio.h>
1.3       deraadt    83: #include <stdlib.h>
                     84: #include <string.h>
                     85: #include <unistd.h>
1.9       mickey     86: #include <fcntl.h>
                     87: #include <nl_types.h>
                     88: #include <err.h>
1.3       deraadt    89:
                     90: struct _msgT {
                     91:        long    msgId;
                     92:        char   *str;
                     93:         LIST_ENTRY(_msgT) entries;
                     94: };
                     95:
                     96: struct _setT {
                     97:        long    setId;
                     98:         LIST_HEAD(msghead, _msgT) msghead;
                     99:         LIST_ENTRY(_setT) entries;
                    100: };
1.1       deraadt   101:
1.3       deraadt   102: LIST_HEAD(sethead, _setT) sethead;
                    103: static struct _setT *curSet;
1.1       deraadt   104:
1.3       deraadt   105: static char *curline = NULL;
                    106: static long lineno = 0;
1.1       deraadt   107:
1.6       danh      108: extern char    *__progname;            /* from crt0.o */
                    109:
1.7       millert   110: static char   *cskip(char *);
                    111: static void    error(char *, char *);
                    112: static void    nomem(void);
                    113: static char   *getline(int);
                    114: static char   *getmsg(int, char *, char);
                    115: static void    warning(char *, char *);
                    116: static char   *wskip(char *);
                    117: static char   *xstrdup(const char *);
                    118: static void   *xmalloc(size_t);
                    119: static void   *xrealloc(void *, size_t);
                    120:
                    121: void   MCParse(int fd);
                    122: void   MCWriteCat(int fd);
                    123: void   MCDelMsg(int msgId);
                    124: void   MCAddMsg(int msgId, const char *msg);
                    125: void   MCAddSet(int setId);
                    126: void   MCDelSet(int setId);
                    127: int    main(int, char **);
                    128: void   usage(void);
1.6       danh      129:
                    130:
1.3       deraadt   131: void
1.8       deraadt   132: usage(void)
1.3       deraadt   133: {
1.6       danh      134:        fprintf(stderr, "Usage: %s catfile msgfile ...\n", __progname);
1.3       deraadt   135:        exit(1);
                    136: }
1.1       deraadt   137:
1.3       deraadt   138: int
1.8       deraadt   139: main(int argc, char *argv[])
1.3       deraadt   140: {
                    141:        int     ofd, ifd;
                    142:        char   *catfile = NULL;
                    143:        int     c;
                    144:
                    145:        while ((c = getopt(argc, argv, "")) != -1) {
                    146:                switch (c) {
                    147:                case '?':
                    148:                default:
                    149:                        usage();
                    150:                        /* NOTREACHED */
                    151:                }
                    152:        }
                    153:        argc -= optind;
                    154:        argv += optind;
1.1       deraadt   155:
1.3       deraadt   156:        if (argc < 2) {
1.1       deraadt   157:                usage();
1.3       deraadt   158:                /* NOTREACHED */
                    159:        }
                    160:        catfile = *argv++;
                    161:
                    162:        for (; *argv; argv++) {
1.6       danh      163:                if ((ifd = open(*argv, O_RDONLY)) < 0)
                    164:                        err(1, "Unable to read %s", *argv);
1.1       deraadt   165:                MCParse(ifd);
                    166:                close(ifd);
                    167:        }
1.3       deraadt   168:
1.6       danh      169:        if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0)
                    170:                err(1, "Unable to create a new %s", catfile);
1.1       deraadt   171:        MCWriteCat(ofd);
                    172:        exit(0);
1.3       deraadt   173: }
                    174:
                    175: static void
1.8       deraadt   176: warning(char *cptr, char *msg)
1.3       deraadt   177: {
1.9       mickey    178:        warnx("%s on line %ld\n%s", msg, lineno, curline);
1.3       deraadt   179:        if (cptr) {
                    180:                char   *tptr;
                    181:                for (tptr = curline; tptr < cptr; ++tptr)
                    182:                        putc(' ', stderr);
                    183:                fprintf(stderr, "^\n");
                    184:        }
                    185: }
                    186:
                    187: static void
1.8       deraadt   188: error(char *cptr, char *msg)
1.3       deraadt   189: {
                    190:        warning(cptr, msg);
1.1       deraadt   191:        exit(1);
                    192: }
                    193:
1.3       deraadt   194: static void
1.8       deraadt   195: nomem(void)
1.3       deraadt   196: {
                    197:        error(NULL, "out of memory");
                    198: }
                    199:
                    200: static void *
1.8       deraadt   201: xmalloc(size_t len)
1.3       deraadt   202: {
                    203:        void   *p;
                    204:
                    205:        if ((p = malloc(len)) == NULL)
                    206:                nomem();
                    207:        return (p);
                    208: }
                    209:
                    210: static void *
1.8       deraadt   211: xrealloc(void *ptr, size_t size)
1.3       deraadt   212: {
                    213:        if ((ptr = realloc(ptr, size)) == NULL)
                    214:                nomem();
                    215:        return (ptr);
                    216: }
                    217:
                    218: static char *
1.8       deraadt   219: xstrdup(const char *str)
1.3       deraadt   220: {
1.6       danh      221:        char *nstr;
                    222:
                    223:        if ((nstr = strdup(str)) == NULL)
1.3       deraadt   224:                nomem();
1.6       danh      225:        return (nstr);
1.3       deraadt   226: }
                    227:
                    228: static char *
1.8       deraadt   229: getline(int fd)
1.3       deraadt   230: {
                    231:        static long curlen = BUFSIZ;
                    232:        static char buf[BUFSIZ], *bptr = buf, *bend = buf;
                    233:        char   *cptr, *cend;
                    234:        long    buflen;
                    235:
                    236:        if (!curline) {
                    237:                curline = xmalloc(curlen);
                    238:        }
                    239:        ++lineno;
                    240:
                    241:        cptr = curline;
                    242:        cend = curline + curlen;
                    243:        for (;;) {
                    244:                for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
                    245:                        if (*bptr == '\n') {
                    246:                                *cptr = '\0';
                    247:                                ++bptr;
                    248:                                return (curline);
                    249:                        } else
                    250:                                *cptr = *bptr;
                    251:                }
                    252:                if (bptr == bend) {
                    253:                        buflen = read(fd, buf, BUFSIZ);
                    254:                        if (buflen <= 0) {
                    255:                                if (cptr > curline) {
                    256:                                        *cptr = '\0';
                    257:                                        return (curline);
                    258:                                }
                    259:                                return (NULL);
                    260:                        }
                    261:                        bend = buf + buflen;
                    262:                        bptr = buf;
                    263:                }
                    264:                if (cptr == cend) {
                    265:                        cptr = curline = xrealloc(curline, curlen *= 2);
                    266:                        cend = curline + curlen;
                    267:                }
                    268:        }
                    269: }
                    270:
                    271: static char *
1.8       deraadt   272: wskip(char *cptr)
1.3       deraadt   273: {
1.5       jdm       274:        if (!*cptr || !ISSPACE(*cptr)) {
1.3       deraadt   275:                warning(cptr, "expected a space");
                    276:                return (cptr);
                    277:        }
1.5       jdm       278:        while (*cptr && ISSPACE(*cptr))
1.3       deraadt   279:                ++cptr;
                    280:        return (cptr);
                    281: }
                    282:
                    283: static char *
1.8       deraadt   284: cskip(char *cptr)
1.3       deraadt   285: {
1.5       jdm       286:        if (!*cptr || ISSPACE(*cptr)) {
1.3       deraadt   287:                warning(cptr, "wasn't expecting a space");
                    288:                return (cptr);
                    289:        }
1.5       jdm       290:        while (*cptr && !ISSPACE(*cptr))
1.3       deraadt   291:                ++cptr;
                    292:        return (cptr);
                    293: }
                    294:
                    295: static char *
1.8       deraadt   296: getmsg(int fd, char *cptr, char quote)
1.3       deraadt   297: {
                    298:        static char *msg = NULL;
                    299:        static long msglen = 0;
                    300:        long    clen, i;
                    301:        char   *tptr;
                    302:
                    303:        if (quote && *cptr == quote) {
                    304:                ++cptr;
1.6       danh      305:        }
1.3       deraadt   306:
                    307:        clen = strlen(cptr) + 1;
                    308:        if (clen > msglen) {
                    309:                if (msglen)
                    310:                        msg = xrealloc(msg, clen);
                    311:                else
                    312:                        msg = xmalloc(clen);
                    313:                msglen = clen;
                    314:        }
                    315:        tptr = msg;
                    316:
                    317:        while (*cptr) {
                    318:                if (quote && *cptr == quote) {
                    319:                        char   *tmp;
                    320:                        tmp = cptr + 1;
1.5       jdm       321:                        if (*tmp && (!ISSPACE(*tmp) || *wskip(tmp))) {
                    322:                                warning(cptr, "unexpected quote character, ignoring");
1.3       deraadt   323:                                *tptr++ = *cptr++;
                    324:                        } else {
                    325:                                *cptr = '\0';
                    326:                        }
                    327:                } else
                    328:                        if (*cptr == '\\') {
                    329:                                ++cptr;
                    330:                                switch (*cptr) {
                    331:                                case '\0':
                    332:                                        cptr = getline(fd);
                    333:                                        if (!cptr)
                    334:                                                error(NULL, "premature end of file");
                    335:                                        msglen += strlen(cptr);
                    336:                                        i = tptr - msg;
                    337:                                        msg = xrealloc(msg, msglen);
                    338:                                        tptr = msg + i;
                    339:                                        break;
                    340:                                case 'n':
                    341:                                        *tptr++ = '\n';
                    342:                                        ++cptr;
                    343:                                        break;
                    344:                                case 't':
                    345:                                        *tptr++ = '\t';
                    346:                                        ++cptr;
                    347:                                        break;
                    348:                                case 'v':
                    349:                                        *tptr++ = '\v';
                    350:                                        ++cptr;
                    351:                                        break;
                    352:                                case 'b':
                    353:                                        *tptr++ = '\b';
                    354:                                        ++cptr;
                    355:                                        break;
                    356:                                case 'r':
                    357:                                        *tptr++ = '\r';
                    358:                                        ++cptr;
                    359:                                        break;
                    360:                                case 'f':
                    361:                                        *tptr++ = '\f';
                    362:                                        ++cptr;
                    363:                                        break;
                    364:                                case '\\':
                    365:                                        *tptr++ = '\\';
                    366:                                        ++cptr;
                    367:                                        break;
1.6       danh      368:                                case '"':
                    369:                                        /* FALLTHROUGH */
1.5       jdm       370:                                case '\'':
1.6       danh      371:                                        /*
1.5       jdm       372:                                         * While it isn't necessary to
                    373:                                         * escape ' and ", let's accept
                    374:                                         * them escaped and not complain.
                    375:                                         * (XPG4 states that '\' should be
1.6       danh      376:                                         * ignored when not used in a
1.5       jdm       377:                                         * valid escape sequence)
                    378:                                         */
                    379:                                        *tptr++ = '"';
                    380:                                        ++cptr;
                    381:                                        break;
1.3       deraadt   382:                                default:
1.6       danh      383:                                        if (quote && *cptr == quote) {
                    384:                                                *tptr++ = *cptr++;
                    385:                                        } else if (isdigit((unsigned char) *cptr)) {
1.3       deraadt   386:                                                *tptr = 0;
                    387:                                                for (i = 0; i < 3; ++i) {
1.6       danh      388:                                                        if (!isdigit((unsigned char) *cptr))
1.3       deraadt   389:                                                                break;
                    390:                                                        if (*cptr > '7')
                    391:                                                                warning(cptr, "octal number greater than 7?!");
                    392:                                                        *tptr *= 8;
                    393:                                                        *tptr += (*cptr - '0');
                    394:                                                        ++cptr;
                    395:                                                }
                    396:                                        } else {
1.6       danh      397:                                                warning(cptr, "unrecognized escape sequence; ignoring esacpe character");
1.3       deraadt   398:                                        }
1.6       danh      399:                                        break;
1.3       deraadt   400:                                }
                    401:                        } else {
                    402:                                *tptr++ = *cptr++;
                    403:                        }
                    404:        }
                    405:        *tptr = '\0';
                    406:        return (msg);
                    407: }
                    408:
                    409: void
1.8       deraadt   410: MCParse(int fd)
1.3       deraadt   411: {
                    412:        char   *cptr, *str;
                    413:        int     setid, msgid = 0;
                    414:        char    quote = 0;
                    415:
                    416:        /* XXX: init sethead? */
                    417:
                    418:        while ((cptr = getline(fd))) {
                    419:                if (*cptr == '$') {
                    420:                        ++cptr;
                    421:                        if (strncmp(cptr, "set", 3) == 0) {
                    422:                                cptr += 3;
                    423:                                cptr = wskip(cptr);
                    424:                                setid = atoi(cptr);
                    425:                                MCAddSet(setid);
                    426:                                msgid = 0;
                    427:                        } else if (strncmp(cptr, "delset", 6) == 0) {
                    428:                                cptr += 6;
                    429:                                cptr = wskip(cptr);
                    430:                                setid = atoi(cptr);
                    431:                                MCDelSet(setid);
                    432:                        } else if (strncmp(cptr, "quote", 5) == 0) {
                    433:                                cptr += 5;
                    434:                                if (!*cptr)
                    435:                                        quote = 0;
                    436:                                else {
                    437:                                        cptr = wskip(cptr);
                    438:                                        if (!*cptr)
                    439:                                                quote = 0;
                    440:                                        else
                    441:                                                quote = *cptr;
                    442:                                }
1.5       jdm       443:                        } else if (ISSPACE(*cptr)) {
1.3       deraadt   444:                                ;
                    445:                        } else {
                    446:                                if (*cptr) {
                    447:                                        cptr = wskip(cptr);
                    448:                                        if (*cptr)
                    449:                                                warning(cptr, "unrecognized line");
                    450:                                }
                    451:                        }
                    452:                } else {
1.6       danh      453:                        /*
                    454:                         * First check for (and eat) empty lines....
                    455:                         */
                    456:                        if (!*cptr)
                    457:                                continue;
                    458:                        /*
                    459:                         * We have a digit? Start of a message. Else,
                    460:                         * syntax error.
                    461:                         */
                    462:                        if (isdigit((unsigned char) *cptr)) {
1.3       deraadt   463:                                msgid = atoi(cptr);
                    464:                                cptr = cskip(cptr);
                    465:                                cptr = wskip(cptr);
                    466:                                /* if (*cptr) ++cptr; */
1.6       danh      467:                        } else {
                    468:                                warning(cptr, "neither blank line nor start of a message id");
                    469:                                continue;
1.3       deraadt   470:                        }
1.6       danh      471:                        /*
                    472:                         * If we have a message ID, but no message,
                    473:                         * then this means "delete this message id
                    474:                         * from the catalog".
                    475:                         */
                    476:                        if (!*cptr) {
1.3       deraadt   477:                                MCDelMsg(msgid);
1.6       danh      478:                        } else {
1.3       deraadt   479:                                str = getmsg(fd, cptr, quote);
                    480:                                MCAddMsg(msgid, str);
                    481:                        }
                    482:                }
                    483:        }
                    484: }
                    485:
                    486: /*
                    487:  * Write message catalog.
                    488:  *
                    489:  * The message catalog is first converted from its internal to its
                    490:  * external representation in a chunk of memory allocated for this
                    491:  * purpose.  Then the completed catalog is written.  This approach
                    492:  * avoids additional housekeeping variables and/or a lot of seeks
                    493:  * that would otherwise be required.
                    494:  */
                    495: void
1.8       deraadt   496: MCWriteCat(int fd)
1.1       deraadt   497: {
1.3       deraadt   498:        int     nsets;          /* number of sets */
                    499:        int     nmsgs;          /* number of msgs */
                    500:        int     string_size;    /* total size of string pool */
                    501:        int     msgcat_size;    /* total size of message catalog */
                    502:        void   *msgcat;         /* message catalog data */
                    503:        struct _nls_cat_hdr *cat_hdr;
                    504:        struct _nls_set_hdr *set_hdr;
                    505:        struct _nls_msg_hdr *msg_hdr;
                    506:        char   *strings;
                    507:        struct _setT *set;
                    508:        struct _msgT *msg;
                    509:        int     msg_index;
                    510:        int     msg_offset;
                    511:
                    512:        /* determine number of sets, number of messages, and size of the
                    513:         * string pool */
                    514:        nsets = 0;
                    515:        nmsgs = 0;
                    516:        string_size = 0;
                    517:
1.10      otto      518:        LIST_FOREACH(set, &sethead, entries) {
1.3       deraadt   519:                nsets++;
                    520:
1.10      otto      521:                LIST_FOREACH(msg, &set->msghead, entries) {
1.3       deraadt   522:                        nmsgs++;
                    523:                        string_size += strlen(msg->str) + 1;
                    524:                }
                    525:        }
                    526:
                    527: #ifdef DEBUG
                    528:        printf("number of sets: %d\n", nsets);
                    529:        printf("number of msgs: %d\n", nmsgs);
                    530:        printf("string pool size: %d\n", string_size);
                    531: #endif
                    532:
                    533:        /* determine size and then allocate buffer for constructing external
                    534:         * message catalog representation */
                    535:        msgcat_size = sizeof(struct _nls_cat_hdr)
                    536:            + (nsets * sizeof(struct _nls_set_hdr))
                    537:            + (nmsgs * sizeof(struct _nls_msg_hdr))
                    538:            + string_size;
                    539:
                    540:        msgcat = xmalloc(msgcat_size);
                    541:        memset(msgcat, '\0', msgcat_size);
                    542:
                    543:        /* fill in msg catalog header */
                    544:        cat_hdr = (struct _nls_cat_hdr *) msgcat;
                    545:        cat_hdr->__magic = htonl(_NLS_MAGIC);
                    546:        cat_hdr->__nsets = htonl(nsets);
                    547:        cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr));
                    548:        cat_hdr->__msg_hdr_offset =
                    549:            htonl(nsets * sizeof(struct _nls_set_hdr));
                    550:        cat_hdr->__msg_txt_offset =
                    551:            htonl(nsets * sizeof(struct _nls_set_hdr) +
                    552:            nmsgs * sizeof(struct _nls_msg_hdr));
                    553:
                    554:        /* compute offsets for set & msg header tables and string pool */
                    555:        set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
                    556:            sizeof(struct _nls_cat_hdr));
                    557:        msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
                    558:            sizeof(struct _nls_cat_hdr) +
                    559:            nsets * sizeof(struct _nls_set_hdr));
                    560:        strings = (char *) msgcat +
                    561:            sizeof(struct _nls_cat_hdr) +
                    562:            nsets * sizeof(struct _nls_set_hdr) +
                    563:            nmsgs * sizeof(struct _nls_msg_hdr);
                    564:
                    565:        msg_index = 0;
                    566:        msg_offset = 0;
1.10      otto      567:        LIST_FOREACH(set, &sethead, entries) {
1.3       deraadt   568:
                    569:                nmsgs = 0;
1.10      otto      570:                LIST_FOREACH(msg, &set->msghead, entries) {
1.3       deraadt   571:                        int     msg_len = strlen(msg->str) + 1;
                    572:
                    573:                        msg_hdr->__msgno = htonl(msg->msgId);
                    574:                        msg_hdr->__msglen = htonl(msg_len);
                    575:                        msg_hdr->__offset = htonl(msg_offset);
                    576:
                    577:                        memcpy(strings, msg->str, msg_len);
                    578:                        strings += msg_len;
                    579:                        msg_offset += msg_len;
                    580:
                    581:                        nmsgs++;
                    582:                        msg_hdr++;
                    583:                }
                    584:
                    585:                set_hdr->__setno = htonl(set->setId);
                    586:                set_hdr->__nmsgs = htonl(nmsgs);
                    587:                set_hdr->__index = htonl(msg_index);
                    588:                msg_index += nmsgs;
                    589:                set_hdr++;
                    590:        }
                    591:
                    592:        /* write out catalog.  XXX: should this be done in small chunks? */
                    593:        write(fd, msgcat, msgcat_size);
                    594: }
                    595:
                    596: void
1.8       deraadt   597: MCAddSet(int setId)
1.3       deraadt   598: {
                    599:        struct _setT *p, *q;
                    600:
                    601:        if (setId <= 0) {
                    602:                error(NULL, "setId's must be greater than zero");
                    603:                /* NOTREACHED */
                    604:        }
                    605: #if 0
                    606:        /* XXX */
                    607:        if (setId > NL_SETMAX) {
                    608:                error(NULL, "setId %d exceeds limit (%d)");
                    609:                /* NOTREACHED */
                    610:        }
                    611: #endif
                    612:
1.10      otto      613:        p = LIST_FIRST(&sethead);
1.3       deraadt   614:        q = NULL;
1.10      otto      615:        for (; p != NULL && p->setId < setId; q = p, p = LIST_NEXT(p, entries));
1.3       deraadt   616:
                    617:        if (p && p->setId == setId) {
                    618:                ;
                    619:        } else {
                    620:                p = xmalloc(sizeof(struct _setT));
                    621:                memset(p, '\0', sizeof(struct _setT));
                    622:                LIST_INIT(&p->msghead);
                    623:
                    624:                p->setId = setId;
                    625:
                    626:                if (q == NULL) {
                    627:                        LIST_INSERT_HEAD(&sethead, p, entries);
                    628:                } else {
                    629:                        LIST_INSERT_AFTER(q, p, entries);
                    630:                }
                    631:        }
                    632:
                    633:        curSet = p;
                    634: }
                    635:
                    636: void
1.8       deraadt   637: MCAddMsg(int msgId, const char *str)
1.3       deraadt   638: {
                    639:        struct _msgT *p, *q;
                    640:
                    641:        if (!curSet)
                    642:                error(NULL, "can't specify a message when no set exists");
                    643:
                    644:        if (msgId <= 0) {
                    645:                error(NULL, "msgId's must be greater than zero");
                    646:                /* NOTREACHED */
                    647:        }
                    648: #if 0
                    649:        /* XXX */
                    650:        if (msgId > NL_SETMAX) {
1.5       jdm       651:                error(NULL, "msgId %d exceeds limit (%d)");
1.3       deraadt   652:                /* NOTREACHED */
                    653:        }
                    654: #endif
                    655:
1.10      otto      656:        p = LIST_FIRST(&curSet->msghead);
1.3       deraadt   657:        q = NULL;
1.10      otto      658:        for (; p != NULL && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries));
1.3       deraadt   659:
                    660:        if (p && p->msgId == msgId) {
                    661:                free(p->str);
                    662:        } else {
                    663:                p = xmalloc(sizeof(struct _msgT));
                    664:                memset(p, '\0', sizeof(struct _msgT));
                    665:
                    666:                if (q == NULL) {
                    667:                        LIST_INSERT_HEAD(&curSet->msghead, p, entries);
                    668:                } else {
                    669:                        LIST_INSERT_AFTER(q, p, entries);
                    670:                }
                    671:        }
                    672:
                    673:        p->msgId = msgId;
                    674:        p->str = xstrdup(str);
                    675: }
                    676:
                    677: void
1.8       deraadt   678: MCDelSet(int setId)
1.3       deraadt   679: {
                    680:        struct _setT *set;
                    681:        struct _msgT *msg;
                    682:
1.10      otto      683:        set = LIST_FIRST(&sethead);
                    684:        for (; set != NULL && set->setId < setId;
                    685:            set = LIST_NEXT(set, entries));
1.3       deraadt   686:
                    687:        if (set && set->setId == setId) {
                    688:
1.10      otto      689:                msg = LIST_FIRST(&set->msghead);
1.3       deraadt   690:                while (msg) {
                    691:                        free(msg->str);
1.5       jdm       692:                        LIST_REMOVE(msg, entries);
1.3       deraadt   693:                }
                    694:
                    695:                LIST_REMOVE(set, entries);
                    696:                return;
                    697:        }
                    698:        warning(NULL, "specified set doesn't exist");
                    699: }
1.1       deraadt   700:
1.3       deraadt   701: void
1.8       deraadt   702: MCDelMsg(int msgId)
1.3       deraadt   703: {
                    704:        struct _msgT *msg;
1.1       deraadt   705:
1.3       deraadt   706:        if (!curSet)
                    707:                error(NULL, "you can't delete a message before defining the set");
1.1       deraadt   708:
1.10      otto      709:        msg = LIST_FIRST(&curSet->msghead);
                    710:        for (; msg != NULL && msg->msgId < msgId;
                    711:            msg = LIST_NEXT(msg, entries));
1.1       deraadt   712:
1.3       deraadt   713:        if (msg && msg->msgId == msgId) {
                    714:                free(msg->str);
                    715:                LIST_REMOVE(msg, entries);
                    716:                return;
                    717:        }
                    718:        warning(NULL, "specified msg doesn't exist");
1.1       deraadt   719: }