Blame bin/gencat.c

Kylie McClain b80dee
/*
Kylie McClain b80dee
 * Copyright (c) 1996 The NetBSD Foundation, Inc.
Kylie McClain b80dee
 * All rights reserved.
Kylie McClain b80dee
 *
Kylie McClain b80dee
 * This code is derived from software contributed to The NetBSD Foundation
Kylie McClain b80dee
 * by J.T. Conklin.
Kylie McClain b80dee
 *
Kylie McClain b80dee
 * Redistribution and use in source and binary forms, with or without
Kylie McClain b80dee
 * modification, are permitted provided that the following conditions
Kylie McClain b80dee
 * are met:
Kylie McClain b80dee
 * 1. Redistributions of source code must retain the above copyright
Kylie McClain b80dee
 *    notice, this list of conditions and the following disclaimer.
Kylie McClain b80dee
 * 2. Redistributions in binary form must reproduce the above copyright
Kylie McClain b80dee
 *    notice, this list of conditions and the following disclaimer in the
Kylie McClain b80dee
 *    documentation and/or other materials provided with the distribution.
Kylie McClain b80dee
 *
Kylie McClain b80dee
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
Kylie McClain b80dee
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Kylie McClain b80dee
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Kylie McClain b80dee
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 
Kylie McClain b80dee
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Kylie McClain b80dee
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Kylie McClain b80dee
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Kylie McClain b80dee
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Kylie McClain b80dee
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Kylie McClain b80dee
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Kylie McClain b80dee
 * POSSIBILITY OF SUCH DAMAGE.
Kylie McClain b80dee
 */
Kylie McClain b80dee
Kylie McClain b80dee
/***********************************************************
Kylie McClain b80dee
Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
Kylie McClain b80dee
Kylie McClain b80dee
                        All Rights Reserved
Kylie McClain b80dee
Kylie McClain b80dee
Permission to use, copy, modify, and distribute this software and its
Kylie McClain b80dee
documentation for any purpose and without fee is hereby granted,
Kylie McClain b80dee
provided that the above copyright notice appear in all copies and that
Kylie McClain b80dee
both that copyright notice and this permission notice appear in
Kylie McClain b80dee
supporting documentation, and that Alfalfa's name not be used in
Kylie McClain b80dee
advertising or publicity pertaining to distribution of the software
Kylie McClain b80dee
without specific, written prior permission.
Kylie McClain b80dee
Kylie McClain b80dee
ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Kylie McClain b80dee
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Kylie McClain b80dee
ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Kylie McClain b80dee
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Kylie McClain b80dee
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Kylie McClain b80dee
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Kylie McClain b80dee
SOFTWARE.
Kylie McClain b80dee
Kylie McClain b80dee
If you make any modifications, bugfixes or other changes to this software
Kylie McClain b80dee
we'd appreciate it if you could send a copy to us so we can keep things
Kylie McClain b80dee
up-to-date.  Many thanks.
Kylie McClain b80dee
				Kee Hinckley
Kylie McClain b80dee
				Alfalfa Software, Inc.
Kylie McClain b80dee
				267 Allston St., #3
Kylie McClain b80dee
				Cambridge, MA 02139  USA
Kylie McClain b80dee
				nazgul@alfalfa.com
Kylie McClain b80dee
Kylie McClain b80dee
******************************************************************/
Kylie McClain b80dee
Kylie McClain b80dee
#define _NLS_PRIVATE
Kylie McClain b80dee
Kylie McClain b80dee
#include <sys/types.h>
Kylie McClain b80dee
#include <utime.h>
Kylie McClain b80dee
#include <sys/queue.h>
Kylie McClain b80dee
Kylie McClain b80dee
#include <arpa/inet.h>	/* Needed for htonl() on POSIX systems */
Kylie McClain b80dee
Kylie McClain b80dee
#include <ctype.h>
Kylie McClain b80dee
#include <err.h>
Kylie McClain b80dee
#include <errno.h>
Kylie McClain b80dee
#include <fcntl.h>
Kylie McClain b80dee
#include <limits.h>
Kylie McClain b80dee
#include <nl_types.h>
Kylie McClain b80dee
#include <stdio.h>
Kylie McClain b80dee
#include <stdlib.h>
Kylie McClain b80dee
#include <string.h>
Kylie McClain b80dee
#include <unistd.h>
Kylie McClain b80dee
Kylie McClain b80dee
#ifndef NL_SETMAX
Kylie McClain b80dee
#define NL_SETMAX 255
Kylie McClain b80dee
#endif
Kylie McClain b80dee
#ifndef NL_MSGMAX
Kylie McClain b80dee
#define NL_MSGMAX 2048
Kylie McClain b80dee
#endif
Kylie McClain b80dee
Kylie McClain b80dee
struct _msgT {
Kylie McClain b80dee
	long    msgId;
Kylie McClain b80dee
	char   *str;
Kylie McClain b80dee
        LIST_ENTRY(_msgT) entries;
Kylie McClain b80dee
};
Kylie McClain b80dee
Kylie McClain b80dee
struct _setT {
Kylie McClain b80dee
	long    setId;
Kylie McClain b80dee
        LIST_HEAD(msghead, _msgT) msghead;
Kylie McClain b80dee
        LIST_ENTRY(_setT) entries;
Kylie McClain b80dee
};
Kylie McClain b80dee
Kylie McClain b80dee
static LIST_HEAD(sethead, _setT) sethead = LIST_HEAD_INITIALIZER(sethead);
Kylie McClain b80dee
static struct _setT *curSet;
Kylie McClain b80dee
Kylie McClain b80dee
static const char *curfile;
Kylie McClain b80dee
static char *curline = NULL;
Kylie McClain b80dee
static long lineno = 0;
Kylie McClain b80dee
Kylie McClain b80dee
static	char   *cskip(char *);
Kylie McClain b80dee
static	void	error(const char *);
Kylie McClain b80dee
static	char   *get_line(int);
Kylie McClain b80dee
static	char   *getmsg(int, char *, char);
Kylie McClain b80dee
static	void	warning(const char *, const char *);
Kylie McClain b80dee
static	char   *wskip(char *);
Kylie McClain b80dee
static	char   *xstrdup(const char *);
Kylie McClain b80dee
static	void   *xmalloc(size_t);
Kylie McClain b80dee
static	void   *xrealloc(void *, size_t);
Kylie McClain b80dee
Kylie McClain b80dee
static void	MCParse(int fd);
Kylie McClain b80dee
static void	MCReadCat(int fd);
Kylie McClain b80dee
static void	MCWriteCat(int fd);
Kylie McClain b80dee
static void	MCDelMsg(int msgId);
Kylie McClain b80dee
static void	MCAddMsg(int msgId, const char *msg);
Kylie McClain b80dee
static void	MCAddSet(int setId);
Kylie McClain b80dee
static void	MCDelSet(int setId);
Kylie McClain b80dee
static void	usage(void);
Kylie McClain b80dee
Kylie McClain b80dee
/* Define things on BSD's nl_types.h */
Kylie McClain b80dee
#define _NLS_MAGIC	0xff88ff89
Kylie McClain b80dee
Kylie McClain b80dee
struct _nls_cat_hdr {
Kylie McClain b80dee
	int32_t __magic;
Kylie McClain b80dee
	int32_t __nsets;
Kylie McClain b80dee
	int32_t __mem;
Kylie McClain b80dee
	int32_t __msg_hdr_offset;
Kylie McClain b80dee
	int32_t __msg_txt_offset;
Kylie McClain b80dee
} ;
Kylie McClain b80dee
Kylie McClain b80dee
struct _nls_set_hdr {
Kylie McClain b80dee
	int32_t __setno;	/* set number: 0 < x <= NL_SETMAX */
Kylie McClain b80dee
	int32_t __nmsgs;	/* number of messages in the set  */
Kylie McClain b80dee
	int32_t __index;	/* index of first msg_hdr in msg_hdr table */
Kylie McClain b80dee
} ;
Kylie McClain b80dee
Kylie McClain b80dee
struct _nls_msg_hdr {
Kylie McClain b80dee
	int32_t __msgno;	/* msg number: 0 < x <= NL_MSGMAX */
Kylie McClain b80dee
	int32_t __msglen;
Kylie McClain b80dee
	int32_t __offset;
Kylie McClain b80dee
} ;
Kylie McClain b80dee
Kylie McClain b80dee
#define CORRUPT			"corrupt message catalog"
Kylie McClain b80dee
#define NOMEMORY		"out of memory"
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
usage(void)
Kylie McClain b80dee
{
Kylie McClain b80dee
	fprintf(stderr, "usage: %s catfile [msgfile|- ...]\n", "gencat");
Kylie McClain b80dee
	exit(1);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
int
Kylie McClain b80dee
main(int argc, char *argv[])
Kylie McClain b80dee
{
Kylie McClain b80dee
	int     ofd, ifd;
Kylie McClain b80dee
	char   *catfile = NULL;
Kylie McClain b80dee
	int     c;
Kylie McClain b80dee
	int	updatecat = 0;
Kylie McClain b80dee
Kylie McClain b80dee
	while ((c = getopt(argc, argv, "")) != -1) {
Kylie McClain b80dee
		switch (c) {
Kylie McClain b80dee
		case '?':
Kylie McClain b80dee
		default:
Kylie McClain b80dee
			usage();
Kylie McClain b80dee
			/* NOTREACHED */
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
	argc -= optind;
Kylie McClain b80dee
	argv += optind;
Kylie McClain b80dee
Kylie McClain b80dee
	if (argc < 1) {
Kylie McClain b80dee
		usage();
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
	catfile = *argv++;
Kylie McClain b80dee
Kylie McClain b80dee
	if ((catfile[0] == '-') && (catfile[1] == '\0')) {
Kylie McClain b80dee
		ofd = STDOUT_FILENO;
Kylie McClain b80dee
	} else {
Kylie McClain b80dee
		ofd = open(catfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
Kylie McClain b80dee
		if (ofd < 0) {
Kylie McClain b80dee
			if (errno == EEXIST) {
Kylie McClain b80dee
				if ((ofd = open(catfile, O_RDWR)) < 0) {
Kylie McClain b80dee
					err(1, "Unable to open %s", catfile);
Kylie McClain b80dee
					/* NOTREACHED */
Kylie McClain b80dee
				}
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				err(1, "Unable to create new %s", catfile);
Kylie McClain b80dee
				/* NOTREACHED */
Kylie McClain b80dee
			}
Kylie McClain b80dee
			curfile = catfile;
Kylie McClain b80dee
			updatecat = 1;
Kylie McClain b80dee
			MCReadCat(ofd);
Kylie McClain b80dee
			if (lseek(ofd, (off_t)0, SEEK_SET) == (off_t)-1) {
Kylie McClain b80dee
				err(1, "Unable to seek on %s", catfile);
Kylie McClain b80dee
				/* NOTREACHED */
Kylie McClain b80dee
			}
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	if (argc < 2 || (((*argv)[0] == '-') && ((*argv)[1] == '\0'))) {
Kylie McClain b80dee
		if (argc > 2)
Kylie McClain b80dee
			usage();
Kylie McClain b80dee
			/* NOTREACHED */
Kylie McClain b80dee
		MCParse(STDIN_FILENO);
Kylie McClain b80dee
	} else {
Kylie McClain b80dee
		for (; *argv; argv++) {
Kylie McClain b80dee
			if ((ifd = open(*argv, O_RDONLY)) < 0)
Kylie McClain b80dee
				err(1, "Unable to read %s", *argv);
Kylie McClain b80dee
			curfile = *argv;
Kylie McClain b80dee
			lineno = 0;
Kylie McClain b80dee
			MCParse(ifd);
Kylie McClain b80dee
			close(ifd);
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	if (updatecat) {
Kylie McClain b80dee
		if (ftruncate(ofd, 0) != 0) {
Kylie McClain b80dee
			err(1, "Unable to truncate %s", catfile);
Kylie McClain b80dee
			/* NOTREACHED */
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	MCWriteCat(ofd);
Kylie McClain b80dee
	exit(0);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
warning(const char *cptr, const char *msg)
Kylie McClain b80dee
{
Kylie McClain b80dee
	if (lineno) {
Kylie McClain b80dee
		fprintf(stderr, "%s: %s on line %ld, %s\n",
Kylie McClain b80dee
			"gencat", msg, lineno, curfile);
Kylie McClain b80dee
		fprintf(stderr, "%s\n", curline);
Kylie McClain b80dee
		if (cptr) {
Kylie McClain b80dee
			char   *tptr;
Kylie McClain b80dee
			for (tptr = curline; tptr < cptr; ++tptr)
Kylie McClain b80dee
				putc(' ', stderr);
Kylie McClain b80dee
			fprintf(stderr, "^\n");
Kylie McClain b80dee
		}
Kylie McClain b80dee
	} else {
Kylie McClain b80dee
		fprintf(stderr, "%s: %s, %s\n", "gencat", msg, curfile);
Kylie McClain b80dee
	}
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
error(const char *msg)
Kylie McClain b80dee
{
Kylie McClain b80dee
	warning(NULL, msg);
Kylie McClain b80dee
	exit(1);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void *
Kylie McClain b80dee
xmalloc(size_t len)
Kylie McClain b80dee
{
Kylie McClain b80dee
	void   *p;
Kylie McClain b80dee
Kylie McClain b80dee
	if ((p = malloc(len)) == NULL)
Kylie McClain b80dee
		errx(1, NOMEMORY);
Kylie McClain b80dee
	return (p);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void *
Kylie McClain b80dee
xrealloc(void *ptr, size_t size)
Kylie McClain b80dee
{
Kylie McClain b80dee
	if ((ptr = realloc(ptr, size)) == NULL)
Kylie McClain b80dee
		errx(1, NOMEMORY);
Kylie McClain b80dee
	return (ptr);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static char *
Kylie McClain b80dee
xstrdup(const char *str)
Kylie McClain b80dee
{
Kylie McClain b80dee
	char *nstr;
Kylie McClain b80dee
Kylie McClain b80dee
	if ((nstr = strdup(str)) == NULL)
Kylie McClain b80dee
		errx(1, NOMEMORY);
Kylie McClain b80dee
	return (nstr);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static char *
Kylie McClain b80dee
get_line(int fd)
Kylie McClain b80dee
{
Kylie McClain b80dee
	static long curlen = BUFSIZ;
Kylie McClain b80dee
	static char buf[BUFSIZ], *bptr = buf, *bend = buf;
Kylie McClain b80dee
	char   *cptr, *cend;
Kylie McClain b80dee
	long    buflen;
Kylie McClain b80dee
Kylie McClain b80dee
	if (!curline) {
Kylie McClain b80dee
		curline = xmalloc(curlen);
Kylie McClain b80dee
	}
Kylie McClain b80dee
	++lineno;
Kylie McClain b80dee
Kylie McClain b80dee
	cptr = curline;
Kylie McClain b80dee
	cend = curline + curlen;
Kylie McClain b80dee
	for (;;) {
Kylie McClain b80dee
		for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
Kylie McClain b80dee
			if (*bptr == '\n') {
Kylie McClain b80dee
				*cptr = '\0';
Kylie McClain b80dee
				++bptr;
Kylie McClain b80dee
				return (curline);
Kylie McClain b80dee
			} else
Kylie McClain b80dee
				*cptr = *bptr;
Kylie McClain b80dee
		}
Kylie McClain b80dee
		if (cptr == cend) {
Kylie McClain b80dee
			cptr = curline = xrealloc(curline, curlen *= 2);
Kylie McClain b80dee
			cend = curline + curlen;
Kylie McClain b80dee
		}
Kylie McClain b80dee
		if (bptr == bend) {
Kylie McClain b80dee
			buflen = read(fd, buf, BUFSIZ);
Kylie McClain b80dee
			if (buflen <= 0) {
Kylie McClain b80dee
				if (cptr > curline) {
Kylie McClain b80dee
					*cptr = '\0';
Kylie McClain b80dee
					return (curline);
Kylie McClain b80dee
				}
Kylie McClain b80dee
				return (NULL);
Kylie McClain b80dee
			}
Kylie McClain b80dee
			bend = buf + buflen;
Kylie McClain b80dee
			bptr = buf;
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static char *
Kylie McClain b80dee
wskip(char *cptr)
Kylie McClain b80dee
{
Kylie McClain b80dee
	if (!*cptr || !isspace((unsigned char) *cptr)) {
Kylie McClain b80dee
		warning(cptr, "expected a space");
Kylie McClain b80dee
		return (cptr);
Kylie McClain b80dee
	}
Kylie McClain b80dee
	while (*cptr && isspace((unsigned char) *cptr))
Kylie McClain b80dee
		++cptr;
Kylie McClain b80dee
	return (cptr);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static char *
Kylie McClain b80dee
cskip(char *cptr)
Kylie McClain b80dee
{
Kylie McClain b80dee
	if (!*cptr || isspace((unsigned char) *cptr)) {
Kylie McClain b80dee
		warning(cptr, "wasn't expecting a space");
Kylie McClain b80dee
		return (cptr);
Kylie McClain b80dee
	}
Kylie McClain b80dee
	while (*cptr && !isspace((unsigned char) *cptr))
Kylie McClain b80dee
		++cptr;
Kylie McClain b80dee
	return (cptr);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static char *
Kylie McClain b80dee
getmsg(int fd, char *cptr, char quote)
Kylie McClain b80dee
{
Kylie McClain b80dee
	static char *msg = NULL;
Kylie McClain b80dee
	static size_t msglen = 0;
Kylie McClain b80dee
	size_t  clen, i;
Kylie McClain b80dee
	int     in_quote = 0;
Kylie McClain b80dee
	char   *tptr;
Kylie McClain b80dee
Kylie McClain b80dee
	if (quote && *cptr == quote) {
Kylie McClain b80dee
		++cptr;
Kylie McClain b80dee
		in_quote = 1;
Kylie McClain b80dee
	} 
Kylie McClain b80dee
Kylie McClain b80dee
	clen = strlen(cptr) + 1;
Kylie McClain b80dee
	if (clen > msglen) {
Kylie McClain b80dee
		if (msglen)
Kylie McClain b80dee
			msg = xrealloc(msg, clen);
Kylie McClain b80dee
		else
Kylie McClain b80dee
			msg = xmalloc(clen);
Kylie McClain b80dee
		msglen = clen;
Kylie McClain b80dee
	}
Kylie McClain b80dee
	tptr = msg;
Kylie McClain b80dee
Kylie McClain b80dee
	while (*cptr) {
Kylie McClain b80dee
		if (quote && *cptr == quote) {
Kylie McClain b80dee
			char   *tmp;
Kylie McClain b80dee
			tmp = cptr + 1;
Kylie McClain b80dee
			if (!in_quote) {
Kylie McClain b80dee
				/* XXX hard error? */
Kylie McClain b80dee
				warning(cptr, "unexpected quote character, ignoring");
Kylie McClain b80dee
				*tptr++ = *cptr++;
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				cptr++;
Kylie McClain b80dee
				/* don't use wskip() */
Kylie McClain b80dee
				while (*cptr && isspace((unsigned char) *cptr))
Kylie McClain b80dee
#ifndef _BACKWARDS_COMPAT
Kylie McClain b80dee
					cptr++;
Kylie McClain b80dee
#else
Kylie McClain b80dee
					*tptr++ = *cptr++;
Kylie McClain b80dee
#endif
Kylie McClain b80dee
				/* XXX hard error? */
Kylie McClain b80dee
				if (*cptr)
Kylie McClain b80dee
					warning(tmp, "unexpected extra characters, ignoring");
Kylie McClain b80dee
				in_quote = 0;
Kylie McClain b80dee
#ifndef _BACKWARDS_COMPAT
Kylie McClain b80dee
				break;
Kylie McClain b80dee
#endif
Kylie McClain b80dee
			}
Kylie McClain b80dee
		} else {
Kylie McClain b80dee
			if (*cptr == '\\') {
Kylie McClain b80dee
				++cptr;
Kylie McClain b80dee
				switch (*cptr) {
Kylie McClain b80dee
				case '\0':
Kylie McClain b80dee
					cptr = get_line(fd);
Kylie McClain b80dee
					if (!cptr)
Kylie McClain b80dee
						error("premature end of file");
Kylie McClain b80dee
					msglen += strlen(cptr);
Kylie McClain b80dee
					i = tptr - msg;
Kylie McClain b80dee
					msg = xrealloc(msg, msglen);
Kylie McClain b80dee
					tptr = msg + i;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 'n':
Kylie McClain b80dee
					*tptr++ = '\n';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 't':
Kylie McClain b80dee
					*tptr++ = '\t';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 'v':
Kylie McClain b80dee
					*tptr++ = '\v';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 'b':
Kylie McClain b80dee
					*tptr++ = '\b';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 'r':
Kylie McClain b80dee
					*tptr++ = '\r';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case 'f':
Kylie McClain b80dee
					*tptr++ = '\f';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				case '\\':
Kylie McClain b80dee
					*tptr++ = '\\';
Kylie McClain b80dee
					++cptr;
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				default:
Kylie McClain b80dee
					if (quote && *cptr == quote) {
Kylie McClain b80dee
						*tptr++ = *cptr++;
Kylie McClain b80dee
					} else if (isdigit((unsigned char) *cptr)) {
Kylie McClain b80dee
						*tptr = 0;
Kylie McClain b80dee
						for (i = 0; i < 3; ++i) {
Kylie McClain b80dee
							if (!isdigit((unsigned char) *cptr))
Kylie McClain b80dee
								break;
Kylie McClain b80dee
							if (*cptr > '7')
Kylie McClain b80dee
								warning(cptr, "octal number greater than 7?!");
Kylie McClain b80dee
							*tptr *= 8;
Kylie McClain b80dee
							*tptr += (*cptr - '0');
Kylie McClain b80dee
							++cptr;
Kylie McClain b80dee
						}
Kylie McClain b80dee
					} else {
Kylie McClain b80dee
						warning(cptr, "unrecognized escape sequence");
Kylie McClain b80dee
					}
Kylie McClain b80dee
					break;
Kylie McClain b80dee
				}
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				*tptr++ = *cptr++;
Kylie McClain b80dee
			}
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	if (in_quote)
Kylie McClain b80dee
		warning(cptr, "unterminated quoted message, ignoring");
Kylie McClain b80dee
Kylie McClain b80dee
	*tptr = '\0';
Kylie McClain b80dee
	return (msg);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCParse(int fd)
Kylie McClain b80dee
{
Kylie McClain b80dee
	char   *cptr, *str;
Kylie McClain b80dee
	int	msgid = 0;
Kylie McClain b80dee
	int     setid = 0;
Kylie McClain b80dee
	char    quote = 0;
Kylie McClain b80dee
Kylie McClain b80dee
	while ((cptr = get_line(fd))) {
Kylie McClain b80dee
		if (*cptr == '$') {
Kylie McClain b80dee
			++cptr;
Kylie McClain b80dee
			if (strncmp(cptr, "set", 3) == 0) {
Kylie McClain b80dee
				cptr += 3;
Kylie McClain b80dee
				cptr = wskip(cptr);
Kylie McClain b80dee
				setid = atoi(cptr);
Kylie McClain b80dee
				MCAddSet(setid);
Kylie McClain b80dee
				msgid = 0;
Kylie McClain b80dee
			} else if (strncmp(cptr, "delset", 6) == 0) {
Kylie McClain b80dee
				cptr += 6;
Kylie McClain b80dee
				cptr = wskip(cptr);
Kylie McClain b80dee
				setid = atoi(cptr);
Kylie McClain b80dee
				MCDelSet(setid);
Kylie McClain b80dee
			} else if (strncmp(cptr, "quote", 5) == 0) {
Kylie McClain b80dee
				cptr += 5;
Kylie McClain b80dee
				if (!*cptr)
Kylie McClain b80dee
					quote = 0;
Kylie McClain b80dee
				else {
Kylie McClain b80dee
					cptr = wskip(cptr);
Kylie McClain b80dee
					if (!*cptr)
Kylie McClain b80dee
						quote = 0;
Kylie McClain b80dee
					else
Kylie McClain b80dee
						quote = *cptr;
Kylie McClain b80dee
				}
Kylie McClain b80dee
			} else if (isspace((unsigned char) *cptr)) {
Kylie McClain b80dee
				;
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				if (*cptr) {
Kylie McClain b80dee
					cptr = wskip(cptr);
Kylie McClain b80dee
					if (*cptr)
Kylie McClain b80dee
						warning(cptr, "unrecognized line");
Kylie McClain b80dee
				}
Kylie McClain b80dee
			}
Kylie McClain b80dee
		} else {
Kylie McClain b80dee
			/*
Kylie McClain b80dee
			 * First check for (and eat) empty lines....
Kylie McClain b80dee
			 */
Kylie McClain b80dee
			if (!*cptr)
Kylie McClain b80dee
				continue;
Kylie McClain b80dee
			/*
Kylie McClain b80dee
			 * We have a digit? Start of a message. Else,
Kylie McClain b80dee
			 * syntax error.
Kylie McClain b80dee
			 */
Kylie McClain b80dee
			if (isdigit((unsigned char) *cptr)) {
Kylie McClain b80dee
				msgid = atoi(cptr);
Kylie McClain b80dee
				cptr = cskip(cptr);
Kylie McClain b80dee
				if (*cptr) {
Kylie McClain b80dee
					cptr = wskip(cptr);
Kylie McClain b80dee
					if (!*cptr) {
Kylie McClain b80dee
						MCAddMsg(msgid, "");
Kylie McClain b80dee
						continue;
Kylie McClain b80dee
					}
Kylie McClain b80dee
				}
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				warning(cptr, "neither blank line nor start of a message id");
Kylie McClain b80dee
				continue;
Kylie McClain b80dee
			}
Kylie McClain b80dee
			/*
Kylie McClain b80dee
			 * If no set directive specified, all messages
Kylie McClain b80dee
			 * shall be in default message set NL_SETD.
Kylie McClain b80dee
			 */
Kylie McClain b80dee
			if (setid == 0) {
Kylie McClain b80dee
				setid = NL_SETD;
Kylie McClain b80dee
				MCAddSet(setid);
Kylie McClain b80dee
			}
Kylie McClain b80dee
			/*
Kylie McClain b80dee
			 * If we have a message ID, but no message,
Kylie McClain b80dee
			 * then this means "delete this message id
Kylie McClain b80dee
			 * from the catalog".
Kylie McClain b80dee
			 */
Kylie McClain b80dee
			if (!*cptr) {
Kylie McClain b80dee
				MCDelMsg(msgid);
Kylie McClain b80dee
			} else {
Kylie McClain b80dee
				str = getmsg(fd, cptr, quote);
Kylie McClain b80dee
				MCAddMsg(msgid, str);
Kylie McClain b80dee
			}
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCReadCat(int fd)
Kylie McClain b80dee
{
Kylie McClain b80dee
	void   *msgcat;		/* message catalog data */
Kylie McClain b80dee
	struct _nls_cat_hdr cat_hdr;
Kylie McClain b80dee
	struct _nls_set_hdr *set_hdr;
Kylie McClain b80dee
	struct _nls_msg_hdr *msg_hdr;
Kylie McClain b80dee
	char   *strings;
Kylie McClain b80dee
	ssize_t	n;
Kylie McClain b80dee
	int	m, s;
Kylie McClain b80dee
	int	msgno, setno;
Kylie McClain b80dee
Kylie McClain b80dee
	n = read(fd, &cat_hdr, sizeof(cat_hdr));
Kylie McClain b80dee
	if (n < (ssize_t)sizeof(cat_hdr)) {
Kylie McClain b80dee
		if (n == 0)
Kylie McClain b80dee
			return;		/* empty file */
Kylie McClain b80dee
		else if (n == -1)
Kylie McClain b80dee
			err(1, "header read");
Kylie McClain b80dee
		else
Kylie McClain b80dee
			errx(1, CORRUPT);
Kylie McClain b80dee
	}
Kylie McClain b80dee
	if (ntohl((uint32_t)cat_hdr.__magic) != _NLS_MAGIC)
Kylie McClain b80dee
		errx(1, "%s: bad magic number (%#x)", CORRUPT, cat_hdr.__magic);
Kylie McClain b80dee
Kylie McClain b80dee
	cat_hdr.__mem = ntohl(cat_hdr.__mem);
Kylie McClain b80dee
Kylie McClain b80dee
	cat_hdr.__nsets = ntohl(cat_hdr.__nsets);
Kylie McClain b80dee
	cat_hdr.__msg_hdr_offset = ntohl(cat_hdr.__msg_hdr_offset);
Kylie McClain b80dee
	cat_hdr.__msg_txt_offset = ntohl(cat_hdr.__msg_txt_offset);
Kylie McClain b80dee
	if ((cat_hdr.__mem < 0) ||
Kylie McClain b80dee
	    (cat_hdr.__msg_hdr_offset < 0) ||
Kylie McClain b80dee
	    (cat_hdr.__msg_txt_offset < 0) ||
Kylie McClain b80dee
	    (cat_hdr.__mem < (int32_t)(cat_hdr.__nsets * sizeof(struct _nls_set_hdr))) ||
Kylie McClain b80dee
	    (cat_hdr.__mem < cat_hdr.__msg_hdr_offset) ||
Kylie McClain b80dee
	    (cat_hdr.__mem < cat_hdr.__msg_txt_offset))
Kylie McClain b80dee
		errx(1, "%s: catalog header", CORRUPT);
Kylie McClain b80dee
Kylie McClain b80dee
	msgcat = xmalloc(cat_hdr.__mem);
Kylie McClain b80dee
Kylie McClain b80dee
	n = read(fd, msgcat, cat_hdr.__mem);
Kylie McClain b80dee
	if (n < cat_hdr.__mem) {
Kylie McClain b80dee
		if (n == -1)
Kylie McClain b80dee
			err(1, "data read");
Kylie McClain b80dee
		else
Kylie McClain b80dee
			errx(1, CORRUPT);
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	set_hdr = (struct _nls_set_hdr *)msgcat;
Kylie McClain b80dee
	msg_hdr = (struct _nls_msg_hdr *)((char *)msgcat +
Kylie McClain b80dee
	    cat_hdr.__msg_hdr_offset);
Kylie McClain b80dee
	strings = (char *)msgcat + cat_hdr.__msg_txt_offset;
Kylie McClain b80dee
Kylie McClain b80dee
	setno = 0;
Kylie McClain b80dee
	for (s = 0; s < cat_hdr.__nsets; s++, set_hdr++) {
Kylie McClain b80dee
		set_hdr->__setno = ntohl(set_hdr->__setno);
Kylie McClain b80dee
		if (set_hdr->__setno < setno)
Kylie McClain b80dee
			errx(1, "%s: bad set number (%d)",
Kylie McClain b80dee
		       	     CORRUPT, set_hdr->__setno);
Kylie McClain b80dee
		setno = set_hdr->__setno;
Kylie McClain b80dee
Kylie McClain b80dee
		MCAddSet(setno);
Kylie McClain b80dee
Kylie McClain b80dee
		set_hdr->__nmsgs = ntohl(set_hdr->__nmsgs);
Kylie McClain b80dee
		set_hdr->__index = ntohl(set_hdr->__index);
Kylie McClain b80dee
		if (set_hdr->__nmsgs < 0 || set_hdr->__index < 0)
Kylie McClain b80dee
			errx(1, "%s: set header", CORRUPT);
Kylie McClain b80dee
Kylie McClain b80dee
		/* Get the data */
Kylie McClain b80dee
		msgno = 0;
Kylie McClain b80dee
		for (m = 0; m < set_hdr->__nmsgs; m++, msg_hdr++) {
Kylie McClain b80dee
			msg_hdr->__msgno = ntohl(msg_hdr->__msgno);
Kylie McClain b80dee
			msg_hdr->__offset = ntohl(msg_hdr->__offset);
Kylie McClain b80dee
			if (msg_hdr->__msgno < msgno)
Kylie McClain b80dee
				errx(1, "%s: bad message number (%d)",
Kylie McClain b80dee
				     CORRUPT, msg_hdr->__msgno);
Kylie McClain b80dee
		        if ((msg_hdr->__offset < 0) ||
Kylie McClain b80dee
			    ((strings + msg_hdr->__offset) >
Kylie McClain b80dee
			     ((char *)msgcat + cat_hdr.__mem)))
Kylie McClain b80dee
				errx(1, "%s: message header", CORRUPT);
Kylie McClain b80dee
Kylie McClain b80dee
			msgno = msg_hdr->__msgno;
Kylie McClain b80dee
			MCAddMsg(msgno, strings + msg_hdr->__offset);
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
	free(msgcat);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
/*
Kylie McClain b80dee
 * Write message catalog.
Kylie McClain b80dee
 *
Kylie McClain b80dee
 * The message catalog is first converted from its internal to its
Kylie McClain b80dee
 * external representation in a chunk of memory allocated for this
Kylie McClain b80dee
 * purpose.  Then the completed catalog is written.  This approach
Kylie McClain b80dee
 * avoids additional housekeeping variables and/or a lot of seeks
Kylie McClain b80dee
 * that would otherwise be required.
Kylie McClain b80dee
 */
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCWriteCat(int fd)
Kylie McClain b80dee
{
Kylie McClain b80dee
	int     nsets;		/* number of sets */
Kylie McClain b80dee
	int     nmsgs;		/* number of msgs */
Kylie McClain b80dee
	int     string_size;	/* total size of string pool */
Kylie McClain b80dee
	int     msgcat_size;	/* total size of message catalog */
Kylie McClain b80dee
	void   *msgcat;		/* message catalog data */
Kylie McClain b80dee
	struct _nls_cat_hdr *cat_hdr;
Kylie McClain b80dee
	struct _nls_set_hdr *set_hdr;
Kylie McClain b80dee
	struct _nls_msg_hdr *msg_hdr;
Kylie McClain b80dee
	char   *strings;
Kylie McClain b80dee
	struct _setT *set;
Kylie McClain b80dee
	struct _msgT *msg;
Kylie McClain b80dee
	int     msg_index;
Kylie McClain b80dee
	int     msg_offset;
Kylie McClain b80dee
Kylie McClain b80dee
	/* determine number of sets, number of messages, and size of the
Kylie McClain b80dee
	 * string pool */
Kylie McClain b80dee
	nsets = 0;
Kylie McClain b80dee
	nmsgs = 0;
Kylie McClain b80dee
	string_size = 0;
Kylie McClain b80dee
Kylie McClain b80dee
	LIST_FOREACH(set, &sethead, entries) {
Kylie McClain b80dee
		nsets++;
Kylie McClain b80dee
Kylie McClain b80dee
		LIST_FOREACH(msg, &set->msghead, entries) {
Kylie McClain b80dee
			nmsgs++;
Kylie McClain b80dee
			string_size += strlen(msg->str) + 1;
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
#ifdef DEBUG
Kylie McClain b80dee
	printf("number of sets: %d\n", nsets);
Kylie McClain b80dee
	printf("number of msgs: %d\n", nmsgs);
Kylie McClain b80dee
	printf("string pool size: %d\n", string_size);
Kylie McClain b80dee
#endif
Kylie McClain b80dee
Kylie McClain b80dee
	/* determine size and then allocate buffer for constructing external
Kylie McClain b80dee
	 * message catalog representation */
Kylie McClain b80dee
	msgcat_size = sizeof(struct _nls_cat_hdr)
Kylie McClain b80dee
	    + (nsets * sizeof(struct _nls_set_hdr))
Kylie McClain b80dee
	    + (nmsgs * sizeof(struct _nls_msg_hdr))
Kylie McClain b80dee
	    + string_size;
Kylie McClain b80dee
Kylie McClain b80dee
	msgcat = xmalloc(msgcat_size);
Kylie McClain b80dee
	memset(msgcat, '\0', msgcat_size);
Kylie McClain b80dee
Kylie McClain b80dee
	/* fill in msg catalog header */
Kylie McClain b80dee
	cat_hdr = (struct _nls_cat_hdr *) msgcat;
Kylie McClain b80dee
	cat_hdr->__magic = htonl(_NLS_MAGIC);
Kylie McClain b80dee
	cat_hdr->__nsets = htonl(nsets);
Kylie McClain b80dee
	cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr));
Kylie McClain b80dee
	cat_hdr->__msg_hdr_offset =
Kylie McClain b80dee
	    htonl(nsets * sizeof(struct _nls_set_hdr));
Kylie McClain b80dee
	cat_hdr->__msg_txt_offset =
Kylie McClain b80dee
	    htonl(nsets * sizeof(struct _nls_set_hdr) +
Kylie McClain b80dee
	    nmsgs * sizeof(struct _nls_msg_hdr));
Kylie McClain b80dee
Kylie McClain b80dee
	/* compute offsets for set & msg header tables and string pool */
Kylie McClain b80dee
	set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
Kylie McClain b80dee
	    sizeof(struct _nls_cat_hdr));
Kylie McClain b80dee
	msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
Kylie McClain b80dee
	    sizeof(struct _nls_cat_hdr) +
Kylie McClain b80dee
	    nsets * sizeof(struct _nls_set_hdr));
Kylie McClain b80dee
	strings = (char *) msgcat +
Kylie McClain b80dee
	    sizeof(struct _nls_cat_hdr) +
Kylie McClain b80dee
	    nsets * sizeof(struct _nls_set_hdr) +
Kylie McClain b80dee
	    nmsgs * sizeof(struct _nls_msg_hdr);
Kylie McClain b80dee
Kylie McClain b80dee
	msg_index = 0;
Kylie McClain b80dee
	msg_offset = 0;
Kylie McClain b80dee
	LIST_FOREACH(set, &sethead, entries) {
Kylie McClain b80dee
Kylie McClain b80dee
		nmsgs = 0;
Kylie McClain b80dee
		LIST_FOREACH(msg, &set->msghead, entries) {
Kylie McClain b80dee
			int32_t     msg_len = strlen(msg->str) + 1;
Kylie McClain b80dee
Kylie McClain b80dee
			msg_hdr->__msgno = htonl(msg->msgId);
Kylie McClain b80dee
			msg_hdr->__msglen = htonl(msg_len);
Kylie McClain b80dee
			msg_hdr->__offset = htonl(msg_offset);
Kylie McClain b80dee
Kylie McClain b80dee
			memcpy(strings, msg->str, msg_len);
Kylie McClain b80dee
			strings += msg_len;
Kylie McClain b80dee
			msg_offset += msg_len;
Kylie McClain b80dee
Kylie McClain b80dee
			nmsgs++;
Kylie McClain b80dee
			msg_hdr++;
Kylie McClain b80dee
		}
Kylie McClain b80dee
Kylie McClain b80dee
		set_hdr->__setno = htonl(set->setId);
Kylie McClain b80dee
		set_hdr->__nmsgs = htonl(nmsgs);
Kylie McClain b80dee
		set_hdr->__index = htonl(msg_index);
Kylie McClain b80dee
		msg_index += nmsgs;
Kylie McClain b80dee
		set_hdr++;
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	/* write out catalog.  XXX: should this be done in small chunks? */
Kylie McClain b80dee
	write(fd, msgcat, msgcat_size);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCAddSet(int setId)
Kylie McClain b80dee
{
Kylie McClain b80dee
	struct _setT *p, *q;
Kylie McClain b80dee
Kylie McClain b80dee
	if (setId <= 0) {
Kylie McClain b80dee
		error("setId's must be greater than zero");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
	if (setId > NL_SETMAX) {
Kylie McClain b80dee
		error("setId exceeds limit");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	p = LIST_FIRST(&sethead);
Kylie McClain b80dee
	q = NULL;
Kylie McClain b80dee
	for (; p != NULL && p->setId < setId; q = p, p = LIST_NEXT(p, entries))
Kylie McClain b80dee
		continue;
Kylie McClain b80dee
Kylie McClain b80dee
	if (p && p->setId == setId) {
Kylie McClain b80dee
		;
Kylie McClain b80dee
	} else {
Kylie McClain b80dee
		p = xmalloc(sizeof(struct _setT));
Kylie McClain b80dee
		memset(p, '\0', sizeof(struct _setT));
Kylie McClain b80dee
		LIST_INIT(&p->msghead);
Kylie McClain b80dee
Kylie McClain b80dee
		p->setId = setId;
Kylie McClain b80dee
Kylie McClain b80dee
		if (q == NULL) {
Kylie McClain b80dee
			LIST_INSERT_HEAD(&sethead, p, entries);
Kylie McClain b80dee
		} else {
Kylie McClain b80dee
			LIST_INSERT_AFTER(q, p, entries);
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	curSet = p;
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCAddMsg(int msgId, const char *str)
Kylie McClain b80dee
{
Kylie McClain b80dee
	struct _msgT *p, *q;
Kylie McClain b80dee
Kylie McClain b80dee
	if (!curSet)
Kylie McClain b80dee
		error("can't specify a message when no set exists");
Kylie McClain b80dee
Kylie McClain b80dee
	if (msgId <= 0) {
Kylie McClain b80dee
		error("msgId's must be greater than zero");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
	if (msgId > NL_MSGMAX) {
Kylie McClain b80dee
		error("msgID exceeds limit");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	p = LIST_FIRST(&curSet->msghead);
Kylie McClain b80dee
	q = NULL;
Kylie McClain b80dee
	for (; p != NULL && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries))
Kylie McClain b80dee
		continue;
Kylie McClain b80dee
Kylie McClain b80dee
	if (p && p->msgId == msgId) {
Kylie McClain b80dee
		free(p->str);
Kylie McClain b80dee
	} else {
Kylie McClain b80dee
		p = xmalloc(sizeof(struct _msgT));
Kylie McClain b80dee
		memset(p, '\0', sizeof(struct _msgT));
Kylie McClain b80dee
Kylie McClain b80dee
		if (q == NULL) {
Kylie McClain b80dee
			LIST_INSERT_HEAD(&curSet->msghead, p, entries);
Kylie McClain b80dee
		} else {
Kylie McClain b80dee
			LIST_INSERT_AFTER(q, p, entries);
Kylie McClain b80dee
		}
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	p->msgId = msgId;
Kylie McClain b80dee
	p->str = xstrdup(str);
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCDelSet(int setId)
Kylie McClain b80dee
{
Kylie McClain b80dee
	struct _setT *set;
Kylie McClain b80dee
	struct _msgT *msg;
Kylie McClain b80dee
Kylie McClain b80dee
	if (setId <= 0) {
Kylie McClain b80dee
		error("setId's must be greater than zero");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
	if (setId > NL_SETMAX) {
Kylie McClain b80dee
		error("setId exceeds limit");
Kylie McClain b80dee
		/* NOTREACHED */
Kylie McClain b80dee
	}
Kylie McClain b80dee
Kylie McClain b80dee
	set = LIST_FIRST(&sethead);
Kylie McClain b80dee
	for (; set != NULL && set->setId < setId; set = LIST_NEXT(set, entries))
Kylie McClain b80dee
		continue;
Kylie McClain b80dee
Kylie McClain b80dee
	if (set && set->setId == setId) {
Kylie McClain b80dee
		LIST_REMOVE(set, entries);
Kylie McClain b80dee
		while ((msg = LIST_FIRST(&set->msghead)) != NULL) {
Kylie McClain b80dee
			LIST_REMOVE(msg, entries);
Kylie McClain b80dee
			free(msg->str);
Kylie McClain b80dee
			free(msg);
Kylie McClain b80dee
		}
Kylie McClain b80dee
		free(set);
Kylie McClain b80dee
		return;
Kylie McClain b80dee
	}
Kylie McClain b80dee
	warning(NULL, "specified set doesn't exist");
Kylie McClain b80dee
}
Kylie McClain b80dee
Kylie McClain b80dee
static void
Kylie McClain b80dee
MCDelMsg(int msgId)
Kylie McClain b80dee
{
Kylie McClain b80dee
	struct _msgT *msg;
Kylie McClain b80dee
Kylie McClain b80dee
	if (!curSet)
Kylie McClain b80dee
		error("you can't delete a message before defining the set");
Kylie McClain b80dee
Kylie McClain b80dee
	msg = LIST_FIRST(&curSet->msghead);
Kylie McClain b80dee
	for (; msg != NULL && msg->msgId < msgId; msg = LIST_NEXT(msg, entries))
Kylie McClain b80dee
		continue;
Kylie McClain b80dee
Kylie McClain b80dee
	if (msg && msg->msgId == msgId) {
Kylie McClain b80dee
		LIST_REMOVE(msg, entries);
Kylie McClain b80dee
		free(msg->str);
Kylie McClain b80dee
		free(msg);
Kylie McClain b80dee
		return;
Kylie McClain b80dee
	}
Kylie McClain b80dee
	warning(NULL, "specified msg doesn't exist");
Kylie McClain b80dee
}