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