1*16d86563SAlexander Pyhalov /*
2*16d86563SAlexander Pyhalov  * CDDL HEADER START
3*16d86563SAlexander Pyhalov  *
4*16d86563SAlexander Pyhalov  * The contents of this file are subject to the terms of the
5*16d86563SAlexander Pyhalov  * Common Development and Distribution License (the "License").
6*16d86563SAlexander Pyhalov  * You may not use this file except in compliance with the License.
7*16d86563SAlexander Pyhalov  *
8*16d86563SAlexander Pyhalov  * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9*16d86563SAlexander Pyhalov  * or http://www.opensolaris.org/os/licensing.
10*16d86563SAlexander Pyhalov  * See the License for the specific language governing permissions
11*16d86563SAlexander Pyhalov  * and limitations under the License.
12*16d86563SAlexander Pyhalov  *
13*16d86563SAlexander Pyhalov  * When distributing Covered Code, include this CDDL HEADER in each
14*16d86563SAlexander Pyhalov  * file and include the License file at src/OPENSOLARIS.LICENSE.
15*16d86563SAlexander Pyhalov  * If applicable, add the following below this CDDL HEADER, with the
16*16d86563SAlexander Pyhalov  * fields enclosed by brackets "[]" replaced with your own identifying
17*16d86563SAlexander Pyhalov  * information: Portions Copyright [yyyy] [name of copyright owner]
18*16d86563SAlexander Pyhalov  *
19*16d86563SAlexander Pyhalov  * CDDL HEADER END
20*16d86563SAlexander Pyhalov  */
21*16d86563SAlexander Pyhalov /*
22*16d86563SAlexander Pyhalov  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23*16d86563SAlexander Pyhalov  * Use is subject to license terms.
24*16d86563SAlexander Pyhalov  */
25*16d86563SAlexander Pyhalov 
26*16d86563SAlexander Pyhalov #include <stdlib.h>
27*16d86563SAlexander Pyhalov #include <errno.h>
28*16d86563SAlexander Pyhalov #include <sys/types.h>
29*16d86563SAlexander Pyhalov #include <dlfcn.h>
30*16d86563SAlexander Pyhalov #include <link.h>
31*16d86563SAlexander Pyhalov #include <sys/utsname.h>
32*16d86563SAlexander Pyhalov #include <ctype.h>
33*16d86563SAlexander Pyhalov #include <strings.h>
34*16d86563SAlexander Pyhalov #include <string.h>
35*16d86563SAlexander Pyhalov #include <idn/api.h>
36*16d86563SAlexander Pyhalov #include <idn/version.h>
37*16d86563SAlexander Pyhalov #include "ace.h"
38*16d86563SAlexander Pyhalov 
39*16d86563SAlexander Pyhalov 
40*16d86563SAlexander Pyhalov void *
_icv_open()41*16d86563SAlexander Pyhalov _icv_open()
42*16d86563SAlexander Pyhalov {
43*16d86563SAlexander Pyhalov 	ace_state_t *cd;
44*16d86563SAlexander Pyhalov 
45*16d86563SAlexander Pyhalov 	cd = (ace_state_t *)calloc(1, sizeof(ace_state_t));
46*16d86563SAlexander Pyhalov 	if (cd == (ace_state_t *)NULL) {
47*16d86563SAlexander Pyhalov 		errno = ENOMEM;
48*16d86563SAlexander Pyhalov 		return ((void *)-1);
49*16d86563SAlexander Pyhalov 	}
50*16d86563SAlexander Pyhalov 
51*16d86563SAlexander Pyhalov 	cd->libidnkit = dlopen(ICV_LIBIDNKITPATH, RTLD_LAZY);
52*16d86563SAlexander Pyhalov 	if (cd->libidnkit == (void *)NULL) {
53*16d86563SAlexander Pyhalov 		free((void *)cd);
54*16d86563SAlexander Pyhalov 		errno = EINVAL;
55*16d86563SAlexander Pyhalov 		return ((void *)-1);
56*16d86563SAlexander Pyhalov 	}
57*16d86563SAlexander Pyhalov 
58*16d86563SAlexander Pyhalov 	cd->idn_function = (idn_result_t(*)(int, const char *, char *,
59*16d86563SAlexander Pyhalov #if defined(ICV_ACE_TO_UTF8)
60*16d86563SAlexander Pyhalov 		size_t))dlsym(cd->libidnkit, "idn_decodename");
61*16d86563SAlexander Pyhalov #else
62*16d86563SAlexander Pyhalov 		size_t))dlsym(cd->libidnkit, "idn_encodename");
63*16d86563SAlexander Pyhalov #endif	/* defined(ICV_ACE_TO_UTF8) */
64*16d86563SAlexander Pyhalov 	if (cd->idn_function ==
65*16d86563SAlexander Pyhalov 	    (idn_result_t(*)(int, const char *, char *, size_t))NULL) {
66*16d86563SAlexander Pyhalov 		(void) dlclose(cd->libidnkit);
67*16d86563SAlexander Pyhalov 		free((void *)cd);
68*16d86563SAlexander Pyhalov 		errno = EINVAL;
69*16d86563SAlexander Pyhalov 		return ((void *)-1);
70*16d86563SAlexander Pyhalov 	}
71*16d86563SAlexander Pyhalov 
72*16d86563SAlexander Pyhalov 	cd->ib = (uchar_t *)malloc(_SYS_NMLN);
73*16d86563SAlexander Pyhalov 	if (cd->ib == (uchar_t *)NULL) {
74*16d86563SAlexander Pyhalov 		(void) dlclose(cd->libidnkit);
75*16d86563SAlexander Pyhalov 		free((void *)cd);
76*16d86563SAlexander Pyhalov 		errno = ENOMEM;
77*16d86563SAlexander Pyhalov 		return ((void *)-1);
78*16d86563SAlexander Pyhalov 	}
79*16d86563SAlexander Pyhalov 
80*16d86563SAlexander Pyhalov 	cd->ob = (uchar_t *)malloc(_SYS_NMLN);
81*16d86563SAlexander Pyhalov 	if (cd->ob == (uchar_t *)NULL) {
82*16d86563SAlexander Pyhalov 		(void) dlclose(cd->libidnkit);
83*16d86563SAlexander Pyhalov 		free((void *)cd->ib);
84*16d86563SAlexander Pyhalov 		free((void *)cd);
85*16d86563SAlexander Pyhalov 		errno = ENOMEM;
86*16d86563SAlexander Pyhalov 		return ((void *)-1);
87*16d86563SAlexander Pyhalov 	}
88*16d86563SAlexander Pyhalov 
89*16d86563SAlexander Pyhalov 	cd->ibl = cd->obl = _SYS_NMLN;
90*16d86563SAlexander Pyhalov 	cd->iblconsumed = cd->oblremaining = 0;
91*16d86563SAlexander Pyhalov 
92*16d86563SAlexander Pyhalov 	return ((void *)cd);
93*16d86563SAlexander Pyhalov }
94*16d86563SAlexander Pyhalov 
95*16d86563SAlexander Pyhalov 
96*16d86563SAlexander Pyhalov void
_icv_close(ace_state_t * cd)97*16d86563SAlexander Pyhalov _icv_close(ace_state_t *cd)
98*16d86563SAlexander Pyhalov {
99*16d86563SAlexander Pyhalov 	if (! cd)
100*16d86563SAlexander Pyhalov 		errno = EBADF;
101*16d86563SAlexander Pyhalov 	else {
102*16d86563SAlexander Pyhalov 		(void) dlclose(cd->libidnkit);
103*16d86563SAlexander Pyhalov 		free((void *)cd->ib);
104*16d86563SAlexander Pyhalov 		free((void *)cd->ob);
105*16d86563SAlexander Pyhalov 		free((void *)cd);
106*16d86563SAlexander Pyhalov 	}
107*16d86563SAlexander Pyhalov }
108*16d86563SAlexander Pyhalov 
109*16d86563SAlexander Pyhalov 
110*16d86563SAlexander Pyhalov size_t
_icv_iconv(ace_state_t * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)111*16d86563SAlexander Pyhalov _icv_iconv(ace_state_t *cd, char **inbuf, size_t *inbufleft, char **outbuf,
112*16d86563SAlexander Pyhalov                 size_t *outbufleft)
113*16d86563SAlexander Pyhalov {
114*16d86563SAlexander Pyhalov 	size_t ret_val = 0;
115*16d86563SAlexander Pyhalov 	uchar_t *ib;
116*16d86563SAlexander Pyhalov 	uchar_t *ob;
117*16d86563SAlexander Pyhalov 	uchar_t *ibtail;
118*16d86563SAlexander Pyhalov 	uchar_t *obtail;
119*16d86563SAlexander Pyhalov 	uchar_t *tmps;
120*16d86563SAlexander Pyhalov 	idn_result_t idnres;
121*16d86563SAlexander Pyhalov 	idn_action_t actions;
122*16d86563SAlexander Pyhalov 	int i;
123*16d86563SAlexander Pyhalov 
124*16d86563SAlexander Pyhalov 
125*16d86563SAlexander Pyhalov 	if (! cd) {
126*16d86563SAlexander Pyhalov 		errno = EBADF;
127*16d86563SAlexander Pyhalov 		return((size_t)-1);
128*16d86563SAlexander Pyhalov 	}
129*16d86563SAlexander Pyhalov 
130*16d86563SAlexander Pyhalov 	/*
131*16d86563SAlexander Pyhalov 	 * We need an output buffer in pretty much anycase and so we check it
132*16d86563SAlexander Pyhalov 	 * here and issue E2BIG if there the output buffer isn't supplied
133*16d86563SAlexander Pyhalov 	 * properly.
134*16d86563SAlexander Pyhalov 	 */
135*16d86563SAlexander Pyhalov 	if (!outbuf || !(*outbuf)) {
136*16d86563SAlexander Pyhalov 		errno = E2BIG;
137*16d86563SAlexander Pyhalov 		return ((size_t)-1);
138*16d86563SAlexander Pyhalov 	}
139*16d86563SAlexander Pyhalov 
140*16d86563SAlexander Pyhalov 	ob = (uchar_t *)*outbuf;
141*16d86563SAlexander Pyhalov 	obtail = ob + *outbufleft;
142*16d86563SAlexander Pyhalov 
143*16d86563SAlexander Pyhalov 	/*
144*16d86563SAlexander Pyhalov 	 * Always flush first any previously remaining output buffer at
145*16d86563SAlexander Pyhalov 	 * the conversion descriptor.
146*16d86563SAlexander Pyhalov 	 */
147*16d86563SAlexander Pyhalov 	for (i = 0; i < cd->oblremaining; i++) {
148*16d86563SAlexander Pyhalov 		if (ob >= obtail) {
149*16d86563SAlexander Pyhalov 			errno = E2BIG;
150*16d86563SAlexander Pyhalov 			cd->oblremaining -= i;
151*16d86563SAlexander Pyhalov 			(void) memmove((void *)cd->ob,
152*16d86563SAlexander Pyhalov 				(const void *)(cd->ob + i), cd->oblremaining);
153*16d86563SAlexander Pyhalov 			ret_val = (size_t)-1;
154*16d86563SAlexander Pyhalov 			goto ICV_ICONV_RETURN_TWO;
155*16d86563SAlexander Pyhalov 		}
156*16d86563SAlexander Pyhalov 		*ob++ = cd->ob[i];
157*16d86563SAlexander Pyhalov 	}
158*16d86563SAlexander Pyhalov 	cd->oblremaining = 0;
159*16d86563SAlexander Pyhalov 
160*16d86563SAlexander Pyhalov #ifdef IDNKIT_VERSION_LIBIDN
161*16d86563SAlexander Pyhalov 
162*16d86563SAlexander Pyhalov 	/* IDNkit v2 */
163*16d86563SAlexander Pyhalov 
164*16d86563SAlexander Pyhalov 	actions =
165*16d86563SAlexander Pyhalov 		 IDN_RTCONV
166*16d86563SAlexander Pyhalov 		|IDN_PROHCHECK
167*16d86563SAlexander Pyhalov 		|IDN_NFCCHECK
168*16d86563SAlexander Pyhalov 		|IDN_PREFCHECK
169*16d86563SAlexander Pyhalov 		|IDN_COMBCHECK
170*16d86563SAlexander Pyhalov 		|IDN_CTXOLITECHECK
171*16d86563SAlexander Pyhalov 		|IDN_BIDICHECK
172*16d86563SAlexander Pyhalov 		|IDN_LOCALCHECK
173*16d86563SAlexander Pyhalov 		|IDN_IDNCONV
174*16d86563SAlexander Pyhalov 		|IDN_LENCHECK;
175*16d86563SAlexander Pyhalov 
176*16d86563SAlexander Pyhalov # if defined(ICV_ACE_TO_UTF8)
177*16d86563SAlexander Pyhalov 	actions |= IDN_RTCHECK;
178*16d86563SAlexander Pyhalov # else
179*16d86563SAlexander Pyhalov 	actions |= IDN_MAP;
180*16d86563SAlexander Pyhalov # endif
181*16d86563SAlexander Pyhalov 
182*16d86563SAlexander Pyhalov #else
183*16d86563SAlexander Pyhalov 
184*16d86563SAlexander Pyhalov 	/* IDNkit v1 */
185*16d86563SAlexander Pyhalov 	actions =
186*16d86563SAlexander Pyhalov 		 IDN_DELIMMAP
187*16d86563SAlexander Pyhalov 		|IDN_NAMEPREP
188*16d86563SAlexander Pyhalov 		|IDN_IDNCONV
189*16d86563SAlexander Pyhalov 		|IDN_ASCCHECK;
190*16d86563SAlexander Pyhalov 
191*16d86563SAlexander Pyhalov # if defined(ICV_ACE_TO_UTF8)
192*16d86563SAlexander Pyhalov 	actions |= IDN_RTCHECK;
193*16d86563SAlexander Pyhalov # else
194*16d86563SAlexander Pyhalov 	actions |= IDN_LOCALMAP;
195*16d86563SAlexander Pyhalov # endif
196*16d86563SAlexander Pyhalov 
197*16d86563SAlexander Pyhalov #endif
198*16d86563SAlexander Pyhalov 
199*16d86563SAlexander Pyhalov #if !defined(ICV_IDN_ALLOW_UNASSIGNED)
200*16d86563SAlexander Pyhalov 	actions |= IDN_UNASCHECK;
201*16d86563SAlexander Pyhalov #endif
202*16d86563SAlexander Pyhalov 
203*16d86563SAlexander Pyhalov 	/* Process reset request. */
204*16d86563SAlexander Pyhalov 	if (!inbuf || !(*inbuf)) {
205*16d86563SAlexander Pyhalov 		if (cd->iblconsumed > 0) {
206*16d86563SAlexander Pyhalov 			if (cd->iblconsumed >= cd->ibl) {
207*16d86563SAlexander Pyhalov 				cd->ibl += _SYS_NMLN;
208*16d86563SAlexander Pyhalov 				tmps = (uchar_t *)realloc((void *)cd->ib,
209*16d86563SAlexander Pyhalov 							cd->ibl);
210*16d86563SAlexander Pyhalov 				if (tmps == (uchar_t *)NULL) {
211*16d86563SAlexander Pyhalov 					/*
212*16d86563SAlexander Pyhalov 					 * We couldn't allocate any more;
213*16d86563SAlexander Pyhalov 					 * return with realloc()'s errno.
214*16d86563SAlexander Pyhalov 					 */
215*16d86563SAlexander Pyhalov 					cd->ibl -= _SYS_NMLN;
216*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
217*16d86563SAlexander Pyhalov 					goto ICV_ICONV_RETURN_TWO;
218*16d86563SAlexander Pyhalov 				}
219*16d86563SAlexander Pyhalov 				cd->ib = tmps;
220*16d86563SAlexander Pyhalov 			}
221*16d86563SAlexander Pyhalov 
222*16d86563SAlexander Pyhalov 			*(cd->ib + cd->iblconsumed++) = '\0';
223*16d86563SAlexander Pyhalov 
224*16d86563SAlexander Pyhalov 			i = 0;
225*16d86563SAlexander Pyhalov ICV_ICONV_LOOP_ONE:
226*16d86563SAlexander Pyhalov 			idnres = (*(cd->idn_function))(actions,
227*16d86563SAlexander Pyhalov 			    (const char *)cd->ib, (char *)cd->ob,
228*16d86563SAlexander Pyhalov 				cd->obl);
229*16d86563SAlexander Pyhalov 			switch (idnres) {
230*16d86563SAlexander Pyhalov 			case idn_success:
231*16d86563SAlexander Pyhalov 				break;
232*16d86563SAlexander Pyhalov 			case idn_buffer_overflow:
233*16d86563SAlexander Pyhalov 				if (++i >= 2) {
234*16d86563SAlexander Pyhalov 					errno = EILSEQ;
235*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
236*16d86563SAlexander Pyhalov 					goto ICV_ICONV_RETURN_TWO;
237*16d86563SAlexander Pyhalov 				}
238*16d86563SAlexander Pyhalov 				cd->obl += _SYS_NMLN;
239*16d86563SAlexander Pyhalov 				tmps = (uchar_t *)realloc((void *)cd->ob,
240*16d86563SAlexander Pyhalov 							cd->obl);
241*16d86563SAlexander Pyhalov 				if (tmps == (uchar_t *)NULL) {
242*16d86563SAlexander Pyhalov 					/*
243*16d86563SAlexander Pyhalov 					 * We couldn't allocate any more;
244*16d86563SAlexander Pyhalov 					 * return with realloc()'s errno.
245*16d86563SAlexander Pyhalov 					 */
246*16d86563SAlexander Pyhalov 					cd->obl -= _SYS_NMLN;
247*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
248*16d86563SAlexander Pyhalov 					goto ICV_ICONV_RETURN_TWO;
249*16d86563SAlexander Pyhalov 				}
250*16d86563SAlexander Pyhalov 				cd->ob = tmps;
251*16d86563SAlexander Pyhalov 				goto ICV_ICONV_LOOP_ONE;
252*16d86563SAlexander Pyhalov 			default:
253*16d86563SAlexander Pyhalov 				/*
254*16d86563SAlexander Pyhalov 				 * Anything else we just treat
255*16d86563SAlexander Pyhalov 				 * as illegal sequence error.
256*16d86563SAlexander Pyhalov 				 */
257*16d86563SAlexander Pyhalov 				errno = EILSEQ;
258*16d86563SAlexander Pyhalov 				ret_val = (size_t)-1;
259*16d86563SAlexander Pyhalov 				goto ICV_ICONV_RETURN_TWO;
260*16d86563SAlexander Pyhalov 			}
261*16d86563SAlexander Pyhalov 
262*16d86563SAlexander Pyhalov 			cd->iblconsumed = 0;
263*16d86563SAlexander Pyhalov 
264*16d86563SAlexander Pyhalov 			cd->oblremaining = strlen((const char *)cd->ob);
265*16d86563SAlexander Pyhalov 			for (i = 0; i < cd->oblremaining; i++) {
266*16d86563SAlexander Pyhalov 				if (ob >= obtail) {
267*16d86563SAlexander Pyhalov 					errno = E2BIG;
268*16d86563SAlexander Pyhalov 					cd->oblremaining -= i;
269*16d86563SAlexander Pyhalov 					(void) memmove((void *)cd->ob,
270*16d86563SAlexander Pyhalov 					    (const void *)(cd->ob + i),
271*16d86563SAlexander Pyhalov 						cd->oblremaining);
272*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
273*16d86563SAlexander Pyhalov 					goto ICV_ICONV_RETURN_TWO;
274*16d86563SAlexander Pyhalov 				}
275*16d86563SAlexander Pyhalov 				*ob++ = cd->ob[i];
276*16d86563SAlexander Pyhalov 			}
277*16d86563SAlexander Pyhalov 			cd->oblremaining = 0;
278*16d86563SAlexander Pyhalov 		}
279*16d86563SAlexander Pyhalov 
280*16d86563SAlexander Pyhalov 		ret_val = (size_t)0;
281*16d86563SAlexander Pyhalov 		goto ICV_ICONV_RETURN_TWO;
282*16d86563SAlexander Pyhalov 	}
283*16d86563SAlexander Pyhalov 
284*16d86563SAlexander Pyhalov 	ib = (uchar_t *)*inbuf;
285*16d86563SAlexander Pyhalov 	ibtail = ib + *inbufleft;
286*16d86563SAlexander Pyhalov 
287*16d86563SAlexander Pyhalov 	while (ib < ibtail) {
288*16d86563SAlexander Pyhalov 		/*
289*16d86563SAlexander Pyhalov 		 * We only use bare minimum single byte space class characters
290*16d86563SAlexander Pyhalov 		 * as delimiters between names.
291*16d86563SAlexander Pyhalov 		 */
292*16d86563SAlexander Pyhalov 		if (isspace(*ib)) {
293*16d86563SAlexander Pyhalov 			if (cd->iblconsumed > 0) {
294*16d86563SAlexander Pyhalov 				if (cd->iblconsumed >= cd->ibl) {
295*16d86563SAlexander Pyhalov 					cd->ibl += _SYS_NMLN;
296*16d86563SAlexander Pyhalov 					tmps = (uchar_t *)realloc(
297*16d86563SAlexander Pyhalov 						(void *)cd->ib, cd->ibl);
298*16d86563SAlexander Pyhalov 					if (tmps == (uchar_t *)NULL) {
299*16d86563SAlexander Pyhalov 						/*
300*16d86563SAlexander Pyhalov 						 * We couldn't allocate any
301*16d86563SAlexander Pyhalov 						 * more; return with
302*16d86563SAlexander Pyhalov 						 * realloc()'s errno.
303*16d86563SAlexander Pyhalov 						 */
304*16d86563SAlexander Pyhalov 						cd->ibl -= _SYS_NMLN;
305*16d86563SAlexander Pyhalov 						ret_val = (size_t)-1;
306*16d86563SAlexander Pyhalov 						break;
307*16d86563SAlexander Pyhalov 					}
308*16d86563SAlexander Pyhalov 					cd->ib = tmps;
309*16d86563SAlexander Pyhalov 				}
310*16d86563SAlexander Pyhalov 				*(cd->ib + cd->iblconsumed) = '\0';
311*16d86563SAlexander Pyhalov 				i = 0;
312*16d86563SAlexander Pyhalov ICV_ICONV_LOOP:
313*16d86563SAlexander Pyhalov 				idnres = (*(cd->idn_function))(actions,
314*16d86563SAlexander Pyhalov 				    (const char *)cd->ib, (char *)cd->ob,
315*16d86563SAlexander Pyhalov 					cd->obl);
316*16d86563SAlexander Pyhalov 				switch (idnres) {
317*16d86563SAlexander Pyhalov 				case idn_success:
318*16d86563SAlexander Pyhalov 					break;
319*16d86563SAlexander Pyhalov 				case idn_buffer_overflow:
320*16d86563SAlexander Pyhalov 					if (++i >= 2) {
321*16d86563SAlexander Pyhalov 						errno = EILSEQ;
322*16d86563SAlexander Pyhalov 						ret_val = (size_t)-1;
323*16d86563SAlexander Pyhalov 						goto ICV_ICONV_RETURN;
324*16d86563SAlexander Pyhalov 					}
325*16d86563SAlexander Pyhalov 					cd->obl += _SYS_NMLN;
326*16d86563SAlexander Pyhalov 					tmps = (uchar_t *)realloc(
327*16d86563SAlexander Pyhalov 						(void *)cd->ob, cd->obl);
328*16d86563SAlexander Pyhalov 					if (tmps == (uchar_t *)NULL) {
329*16d86563SAlexander Pyhalov 						/*
330*16d86563SAlexander Pyhalov 						 * We couldn't allocate any
331*16d86563SAlexander Pyhalov 						 * more; return with
332*16d86563SAlexander Pyhalov 						 * realloc()'s errno.
333*16d86563SAlexander Pyhalov 						 */
334*16d86563SAlexander Pyhalov 						cd->obl -= _SYS_NMLN;
335*16d86563SAlexander Pyhalov 						ret_val = (size_t)-1;
336*16d86563SAlexander Pyhalov 						goto ICV_ICONV_RETURN;
337*16d86563SAlexander Pyhalov 					}
338*16d86563SAlexander Pyhalov 					cd->ob = tmps;
339*16d86563SAlexander Pyhalov 					goto ICV_ICONV_LOOP;
340*16d86563SAlexander Pyhalov 				default:
341*16d86563SAlexander Pyhalov 					/*
342*16d86563SAlexander Pyhalov 					 * Anything else we just treat
343*16d86563SAlexander Pyhalov 					 * as illegal sequence error.
344*16d86563SAlexander Pyhalov 					 */
345*16d86563SAlexander Pyhalov 					errno = EILSEQ;
346*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
347*16d86563SAlexander Pyhalov 					goto ICV_ICONV_RETURN;
348*16d86563SAlexander Pyhalov 				}
349*16d86563SAlexander Pyhalov 
350*16d86563SAlexander Pyhalov 				cd->iblconsumed = 0;
351*16d86563SAlexander Pyhalov 
352*16d86563SAlexander Pyhalov 				cd->oblremaining = strlen((const char *)cd->ob);
353*16d86563SAlexander Pyhalov 				for (i = 0; i < cd->oblremaining; i++) {
354*16d86563SAlexander Pyhalov 					if (ob >= obtail) {
355*16d86563SAlexander Pyhalov 						errno = E2BIG;
356*16d86563SAlexander Pyhalov 						ret_val = (size_t)-1;
357*16d86563SAlexander Pyhalov 						cd->oblremaining -= i;
358*16d86563SAlexander Pyhalov 						(void) memmove((void *)cd->ob,
359*16d86563SAlexander Pyhalov 						    (const void *)(cd->ob + i),
360*16d86563SAlexander Pyhalov 							cd->oblremaining);
361*16d86563SAlexander Pyhalov 						goto ICV_ICONV_RETURN;
362*16d86563SAlexander Pyhalov 					}
363*16d86563SAlexander Pyhalov 					*ob++ = cd->ob[i];
364*16d86563SAlexander Pyhalov 				}
365*16d86563SAlexander Pyhalov 				cd->oblremaining = 0;
366*16d86563SAlexander Pyhalov 			}
367*16d86563SAlexander Pyhalov 			if (ob >= obtail) {
368*16d86563SAlexander Pyhalov 				errno = E2BIG;
369*16d86563SAlexander Pyhalov 				ret_val = (size_t)-1;
370*16d86563SAlexander Pyhalov 				break;
371*16d86563SAlexander Pyhalov 			}
372*16d86563SAlexander Pyhalov 			*ob++ = *ib++;
373*16d86563SAlexander Pyhalov 		} else {
374*16d86563SAlexander Pyhalov 			if (cd->iblconsumed >= cd->ibl) {
375*16d86563SAlexander Pyhalov 				cd->ibl += _SYS_NMLN;
376*16d86563SAlexander Pyhalov 				tmps = (uchar_t *)realloc((void *)cd->ib,
377*16d86563SAlexander Pyhalov 						cd->ibl);
378*16d86563SAlexander Pyhalov 				if (tmps == (uchar_t *)NULL) {
379*16d86563SAlexander Pyhalov 					/*
380*16d86563SAlexander Pyhalov 					 * We couldn't allocate any more;
381*16d86563SAlexander Pyhalov 					 * return with realloc()'s errno.
382*16d86563SAlexander Pyhalov 					 */
383*16d86563SAlexander Pyhalov 					cd->ibl -= _SYS_NMLN;
384*16d86563SAlexander Pyhalov 					ret_val = (size_t)-1;
385*16d86563SAlexander Pyhalov 					break;
386*16d86563SAlexander Pyhalov 				}
387*16d86563SAlexander Pyhalov 				cd->ib = tmps;
388*16d86563SAlexander Pyhalov 			}
389*16d86563SAlexander Pyhalov 			*(cd->ib + cd->iblconsumed++) = *ib++;
390*16d86563SAlexander Pyhalov 		}
391*16d86563SAlexander Pyhalov 	} /* while (ib < ibtail) */
392*16d86563SAlexander Pyhalov 
393*16d86563SAlexander Pyhalov ICV_ICONV_RETURN:
394*16d86563SAlexander Pyhalov 	*inbuf = (char *)ib;
395*16d86563SAlexander Pyhalov 	*inbufleft = ibtail - ib;
396*16d86563SAlexander Pyhalov ICV_ICONV_RETURN_TWO:
397*16d86563SAlexander Pyhalov 	*outbuf = (char *)ob;
398*16d86563SAlexander Pyhalov 	*outbufleft = obtail - ob;
399*16d86563SAlexander Pyhalov 
400*16d86563SAlexander Pyhalov 	return(ret_val);
401*16d86563SAlexander Pyhalov }
402