|
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 |
}
|