1*36dcc4a4SLionel Sambuc /* $NetBSD: gencat.c,v 1.36 2013/11/27 17:38:11 apb Exp $ */
2*36dcc4a4SLionel Sambuc
3*36dcc4a4SLionel Sambuc /*
4*36dcc4a4SLionel Sambuc * Copyright (c) 1996 The NetBSD Foundation, Inc.
5*36dcc4a4SLionel Sambuc * All rights reserved.
6*36dcc4a4SLionel Sambuc *
7*36dcc4a4SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
8*36dcc4a4SLionel Sambuc * by J.T. Conklin.
9*36dcc4a4SLionel Sambuc *
10*36dcc4a4SLionel Sambuc * Redistribution and use in source and binary forms, with or without
11*36dcc4a4SLionel Sambuc * modification, are permitted provided that the following conditions
12*36dcc4a4SLionel Sambuc * are met:
13*36dcc4a4SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14*36dcc4a4SLionel Sambuc * notice, this list of conditions and the following disclaimer.
15*36dcc4a4SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*36dcc4a4SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17*36dcc4a4SLionel Sambuc * documentation and/or other materials provided with the distribution.
18*36dcc4a4SLionel Sambuc *
19*36dcc4a4SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*36dcc4a4SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*36dcc4a4SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*36dcc4a4SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*36dcc4a4SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*36dcc4a4SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*36dcc4a4SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*36dcc4a4SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*36dcc4a4SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*36dcc4a4SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*36dcc4a4SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
30*36dcc4a4SLionel Sambuc */
31*36dcc4a4SLionel Sambuc
32*36dcc4a4SLionel Sambuc #include <sys/cdefs.h>
33*36dcc4a4SLionel Sambuc #if defined(__RCSID) && !defined(lint)
34*36dcc4a4SLionel Sambuc __RCSID("$NetBSD: gencat.c,v 1.36 2013/11/27 17:38:11 apb Exp $");
35*36dcc4a4SLionel Sambuc #endif
36*36dcc4a4SLionel Sambuc
37*36dcc4a4SLionel Sambuc /***********************************************************
38*36dcc4a4SLionel Sambuc Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
39*36dcc4a4SLionel Sambuc
40*36dcc4a4SLionel Sambuc All Rights Reserved
41*36dcc4a4SLionel Sambuc
42*36dcc4a4SLionel Sambuc Permission to use, copy, modify, and distribute this software and its
43*36dcc4a4SLionel Sambuc documentation for any purpose and without fee is hereby granted,
44*36dcc4a4SLionel Sambuc provided that the above copyright notice appear in all copies and that
45*36dcc4a4SLionel Sambuc both that copyright notice and this permission notice appear in
46*36dcc4a4SLionel Sambuc supporting documentation, and that Alfalfa's name not be used in
47*36dcc4a4SLionel Sambuc advertising or publicity pertaining to distribution of the software
48*36dcc4a4SLionel Sambuc without specific, written prior permission.
49*36dcc4a4SLionel Sambuc
50*36dcc4a4SLionel Sambuc ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51*36dcc4a4SLionel Sambuc ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
52*36dcc4a4SLionel Sambuc ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53*36dcc4a4SLionel Sambuc ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54*36dcc4a4SLionel Sambuc WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55*36dcc4a4SLionel Sambuc ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56*36dcc4a4SLionel Sambuc SOFTWARE.
57*36dcc4a4SLionel Sambuc
58*36dcc4a4SLionel Sambuc If you make any modifications, bugfixes or other changes to this software
59*36dcc4a4SLionel Sambuc we'd appreciate it if you could send a copy to us so we can keep things
60*36dcc4a4SLionel Sambuc up-to-date. Many thanks.
61*36dcc4a4SLionel Sambuc Kee Hinckley
62*36dcc4a4SLionel Sambuc Alfalfa Software, Inc.
63*36dcc4a4SLionel Sambuc 267 Allston St., #3
64*36dcc4a4SLionel Sambuc Cambridge, MA 02139 USA
65*36dcc4a4SLionel Sambuc nazgul@alfalfa.com
66*36dcc4a4SLionel Sambuc
67*36dcc4a4SLionel Sambuc ******************************************************************/
68*36dcc4a4SLionel Sambuc
69*36dcc4a4SLionel Sambuc #if HAVE_NBTOOL_CONFIG_H
70*36dcc4a4SLionel Sambuc #include "nbtool_config.h"
71*36dcc4a4SLionel Sambuc #endif
72*36dcc4a4SLionel Sambuc
73*36dcc4a4SLionel Sambuc #define _NLS_PRIVATE
74*36dcc4a4SLionel Sambuc
75*36dcc4a4SLionel Sambuc #include <sys/types.h>
76*36dcc4a4SLionel Sambuc #include <sys/queue.h>
77*36dcc4a4SLionel Sambuc
78*36dcc4a4SLionel Sambuc #include <netinet/in.h> /* Needed by arpa/inet.h on NetBSD */
79*36dcc4a4SLionel Sambuc #include <arpa/inet.h> /* Needed for htonl() on POSIX systems */
80*36dcc4a4SLionel Sambuc
81*36dcc4a4SLionel Sambuc #include <ctype.h>
82*36dcc4a4SLionel Sambuc #include <err.h>
83*36dcc4a4SLionel Sambuc #include <errno.h>
84*36dcc4a4SLionel Sambuc #include <fcntl.h>
85*36dcc4a4SLionel Sambuc #include <limits.h>
86*36dcc4a4SLionel Sambuc #include <nl_types.h>
87*36dcc4a4SLionel Sambuc #include <stdio.h>
88*36dcc4a4SLionel Sambuc #include <stdlib.h>
89*36dcc4a4SLionel Sambuc #include <string.h>
90*36dcc4a4SLionel Sambuc #include <unistd.h>
91*36dcc4a4SLionel Sambuc
92*36dcc4a4SLionel Sambuc #ifndef NL_SETMAX
93*36dcc4a4SLionel Sambuc #define NL_SETMAX 255
94*36dcc4a4SLionel Sambuc #endif
95*36dcc4a4SLionel Sambuc #ifndef NL_MSGMAX
96*36dcc4a4SLionel Sambuc #define NL_MSGMAX 2048
97*36dcc4a4SLionel Sambuc #endif
98*36dcc4a4SLionel Sambuc
99*36dcc4a4SLionel Sambuc struct _msgT {
100*36dcc4a4SLionel Sambuc long msgId;
101*36dcc4a4SLionel Sambuc char *str;
102*36dcc4a4SLionel Sambuc LIST_ENTRY(_msgT) entries;
103*36dcc4a4SLionel Sambuc };
104*36dcc4a4SLionel Sambuc
105*36dcc4a4SLionel Sambuc struct _setT {
106*36dcc4a4SLionel Sambuc long setId;
107*36dcc4a4SLionel Sambuc LIST_HEAD(msghead, _msgT) msghead;
108*36dcc4a4SLionel Sambuc LIST_ENTRY(_setT) entries;
109*36dcc4a4SLionel Sambuc };
110*36dcc4a4SLionel Sambuc
111*36dcc4a4SLionel Sambuc static LIST_HEAD(sethead, _setT) sethead = LIST_HEAD_INITIALIZER(sethead);
112*36dcc4a4SLionel Sambuc static struct _setT *curSet;
113*36dcc4a4SLionel Sambuc
114*36dcc4a4SLionel Sambuc static const char *curfile;
115*36dcc4a4SLionel Sambuc static char *curline = NULL;
116*36dcc4a4SLionel Sambuc static long lineno = 0;
117*36dcc4a4SLionel Sambuc
118*36dcc4a4SLionel Sambuc static char *cskip(char *);
119*36dcc4a4SLionel Sambuc __dead static void error(const char *);
120*36dcc4a4SLionel Sambuc static char *get_line(int);
121*36dcc4a4SLionel Sambuc static char *getmsg(int, char *, char);
122*36dcc4a4SLionel Sambuc static void warning(const char *, const char *);
123*36dcc4a4SLionel Sambuc static char *wskip(char *);
124*36dcc4a4SLionel Sambuc static char *xstrdup(const char *);
125*36dcc4a4SLionel Sambuc static void *xmalloc(size_t);
126*36dcc4a4SLionel Sambuc static void *xrealloc(void *, size_t);
127*36dcc4a4SLionel Sambuc
128*36dcc4a4SLionel Sambuc static void MCParse(int fd);
129*36dcc4a4SLionel Sambuc static void MCReadCat(int fd);
130*36dcc4a4SLionel Sambuc static void MCWriteCat(int fd);
131*36dcc4a4SLionel Sambuc static void MCDelMsg(int msgId);
132*36dcc4a4SLionel Sambuc static void MCAddMsg(int msgId, const char *msg);
133*36dcc4a4SLionel Sambuc static void MCAddSet(int setId);
134*36dcc4a4SLionel Sambuc static void MCDelSet(int setId);
135*36dcc4a4SLionel Sambuc __dead static void usage(void);
136*36dcc4a4SLionel Sambuc
137*36dcc4a4SLionel Sambuc #define CORRUPT "corrupt message catalog"
138*36dcc4a4SLionel Sambuc #define NOMEMORY "out of memory"
139*36dcc4a4SLionel Sambuc
140*36dcc4a4SLionel Sambuc static void
usage(void)141*36dcc4a4SLionel Sambuc usage(void)
142*36dcc4a4SLionel Sambuc {
143*36dcc4a4SLionel Sambuc fprintf(stderr, "usage: %s catfile [msgfile|- ...]\n", getprogname());
144*36dcc4a4SLionel Sambuc exit(1);
145*36dcc4a4SLionel Sambuc }
146*36dcc4a4SLionel Sambuc
147*36dcc4a4SLionel Sambuc int
main(int argc,char * argv[])148*36dcc4a4SLionel Sambuc main(int argc, char *argv[])
149*36dcc4a4SLionel Sambuc {
150*36dcc4a4SLionel Sambuc int ofd, ifd;
151*36dcc4a4SLionel Sambuc char *catfile = NULL;
152*36dcc4a4SLionel Sambuc int c;
153*36dcc4a4SLionel Sambuc int updatecat = 0;
154*36dcc4a4SLionel Sambuc
155*36dcc4a4SLionel Sambuc while ((c = getopt(argc, argv, "")) != -1) {
156*36dcc4a4SLionel Sambuc switch (c) {
157*36dcc4a4SLionel Sambuc case '?':
158*36dcc4a4SLionel Sambuc default:
159*36dcc4a4SLionel Sambuc usage();
160*36dcc4a4SLionel Sambuc /* NOTREACHED */
161*36dcc4a4SLionel Sambuc }
162*36dcc4a4SLionel Sambuc }
163*36dcc4a4SLionel Sambuc argc -= optind;
164*36dcc4a4SLionel Sambuc argv += optind;
165*36dcc4a4SLionel Sambuc
166*36dcc4a4SLionel Sambuc if (argc < 1) {
167*36dcc4a4SLionel Sambuc usage();
168*36dcc4a4SLionel Sambuc /* NOTREACHED */
169*36dcc4a4SLionel Sambuc }
170*36dcc4a4SLionel Sambuc catfile = *argv++;
171*36dcc4a4SLionel Sambuc
172*36dcc4a4SLionel Sambuc if ((catfile[0] == '-') && (catfile[1] == '\0')) {
173*36dcc4a4SLionel Sambuc ofd = STDOUT_FILENO;
174*36dcc4a4SLionel Sambuc } else {
175*36dcc4a4SLionel Sambuc ofd = open(catfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
176*36dcc4a4SLionel Sambuc if (ofd < 0) {
177*36dcc4a4SLionel Sambuc if (errno == EEXIST) {
178*36dcc4a4SLionel Sambuc if ((ofd = open(catfile, O_RDWR)) < 0) {
179*36dcc4a4SLionel Sambuc err(1, "Unable to open %s", catfile);
180*36dcc4a4SLionel Sambuc /* NOTREACHED */
181*36dcc4a4SLionel Sambuc }
182*36dcc4a4SLionel Sambuc } else {
183*36dcc4a4SLionel Sambuc err(1, "Unable to create new %s", catfile);
184*36dcc4a4SLionel Sambuc /* NOTREACHED */
185*36dcc4a4SLionel Sambuc }
186*36dcc4a4SLionel Sambuc curfile = catfile;
187*36dcc4a4SLionel Sambuc updatecat = 1;
188*36dcc4a4SLionel Sambuc MCReadCat(ofd);
189*36dcc4a4SLionel Sambuc if (lseek(ofd, (off_t)0, SEEK_SET) == (off_t)-1) {
190*36dcc4a4SLionel Sambuc err(1, "Unable to seek on %s", catfile);
191*36dcc4a4SLionel Sambuc /* NOTREACHED */
192*36dcc4a4SLionel Sambuc }
193*36dcc4a4SLionel Sambuc }
194*36dcc4a4SLionel Sambuc }
195*36dcc4a4SLionel Sambuc
196*36dcc4a4SLionel Sambuc if (argc < 2 || (((*argv)[0] == '-') && ((*argv)[1] == '\0'))) {
197*36dcc4a4SLionel Sambuc if (argc > 2)
198*36dcc4a4SLionel Sambuc usage();
199*36dcc4a4SLionel Sambuc /* NOTREACHED */
200*36dcc4a4SLionel Sambuc MCParse(STDIN_FILENO);
201*36dcc4a4SLionel Sambuc } else {
202*36dcc4a4SLionel Sambuc for (; *argv; argv++) {
203*36dcc4a4SLionel Sambuc if ((ifd = open(*argv, O_RDONLY)) < 0)
204*36dcc4a4SLionel Sambuc err(1, "Unable to read %s", *argv);
205*36dcc4a4SLionel Sambuc curfile = *argv;
206*36dcc4a4SLionel Sambuc lineno = 0;
207*36dcc4a4SLionel Sambuc MCParse(ifd);
208*36dcc4a4SLionel Sambuc close(ifd);
209*36dcc4a4SLionel Sambuc }
210*36dcc4a4SLionel Sambuc }
211*36dcc4a4SLionel Sambuc
212*36dcc4a4SLionel Sambuc if (updatecat) {
213*36dcc4a4SLionel Sambuc if (ftruncate(ofd, 0) != 0) {
214*36dcc4a4SLionel Sambuc err(1, "Unable to truncate %s", catfile);
215*36dcc4a4SLionel Sambuc /* NOTREACHED */
216*36dcc4a4SLionel Sambuc }
217*36dcc4a4SLionel Sambuc }
218*36dcc4a4SLionel Sambuc
219*36dcc4a4SLionel Sambuc MCWriteCat(ofd);
220*36dcc4a4SLionel Sambuc exit(0);
221*36dcc4a4SLionel Sambuc }
222*36dcc4a4SLionel Sambuc
223*36dcc4a4SLionel Sambuc static void
warning(const char * cptr,const char * msg)224*36dcc4a4SLionel Sambuc warning(const char *cptr, const char *msg)
225*36dcc4a4SLionel Sambuc {
226*36dcc4a4SLionel Sambuc if (lineno) {
227*36dcc4a4SLionel Sambuc fprintf(stderr, "%s: %s on line %ld, %s\n",
228*36dcc4a4SLionel Sambuc getprogname(), msg, lineno, curfile);
229*36dcc4a4SLionel Sambuc fprintf(stderr, "%s\n", curline);
230*36dcc4a4SLionel Sambuc if (cptr) {
231*36dcc4a4SLionel Sambuc char *tptr;
232*36dcc4a4SLionel Sambuc for (tptr = curline; tptr < cptr; ++tptr)
233*36dcc4a4SLionel Sambuc putc(' ', stderr);
234*36dcc4a4SLionel Sambuc fprintf(stderr, "^\n");
235*36dcc4a4SLionel Sambuc }
236*36dcc4a4SLionel Sambuc } else {
237*36dcc4a4SLionel Sambuc fprintf(stderr, "%s: %s, %s\n", getprogname(), msg, curfile);
238*36dcc4a4SLionel Sambuc }
239*36dcc4a4SLionel Sambuc }
240*36dcc4a4SLionel Sambuc
241*36dcc4a4SLionel Sambuc static void
error(const char * msg)242*36dcc4a4SLionel Sambuc error(const char *msg)
243*36dcc4a4SLionel Sambuc {
244*36dcc4a4SLionel Sambuc warning(NULL, msg);
245*36dcc4a4SLionel Sambuc exit(1);
246*36dcc4a4SLionel Sambuc }
247*36dcc4a4SLionel Sambuc
248*36dcc4a4SLionel Sambuc static void *
xmalloc(size_t len)249*36dcc4a4SLionel Sambuc xmalloc(size_t len)
250*36dcc4a4SLionel Sambuc {
251*36dcc4a4SLionel Sambuc void *p;
252*36dcc4a4SLionel Sambuc
253*36dcc4a4SLionel Sambuc if ((p = malloc(len)) == NULL)
254*36dcc4a4SLionel Sambuc errx(1, NOMEMORY);
255*36dcc4a4SLionel Sambuc return (p);
256*36dcc4a4SLionel Sambuc }
257*36dcc4a4SLionel Sambuc
258*36dcc4a4SLionel Sambuc static void *
xrealloc(void * ptr,size_t size)259*36dcc4a4SLionel Sambuc xrealloc(void *ptr, size_t size)
260*36dcc4a4SLionel Sambuc {
261*36dcc4a4SLionel Sambuc if ((ptr = realloc(ptr, size)) == NULL)
262*36dcc4a4SLionel Sambuc errx(1, NOMEMORY);
263*36dcc4a4SLionel Sambuc return (ptr);
264*36dcc4a4SLionel Sambuc }
265*36dcc4a4SLionel Sambuc
266*36dcc4a4SLionel Sambuc static char *
xstrdup(const char * str)267*36dcc4a4SLionel Sambuc xstrdup(const char *str)
268*36dcc4a4SLionel Sambuc {
269*36dcc4a4SLionel Sambuc char *nstr;
270*36dcc4a4SLionel Sambuc
271*36dcc4a4SLionel Sambuc if ((nstr = strdup(str)) == NULL)
272*36dcc4a4SLionel Sambuc errx(1, NOMEMORY);
273*36dcc4a4SLionel Sambuc return (nstr);
274*36dcc4a4SLionel Sambuc }
275*36dcc4a4SLionel Sambuc
276*36dcc4a4SLionel Sambuc static char *
get_line(int fd)277*36dcc4a4SLionel Sambuc get_line(int fd)
278*36dcc4a4SLionel Sambuc {
279*36dcc4a4SLionel Sambuc static long curlen = BUFSIZ;
280*36dcc4a4SLionel Sambuc static char buf[BUFSIZ], *bptr = buf, *bend = buf;
281*36dcc4a4SLionel Sambuc char *cptr, *cend;
282*36dcc4a4SLionel Sambuc long buflen;
283*36dcc4a4SLionel Sambuc
284*36dcc4a4SLionel Sambuc if (!curline) {
285*36dcc4a4SLionel Sambuc curline = xmalloc(curlen);
286*36dcc4a4SLionel Sambuc }
287*36dcc4a4SLionel Sambuc ++lineno;
288*36dcc4a4SLionel Sambuc
289*36dcc4a4SLionel Sambuc cptr = curline;
290*36dcc4a4SLionel Sambuc cend = curline + curlen;
291*36dcc4a4SLionel Sambuc for (;;) {
292*36dcc4a4SLionel Sambuc for (; bptr < bend && cptr < cend; ++cptr, ++bptr) {
293*36dcc4a4SLionel Sambuc if (*bptr == '\n') {
294*36dcc4a4SLionel Sambuc *cptr = '\0';
295*36dcc4a4SLionel Sambuc ++bptr;
296*36dcc4a4SLionel Sambuc return (curline);
297*36dcc4a4SLionel Sambuc } else
298*36dcc4a4SLionel Sambuc *cptr = *bptr;
299*36dcc4a4SLionel Sambuc }
300*36dcc4a4SLionel Sambuc if (cptr == cend) {
301*36dcc4a4SLionel Sambuc cptr = curline = xrealloc(curline, curlen *= 2);
302*36dcc4a4SLionel Sambuc cend = curline + curlen;
303*36dcc4a4SLionel Sambuc }
304*36dcc4a4SLionel Sambuc if (bptr == bend) {
305*36dcc4a4SLionel Sambuc buflen = read(fd, buf, BUFSIZ);
306*36dcc4a4SLionel Sambuc if (buflen <= 0) {
307*36dcc4a4SLionel Sambuc if (cptr > curline) {
308*36dcc4a4SLionel Sambuc *cptr = '\0';
309*36dcc4a4SLionel Sambuc return (curline);
310*36dcc4a4SLionel Sambuc }
311*36dcc4a4SLionel Sambuc return (NULL);
312*36dcc4a4SLionel Sambuc }
313*36dcc4a4SLionel Sambuc bend = buf + buflen;
314*36dcc4a4SLionel Sambuc bptr = buf;
315*36dcc4a4SLionel Sambuc }
316*36dcc4a4SLionel Sambuc }
317*36dcc4a4SLionel Sambuc }
318*36dcc4a4SLionel Sambuc
319*36dcc4a4SLionel Sambuc static char *
wskip(char * cptr)320*36dcc4a4SLionel Sambuc wskip(char *cptr)
321*36dcc4a4SLionel Sambuc {
322*36dcc4a4SLionel Sambuc if (!*cptr || !isspace((unsigned char) *cptr)) {
323*36dcc4a4SLionel Sambuc warning(cptr, "expected a space");
324*36dcc4a4SLionel Sambuc return (cptr);
325*36dcc4a4SLionel Sambuc }
326*36dcc4a4SLionel Sambuc while (*cptr && isspace((unsigned char) *cptr))
327*36dcc4a4SLionel Sambuc ++cptr;
328*36dcc4a4SLionel Sambuc return (cptr);
329*36dcc4a4SLionel Sambuc }
330*36dcc4a4SLionel Sambuc
331*36dcc4a4SLionel Sambuc static char *
cskip(char * cptr)332*36dcc4a4SLionel Sambuc cskip(char *cptr)
333*36dcc4a4SLionel Sambuc {
334*36dcc4a4SLionel Sambuc if (!*cptr || isspace((unsigned char) *cptr)) {
335*36dcc4a4SLionel Sambuc warning(cptr, "wasn't expecting a space");
336*36dcc4a4SLionel Sambuc return (cptr);
337*36dcc4a4SLionel Sambuc }
338*36dcc4a4SLionel Sambuc while (*cptr && !isspace((unsigned char) *cptr))
339*36dcc4a4SLionel Sambuc ++cptr;
340*36dcc4a4SLionel Sambuc return (cptr);
341*36dcc4a4SLionel Sambuc }
342*36dcc4a4SLionel Sambuc
343*36dcc4a4SLionel Sambuc static char *
getmsg(int fd,char * cptr,char quote)344*36dcc4a4SLionel Sambuc getmsg(int fd, char *cptr, char quote)
345*36dcc4a4SLionel Sambuc {
346*36dcc4a4SLionel Sambuc static char *msg = NULL;
347*36dcc4a4SLionel Sambuc static size_t msglen = 0;
348*36dcc4a4SLionel Sambuc size_t clen, i;
349*36dcc4a4SLionel Sambuc int in_quote = 0;
350*36dcc4a4SLionel Sambuc char *tptr;
351*36dcc4a4SLionel Sambuc
352*36dcc4a4SLionel Sambuc if (quote && *cptr == quote) {
353*36dcc4a4SLionel Sambuc ++cptr;
354*36dcc4a4SLionel Sambuc in_quote = 1;
355*36dcc4a4SLionel Sambuc }
356*36dcc4a4SLionel Sambuc
357*36dcc4a4SLionel Sambuc clen = strlen(cptr) + 1;
358*36dcc4a4SLionel Sambuc if (clen > msglen) {
359*36dcc4a4SLionel Sambuc if (msglen)
360*36dcc4a4SLionel Sambuc msg = xrealloc(msg, clen);
361*36dcc4a4SLionel Sambuc else
362*36dcc4a4SLionel Sambuc msg = xmalloc(clen);
363*36dcc4a4SLionel Sambuc msglen = clen;
364*36dcc4a4SLionel Sambuc }
365*36dcc4a4SLionel Sambuc tptr = msg;
366*36dcc4a4SLionel Sambuc
367*36dcc4a4SLionel Sambuc while (*cptr) {
368*36dcc4a4SLionel Sambuc if (quote && *cptr == quote) {
369*36dcc4a4SLionel Sambuc char *tmp;
370*36dcc4a4SLionel Sambuc tmp = cptr + 1;
371*36dcc4a4SLionel Sambuc if (!in_quote) {
372*36dcc4a4SLionel Sambuc /* XXX hard error? */
373*36dcc4a4SLionel Sambuc warning(cptr, "unexpected quote character, ignoring");
374*36dcc4a4SLionel Sambuc *tptr++ = *cptr++;
375*36dcc4a4SLionel Sambuc } else {
376*36dcc4a4SLionel Sambuc cptr++;
377*36dcc4a4SLionel Sambuc /* don't use wskip() */
378*36dcc4a4SLionel Sambuc while (*cptr && isspace((unsigned char) *cptr))
379*36dcc4a4SLionel Sambuc #ifndef _BACKWARDS_COMPAT
380*36dcc4a4SLionel Sambuc cptr++;
381*36dcc4a4SLionel Sambuc #else
382*36dcc4a4SLionel Sambuc *tptr++ = *cptr++;
383*36dcc4a4SLionel Sambuc #endif
384*36dcc4a4SLionel Sambuc /* XXX hard error? */
385*36dcc4a4SLionel Sambuc if (*cptr)
386*36dcc4a4SLionel Sambuc warning(tmp, "unexpected extra characters, ignoring");
387*36dcc4a4SLionel Sambuc in_quote = 0;
388*36dcc4a4SLionel Sambuc #ifndef _BACKWARDS_COMPAT
389*36dcc4a4SLionel Sambuc break;
390*36dcc4a4SLionel Sambuc #endif
391*36dcc4a4SLionel Sambuc }
392*36dcc4a4SLionel Sambuc } else {
393*36dcc4a4SLionel Sambuc if (*cptr == '\\') {
394*36dcc4a4SLionel Sambuc ++cptr;
395*36dcc4a4SLionel Sambuc switch (*cptr) {
396*36dcc4a4SLionel Sambuc case '\0':
397*36dcc4a4SLionel Sambuc cptr = get_line(fd);
398*36dcc4a4SLionel Sambuc if (!cptr)
399*36dcc4a4SLionel Sambuc error("premature end of file");
400*36dcc4a4SLionel Sambuc msglen += strlen(cptr);
401*36dcc4a4SLionel Sambuc i = tptr - msg;
402*36dcc4a4SLionel Sambuc msg = xrealloc(msg, msglen);
403*36dcc4a4SLionel Sambuc tptr = msg + i;
404*36dcc4a4SLionel Sambuc break;
405*36dcc4a4SLionel Sambuc case 'n':
406*36dcc4a4SLionel Sambuc *tptr++ = '\n';
407*36dcc4a4SLionel Sambuc ++cptr;
408*36dcc4a4SLionel Sambuc break;
409*36dcc4a4SLionel Sambuc case 't':
410*36dcc4a4SLionel Sambuc *tptr++ = '\t';
411*36dcc4a4SLionel Sambuc ++cptr;
412*36dcc4a4SLionel Sambuc break;
413*36dcc4a4SLionel Sambuc case 'v':
414*36dcc4a4SLionel Sambuc *tptr++ = '\v';
415*36dcc4a4SLionel Sambuc ++cptr;
416*36dcc4a4SLionel Sambuc break;
417*36dcc4a4SLionel Sambuc case 'b':
418*36dcc4a4SLionel Sambuc *tptr++ = '\b';
419*36dcc4a4SLionel Sambuc ++cptr;
420*36dcc4a4SLionel Sambuc break;
421*36dcc4a4SLionel Sambuc case 'r':
422*36dcc4a4SLionel Sambuc *tptr++ = '\r';
423*36dcc4a4SLionel Sambuc ++cptr;
424*36dcc4a4SLionel Sambuc break;
425*36dcc4a4SLionel Sambuc case 'f':
426*36dcc4a4SLionel Sambuc *tptr++ = '\f';
427*36dcc4a4SLionel Sambuc ++cptr;
428*36dcc4a4SLionel Sambuc break;
429*36dcc4a4SLionel Sambuc case '\\':
430*36dcc4a4SLionel Sambuc *tptr++ = '\\';
431*36dcc4a4SLionel Sambuc ++cptr;
432*36dcc4a4SLionel Sambuc break;
433*36dcc4a4SLionel Sambuc default:
434*36dcc4a4SLionel Sambuc if (quote && *cptr == quote) {
435*36dcc4a4SLionel Sambuc *tptr++ = *cptr++;
436*36dcc4a4SLionel Sambuc } else if (isdigit((unsigned char) *cptr)) {
437*36dcc4a4SLionel Sambuc *tptr = 0;
438*36dcc4a4SLionel Sambuc for (i = 0; i < 3; ++i) {
439*36dcc4a4SLionel Sambuc if (!isdigit((unsigned char) *cptr))
440*36dcc4a4SLionel Sambuc break;
441*36dcc4a4SLionel Sambuc if (*cptr > '7')
442*36dcc4a4SLionel Sambuc warning(cptr, "octal number greater than 7?!");
443*36dcc4a4SLionel Sambuc *tptr *= 8;
444*36dcc4a4SLionel Sambuc *tptr += (*cptr - '0');
445*36dcc4a4SLionel Sambuc ++cptr;
446*36dcc4a4SLionel Sambuc }
447*36dcc4a4SLionel Sambuc } else {
448*36dcc4a4SLionel Sambuc warning(cptr, "unrecognized escape sequence");
449*36dcc4a4SLionel Sambuc }
450*36dcc4a4SLionel Sambuc break;
451*36dcc4a4SLionel Sambuc }
452*36dcc4a4SLionel Sambuc } else {
453*36dcc4a4SLionel Sambuc *tptr++ = *cptr++;
454*36dcc4a4SLionel Sambuc }
455*36dcc4a4SLionel Sambuc }
456*36dcc4a4SLionel Sambuc }
457*36dcc4a4SLionel Sambuc
458*36dcc4a4SLionel Sambuc if (in_quote)
459*36dcc4a4SLionel Sambuc warning(cptr, "unterminated quoted message, ignoring");
460*36dcc4a4SLionel Sambuc
461*36dcc4a4SLionel Sambuc *tptr = '\0';
462*36dcc4a4SLionel Sambuc return (msg);
463*36dcc4a4SLionel Sambuc }
464*36dcc4a4SLionel Sambuc
465*36dcc4a4SLionel Sambuc static void
MCParse(int fd)466*36dcc4a4SLionel Sambuc MCParse(int fd)
467*36dcc4a4SLionel Sambuc {
468*36dcc4a4SLionel Sambuc char *cptr, *str;
469*36dcc4a4SLionel Sambuc int msgid = 0;
470*36dcc4a4SLionel Sambuc int setid = 0;
471*36dcc4a4SLionel Sambuc char quote = 0;
472*36dcc4a4SLionel Sambuc
473*36dcc4a4SLionel Sambuc while ((cptr = get_line(fd))) {
474*36dcc4a4SLionel Sambuc if (*cptr == '$') {
475*36dcc4a4SLionel Sambuc ++cptr;
476*36dcc4a4SLionel Sambuc if (strncmp(cptr, "set", 3) == 0) {
477*36dcc4a4SLionel Sambuc cptr += 3;
478*36dcc4a4SLionel Sambuc cptr = wskip(cptr);
479*36dcc4a4SLionel Sambuc setid = atoi(cptr);
480*36dcc4a4SLionel Sambuc MCAddSet(setid);
481*36dcc4a4SLionel Sambuc msgid = 0;
482*36dcc4a4SLionel Sambuc } else if (strncmp(cptr, "delset", 6) == 0) {
483*36dcc4a4SLionel Sambuc cptr += 6;
484*36dcc4a4SLionel Sambuc cptr = wskip(cptr);
485*36dcc4a4SLionel Sambuc setid = atoi(cptr);
486*36dcc4a4SLionel Sambuc MCDelSet(setid);
487*36dcc4a4SLionel Sambuc } else if (strncmp(cptr, "quote", 5) == 0) {
488*36dcc4a4SLionel Sambuc cptr += 5;
489*36dcc4a4SLionel Sambuc if (!*cptr)
490*36dcc4a4SLionel Sambuc quote = 0;
491*36dcc4a4SLionel Sambuc else {
492*36dcc4a4SLionel Sambuc cptr = wskip(cptr);
493*36dcc4a4SLionel Sambuc if (!*cptr)
494*36dcc4a4SLionel Sambuc quote = 0;
495*36dcc4a4SLionel Sambuc else
496*36dcc4a4SLionel Sambuc quote = *cptr;
497*36dcc4a4SLionel Sambuc }
498*36dcc4a4SLionel Sambuc } else if (isspace((unsigned char) *cptr)) {
499*36dcc4a4SLionel Sambuc ;
500*36dcc4a4SLionel Sambuc } else {
501*36dcc4a4SLionel Sambuc if (*cptr) {
502*36dcc4a4SLionel Sambuc cptr = wskip(cptr);
503*36dcc4a4SLionel Sambuc if (*cptr)
504*36dcc4a4SLionel Sambuc warning(cptr, "unrecognized line");
505*36dcc4a4SLionel Sambuc }
506*36dcc4a4SLionel Sambuc }
507*36dcc4a4SLionel Sambuc } else {
508*36dcc4a4SLionel Sambuc /*
509*36dcc4a4SLionel Sambuc * First check for (and eat) empty lines....
510*36dcc4a4SLionel Sambuc */
511*36dcc4a4SLionel Sambuc if (!*cptr)
512*36dcc4a4SLionel Sambuc continue;
513*36dcc4a4SLionel Sambuc /*
514*36dcc4a4SLionel Sambuc * We have a digit? Start of a message. Else,
515*36dcc4a4SLionel Sambuc * syntax error.
516*36dcc4a4SLionel Sambuc */
517*36dcc4a4SLionel Sambuc if (isdigit((unsigned char) *cptr)) {
518*36dcc4a4SLionel Sambuc msgid = atoi(cptr);
519*36dcc4a4SLionel Sambuc cptr = cskip(cptr);
520*36dcc4a4SLionel Sambuc if (*cptr) {
521*36dcc4a4SLionel Sambuc cptr = wskip(cptr);
522*36dcc4a4SLionel Sambuc if (!*cptr) {
523*36dcc4a4SLionel Sambuc MCAddMsg(msgid, "");
524*36dcc4a4SLionel Sambuc continue;
525*36dcc4a4SLionel Sambuc }
526*36dcc4a4SLionel Sambuc }
527*36dcc4a4SLionel Sambuc } else {
528*36dcc4a4SLionel Sambuc warning(cptr, "neither blank line nor start of a message id");
529*36dcc4a4SLionel Sambuc continue;
530*36dcc4a4SLionel Sambuc }
531*36dcc4a4SLionel Sambuc /*
532*36dcc4a4SLionel Sambuc * If no set directive specified, all messages
533*36dcc4a4SLionel Sambuc * shall be in default message set NL_SETD.
534*36dcc4a4SLionel Sambuc */
535*36dcc4a4SLionel Sambuc if (setid == 0) {
536*36dcc4a4SLionel Sambuc setid = NL_SETD;
537*36dcc4a4SLionel Sambuc MCAddSet(setid);
538*36dcc4a4SLionel Sambuc }
539*36dcc4a4SLionel Sambuc /*
540*36dcc4a4SLionel Sambuc * If we have a message ID, but no message,
541*36dcc4a4SLionel Sambuc * then this means "delete this message id
542*36dcc4a4SLionel Sambuc * from the catalog".
543*36dcc4a4SLionel Sambuc */
544*36dcc4a4SLionel Sambuc if (!*cptr) {
545*36dcc4a4SLionel Sambuc MCDelMsg(msgid);
546*36dcc4a4SLionel Sambuc } else {
547*36dcc4a4SLionel Sambuc str = getmsg(fd, cptr, quote);
548*36dcc4a4SLionel Sambuc MCAddMsg(msgid, str);
549*36dcc4a4SLionel Sambuc }
550*36dcc4a4SLionel Sambuc }
551*36dcc4a4SLionel Sambuc }
552*36dcc4a4SLionel Sambuc }
553*36dcc4a4SLionel Sambuc
554*36dcc4a4SLionel Sambuc static void
MCReadCat(int fd)555*36dcc4a4SLionel Sambuc MCReadCat(int fd)
556*36dcc4a4SLionel Sambuc {
557*36dcc4a4SLionel Sambuc void *msgcat; /* message catalog data */
558*36dcc4a4SLionel Sambuc struct _nls_cat_hdr cat_hdr;
559*36dcc4a4SLionel Sambuc struct _nls_set_hdr *set_hdr;
560*36dcc4a4SLionel Sambuc struct _nls_msg_hdr *msg_hdr;
561*36dcc4a4SLionel Sambuc char *strings;
562*36dcc4a4SLionel Sambuc ssize_t n;
563*36dcc4a4SLionel Sambuc int m, s;
564*36dcc4a4SLionel Sambuc int msgno, setno;
565*36dcc4a4SLionel Sambuc
566*36dcc4a4SLionel Sambuc n = read(fd, &cat_hdr, sizeof(cat_hdr));
567*36dcc4a4SLionel Sambuc if (n < (ssize_t)sizeof(cat_hdr)) {
568*36dcc4a4SLionel Sambuc if (n == 0)
569*36dcc4a4SLionel Sambuc return; /* empty file */
570*36dcc4a4SLionel Sambuc else if (n == -1)
571*36dcc4a4SLionel Sambuc err(1, "header read");
572*36dcc4a4SLionel Sambuc else
573*36dcc4a4SLionel Sambuc errx(1, CORRUPT);
574*36dcc4a4SLionel Sambuc }
575*36dcc4a4SLionel Sambuc if (ntohl((uint32_t)cat_hdr.__magic) != _NLS_MAGIC)
576*36dcc4a4SLionel Sambuc errx(1, "%s: bad magic number (%#x)", CORRUPT, cat_hdr.__magic);
577*36dcc4a4SLionel Sambuc
578*36dcc4a4SLionel Sambuc cat_hdr.__mem = ntohl(cat_hdr.__mem);
579*36dcc4a4SLionel Sambuc
580*36dcc4a4SLionel Sambuc cat_hdr.__nsets = ntohl(cat_hdr.__nsets);
581*36dcc4a4SLionel Sambuc cat_hdr.__msg_hdr_offset = ntohl(cat_hdr.__msg_hdr_offset);
582*36dcc4a4SLionel Sambuc cat_hdr.__msg_txt_offset = ntohl(cat_hdr.__msg_txt_offset);
583*36dcc4a4SLionel Sambuc if ((cat_hdr.__mem < 0) ||
584*36dcc4a4SLionel Sambuc (cat_hdr.__msg_hdr_offset < 0) ||
585*36dcc4a4SLionel Sambuc (cat_hdr.__msg_txt_offset < 0) ||
586*36dcc4a4SLionel Sambuc (cat_hdr.__mem < (int32_t)(cat_hdr.__nsets * sizeof(struct _nls_set_hdr))) ||
587*36dcc4a4SLionel Sambuc (cat_hdr.__mem < cat_hdr.__msg_hdr_offset) ||
588*36dcc4a4SLionel Sambuc (cat_hdr.__mem < cat_hdr.__msg_txt_offset))
589*36dcc4a4SLionel Sambuc errx(1, "%s: catalog header", CORRUPT);
590*36dcc4a4SLionel Sambuc
591*36dcc4a4SLionel Sambuc msgcat = xmalloc(cat_hdr.__mem);
592*36dcc4a4SLionel Sambuc
593*36dcc4a4SLionel Sambuc n = read(fd, msgcat, cat_hdr.__mem);
594*36dcc4a4SLionel Sambuc if (n < cat_hdr.__mem) {
595*36dcc4a4SLionel Sambuc if (n == -1)
596*36dcc4a4SLionel Sambuc err(1, "data read");
597*36dcc4a4SLionel Sambuc else
598*36dcc4a4SLionel Sambuc errx(1, CORRUPT);
599*36dcc4a4SLionel Sambuc }
600*36dcc4a4SLionel Sambuc
601*36dcc4a4SLionel Sambuc set_hdr = (struct _nls_set_hdr *)msgcat;
602*36dcc4a4SLionel Sambuc msg_hdr = (struct _nls_msg_hdr *)((char *)msgcat +
603*36dcc4a4SLionel Sambuc cat_hdr.__msg_hdr_offset);
604*36dcc4a4SLionel Sambuc strings = (char *)msgcat + cat_hdr.__msg_txt_offset;
605*36dcc4a4SLionel Sambuc
606*36dcc4a4SLionel Sambuc setno = 0;
607*36dcc4a4SLionel Sambuc for (s = 0; s < cat_hdr.__nsets; s++, set_hdr++) {
608*36dcc4a4SLionel Sambuc set_hdr->__setno = ntohl(set_hdr->__setno);
609*36dcc4a4SLionel Sambuc if (set_hdr->__setno < setno)
610*36dcc4a4SLionel Sambuc errx(1, "%s: bad set number (%d)",
611*36dcc4a4SLionel Sambuc CORRUPT, set_hdr->__setno);
612*36dcc4a4SLionel Sambuc setno = set_hdr->__setno;
613*36dcc4a4SLionel Sambuc
614*36dcc4a4SLionel Sambuc MCAddSet(setno);
615*36dcc4a4SLionel Sambuc
616*36dcc4a4SLionel Sambuc set_hdr->__nmsgs = ntohl(set_hdr->__nmsgs);
617*36dcc4a4SLionel Sambuc set_hdr->__index = ntohl(set_hdr->__index);
618*36dcc4a4SLionel Sambuc if (set_hdr->__nmsgs < 0 || set_hdr->__index < 0)
619*36dcc4a4SLionel Sambuc errx(1, "%s: set header", CORRUPT);
620*36dcc4a4SLionel Sambuc
621*36dcc4a4SLionel Sambuc /* Get the data */
622*36dcc4a4SLionel Sambuc msgno = 0;
623*36dcc4a4SLionel Sambuc for (m = 0; m < set_hdr->__nmsgs; m++, msg_hdr++) {
624*36dcc4a4SLionel Sambuc msg_hdr->__msgno = ntohl(msg_hdr->__msgno);
625*36dcc4a4SLionel Sambuc msg_hdr->__offset = ntohl(msg_hdr->__offset);
626*36dcc4a4SLionel Sambuc if (msg_hdr->__msgno < msgno)
627*36dcc4a4SLionel Sambuc errx(1, "%s: bad message number (%d)",
628*36dcc4a4SLionel Sambuc CORRUPT, msg_hdr->__msgno);
629*36dcc4a4SLionel Sambuc if ((msg_hdr->__offset < 0) ||
630*36dcc4a4SLionel Sambuc ((strings + msg_hdr->__offset) >
631*36dcc4a4SLionel Sambuc ((char *)msgcat + cat_hdr.__mem)))
632*36dcc4a4SLionel Sambuc errx(1, "%s: message header", CORRUPT);
633*36dcc4a4SLionel Sambuc
634*36dcc4a4SLionel Sambuc msgno = msg_hdr->__msgno;
635*36dcc4a4SLionel Sambuc MCAddMsg(msgno, strings + msg_hdr->__offset);
636*36dcc4a4SLionel Sambuc }
637*36dcc4a4SLionel Sambuc }
638*36dcc4a4SLionel Sambuc free(msgcat);
639*36dcc4a4SLionel Sambuc }
640*36dcc4a4SLionel Sambuc
641*36dcc4a4SLionel Sambuc /*
642*36dcc4a4SLionel Sambuc * Write message catalog.
643*36dcc4a4SLionel Sambuc *
644*36dcc4a4SLionel Sambuc * The message catalog is first converted from its internal to its
645*36dcc4a4SLionel Sambuc * external representation in a chunk of memory allocated for this
646*36dcc4a4SLionel Sambuc * purpose. Then the completed catalog is written. This approach
647*36dcc4a4SLionel Sambuc * avoids additional housekeeping variables and/or a lot of seeks
648*36dcc4a4SLionel Sambuc * that would otherwise be required.
649*36dcc4a4SLionel Sambuc */
650*36dcc4a4SLionel Sambuc static void
MCWriteCat(int fd)651*36dcc4a4SLionel Sambuc MCWriteCat(int fd)
652*36dcc4a4SLionel Sambuc {
653*36dcc4a4SLionel Sambuc int nsets; /* number of sets */
654*36dcc4a4SLionel Sambuc int nmsgs; /* number of msgs */
655*36dcc4a4SLionel Sambuc int string_size; /* total size of string pool */
656*36dcc4a4SLionel Sambuc int msgcat_size; /* total size of message catalog */
657*36dcc4a4SLionel Sambuc void *msgcat; /* message catalog data */
658*36dcc4a4SLionel Sambuc struct _nls_cat_hdr *cat_hdr;
659*36dcc4a4SLionel Sambuc struct _nls_set_hdr *set_hdr;
660*36dcc4a4SLionel Sambuc struct _nls_msg_hdr *msg_hdr;
661*36dcc4a4SLionel Sambuc char *strings;
662*36dcc4a4SLionel Sambuc struct _setT *set;
663*36dcc4a4SLionel Sambuc struct _msgT *msg;
664*36dcc4a4SLionel Sambuc int msg_index;
665*36dcc4a4SLionel Sambuc int msg_offset;
666*36dcc4a4SLionel Sambuc
667*36dcc4a4SLionel Sambuc /* determine number of sets, number of messages, and size of the
668*36dcc4a4SLionel Sambuc * string pool */
669*36dcc4a4SLionel Sambuc nsets = 0;
670*36dcc4a4SLionel Sambuc nmsgs = 0;
671*36dcc4a4SLionel Sambuc string_size = 0;
672*36dcc4a4SLionel Sambuc
673*36dcc4a4SLionel Sambuc LIST_FOREACH(set, &sethead, entries) {
674*36dcc4a4SLionel Sambuc nsets++;
675*36dcc4a4SLionel Sambuc
676*36dcc4a4SLionel Sambuc LIST_FOREACH(msg, &set->msghead, entries) {
677*36dcc4a4SLionel Sambuc nmsgs++;
678*36dcc4a4SLionel Sambuc string_size += strlen(msg->str) + 1;
679*36dcc4a4SLionel Sambuc }
680*36dcc4a4SLionel Sambuc }
681*36dcc4a4SLionel Sambuc
682*36dcc4a4SLionel Sambuc #ifdef DEBUG
683*36dcc4a4SLionel Sambuc printf("number of sets: %d\n", nsets);
684*36dcc4a4SLionel Sambuc printf("number of msgs: %d\n", nmsgs);
685*36dcc4a4SLionel Sambuc printf("string pool size: %d\n", string_size);
686*36dcc4a4SLionel Sambuc #endif
687*36dcc4a4SLionel Sambuc
688*36dcc4a4SLionel Sambuc /* determine size and then allocate buffer for constructing external
689*36dcc4a4SLionel Sambuc * message catalog representation */
690*36dcc4a4SLionel Sambuc msgcat_size = sizeof(struct _nls_cat_hdr)
691*36dcc4a4SLionel Sambuc + (nsets * sizeof(struct _nls_set_hdr))
692*36dcc4a4SLionel Sambuc + (nmsgs * sizeof(struct _nls_msg_hdr))
693*36dcc4a4SLionel Sambuc + string_size;
694*36dcc4a4SLionel Sambuc
695*36dcc4a4SLionel Sambuc msgcat = xmalloc(msgcat_size);
696*36dcc4a4SLionel Sambuc memset(msgcat, '\0', msgcat_size);
697*36dcc4a4SLionel Sambuc
698*36dcc4a4SLionel Sambuc /* fill in msg catalog header */
699*36dcc4a4SLionel Sambuc cat_hdr = (struct _nls_cat_hdr *) msgcat;
700*36dcc4a4SLionel Sambuc cat_hdr->__magic = htonl(_NLS_MAGIC);
701*36dcc4a4SLionel Sambuc cat_hdr->__nsets = htonl(nsets);
702*36dcc4a4SLionel Sambuc cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr));
703*36dcc4a4SLionel Sambuc cat_hdr->__msg_hdr_offset =
704*36dcc4a4SLionel Sambuc htonl(nsets * sizeof(struct _nls_set_hdr));
705*36dcc4a4SLionel Sambuc cat_hdr->__msg_txt_offset =
706*36dcc4a4SLionel Sambuc htonl(nsets * sizeof(struct _nls_set_hdr) +
707*36dcc4a4SLionel Sambuc nmsgs * sizeof(struct _nls_msg_hdr));
708*36dcc4a4SLionel Sambuc
709*36dcc4a4SLionel Sambuc /* compute offsets for set & msg header tables and string pool */
710*36dcc4a4SLionel Sambuc set_hdr = (struct _nls_set_hdr *) ((char *) msgcat +
711*36dcc4a4SLionel Sambuc sizeof(struct _nls_cat_hdr));
712*36dcc4a4SLionel Sambuc msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat +
713*36dcc4a4SLionel Sambuc sizeof(struct _nls_cat_hdr) +
714*36dcc4a4SLionel Sambuc nsets * sizeof(struct _nls_set_hdr));
715*36dcc4a4SLionel Sambuc strings = (char *) msgcat +
716*36dcc4a4SLionel Sambuc sizeof(struct _nls_cat_hdr) +
717*36dcc4a4SLionel Sambuc nsets * sizeof(struct _nls_set_hdr) +
718*36dcc4a4SLionel Sambuc nmsgs * sizeof(struct _nls_msg_hdr);
719*36dcc4a4SLionel Sambuc
720*36dcc4a4SLionel Sambuc msg_index = 0;
721*36dcc4a4SLionel Sambuc msg_offset = 0;
722*36dcc4a4SLionel Sambuc LIST_FOREACH(set, &sethead, entries) {
723*36dcc4a4SLionel Sambuc
724*36dcc4a4SLionel Sambuc nmsgs = 0;
725*36dcc4a4SLionel Sambuc LIST_FOREACH(msg, &set->msghead, entries) {
726*36dcc4a4SLionel Sambuc int32_t msg_len = strlen(msg->str) + 1;
727*36dcc4a4SLionel Sambuc
728*36dcc4a4SLionel Sambuc msg_hdr->__msgno = htonl(msg->msgId);
729*36dcc4a4SLionel Sambuc msg_hdr->__msglen = htonl(msg_len);
730*36dcc4a4SLionel Sambuc msg_hdr->__offset = htonl(msg_offset);
731*36dcc4a4SLionel Sambuc
732*36dcc4a4SLionel Sambuc memcpy(strings, msg->str, msg_len);
733*36dcc4a4SLionel Sambuc strings += msg_len;
734*36dcc4a4SLionel Sambuc msg_offset += msg_len;
735*36dcc4a4SLionel Sambuc
736*36dcc4a4SLionel Sambuc nmsgs++;
737*36dcc4a4SLionel Sambuc msg_hdr++;
738*36dcc4a4SLionel Sambuc }
739*36dcc4a4SLionel Sambuc
740*36dcc4a4SLionel Sambuc set_hdr->__setno = htonl(set->setId);
741*36dcc4a4SLionel Sambuc set_hdr->__nmsgs = htonl(nmsgs);
742*36dcc4a4SLionel Sambuc set_hdr->__index = htonl(msg_index);
743*36dcc4a4SLionel Sambuc msg_index += nmsgs;
744*36dcc4a4SLionel Sambuc set_hdr++;
745*36dcc4a4SLionel Sambuc }
746*36dcc4a4SLionel Sambuc
747*36dcc4a4SLionel Sambuc /* write out catalog. XXX: should this be done in small chunks? */
748*36dcc4a4SLionel Sambuc write(fd, msgcat, msgcat_size);
749*36dcc4a4SLionel Sambuc }
750*36dcc4a4SLionel Sambuc
751*36dcc4a4SLionel Sambuc static void
MCAddSet(int setId)752*36dcc4a4SLionel Sambuc MCAddSet(int setId)
753*36dcc4a4SLionel Sambuc {
754*36dcc4a4SLionel Sambuc struct _setT *p, *q;
755*36dcc4a4SLionel Sambuc
756*36dcc4a4SLionel Sambuc if (setId <= 0) {
757*36dcc4a4SLionel Sambuc error("setId's must be greater than zero");
758*36dcc4a4SLionel Sambuc /* NOTREACHED */
759*36dcc4a4SLionel Sambuc }
760*36dcc4a4SLionel Sambuc if (setId > NL_SETMAX) {
761*36dcc4a4SLionel Sambuc error("setId exceeds limit");
762*36dcc4a4SLionel Sambuc /* NOTREACHED */
763*36dcc4a4SLionel Sambuc }
764*36dcc4a4SLionel Sambuc
765*36dcc4a4SLionel Sambuc p = LIST_FIRST(&sethead);
766*36dcc4a4SLionel Sambuc q = NULL;
767*36dcc4a4SLionel Sambuc for (; p != NULL && p->setId < setId; q = p, p = LIST_NEXT(p, entries))
768*36dcc4a4SLionel Sambuc continue;
769*36dcc4a4SLionel Sambuc
770*36dcc4a4SLionel Sambuc if (p && p->setId == setId) {
771*36dcc4a4SLionel Sambuc ;
772*36dcc4a4SLionel Sambuc } else {
773*36dcc4a4SLionel Sambuc p = xmalloc(sizeof(struct _setT));
774*36dcc4a4SLionel Sambuc memset(p, '\0', sizeof(struct _setT));
775*36dcc4a4SLionel Sambuc LIST_INIT(&p->msghead);
776*36dcc4a4SLionel Sambuc
777*36dcc4a4SLionel Sambuc p->setId = setId;
778*36dcc4a4SLionel Sambuc
779*36dcc4a4SLionel Sambuc if (q == NULL) {
780*36dcc4a4SLionel Sambuc LIST_INSERT_HEAD(&sethead, p, entries);
781*36dcc4a4SLionel Sambuc } else {
782*36dcc4a4SLionel Sambuc LIST_INSERT_AFTER(q, p, entries);
783*36dcc4a4SLionel Sambuc }
784*36dcc4a4SLionel Sambuc }
785*36dcc4a4SLionel Sambuc
786*36dcc4a4SLionel Sambuc curSet = p;
787*36dcc4a4SLionel Sambuc }
788*36dcc4a4SLionel Sambuc
789*36dcc4a4SLionel Sambuc static void
MCAddMsg(int msgId,const char * str)790*36dcc4a4SLionel Sambuc MCAddMsg(int msgId, const char *str)
791*36dcc4a4SLionel Sambuc {
792*36dcc4a4SLionel Sambuc struct _msgT *p, *q;
793*36dcc4a4SLionel Sambuc
794*36dcc4a4SLionel Sambuc if (!curSet)
795*36dcc4a4SLionel Sambuc error("can't specify a message when no set exists");
796*36dcc4a4SLionel Sambuc
797*36dcc4a4SLionel Sambuc if (msgId <= 0) {
798*36dcc4a4SLionel Sambuc error("msgId's must be greater than zero");
799*36dcc4a4SLionel Sambuc /* NOTREACHED */
800*36dcc4a4SLionel Sambuc }
801*36dcc4a4SLionel Sambuc if (msgId > NL_MSGMAX) {
802*36dcc4a4SLionel Sambuc error("msgID exceeds limit");
803*36dcc4a4SLionel Sambuc /* NOTREACHED */
804*36dcc4a4SLionel Sambuc }
805*36dcc4a4SLionel Sambuc
806*36dcc4a4SLionel Sambuc p = LIST_FIRST(&curSet->msghead);
807*36dcc4a4SLionel Sambuc q = NULL;
808*36dcc4a4SLionel Sambuc for (; p != NULL && p->msgId < msgId; q = p, p = LIST_NEXT(p, entries))
809*36dcc4a4SLionel Sambuc continue;
810*36dcc4a4SLionel Sambuc
811*36dcc4a4SLionel Sambuc if (p && p->msgId == msgId) {
812*36dcc4a4SLionel Sambuc free(p->str);
813*36dcc4a4SLionel Sambuc } else {
814*36dcc4a4SLionel Sambuc p = xmalloc(sizeof(struct _msgT));
815*36dcc4a4SLionel Sambuc memset(p, '\0', sizeof(struct _msgT));
816*36dcc4a4SLionel Sambuc
817*36dcc4a4SLionel Sambuc if (q == NULL) {
818*36dcc4a4SLionel Sambuc LIST_INSERT_HEAD(&curSet->msghead, p, entries);
819*36dcc4a4SLionel Sambuc } else {
820*36dcc4a4SLionel Sambuc LIST_INSERT_AFTER(q, p, entries);
821*36dcc4a4SLionel Sambuc }
822*36dcc4a4SLionel Sambuc }
823*36dcc4a4SLionel Sambuc
824*36dcc4a4SLionel Sambuc p->msgId = msgId;
825*36dcc4a4SLionel Sambuc p->str = xstrdup(str);
826*36dcc4a4SLionel Sambuc }
827*36dcc4a4SLionel Sambuc
828*36dcc4a4SLionel Sambuc static void
MCDelSet(int setId)829*36dcc4a4SLionel Sambuc MCDelSet(int setId)
830*36dcc4a4SLionel Sambuc {
831*36dcc4a4SLionel Sambuc struct _setT *set;
832*36dcc4a4SLionel Sambuc struct _msgT *msg;
833*36dcc4a4SLionel Sambuc
834*36dcc4a4SLionel Sambuc if (setId <= 0) {
835*36dcc4a4SLionel Sambuc error("setId's must be greater than zero");
836*36dcc4a4SLionel Sambuc /* NOTREACHED */
837*36dcc4a4SLionel Sambuc }
838*36dcc4a4SLionel Sambuc if (setId > NL_SETMAX) {
839*36dcc4a4SLionel Sambuc error("setId exceeds limit");
840*36dcc4a4SLionel Sambuc /* NOTREACHED */
841*36dcc4a4SLionel Sambuc }
842*36dcc4a4SLionel Sambuc
843*36dcc4a4SLionel Sambuc set = LIST_FIRST(&sethead);
844*36dcc4a4SLionel Sambuc for (; set != NULL && set->setId < setId; set = LIST_NEXT(set, entries))
845*36dcc4a4SLionel Sambuc continue;
846*36dcc4a4SLionel Sambuc
847*36dcc4a4SLionel Sambuc if (set && set->setId == setId) {
848*36dcc4a4SLionel Sambuc LIST_REMOVE(set, entries);
849*36dcc4a4SLionel Sambuc while ((msg = LIST_FIRST(&set->msghead)) != NULL) {
850*36dcc4a4SLionel Sambuc LIST_REMOVE(msg, entries);
851*36dcc4a4SLionel Sambuc free(msg->str);
852*36dcc4a4SLionel Sambuc free(msg);
853*36dcc4a4SLionel Sambuc }
854*36dcc4a4SLionel Sambuc free(set);
855*36dcc4a4SLionel Sambuc return;
856*36dcc4a4SLionel Sambuc }
857*36dcc4a4SLionel Sambuc warning(NULL, "specified set doesn't exist");
858*36dcc4a4SLionel Sambuc }
859*36dcc4a4SLionel Sambuc
860*36dcc4a4SLionel Sambuc static void
MCDelMsg(int msgId)861*36dcc4a4SLionel Sambuc MCDelMsg(int msgId)
862*36dcc4a4SLionel Sambuc {
863*36dcc4a4SLionel Sambuc struct _msgT *msg;
864*36dcc4a4SLionel Sambuc
865*36dcc4a4SLionel Sambuc if (!curSet)
866*36dcc4a4SLionel Sambuc error("you can't delete a message before defining the set");
867*36dcc4a4SLionel Sambuc
868*36dcc4a4SLionel Sambuc msg = LIST_FIRST(&curSet->msghead);
869*36dcc4a4SLionel Sambuc for (; msg != NULL && msg->msgId < msgId; msg = LIST_NEXT(msg, entries))
870*36dcc4a4SLionel Sambuc continue;
871*36dcc4a4SLionel Sambuc
872*36dcc4a4SLionel Sambuc if (msg && msg->msgId == msgId) {
873*36dcc4a4SLionel Sambuc LIST_REMOVE(msg, entries);
874*36dcc4a4SLionel Sambuc free(msg->str);
875*36dcc4a4SLionel Sambuc free(msg);
876*36dcc4a4SLionel Sambuc return;
877*36dcc4a4SLionel Sambuc }
878*36dcc4a4SLionel Sambuc warning(NULL, "specified msg doesn't exist");
879*36dcc4a4SLionel Sambuc }
880