2 * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
29 #include <sys/types.h>
31 #include <sys/syslimits.h>
37 #include "setlocale.h"
40 static int split_lines(char *, const char *);
41 static void set_from_buf(const char *, int, const char **);
44 __part_load_locale(const char *name
,
47 const char *category_filename
,
48 int locale_buf_size_max
,
49 int locale_buf_size_min
,
50 const char **dst_localebuf
) {
52 static char locale_buf_C
[] = "C";
59 char filename
[PATH_MAX
];
63 int save_using_locale
;
66 save_using_locale
= *using_locale
;
72 if (!strcmp(name
, "C") || !strcmp(name
, "POSIX"))
76 * If the locale name is the same as our cache, use the cache.
79 if (lbuf
!= NULL
&& strcmp(name
, lbuf
) == 0) {
80 set_from_buf(lbuf
, num_lines
, dst_localebuf
);
86 * Slurp the locale file into the cache.
88 namesize
= strlen(name
) + 1;
92 /* Range checking not needed, 'name' size is limited */
93 strcpy(filename
, _PathLocale
);
94 strcat(filename
, "/");
95 strcat(filename
, name
);
96 strcat(filename
, "/");
97 strcat(filename
, category_filename
);
98 fd
= open(filename
, O_RDONLY
);
101 #ifdef __USE_INTERNAL_STAT64
102 if (fstat64(fd
, &st
) != 0)
104 if (fstat(fd
, &st
) != 0)
109 bufsize
= namesize
+ st
.st_size
;
112 if (lbuf
== NULL
|| lbuf
== locale_buf_C
)
114 lbuf
= malloc(bufsize
);
118 nptr
= realloc(lbuf
, bufsize
);
126 (void) strcpy(lbuf
, name
);
128 plim
= p
+ st
.st_size
;
129 if (read(fd
, p
, (size_t) st
.st_size
) != st
.st_size
)
134 * Parse the locale file into localebuf.
136 if (plim
[-1] != '\n')
138 num_lines
= split_lines(p
, plim
);
139 if (num_lines
>= locale_buf_size_max
)
140 num_lines
= locale_buf_size_max
;
141 else if (num_lines
>= locale_buf_size_min
)
142 num_lines
= locale_buf_size_min
;
145 set_from_buf(lbuf
, num_lines
, dst_localebuf
);
147 * Record the successful parse in the cache.
155 locale_buf
= locale_buf_C
;
156 save_using_locale
= 0;
162 *using_locale
= save_using_locale
;
167 split_lines(char *p
, const char *plim
) {
171 for (i
= 0; p
< plim
; i
++) {
179 set_from_buf(const char *p
, int num_lines
, const char **dst_localebuf
) {
184 for (ap
= dst_localebuf
, i
= 0; i
< num_lines
; ++ap
, ++i
)
185 *ap
= p
+= strlen(p
) + 1;