1 /*
2  * Copyright (c) 2003-2004, Artem B. Bityuckiy
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 #define _DEFAULT_SOURCE
26 #include <_ansi.h>
27 #include <newlib.h>
28 #include <sys/types.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <ctype.h>
33 #include <sys/iconvnls.h>
34 #include "local.h"
35 
36 /*
37  * canonical_form - canonize 'str'.
38  *
39  * PARAMETERS:
40  *   const char *str    - string to canonize.
41  *
42  * DESCRIPTION:
43  *   Converts all letters to small and substitute all '-' characters by '_'
44  *   characters.
45  *
46  * RETURN:
47  *   Returns canonical form of 'str' if success, NULL if failure.
48  */
49 static const char *
canonical_form(const char * str)50 canonical_form (
51                        const char *str)
52 {
53   char *p, *p1;
54 
55   if (str == NULL || (p = p1 = strdup (str)) == NULL)
56     return (const char *)NULL;
57 
58   for (; *str; str++, p++)
59     {
60       if (*str == '-')
61         *p = '_';
62       else
63         *p = tolower (*str);
64     }
65 
66   return (const char *)p1;
67 }
68 
69 /*
70  * find_alias - find encoding name name by it's alias.
71  *
72  * PARAMETERS:
73  *   const char *alias  - alias by which "official" name should be found.
74  *   const char *table  - aliases table.
75  *   int len             - aliases table length.
76  *
77  * DESCRIPTION:
78  *   'table' contains the list of encoding names and aliases.
79  *    Names go first, e.g.:
80  *
81  *   name1 alias11 alias12 alias1N
82  *   name2 alias21 alias22 alias2N
83  *   nameM aliasM1 aliasM2 aliasMN
84  *
85  *   If line begins with backspace it is considered as the continuation of
86  *   previous line.
87  *
88  * RETURN:
89  *   Returns pointer to name found if success. In case of error returns NULL
90  *   and sets current thread's/process's errno.
91  */
92 static char *
find_alias(const char * alias,const char * table,int len)93 find_alias (
94                    const char *alias,
95                    const char *table,
96                    int len)
97 {
98   const char *end;
99   const char *p;
100   int l;
101   const char *ptable = table;
102   const char *table_end = table + len;
103 
104   if (table == NULL || alias == NULL || *table == '\0' || *alias == '\0')
105     return NULL;
106 
107   l = strlen (alias);
108 search_again:
109   if (len < l || (p = strnstr (ptable, alias, len)) == NULL)
110     return NULL;
111 
112   /* Check that substring is segregated by '\n', '\t' or ' ' */
113   if (!((p == table || isspace (*(p-1)) || *(p-1) == '\n')
114      && (p+l == table_end || isspace (*(p+l)) || *(p+l) == '\n')))
115     {
116       ptable = p + l;
117       len = table_end - ptable;
118       goto search_again;
119     }
120 
121   while(--p > table && *p != '\n');
122 
123   if (*(++p) == '#')
124     return NULL;
125 
126   for (end = p + 1; !isspace (*end) && *end != '\n' && *end != '\0'; end++);
127 
128   return strndup (p, (size_t)(end - p));
129 }
130 
131 /*
132  * _iconv_resolve_encoding_name - resolves encoding's name by given alias.
133  *
134  * PARAMETERS:
135  *   const char *ca     - encoding alias to resolve.
136  *
137  * DESCRIPTION:
138  *   First, tries to find 'ca' among built-in aliases. If not found, tries to
139  *   find it external file.
140  *
141  * RETURN:
142  *   Encoding name if found. In case of error returns NULL
143  *   and sets current thread's/process's errno.
144  */
145 char *
_iconv_resolve_encoding_name(const char * ca)146 _iconv_resolve_encoding_name (
147                                      const char *ca)
148 {
149   char *p = (char *)ca;
150 
151   /* Alias shouldn't contain white spaces, '\n' and '\r' symbols */
152   while (*p)
153     if (*p == ' ' || *p == '\r' || *p++ == '\n')
154       return NULL;
155 
156   if ((ca = canonical_form (ca)) == NULL)
157     return NULL;
158 
159   p = find_alias (ca, _iconv_aliases, strlen (_iconv_aliases));
160 
161   free ((void *)ca);
162   return p;
163 }
164 
165