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