From: Corinna Vinschen <[email protected]>

Signed-off-by: Corinna Vinschen <[email protected]>
---
 winsup/utils/gencat.c | 433 ++++++++++++++++++++++++++++++------------
 1 file changed, 310 insertions(+), 123 deletions(-)

diff --git a/winsup/utils/gencat.c b/winsup/utils/gencat.c
index a583a884381f..f86b17b4a922 100644
--- a/winsup/utils/gencat.c
+++ b/winsup/utils/gencat.c
@@ -1,11 +1,6 @@
-/* ex:ts=4
- */
-
-/*     $NetBSD: gencat.c,v 1.18 2003/10/27 00:12:43 lukem Exp $        */
+/*     $NetBSD: gencat.c,v 1.36 2013/11/27 17:38:11 apb Exp $  */
 
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND MIT
- *
+/*
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
@@ -24,7 +19,7 @@
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 
  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
@@ -34,6 +29,11 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: gencat.c,v 1.36 2013/11/27 17:38:11 apb Exp $");
+#endif
+
 /***********************************************************
 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
 
@@ -66,18 +66,21 @@ up-to-date.  Many thanks.
 
 ******************************************************************/
 
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
 
 #define _NLS_PRIVATE
 
 #include <sys/types.h>
 #include <sys/queue.h>
 
-#include <arpa/inet.h>         /* for htonl() */
+#include <netinet/in.h>        /* Needed by arpa/inet.h on NetBSD */
+#include <arpa/inet.h> /* Needed for htonl() on POSIX systems */
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <nl_types.h>
@@ -86,26 +89,38 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#ifndef NL_SETMAX
+#define NL_SETMAX 255
+#endif
+#ifndef NL_MSGMAX
+#define NL_MSGMAX 2048
+#endif
+
 struct _msgT {
        long    msgId;
        char   *str;
-       LIST_ENTRY(_msgT) entries;
+        LIST_ENTRY(_msgT) entries;
 };
 
 struct _setT {
        long    setId;
-       LIST_HEAD(msghead, _msgT) msghead;
-       LIST_ENTRY(_setT) entries;
+        LIST_HEAD(msghead, _msgT) msghead;
+        LIST_ENTRY(_setT) entries;
 };
 
-static LIST_HEAD(sethead, _setT) sethead;
+static LIST_HEAD(sethead, _setT) sethead = LIST_HEAD_INITIALIZER(sethead);
 static struct _setT *curSet;
 
+static const char *curfile;
 static char *curline = NULL;
 static long lineno = 0;
 
+#ifndef __dead
+#define __dead __attribute__((__noreturn__))
+#endif
+
 static char   *cskip(char *);
-static void    error(const char *);
+__dead static  void    error(const char *);
 static char   *get_line(int);
 static char   *getmsg(int, char *, char);
 static void    warning(const char *, const char *);
@@ -114,45 +129,35 @@ static    char   *xstrdup(const char *);
 static void   *xmalloc(size_t);
 static void   *xrealloc(void *, size_t);
 
-void   MCParse(int);
-void   MCReadCat(int);
-void   MCWriteCat(int);
-void   MCDelMsg(int);
-void   MCAddMsg(int, const char *);
-void   MCAddSet(int);
-void   MCDelSet(int);
-void   usage(void);
-int    main(int, char **);
-
-void
+static void    MCParse(int fd);
+static void    MCReadCat(int fd);
+static void    MCWriteCat(int fd);
+static void    MCDelMsg(int msgId);
+static void    MCAddMsg(int msgId, const char *msg);
+static void    MCAddSet(int setId);
+static void    MCDelSet(int setId);
+__dead static void     usage(void);
+
+#define CORRUPT                        "corrupt message catalog"
+#define NOMEMORY               "out of memory"
+
+static void
 usage(void)
 {
-       fprintf(stderr, "usage: %s catfile msgfile ...\n", getprogname());
+       fprintf(stderr, "usage: %s catfile [msgfile|- ...]\n", getprogname());
        exit(1);
 }
 
 int
-main(int argc, char **argv)
+main(int argc, char *argv[])
 {
        int     ofd, ifd;
-       char    *catfile = NULL;
+       char   *catfile = NULL;
        int     c;
+       int     updatecat = 0;
 
-#define DEPRECATEDMSG  1
-
-#ifdef DEPRECATEDMSG
-       while ((c = getopt(argc, argv, "new")) != -1) {
-#else
        while ((c = getopt(argc, argv, "")) != -1) {
-#endif
                switch (c) {
-#ifdef DEPRECATEDMSG
-               case 'n':
-                       fprintf(stderr, "WARNING: Usage of \"-new\" argument is 
deprecated.\n");
-               case 'e':
-               case 'w':
-                       break;
-#endif
                case '?':
                default:
                        usage();
@@ -162,21 +167,59 @@ main(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
-       if (argc < 2) {
+       if (argc < 1) {
                usage();
                /* NOTREACHED */
        }
        catfile = *argv++;
 
-       for (; *argv; argv++) {
-               if ((ifd = open(*argv, O_RDONLY)) < 0)
-                       err(1, "Unable to read %s", *argv);
-               MCParse(ifd);
-               close(ifd);
+       if ((catfile[0] == '-') && (catfile[1] == '\0')) {
+               ofd = STDOUT_FILENO;
+       } else {
+               ofd = open(catfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
+               if (ofd < 0) {
+                       if (errno == EEXIST) {
+                               if ((ofd = open(catfile, O_RDWR)) < 0) {
+                                       err(1, "Unable to open %s", catfile);
+                                       /* NOTREACHED */
+                               }
+                       } else {
+                               err(1, "Unable to create new %s", catfile);
+                               /* NOTREACHED */
+                       }
+                       curfile = catfile;
+                       updatecat = 1;
+                       MCReadCat(ofd);
+                       if (lseek(ofd, (off_t)0, SEEK_SET) == (off_t)-1) {
+                               err(1, "Unable to seek on %s", catfile);
+                               /* NOTREACHED */
+                       }
+               }
+       }
+
+       if (argc < 2 || (((*argv)[0] == '-') && ((*argv)[1] == '\0'))) {
+               if (argc > 2)
+                       usage();
+                       /* NOTREACHED */
+               MCParse(STDIN_FILENO);
+       } else {
+               for (; *argv; argv++) {
+                       if ((ifd = open(*argv, O_RDONLY)) < 0)
+                               err(1, "Unable to read %s", *argv);
+                       curfile = *argv;
+                       lineno = 0;
+                       MCParse(ifd);
+                       close(ifd);
+               }
+       }
+
+       if (updatecat) {
+               if (ftruncate(ofd, 0) != 0) {
+                       err(1, "Unable to truncate %s", catfile);
+                       /* NOTREACHED */
+               }
        }
 
-       if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0)
-               err(1, "Unable to create a new %s", catfile);
        MCWriteCat(ofd);
        exit(0);
 }
@@ -184,19 +227,21 @@ main(int argc, char **argv)
 static void
 warning(const char *cptr, const char *msg)
 {
-       fprintf(stderr, "%s: %s on line %ld\n", getprogname(), msg, lineno);
-       fprintf(stderr, "%s\n", curline);
-       if (cptr) {
-               char   *tptr;
-               for (tptr = curline; tptr < cptr; ++tptr)
-                       putc(' ', stderr);
-               fprintf(stderr, "^\n");
+       if (lineno) {
+               fprintf(stderr, "%s: %s on line %ld, %s\n",
+                       getprogname(), msg, lineno, curfile);
+               fprintf(stderr, "%s\n", curline);
+               if (cptr) {
+                       char   *tptr;
+                       for (tptr = curline; tptr < cptr; ++tptr)
+                               putc(' ', stderr);
+                       fprintf(stderr, "^\n");
+               }
+       } else {
+               fprintf(stderr, "%s: %s, %s\n", getprogname(), msg, curfile);
        }
 }
 
-#define        CORRUPT()       { error("corrupt message catalog"); }
-#define        NOMEM()         { error("out of memory"); }
-
 static void
 error(const char *msg)
 {
@@ -210,7 +255,7 @@ xmalloc(size_t len)
        void   *p;
 
        if ((p = malloc(len)) == NULL)
-               NOMEM();
+               errx(1, NOMEMORY);
        return (p);
 }
 
@@ -218,7 +263,7 @@ static void *
 xrealloc(void *ptr, size_t size)
 {
        if ((ptr = realloc(ptr, size)) == NULL)
-               NOMEM();
+               errx(1, NOMEMORY);
        return (ptr);
 }
 
@@ -228,7 +273,7 @@ xstrdup(const char *str)
        char *nstr;
 
        if ((nstr = strdup(str)) == NULL)
-               NOMEM();
+               errx(1, NOMEMORY);
        return (nstr);
 }
 
@@ -303,13 +348,15 @@ static char *
 getmsg(int fd, char *cptr, char quote)
 {
        static char *msg = NULL;
-       static long msglen = 0;
-       long    clen, i;
+       static size_t msglen = 0;
+       size_t  clen, i;
+       int     in_quote = 0;
        char   *tptr;
 
        if (quote && *cptr == quote) {
                ++cptr;
-       }
+               in_quote = 1;
+       } 
 
        clen = strlen(cptr) + 1;
        if (clen > msglen) {
@@ -325,13 +372,28 @@ getmsg(int fd, char *cptr, char quote)
                if (quote && *cptr == quote) {
                        char   *tmp;
                        tmp = cptr + 1;
-                       if (*tmp && (!isspace((unsigned char) *tmp) || 
*wskip(tmp))) {
+                       if (!in_quote) {
+                               /* XXX hard error? */
                                warning(cptr, "unexpected quote character, 
ignoring");
                                *tptr++ = *cptr++;
                        } else {
-                               *cptr = '\0';
+                               cptr++;
+                               /* don't use wskip() */
+                               while (*cptr && isspace((unsigned char) *cptr))
+#ifndef _BACKWARDS_COMPAT
+                                       cptr++;
+#else
+                                       *tptr++ = *cptr++;
+#endif
+                               /* XXX hard error? */
+                               if (*cptr)
+                                       warning(tmp, "unexpected extra 
characters, ignoring");
+                               in_quote = 0;
+#ifndef _BACKWARDS_COMPAT
+                               break;
+#endif
                        }
-               } else
+               } else {
                        if (*cptr == '\\') {
                                ++cptr;
                                switch (*cptr) {
@@ -344,22 +406,34 @@ getmsg(int fd, char *cptr, char quote)
                                        msg = xrealloc(msg, msglen);
                                        tptr = msg + i;
                                        break;
-
-               #define CASEOF(CS, CH)          \
-                       case CS:                \
-                               *tptr++ = CH;   \
-                               ++cptr;         \
-                               break;          \
-
-                               CASEOF('n', '\n');
-                               CASEOF('t', '\t');
-                               CASEOF('v', '\v');
-                               CASEOF('b', '\b');
-                               CASEOF('r', '\r');
-                               CASEOF('f', '\f');
-                               CASEOF('"', '"');
-                               CASEOF('\\', '\\');
-
+                               case 'n':
+                                       *tptr++ = '\n';
+                                       ++cptr;
+                                       break;
+                               case 't':
+                                       *tptr++ = '\t';
+                                       ++cptr;
+                                       break;
+                               case 'v':
+                                       *tptr++ = '\v';
+                                       ++cptr;
+                                       break;
+                               case 'b':
+                                       *tptr++ = '\b';
+                                       ++cptr;
+                                       break;
+                               case 'r':
+                                       *tptr++ = '\r';
+                                       ++cptr;
+                                       break;
+                               case 'f':
+                                       *tptr++ = '\f';
+                                       ++cptr;
+                                       break;
+                               case '\\':
+                                       *tptr++ = '\\';
+                                       ++cptr;
+                                       break;
                                default:
                                        if (quote && *cptr == quote) {
                                                *tptr++ = *cptr++;
@@ -382,20 +456,24 @@ getmsg(int fd, char *cptr, char quote)
                        } else {
                                *tptr++ = *cptr++;
                        }
+               }
        }
+
+       if (in_quote)
+               warning(cptr, "unterminated quoted message, ignoring");
+
        *tptr = '\0';
        return (msg);
 }
 
-void
+static void
 MCParse(int fd)
 {
        char   *cptr, *str;
-       int     setid, msgid = 0;
+       int     msgid = 0;
+       int     setid = 0;
        char    quote = 0;
 
-       /* XXX: init sethead? */
-
        while ((cptr = get_line(fd))) {
                if (*cptr == '$') {
                        ++cptr;
@@ -443,12 +521,25 @@ MCParse(int fd)
                        if (isdigit((unsigned char) *cptr)) {
                                msgid = atoi(cptr);
                                cptr = cskip(cptr);
-                               cptr = wskip(cptr);
-                               /* if (*cptr) ++cptr; */
+                               if (*cptr) {
+                                       cptr = wskip(cptr);
+                                       if (!*cptr) {
+                                               MCAddMsg(msgid, "");
+                                               continue;
+                                       }
+                               }
                        } else {
                                warning(cptr, "neither blank line nor start of 
a message id");
                                continue;
                        }
+                       /*
+                        * If no set directive specified, all messages
+                        * shall be in default message set NL_SETD.
+                        */
+                       if (setid == 0) {
+                               setid = NL_SETD;
+                               MCAddSet(setid);
+                       }
                        /*
                         * If we have a message ID, but no message,
                         * then this means "delete this message id
@@ -464,6 +555,93 @@ MCParse(int fd)
        }
 }
 
+static void
+MCReadCat(int fd)
+{
+       void   *msgcat;         /* message catalog data */
+       struct _nls_cat_hdr cat_hdr;
+       struct _nls_set_hdr *set_hdr;
+       struct _nls_msg_hdr *msg_hdr;
+       char   *strings;
+       ssize_t n;
+       int     m, s;
+       int     msgno, setno;
+
+       n = read(fd, &cat_hdr, sizeof(cat_hdr));
+       if (n < (ssize_t)sizeof(cat_hdr)) {
+               if (n == 0)
+                       return;         /* empty file */
+               else if (n == -1)
+                       err(1, "header read");
+               else
+                       errx(1, CORRUPT);
+       }
+       if (ntohl((uint32_t)cat_hdr.__magic) != _NLS_MAGIC)
+               errx(1, "%s: bad magic number (%#x)", CORRUPT, cat_hdr.__magic);
+
+       cat_hdr.__mem = ntohl(cat_hdr.__mem);
+
+       cat_hdr.__nsets = ntohl(cat_hdr.__nsets);
+       cat_hdr.__msg_hdr_offset = ntohl(cat_hdr.__msg_hdr_offset);
+       cat_hdr.__msg_txt_offset = ntohl(cat_hdr.__msg_txt_offset);
+       if ((cat_hdr.__mem < 0) ||
+           (cat_hdr.__msg_hdr_offset < 0) ||
+           (cat_hdr.__msg_txt_offset < 0) ||
+           (cat_hdr.__mem < (int32_t)(cat_hdr.__nsets * sizeof(struct 
_nls_set_hdr))) ||
+           (cat_hdr.__mem < cat_hdr.__msg_hdr_offset) ||
+           (cat_hdr.__mem < cat_hdr.__msg_txt_offset))
+               errx(1, "%s: catalog header", CORRUPT);
+
+       msgcat = xmalloc(cat_hdr.__mem);
+
+       n = read(fd, msgcat, cat_hdr.__mem);
+       if (n < cat_hdr.__mem) {
+               if (n == -1)
+                       err(1, "data read");
+               else
+                       errx(1, CORRUPT);
+       }
+
+       set_hdr = (struct _nls_set_hdr *)msgcat;
+       msg_hdr = (struct _nls_msg_hdr *)((char *)msgcat +
+           cat_hdr.__msg_hdr_offset);
+       strings = (char *)msgcat + cat_hdr.__msg_txt_offset;
+
+       setno = 0;
+       for (s = 0; s < cat_hdr.__nsets; s++, set_hdr++) {
+               set_hdr->__setno = ntohl(set_hdr->__setno);
+               if (set_hdr->__setno < setno)
+                       errx(1, "%s: bad set number (%d)",
+                            CORRUPT, set_hdr->__setno);
+               setno = set_hdr->__setno;
+
+               MCAddSet(setno);
+
+               set_hdr->__nmsgs = ntohl(set_hdr->__nmsgs);
+               set_hdr->__index = ntohl(set_hdr->__index);
+               if (set_hdr->__nmsgs < 0 || set_hdr->__index < 0)
+                       errx(1, "%s: set header", CORRUPT);
+
+               /* Get the data */
+               msgno = 0;
+               for (m = 0; m < set_hdr->__nmsgs; m++, msg_hdr++) {
+                       msg_hdr->__msgno = ntohl(msg_hdr->__msgno);
+                       msg_hdr->__offset = ntohl(msg_hdr->__offset);
+                       if (msg_hdr->__msgno < msgno)
+                               errx(1, "%s: bad message number (%d)",
+                                    CORRUPT, msg_hdr->__msgno);
+                       if ((msg_hdr->__offset < 0) ||
+                           ((strings + msg_hdr->__offset) >
+                            ((char *)msgcat + cat_hdr.__mem)))
+                               errx(1, "%s: message header", CORRUPT);
+
+                       msgno = msg_hdr->__msgno;
+                       MCAddMsg(msgno, strings + msg_hdr->__offset);
+               }
+       }
+       free(msgcat);
+}
+
 /*
  * Write message catalog.
  *
@@ -473,7 +651,7 @@ MCParse(int fd)
  * avoids additional housekeeping variables and/or a lot of seeks
  * that would otherwise be required.
  */
-void
+static void
 MCWriteCat(int fd)
 {
        int     nsets;          /* number of sets */
@@ -496,12 +674,10 @@ MCWriteCat(int fd)
        nmsgs = 0;
        string_size = 0;
 
-       for (set = sethead.lh_first; set != NULL;
-           set = set->entries.le_next) {
+       LIST_FOREACH(set, &sethead, entries) {
                nsets++;
 
-               for (msg = set->msghead.lh_first; msg != NULL;
-                   msg = msg->entries.le_next) {
+               LIST_FOREACH(msg, &set->msghead, entries) {
                        nmsgs++;
                        string_size += strlen(msg->str) + 1;
                }
@@ -535,9 +711,9 @@ MCWriteCat(int fd)
            nmsgs * sizeof(struct _nls_msg_hdr));
 
        /* compute offsets for set & msg header tables and string pool */
-       set_hdr = (struct _nls_set_hdr *)(void *)((char *)msgcat +
+       set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
            sizeof(struct _nls_cat_hdr));
-       msg_hdr = (struct _nls_msg_hdr *)(void *)((char *)msgcat +
+       msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
            sizeof(struct _nls_cat_hdr) +
            nsets * sizeof(struct _nls_set_hdr));
        strings = (char *) msgcat +
@@ -547,13 +723,11 @@ MCWriteCat(int fd)
 
        msg_index = 0;
        msg_offset = 0;
-       for (set = sethead.lh_first; set != NULL;
-           set = set->entries.le_next) {
+       LIST_FOREACH(set, &sethead, entries) {
 
                nmsgs = 0;
-               for (msg = set->msghead.lh_first; msg != NULL;
-                   msg = msg->entries.le_next) {
-                       int     msg_len = strlen(msg->str) + 1;
+               LIST_FOREACH(msg, &set->msghead, entries) {
+                       int32_t     msg_len = strlen(msg->str) + 1;
 
                        msg_hdr->__msgno = htonl(msg->msgId);
                        msg_hdr->__msglen = htonl(msg_len);
@@ -578,7 +752,7 @@ MCWriteCat(int fd)
        write(fd, msgcat, msgcat_size);
 }
 
-void
+static void
 MCAddSet(int setId)
 {
        struct _setT *p, *q;
@@ -592,9 +766,10 @@ MCAddSet(int setId)
                /* NOTREACHED */
        }
 
-       p = sethead.lh_first;
+       p = LIST_FIRST(&sethead);
        q = NULL;
-       for (; p != NULL && p->setId < setId; q = p, p = p->entries.le_next);
+       for (; p != NULL && p->setId < setId; q = p, p = LIST_NEXT(p, entries))
+               continue;
 
        if (p && p->setId == setId) {
                ;
@@ -615,7 +790,7 @@ MCAddSet(int setId)
        curSet = p;
 }
 
-void
+static void
 MCAddMsg(int msgId, const char *str)
 {
        struct _msgT *p, *q;
@@ -632,9 +807,10 @@ MCAddMsg(int msgId, const char *str)
                /* NOTREACHED */
        }
 
-       p = curSet->msghead.lh_first;
+       p = LIST_FIRST(&curSet->msghead);
        q = NULL;
-       for (; p != NULL && p->msgId < msgId; q = p, p = p->entries.le_next);
+       for (; p != NULL && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries))
+               continue;
 
        if (p && p->msgId == msgId) {
                free(p->str);
@@ -653,30 +829,39 @@ MCAddMsg(int msgId, const char *str)
        p->str = xstrdup(str);
 }
 
-void
+static void
 MCDelSet(int setId)
 {
        struct _setT *set;
        struct _msgT *msg;
 
-       set = sethead.lh_first;
-       for (; set != NULL && set->setId < setId; set = set->entries.le_next);
+       if (setId <= 0) {
+               error("setId's must be greater than zero");
+               /* NOTREACHED */
+       }
+       if (setId > NL_SETMAX) {
+               error("setId exceeds limit");
+               /* NOTREACHED */
+       }
+
+       set = LIST_FIRST(&sethead);
+       for (; set != NULL && set->setId < setId; set = LIST_NEXT(set, entries))
+               continue;
 
        if (set && set->setId == setId) {
-
-               msg = set->msghead.lh_first;
-               while (msg) {
-                       free(msg->str);
+               LIST_REMOVE(set, entries);
+               while ((msg = LIST_FIRST(&set->msghead)) != NULL) {
                        LIST_REMOVE(msg, entries);
+                       free(msg->str);
+                       free(msg);
                }
-
-               LIST_REMOVE(set, entries);
+               free(set);
                return;
        }
        warning(NULL, "specified set doesn't exist");
 }
 
-void
+static void
 MCDelMsg(int msgId)
 {
        struct _msgT *msg;
@@ -684,12 +869,14 @@ MCDelMsg(int msgId)
        if (!curSet)
                error("you can't delete a message before defining the set");
 
-       msg = curSet->msghead.lh_first;
-       for (; msg != NULL && msg->msgId < msgId; msg = msg->entries.le_next);
+       msg = LIST_FIRST(&curSet->msghead);
+       for (; msg != NULL && msg->msgId < msgId; msg = LIST_NEXT(msg, entries))
+               continue;
 
        if (msg && msg->msgId == msgId) {
-               free(msg->str);
                LIST_REMOVE(msg, entries);
+               free(msg->str);
+               free(msg);
                return;
        }
        warning(NULL, "specified msg doesn't exist");
-- 
2.52.0

Reply via email to