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 = strlen (alias);
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 search_again:
108   if (len < l || (p = strnstr (ptable, alias, len)) == NULL)
109     return NULL;
110 
111   /* Check that substring is segregated by '\n', '\t' or ' ' */
112   if (!((p == table || isspace (*(p-1)) || *(p-1) == '\n')
113      && (p+l == table_end || isspace (*(p+l)) || *(p+l) == '\n')))
114     {
115       ptable = p + l;
116       len = table_end - ptable;
117       goto search_again;
118     }
119 
120   while(--p > table && *p != '\n');
121 
122   if (*(++p) == '#')
123     return NULL;
124 
125   for (end = p + 1; !isspace (*end) && *end != '\n' && *end != '\0'; end++);
126 
127   return strndup (p, (size_t)(end - p));
128 }
129 
130 /*
131  * _iconv_resolve_encoding_name - resolves encoding's name by given alias.
132  *
133  * PARAMETERS:
134  *   const char *ca     - encoding alias to resolve.
135  *
136  * DESCRIPTION:
137  *   First, tries to find 'ca' among built-in aliases. If not found, tries to
138  *   find it external file.
139  *
140  * RETURN:
141  *   Encoding name if found. In case of error returns NULL
142  *   and sets current thread's/process's errno.
143  */
144 char *
_iconv_resolve_encoding_name(const char * ca)145 _iconv_resolve_encoding_name (
146                                      const char *ca)
147 {
148   char *p = (char *)ca;
149 
150   /* Alias shouldn't contain white spaces, '\n' and '\r' symbols */
151   while (*p)
152     if (*p == ' ' || *p == '\r' || *p++ == '\n')
153       return NULL;
154 
155   if ((ca = canonical_form (ca)) == NULL)
156     return NULL;
157 
158   p = find_alias (ca, _iconv_aliases, strlen (_iconv_aliases));
159 
160   free ((void *)ca);
161   return p;
162 }
163 
164