Annotation of src/usr.bin/gencat/gencat.c, Revision 1.21
1.21 ! cheloha 1: /* $OpenBSD: gencat.c,v 1.20 2019/07/25 13:53:57 schwarze 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: default:
143: usage();
144: /* NOTREACHED */
145: }
146: }
147: argc -= optind;
148: argv += optind;
1.1 deraadt 149:
1.3 deraadt 150: if (argc < 2) {
1.1 deraadt 151: usage();
1.3 deraadt 152: /* NOTREACHED */
153: }
154: catfile = *argv++;
155:
156: for (; *argv; argv++) {
1.19 deraadt 157: if ((ifd = open(*argv, O_RDONLY)) == -1)
1.6 danh 158: err(1, "Unable to read %s", *argv);
1.1 deraadt 159: MCParse(ifd);
160: close(ifd);
161: }
1.3 deraadt 162:
1.19 deraadt 163: if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1)
1.6 danh 164: err(1, "Unable to create a new %s", catfile);
1.1 deraadt 165: MCWriteCat(ofd);
166: exit(0);
1.3 deraadt 167: }
168:
169: static void
1.8 deraadt 170: warning(char *cptr, char *msg)
1.3 deraadt 171: {
1.9 mickey 172: warnx("%s on line %ld\n%s", msg, lineno, curline);
1.3 deraadt 173: if (cptr) {
174: char *tptr;
175: for (tptr = curline; tptr < cptr; ++tptr)
176: putc(' ', stderr);
177: fprintf(stderr, "^\n");
178: }
179: }
180:
181: static void
1.8 deraadt 182: error(char *cptr, char *msg)
1.3 deraadt 183: {
184: warning(cptr, msg);
1.1 deraadt 185: exit(1);
186: }
187:
1.3 deraadt 188: static void
1.8 deraadt 189: nomem(void)
1.3 deraadt 190: {
191: error(NULL, "out of memory");
192: }
193:
194: static void *
1.8 deraadt 195: xmalloc(size_t len)
1.3 deraadt 196: {
197: void *p;
198:
199: if ((p = malloc(len)) == NULL)
200: nomem();
201: return (p);
202: }
203:
204: static void *
1.8 deraadt 205: xrealloc(void *ptr, size_t size)
1.3 deraadt 206: {
207: if ((ptr = realloc(ptr, size)) == NULL)
208: nomem();
209: return (ptr);
210: }
211:
212: static char *
1.8 deraadt 213: xstrdup(const char *str)
1.3 deraadt 214: {
1.6 danh 215: char *nstr;
216:
217: if ((nstr = strdup(str)) == NULL)
1.3 deraadt 218: nomem();
1.6 danh 219: return (nstr);
1.3 deraadt 220: }
221:
222: static char *
1.15 fgsch 223: get_line(int fd)
1.3 deraadt 224: {
225: static long curlen = BUFSIZ;
226: static char buf[BUFSIZ], *bptr = buf, *bend = buf;
227: char *cptr, *cend;
228: long buflen;
229:
230: if (!curline) {
231: curline = xmalloc(curlen);
232: }
233: ++lineno;
234:
235: cptr = curline;
236: cend = curline + curlen;
237: for (;;) {
238: for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
239: if (*bptr == '\n') {
240: *cptr = '\0';
241: ++bptr;
242: return (curline);
243: } else
244: *cptr = *bptr;
245: }
246: if (bptr == bend) {
247: buflen = read(fd, buf, BUFSIZ);
248: if (buflen <= 0) {
249: if (cptr > curline) {
250: *cptr = '\0';
251: return (curline);
252: }
253: return (NULL);
254: }
255: bend = buf + buflen;
256: bptr = buf;
257: }
258: if (cptr == cend) {
259: cptr = curline = xrealloc(curline, curlen *= 2);
260: cend = curline + curlen;
261: }
262: }
263: }
264:
265: static char *
1.8 deraadt 266: wskip(char *cptr)
1.3 deraadt 267: {
1.5 jdm 268: if (!*cptr || !ISSPACE(*cptr)) {
1.3 deraadt 269: warning(cptr, "expected a space");
270: return (cptr);
271: }
1.5 jdm 272: while (*cptr && ISSPACE(*cptr))
1.3 deraadt 273: ++cptr;
274: return (cptr);
275: }
276:
277: static char *
1.8 deraadt 278: cskip(char *cptr)
1.3 deraadt 279: {
1.5 jdm 280: if (!*cptr || ISSPACE(*cptr)) {
1.3 deraadt 281: warning(cptr, "wasn't expecting a space");
282: return (cptr);
283: }
1.5 jdm 284: while (*cptr && !ISSPACE(*cptr))
1.3 deraadt 285: ++cptr;
286: return (cptr);
287: }
288:
289: static char *
1.8 deraadt 290: getmsg(int fd, char *cptr, char quote)
1.3 deraadt 291: {
292: static char *msg = NULL;
293: static long msglen = 0;
294: long clen, i;
295: char *tptr;
296:
297: if (quote && *cptr == quote) {
298: ++cptr;
1.6 danh 299: }
1.3 deraadt 300:
301: clen = strlen(cptr) + 1;
302: if (clen > msglen) {
303: if (msglen)
304: msg = xrealloc(msg, clen);
305: else
306: msg = xmalloc(clen);
307: msglen = clen;
308: }
309: tptr = msg;
310:
311: while (*cptr) {
312: if (quote && *cptr == quote) {
313: char *tmp;
314: tmp = cptr + 1;
1.14 lum 315:
1.5 jdm 316: if (*tmp && (!ISSPACE(*tmp) || *wskip(tmp))) {
317: warning(cptr, "unexpected quote character, ignoring");
1.3 deraadt 318: *tptr++ = *cptr++;
319: } else {
320: *cptr = '\0';
321: }
1.14 lum 322: } else if (*cptr == '\\') {
323: ++cptr;
324: switch (*cptr) {
325: case '\0':
1.15 fgsch 326: cptr = get_line(fd);
1.14 lum 327: if (!cptr)
328: error(NULL, "premature end of file");
329: msglen += strlen(cptr);
330: i = tptr - msg;
331: msg = xrealloc(msg, msglen);
332: tptr = msg + i;
333: break;
334: case 'n':
335: *tptr++ = '\n';
336: ++cptr;
337: break;
338: case 't':
339: *tptr++ = '\t';
340: ++cptr;
341: break;
342: case 'v':
343: *tptr++ = '\v';
344: ++cptr;
345: break;
346: case 'b':
347: *tptr++ = '\b';
348: ++cptr;
349: break;
350: case 'r':
351: *tptr++ = '\r';
352: ++cptr;
353: break;
354: case 'f':
355: *tptr++ = '\f';
1.3 deraadt 356: ++cptr;
1.14 lum 357: break;
358: case '\\':
359: *tptr++ = '\\';
360: ++cptr;
361: break;
362: case '"':
363: /* FALLTHROUGH */
364: case '\'':
365: /*
366: * While it isn't necessary to
367: * escape ' and ", let's accept
368: * them escaped and not complain.
369: * (XPG4 states that '\' should be
370: * ignored when not used in a
371: * valid escape sequence)
372: */
373: *tptr++ = '"';
374: ++cptr;
375: break;
376: default:
377: if (quote && *cptr == quote) {
378: *tptr++ = *cptr++;
379: } else if (isdigit((unsigned char) *cptr)) {
380: *tptr = 0;
381: for (i = 0; i < 3; ++i) {
382: if (!isdigit((unsigned char) *cptr))
383: break;
384: if (*cptr > '7')
385: warning(cptr, "octal number greater than 7?!");
386: *tptr *= 8;
387: *tptr += (*cptr - '0');
388: ++cptr;
1.3 deraadt 389: }
1.14 lum 390: } else {
391: warning(cptr, "unrecognized escape sequence; ignoring esacpe character");
1.3 deraadt 392: }
1.14 lum 393: break;
1.3 deraadt 394: }
1.14 lum 395: } else {
396: *tptr++ = *cptr++;
397: }
1.3 deraadt 398: }
399: *tptr = '\0';
400: return (msg);
401: }
402:
403: void
1.8 deraadt 404: MCParse(int fd)
1.3 deraadt 405: {
406: char *cptr, *str;
1.20 schwarze 407: int setid, msgid;
1.3 deraadt 408: char quote = 0;
409:
410: /* XXX: init sethead? */
411:
1.20 schwarze 412: setid = 0;
1.15 fgsch 413: while ((cptr = get_line(fd))) {
1.3 deraadt 414: if (*cptr == '$') {
415: ++cptr;
416: if (strncmp(cptr, "set", 3) == 0) {
417: cptr += 3;
418: cptr = wskip(cptr);
419: setid = atoi(cptr);
420: MCAddSet(setid);
421: } else if (strncmp(cptr, "delset", 6) == 0) {
422: cptr += 6;
423: cptr = wskip(cptr);
424: setid = atoi(cptr);
425: MCDelSet(setid);
426: } else if (strncmp(cptr, "quote", 5) == 0) {
427: cptr += 5;
428: if (!*cptr)
429: quote = 0;
430: else {
431: cptr = wskip(cptr);
432: if (!*cptr)
433: quote = 0;
434: else
435: quote = *cptr;
436: }
1.5 jdm 437: } else if (ISSPACE(*cptr)) {
1.3 deraadt 438: ;
439: } else {
440: if (*cptr) {
441: cptr = wskip(cptr);
442: if (*cptr)
443: warning(cptr, "unrecognized line");
444: }
445: }
446: } else {
1.6 danh 447: /*
448: * First check for (and eat) empty lines....
449: */
450: if (!*cptr)
451: continue;
452: /*
453: * We have a digit? Start of a message. Else,
454: * syntax error.
455: */
456: if (isdigit((unsigned char) *cptr)) {
1.3 deraadt 457: msgid = atoi(cptr);
458: cptr = cskip(cptr);
459: cptr = wskip(cptr);
460: /* if (*cptr) ++cptr; */
1.6 danh 461: } else {
462: warning(cptr, "neither blank line nor start of a message id");
463: continue;
1.20 schwarze 464: }
465: if (setid == 0) {
466: setid = NL_SETD;
467: MCAddSet(setid);
1.3 deraadt 468: }
1.6 danh 469: /*
470: * If we have a message ID, but no message,
471: * then this means "delete this message id
472: * from the catalog".
473: */
474: if (!*cptr) {
1.3 deraadt 475: MCDelMsg(msgid);
1.6 danh 476: } else {
1.3 deraadt 477: str = getmsg(fd, cptr, quote);
478: MCAddMsg(msgid, str);
479: }
480: }
481: }
482: }
483:
484: /*
485: * Write message catalog.
486: *
487: * The message catalog is first converted from its internal to its
488: * external representation in a chunk of memory allocated for this
489: * purpose. Then the completed catalog is written. This approach
490: * avoids additional housekeeping variables and/or a lot of seeks
491: * that would otherwise be required.
492: */
493: void
1.8 deraadt 494: MCWriteCat(int fd)
1.1 deraadt 495: {
1.3 deraadt 496: int nsets; /* number of sets */
497: int nmsgs; /* number of msgs */
498: int string_size; /* total size of string pool */
499: int msgcat_size; /* total size of message catalog */
500: void *msgcat; /* message catalog data */
501: struct _nls_cat_hdr *cat_hdr;
502: struct _nls_set_hdr *set_hdr;
503: struct _nls_msg_hdr *msg_hdr;
504: char *strings;
505: struct _setT *set;
506: struct _msgT *msg;
507: int msg_index;
508: int msg_offset;
509:
510: /* determine number of sets, number of messages, and size of the
511: * string pool */
512: nsets = 0;
513: nmsgs = 0;
514: string_size = 0;
515:
1.10 otto 516: LIST_FOREACH(set, &sethead, entries) {
1.3 deraadt 517: nsets++;
518:
1.10 otto 519: LIST_FOREACH(msg, &set->msghead, entries) {
1.3 deraadt 520: nmsgs++;
521: string_size += strlen(msg->str) + 1;
522: }
523: }
524:
525: #ifdef DEBUG
526: printf("number of sets: %d\n", nsets);
527: printf("number of msgs: %d\n", nmsgs);
528: printf("string pool size: %d\n", string_size);
529: #endif
530:
531: /* determine size and then allocate buffer for constructing external
532: * message catalog representation */
533: msgcat_size = sizeof(struct _nls_cat_hdr)
534: + (nsets * sizeof(struct _nls_set_hdr))
535: + (nmsgs * sizeof(struct _nls_msg_hdr))
536: + string_size;
537:
538: msgcat = xmalloc(msgcat_size);
539: memset(msgcat, '\0', msgcat_size);
540:
541: /* fill in msg catalog header */
542: cat_hdr = (struct _nls_cat_hdr *) msgcat;
543: cat_hdr->__magic = htonl(_NLS_MAGIC);
544: cat_hdr->__nsets = htonl(nsets);
545: cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr));
546: cat_hdr->__msg_hdr_offset =
547: htonl(nsets * sizeof(struct _nls_set_hdr));
548: cat_hdr->__msg_txt_offset =
549: htonl(nsets * sizeof(struct _nls_set_hdr) +
550: nmsgs * sizeof(struct _nls_msg_hdr));
551:
552: /* compute offsets for set & msg header tables and string pool */
553: set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
554: sizeof(struct _nls_cat_hdr));
555: msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
556: sizeof(struct _nls_cat_hdr) +
557: nsets * sizeof(struct _nls_set_hdr));
558: strings = (char *) msgcat +
559: sizeof(struct _nls_cat_hdr) +
560: nsets * sizeof(struct _nls_set_hdr) +
561: nmsgs * sizeof(struct _nls_msg_hdr);
562:
563: msg_index = 0;
564: msg_offset = 0;
1.10 otto 565: LIST_FOREACH(set, &sethead, entries) {
1.3 deraadt 566:
567: nmsgs = 0;
1.10 otto 568: LIST_FOREACH(msg, &set->msghead, entries) {
1.3 deraadt 569: int msg_len = strlen(msg->str) + 1;
570:
571: msg_hdr->__msgno = htonl(msg->msgId);
572: msg_hdr->__msglen = htonl(msg_len);
573: msg_hdr->__offset = htonl(msg_offset);
574:
575: memcpy(strings, msg->str, msg_len);
576: strings += msg_len;
577: msg_offset += msg_len;
578:
579: nmsgs++;
580: msg_hdr++;
581: }
582:
583: set_hdr->__setno = htonl(set->setId);
584: set_hdr->__nmsgs = htonl(nmsgs);
585: set_hdr->__index = htonl(msg_index);
586: msg_index += nmsgs;
587: set_hdr++;
588: }
589:
590: /* write out catalog. XXX: should this be done in small chunks? */
591: write(fd, msgcat, msgcat_size);
592: }
593:
594: void
1.8 deraadt 595: MCAddSet(int setId)
1.3 deraadt 596: {
597: struct _setT *p, *q;
598:
599: if (setId <= 0) {
600: error(NULL, "setId's must be greater than zero");
601: /* NOTREACHED */
602: }
603: #if 0
604: /* XXX */
605: if (setId > NL_SETMAX) {
606: error(NULL, "setId %d exceeds limit (%d)");
607: /* NOTREACHED */
608: }
609: #endif
610:
1.10 otto 611: p = LIST_FIRST(&sethead);
1.3 deraadt 612: q = NULL;
1.10 otto 613: for (; p != NULL && p->setId < setId; q = p, p = LIST_NEXT(p, entries));
1.3 deraadt 614:
615: if (p && p->setId == setId) {
616: ;
617: } else {
618: p = xmalloc(sizeof(struct _setT));
619: memset(p, '\0', sizeof(struct _setT));
620: LIST_INIT(&p->msghead);
621:
622: p->setId = setId;
623:
624: if (q == NULL) {
625: LIST_INSERT_HEAD(&sethead, p, entries);
626: } else {
627: LIST_INSERT_AFTER(q, p, entries);
628: }
629: }
630:
631: curSet = p;
632: }
633:
634: void
1.8 deraadt 635: MCAddMsg(int msgId, const char *str)
1.3 deraadt 636: {
637: struct _msgT *p, *q;
638:
639: if (!curSet)
640: error(NULL, "can't specify a message when no set exists");
641:
642: if (msgId <= 0) {
643: error(NULL, "msgId's must be greater than zero");
644: /* NOTREACHED */
645: }
646: #if 0
647: /* XXX */
648: if (msgId > NL_SETMAX) {
1.5 jdm 649: error(NULL, "msgId %d exceeds limit (%d)");
1.3 deraadt 650: /* NOTREACHED */
651: }
652: #endif
653:
1.10 otto 654: p = LIST_FIRST(&curSet->msghead);
1.3 deraadt 655: q = NULL;
1.10 otto 656: for (; p != NULL && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries));
1.3 deraadt 657:
658: if (p && p->msgId == msgId) {
659: free(p->str);
660: } else {
661: p = xmalloc(sizeof(struct _msgT));
662: memset(p, '\0', sizeof(struct _msgT));
663:
664: if (q == NULL) {
665: LIST_INSERT_HEAD(&curSet->msghead, p, entries);
666: } else {
667: LIST_INSERT_AFTER(q, p, entries);
668: }
669: }
670:
671: p->msgId = msgId;
672: p->str = xstrdup(str);
673: }
674:
675: void
1.8 deraadt 676: MCDelSet(int setId)
1.3 deraadt 677: {
678: struct _setT *set;
679: struct _msgT *msg;
680:
1.10 otto 681: set = LIST_FIRST(&sethead);
682: for (; set != NULL && set->setId < setId;
683: set = LIST_NEXT(set, entries));
1.3 deraadt 684:
685: if (set && set->setId == setId) {
686:
1.10 otto 687: msg = LIST_FIRST(&set->msghead);
1.3 deraadt 688: while (msg) {
689: free(msg->str);
1.5 jdm 690: LIST_REMOVE(msg, entries);
1.3 deraadt 691: }
692:
693: LIST_REMOVE(set, entries);
694: return;
695: }
696: warning(NULL, "specified set doesn't exist");
697: }
1.1 deraadt 698:
1.3 deraadt 699: void
1.8 deraadt 700: MCDelMsg(int msgId)
1.3 deraadt 701: {
702: struct _msgT *msg;
1.1 deraadt 703:
1.3 deraadt 704: if (!curSet)
705: error(NULL, "you can't delete a message before defining the set");
1.1 deraadt 706:
1.10 otto 707: msg = LIST_FIRST(&curSet->msghead);
708: for (; msg != NULL && msg->msgId < msgId;
709: msg = LIST_NEXT(msg, entries));
1.1 deraadt 710:
1.3 deraadt 711: if (msg && msg->msgId == msgId) {
712: free(msg->str);
713: LIST_REMOVE(msg, entries);
714: return;
715: }
716: warning(NULL, "specified msg doesn't exist");
1.1 deraadt 717: }