xref: /illumos-gate/usr/src/lib/libtsol/common/btos.c (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
1*45916cd2Sjpk /*
2*45916cd2Sjpk  * CDDL HEADER START
3*45916cd2Sjpk  *
4*45916cd2Sjpk  * The contents of this file are subject to the terms of the
5*45916cd2Sjpk  * Common Development and Distribution License (the "License").
6*45916cd2Sjpk  * You may not use this file except in compliance with the License.
7*45916cd2Sjpk  *
8*45916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
10*45916cd2Sjpk  * See the License for the specific language governing permissions
11*45916cd2Sjpk  * and limitations under the License.
12*45916cd2Sjpk  *
13*45916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
14*45916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
16*45916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
17*45916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
18*45916cd2Sjpk  *
19*45916cd2Sjpk  * CDDL HEADER END
20*45916cd2Sjpk  */
21*45916cd2Sjpk /*
22*45916cd2Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*45916cd2Sjpk  * Use is subject to license terms.
24*45916cd2Sjpk  */
25*45916cd2Sjpk 
26*45916cd2Sjpk /*
27*45916cd2Sjpk  *      Binary label to label string translations.
28*45916cd2Sjpk  */
29*45916cd2Sjpk 
30*45916cd2Sjpk #include <locale.h>
31*45916cd2Sjpk #include <stdio.h>
32*45916cd2Sjpk #include <stdlib.h>
33*45916cd2Sjpk #include <string.h>
34*45916cd2Sjpk #include <strings.h>
35*45916cd2Sjpk #include <wchar.h>
36*45916cd2Sjpk 
37*45916cd2Sjpk #include <sys/mman.h>
38*45916cd2Sjpk 
39*45916cd2Sjpk #include <tsol/label.h>
40*45916cd2Sjpk 
41*45916cd2Sjpk #include "clnt.h"
42*45916cd2Sjpk #include "labeld.h"
43*45916cd2Sjpk #include <sys/tsol/label_macro.h>
44*45916cd2Sjpk 
45*45916cd2Sjpk #if	!defined(TEXT_DOMAIN)		/* should be defined by Makefiles */
46*45916cd2Sjpk #define	TEXT_DOMAIN "SYS_TEST"
47*45916cd2Sjpk #endif	/* TEXT_DOMAIN */
48*45916cd2Sjpk 
49*45916cd2Sjpk static bslabel_t slow;	/* static admin_low high sensitivity label */
50*45916cd2Sjpk static bslabel_t shigh;	/* static admin_high sensitivity label */
51*45916cd2Sjpk static bclear_t clrlow, clrhigh; /* static admin_low and admin_high Clearance */
52*45916cd2Sjpk 
53*45916cd2Sjpk static char	*sstring;	/* return string for sb*tos */
54*45916cd2Sjpk static size_t	ssize;		/* current size of return string */
55*45916cd2Sjpk 
56*45916cd2Sjpk static int
return_string(char ** string,int str_len,char * val)57*45916cd2Sjpk return_string(char **string, int str_len, char *val)
58*45916cd2Sjpk {
59*45916cd2Sjpk 	char	*cpyptr;
60*45916cd2Sjpk 	size_t	val_len = strlen(val) + 1;
61*45916cd2Sjpk 
62*45916cd2Sjpk 	if (*string == NULL) {
63*45916cd2Sjpk 		if ((*string = malloc(val_len)) == NULL)
64*45916cd2Sjpk 			return (0);
65*45916cd2Sjpk 	} else if (val_len > str_len) {
66*45916cd2Sjpk 		**string = '\0';
67*45916cd2Sjpk 		return (0);
68*45916cd2Sjpk 	}
69*45916cd2Sjpk 
70*45916cd2Sjpk 	cpyptr = *string;
71*45916cd2Sjpk 	bcopy(val, cpyptr, val_len);
72*45916cd2Sjpk 
73*45916cd2Sjpk 	return (val_len);
74*45916cd2Sjpk }
75*45916cd2Sjpk 
76*45916cd2Sjpk void
set_label_view(uint_t * callflags,uint_t flags)77*45916cd2Sjpk set_label_view(uint_t *callflags, uint_t flags)
78*45916cd2Sjpk {
79*45916cd2Sjpk 	if (flags&VIEW_INTERNAL) {
80*45916cd2Sjpk 		*callflags |= LABELS_VIEW_INTERNAL;
81*45916cd2Sjpk 	} else if (flags&VIEW_EXTERNAL) {
82*45916cd2Sjpk 		*callflags |= LABELS_VIEW_EXTERNAL;
83*45916cd2Sjpk 	}
84*45916cd2Sjpk }
85*45916cd2Sjpk 
86*45916cd2Sjpk int
alloc_string(char ** string,size_t size,char val)87*45916cd2Sjpk alloc_string(char **string, size_t size, char val)
88*45916cd2Sjpk {
89*45916cd2Sjpk 	if (*string == NULL) {
90*45916cd2Sjpk 		if ((*string = malloc(ALLOC_CHUNK)) == NULL)
91*45916cd2Sjpk 			return (0);
92*45916cd2Sjpk 	} else {
93*45916cd2Sjpk 		if ((*string = realloc(*string, size + ALLOC_CHUNK)) == NULL) {
94*45916cd2Sjpk 			**string = val;
95*45916cd2Sjpk 			return (0);
96*45916cd2Sjpk 		}
97*45916cd2Sjpk 	}
98*45916cd2Sjpk 	**string = val;
99*45916cd2Sjpk 	return (ALLOC_CHUNK);
100*45916cd2Sjpk }
101*45916cd2Sjpk 
102*45916cd2Sjpk #define	slcall callp->param.acall.cargs.bsltos_arg
103*45916cd2Sjpk #define	slret callp->param.aret.rvals.bsltos_ret
104*45916cd2Sjpk /*
105*45916cd2Sjpk  *	bsltos - Convert Binary Sensitivity Label to Sensitivity Label string.
106*45916cd2Sjpk  *
107*45916cd2Sjpk  *	Entry	label = Binary Sensitivity Label to be converted.
108*45916cd2Sjpk  *		string = NULL ((char *) 0), if memory to be allocated,
109*45916cd2Sjpk  *			 otherwise, pointer to preallocated memory.
110*45916cd2Sjpk  *		str_len = Length of preallocated memory, else ignored.
111*45916cd2Sjpk  *		flags = Logical sum of:
112*45916cd2Sjpk  *				LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
113*45916cd2Sjpk  *				LONG_WORDS or SHORT_WORDS,
114*45916cd2Sjpk  *				VIEW_INTERNAL or VIEW_EXTERNAL, and
115*45916cd2Sjpk  *				NO_CLASSIFICATION.
116*45916cd2Sjpk  *			LONG_CLASSIFICATION, use long classification names.
117*45916cd2Sjpk  *			SHORT_CLASSIFICATION, use short classification
118*45916cd2Sjpk  *						names (default).
119*45916cd2Sjpk  *			NO_CLASSIFICATION, don't translate classification.
120*45916cd2Sjpk  *			LONG_WORDS, use the long form of words (default).
121*45916cd2Sjpk  *			SHORTWORDS, use the short form of words where available.
122*45916cd2Sjpk  *			VIEW_INTERNAL, don't promote/demote admin low/high.
123*45916cd2Sjpk  *			VIEW_EXTERNAL, promote/demote admin low/high.
124*45916cd2Sjpk  *
125*45916cd2Sjpk  *	Exit	string = Sensitivity Label string, or empty string if
126*45916cd2Sjpk  *			 not enough preallocated memory.
127*45916cd2Sjpk  *
128*45916cd2Sjpk  *	Returns	-1, If unable to access label encodings database.
129*45916cd2Sjpk  *		 0, If unable to allocate string,
130*45916cd2Sjpk  *			or allocated string to short
131*45916cd2Sjpk  *			(and **string = '\0').
132*45916cd2Sjpk  *		length (including null) of Sensitivity Label string,
133*45916cd2Sjpk  *			If successful.
134*45916cd2Sjpk  *
135*45916cd2Sjpk  *	Calls	RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
136*45916cd2Sjpk  *			BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
137*45916cd2Sjpk  *			clnt_perror, malloc, strcat, strlen.
138*45916cd2Sjpk  *
139*45916cd2Sjpk  *	Uses	ADMIN_HIGH, ADMIN_LOW, shigh, slow.
140*45916cd2Sjpk  */
141*45916cd2Sjpk 
142*45916cd2Sjpk ssize_t
bsltos(const bslabel_t * label,char ** string,size_t str_len,int flags)143*45916cd2Sjpk bsltos(const bslabel_t *label, char **string, size_t str_len,
144*45916cd2Sjpk     int flags)
145*45916cd2Sjpk {
146*45916cd2Sjpk 	labeld_data_t	call;
147*45916cd2Sjpk 	labeld_data_t	*callp = &call;
148*45916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
149*45916cd2Sjpk 	size_t	datasize = CALL_SIZE(bsltos_call_t, 0);
150*45916cd2Sjpk 	int	rval;
151*45916cd2Sjpk 
152*45916cd2Sjpk 	if (!BLTYPE(label, SUN_SL_ID)) {
153*45916cd2Sjpk 		return (-1);
154*45916cd2Sjpk 	}
155*45916cd2Sjpk 
156*45916cd2Sjpk 	call.callop = BSLTOS;
157*45916cd2Sjpk 	slcall.label = *label;
158*45916cd2Sjpk 	slcall.flags = (flags&NO_CLASSIFICATION) ? LABELS_NO_CLASS : 0;
159*45916cd2Sjpk 	slcall.flags |= (flags&SHORT_CLASSIFICATION ||
160*45916cd2Sjpk 	    !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
161*45916cd2Sjpk 	slcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
162*45916cd2Sjpk 	    LABELS_SHORT_WORDS : 0;
163*45916cd2Sjpk 	set_label_view(&slcall.flags, flags);
164*45916cd2Sjpk 
165*45916cd2Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
166*45916cd2Sjpk 
167*45916cd2Sjpk 		if (callp->reterr != 0)
168*45916cd2Sjpk 			return (-1);
169*45916cd2Sjpk 
170*45916cd2Sjpk 		/* unpack Sensitivity Label */
171*45916cd2Sjpk 
172*45916cd2Sjpk 		rval = return_string(string, str_len, slret.slabel);
173*45916cd2Sjpk 
174*45916cd2Sjpk 		if (callp != &call)
175*45916cd2Sjpk 			(void) munmap((void *)callp, bufsize);
176*45916cd2Sjpk 		return (rval);
177*45916cd2Sjpk 	} else if (rval == NOSERVER) {
178*45916cd2Sjpk 		/* server not present */
179*45916cd2Sjpk 		/* special case admin_high and admin_low */
180*45916cd2Sjpk 
181*45916cd2Sjpk 		if (!BLTYPE(&slow, SUN_SL_ID)) {
182*45916cd2Sjpk 			/* initialize static labels */
183*45916cd2Sjpk 
184*45916cd2Sjpk 			BSLLOW(&slow);
185*45916cd2Sjpk 			BSLHIGH(&shigh);
186*45916cd2Sjpk 		}
187*45916cd2Sjpk 
188*45916cd2Sjpk 		if (BLEQUAL(label, &slow)) {
189*45916cd2Sjpk 			return (return_string(string, str_len, ADMIN_LOW));
190*45916cd2Sjpk 		} else if (BLEQUAL(label, &shigh)) {
191*45916cd2Sjpk 			return (return_string(string, str_len, ADMIN_HIGH));
192*45916cd2Sjpk 		}
193*45916cd2Sjpk 	}
194*45916cd2Sjpk 	return (-1);
195*45916cd2Sjpk }  /* bsltos */
196*45916cd2Sjpk #undef	slcall
197*45916cd2Sjpk #undef	slret
198*45916cd2Sjpk 
199*45916cd2Sjpk #define	clrcall callp->param.acall.cargs.bcleartos_arg
200*45916cd2Sjpk #define	clrret callp->param.aret.rvals.bcleartos_ret
201*45916cd2Sjpk /*
202*45916cd2Sjpk  *	bcleartos - Convert Binary Clearance to Clearance string.
203*45916cd2Sjpk  *
204*45916cd2Sjpk  *	Entry	clearance = Binary Clearance to be converted.
205*45916cd2Sjpk  *		string = NULL ((char *) 0), if memory to be allocated,
206*45916cd2Sjpk  *			 otherwise, pointer to preallocated memory.
207*45916cd2Sjpk  *		str_len = Length of preallocated memory, else ignored.
208*45916cd2Sjpk  *		flags = Logical sum of:
209*45916cd2Sjpk  *				LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
210*45916cd2Sjpk  *				LONG_WORDS or SHORT_WORDS,
211*45916cd2Sjpk  *				VIEW_INTERNAL or VIEW_EXTERNAL.
212*45916cd2Sjpk  *			LONG_CLASSIFICATION, use long classification names.
213*45916cd2Sjpk  *			SHORT_CLASSIFICATION, use short classification
214*45916cd2Sjpk  *						names (default).
215*45916cd2Sjpk  *			LONG_WORDS, use the long form of words (default).
216*45916cd2Sjpk  *			SHORTWORDS, use the short form of words where available.
217*45916cd2Sjpk  *			VIEW_INTERNAL, don't promote/demote admin low/high.
218*45916cd2Sjpk  *			VIEW_EXTERNAL, promote/demote admin low/high.
219*45916cd2Sjpk  *
220*45916cd2Sjpk  *	Exit	string = Clearance string, or empty string if not
221*45916cd2Sjpk  *			enough preallocated memory.
222*45916cd2Sjpk  *
223*45916cd2Sjpk  *	Returns	-1, If unable to access label encodings database.
224*45916cd2Sjpk  *		 0, If unable to allocate string,
225*45916cd2Sjpk  *			or allocated string to short
226*45916cd2Sjpk  *			(and **string = '\0').
227*45916cd2Sjpk  *		length (including null) of Clearance string,
228*45916cd2Sjpk  *			If successful.
229*45916cd2Sjpk  *
230*45916cd2Sjpk  *	Calls	RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
231*45916cd2Sjpk  *			BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
232*45916cd2Sjpk  *			clnt_perror, malloc, strcat, strlen.
233*45916cd2Sjpk  *
234*45916cd2Sjpk  *	Uses	ADMIN_HIGH, ADMIN_LOW, clrhigh, clrlow.
235*45916cd2Sjpk  */
236*45916cd2Sjpk 
237*45916cd2Sjpk ssize_t
bcleartos(const bclear_t * clearance,char ** string,size_t str_len,int flags)238*45916cd2Sjpk bcleartos(const bclear_t *clearance, char **string, size_t str_len,
239*45916cd2Sjpk     int flags)
240*45916cd2Sjpk {
241*45916cd2Sjpk 	labeld_data_t	call;
242*45916cd2Sjpk 	labeld_data_t	*callp = &call;
243*45916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
244*45916cd2Sjpk 	size_t	datasize = CALL_SIZE(bcleartos_call_t, 0);
245*45916cd2Sjpk 	int	rval;
246*45916cd2Sjpk 
247*45916cd2Sjpk 	if (!BLTYPE(clearance, SUN_CLR_ID)) {
248*45916cd2Sjpk 		return (-1);
249*45916cd2Sjpk 	}
250*45916cd2Sjpk 
251*45916cd2Sjpk 	call.callop = BCLEARTOS;
252*45916cd2Sjpk 	clrcall.clear = *clearance;
253*45916cd2Sjpk 	clrcall.flags = (flags&SHORT_CLASSIFICATION ||
254*45916cd2Sjpk 	    !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
255*45916cd2Sjpk 	clrcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
256*45916cd2Sjpk 	    LABELS_SHORT_WORDS : 0;
257*45916cd2Sjpk 	set_label_view(&clrcall.flags, flags);
258*45916cd2Sjpk 
259*45916cd2Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
260*45916cd2Sjpk 
261*45916cd2Sjpk 		if (callp->reterr != 0)
262*45916cd2Sjpk 			return (-1);
263*45916cd2Sjpk 
264*45916cd2Sjpk 		/* unpack Clearance */
265*45916cd2Sjpk 
266*45916cd2Sjpk 		rval = return_string(string, str_len, clrret.cslabel);
267*45916cd2Sjpk 
268*45916cd2Sjpk 		if (callp != &call)
269*45916cd2Sjpk 			/* release return buffer */
270*45916cd2Sjpk 			(void) munmap((void *)callp, bufsize);
271*45916cd2Sjpk 		return (rval);
272*45916cd2Sjpk 	} else if (rval == NOSERVER) {
273*45916cd2Sjpk 		/* server not present */
274*45916cd2Sjpk 		/* special case admin_high and admin_low */
275*45916cd2Sjpk 
276*45916cd2Sjpk 		if (!BLTYPE(&clrlow, SUN_CLR_ID)) {
277*45916cd2Sjpk 			/* initialize static labels */
278*45916cd2Sjpk 
279*45916cd2Sjpk 			BCLEARLOW(&clrlow);
280*45916cd2Sjpk 			BCLEARHIGH(&clrhigh);
281*45916cd2Sjpk 		}
282*45916cd2Sjpk 		if (BLEQUAL(clearance, &clrlow)) {
283*45916cd2Sjpk 			return (return_string(string, str_len, ADMIN_LOW));
284*45916cd2Sjpk 		} else if (BLEQUAL(clearance, &clrhigh)) {
285*45916cd2Sjpk 			return (return_string(string, str_len, ADMIN_HIGH));
286*45916cd2Sjpk 		}
287*45916cd2Sjpk 	}
288*45916cd2Sjpk 	return (-1);
289*45916cd2Sjpk }  /* bcleartos */
290*45916cd2Sjpk #undef	clrcall
291*45916cd2Sjpk #undef	clrret
292*45916cd2Sjpk 
293*45916cd2Sjpk /*
294*45916cd2Sjpk  *	sbsltos - Convert Sensitivity Label to canonical clipped form.
295*45916cd2Sjpk  *
296*45916cd2Sjpk  *	Entry	label = Sensitivity Label to be converted.
297*45916cd2Sjpk  *		len = Maximum length of translated string, excluding NULL.
298*45916cd2Sjpk  *		      0, full string.
299*45916cd2Sjpk  *		sstring = address of string to translate into.
300*45916cd2Sjpk  *		ssize = size of memory currently allocated to sstring.
301*45916cd2Sjpk  *
302*45916cd2Sjpk  *	Exit	sstring = Newly translated string.
303*45916cd2Sjpk  *		ssize = Updated if more memory pre-allocated.
304*45916cd2Sjpk  *
305*45916cd2Sjpk  *	Returns	NULL, If error, len too small, unable to translate, or get
306*45916cd2Sjpk  *		      memory for string.
307*45916cd2Sjpk  *		Address of string containing converted value.
308*45916cd2Sjpk  *
309*45916cd2Sjpk  *	Calls	alloc_string, bsltos, strcpy.
310*45916cd2Sjpk  *
311*45916cd2Sjpk  *	Uses	ssize, sstring.
312*45916cd2Sjpk  */
313*45916cd2Sjpk 
314*45916cd2Sjpk char *
sbsltos(const bslabel_t * label,size_t len)315*45916cd2Sjpk sbsltos(const bslabel_t *label, size_t len)
316*45916cd2Sjpk {
317*45916cd2Sjpk 	ssize_t	slen;		/* length including NULL */
318*45916cd2Sjpk 	wchar_t *wstring;
319*45916cd2Sjpk 	int	wccount;
320*45916cd2Sjpk 
321*45916cd2Sjpk 	if (ssize == 0) {
322*45916cd2Sjpk 		/* Allocate string memory. */
323*45916cd2Sjpk 		if ((ssize = alloc_string(&sstring, ssize, 's')) == 0)
324*45916cd2Sjpk 			/* can't get initial memory for string */
325*45916cd2Sjpk 			return (NULL);
326*45916cd2Sjpk 	}
327*45916cd2Sjpk 
328*45916cd2Sjpk again:
329*45916cd2Sjpk 	if ((slen = bsltos(label, &sstring, ssize,
330*45916cd2Sjpk 	    (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
331*45916cd2Sjpk 		/* error in translation */
332*45916cd2Sjpk 		if (slen == 0) {
333*45916cd2Sjpk 			if (*sstring == '\0') {
334*45916cd2Sjpk 				int newsize;
335*45916cd2Sjpk 				/* sstring not long enough */
336*45916cd2Sjpk 				if ((newsize = alloc_string(&sstring, ssize,
337*45916cd2Sjpk 				    's')) == 0) {
338*45916cd2Sjpk 					/* Can't get more memory */
339*45916cd2Sjpk 					return (NULL);
340*45916cd2Sjpk 				}
341*45916cd2Sjpk 				ssize += newsize;
342*45916cd2Sjpk 				goto again;
343*45916cd2Sjpk 			}
344*45916cd2Sjpk 		}
345*45916cd2Sjpk 		return (NULL);
346*45916cd2Sjpk 	}
347*45916cd2Sjpk 	if (len == 0) {
348*45916cd2Sjpk 		return (sstring);
349*45916cd2Sjpk 	} else if (len < MIN_SL_LEN) {
350*45916cd2Sjpk 		return (NULL);
351*45916cd2Sjpk 	}
352*45916cd2Sjpk 	if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
353*45916cd2Sjpk 		return (NULL);
354*45916cd2Sjpk 	if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
355*45916cd2Sjpk 		free(wstring);
356*45916cd2Sjpk 		return (NULL);
357*45916cd2Sjpk 	}
358*45916cd2Sjpk 	if (wccount > len) {
359*45916cd2Sjpk 		wchar_t *clipp = wstring + (len - 2);
360*45916cd2Sjpk 
361*45916cd2Sjpk 		/* Adjust string size to desired length */
362*45916cd2Sjpk 
363*45916cd2Sjpk 		clipp[0] = L'<';
364*45916cd2Sjpk 		clipp[1] = L'-';
365*45916cd2Sjpk 		clipp[2] = L'\0';
366*45916cd2Sjpk 
367*45916cd2Sjpk 		while (wcstombs(NULL, wstring, 0) >= ssize) {
368*45916cd2Sjpk 			int newsize;
369*45916cd2Sjpk 
370*45916cd2Sjpk 			/* sstring not long enough */
371*45916cd2Sjpk 			if ((newsize = alloc_string(&sstring, ssize, 's')) ==
372*45916cd2Sjpk 			    0) {
373*45916cd2Sjpk 				/* Can't get more memory */
374*45916cd2Sjpk 				return (NULL);
375*45916cd2Sjpk 			}
376*45916cd2Sjpk 			ssize += newsize;
377*45916cd2Sjpk 		}
378*45916cd2Sjpk 
379*45916cd2Sjpk 		if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
380*45916cd2Sjpk 			free(wstring);
381*45916cd2Sjpk 			return (NULL);
382*45916cd2Sjpk 		}
383*45916cd2Sjpk 	}
384*45916cd2Sjpk 	free(wstring);
385*45916cd2Sjpk 
386*45916cd2Sjpk 	return (sstring);
387*45916cd2Sjpk }  /* sbsltos */
388*45916cd2Sjpk 
389*45916cd2Sjpk /*
390*45916cd2Sjpk  *	sbcleartos - Convert Clearance to canonical clipped form.
391*45916cd2Sjpk  *
392*45916cd2Sjpk  *	Entry	clearance = Clearance to be converted.
393*45916cd2Sjpk  *		len = Maximum length of translated string, excluding NULL.
394*45916cd2Sjpk  *		      0, full string.
395*45916cd2Sjpk  *		sstring = address of string to translate into.
396*45916cd2Sjpk  *		ssize = size of memory currently allocated to sstring.
397*45916cd2Sjpk  *
398*45916cd2Sjpk  *	Exit	sstring = Newly translated string.
399*45916cd2Sjpk  *		ssize = Updated if more memory pre-allocated.
400*45916cd2Sjpk  *
401*45916cd2Sjpk  *	Returns	NULL, If error, len too small, unable to translate, or get
402*45916cd2Sjpk  *		      memory for string.
403*45916cd2Sjpk  *		Address of string containing converted value.
404*45916cd2Sjpk  *
405*45916cd2Sjpk  *	Calls	alloc_string, bcleartos, strcpy.
406*45916cd2Sjpk  *
407*45916cd2Sjpk  *	Uses	ssize, sstring.
408*45916cd2Sjpk  */
409*45916cd2Sjpk 
410*45916cd2Sjpk char *
sbcleartos(const bclear_t * clearance,size_t len)411*45916cd2Sjpk sbcleartos(const bclear_t *clearance, size_t len)
412*45916cd2Sjpk {
413*45916cd2Sjpk 	ssize_t	slen;		/* length including NULL */
414*45916cd2Sjpk 	wchar_t *wstring;
415*45916cd2Sjpk 	int	wccount;
416*45916cd2Sjpk 
417*45916cd2Sjpk 	if (ssize == 0) {
418*45916cd2Sjpk 		/* Allocate string memory. */
419*45916cd2Sjpk 		if ((ssize = alloc_string(&sstring, ssize, 'c')) == 0)
420*45916cd2Sjpk 			/* can't get initial memory for string */
421*45916cd2Sjpk 			return (NULL);
422*45916cd2Sjpk 	}
423*45916cd2Sjpk 
424*45916cd2Sjpk again:
425*45916cd2Sjpk 	if ((slen = bcleartos(clearance, &sstring, ssize,
426*45916cd2Sjpk 	    (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
427*45916cd2Sjpk 		/* error in translation */
428*45916cd2Sjpk 		if (slen == 0) {
429*45916cd2Sjpk 			if (*sstring == '\0') {
430*45916cd2Sjpk 				int newsize;
431*45916cd2Sjpk 				/* sstring not long enough */
432*45916cd2Sjpk 				if ((newsize = alloc_string(&sstring, ssize,
433*45916cd2Sjpk 				    'c')) == 0) {
434*45916cd2Sjpk 					/* Can't get more memory */
435*45916cd2Sjpk 					return (NULL);
436*45916cd2Sjpk 				}
437*45916cd2Sjpk 				ssize += newsize;
438*45916cd2Sjpk 				goto again;
439*45916cd2Sjpk 			}
440*45916cd2Sjpk 		}
441*45916cd2Sjpk 		return (NULL);
442*45916cd2Sjpk 	}
443*45916cd2Sjpk 	if (len == 0) {
444*45916cd2Sjpk 		return (sstring);
445*45916cd2Sjpk 	} else if (len < MIN_CLR_LEN) {
446*45916cd2Sjpk 		return (NULL);
447*45916cd2Sjpk 	}
448*45916cd2Sjpk 	if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
449*45916cd2Sjpk 		return (NULL);
450*45916cd2Sjpk 	if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
451*45916cd2Sjpk 		free(wstring);
452*45916cd2Sjpk 		return (NULL);
453*45916cd2Sjpk 	}
454*45916cd2Sjpk 	if (wccount > len) {
455*45916cd2Sjpk 		wchar_t *clipp = wstring + (len - 2);
456*45916cd2Sjpk 
457*45916cd2Sjpk 		/* Adjust string size to desired length */
458*45916cd2Sjpk 
459*45916cd2Sjpk 		clipp[0] = L'<';
460*45916cd2Sjpk 		clipp[1] = L'-';
461*45916cd2Sjpk 		clipp[2] = L'\0';
462*45916cd2Sjpk 
463*45916cd2Sjpk 		while (wcstombs(NULL, wstring, 0) >= ssize) {
464*45916cd2Sjpk 			int newsize;
465*45916cd2Sjpk 
466*45916cd2Sjpk 			/* sstring not long enough */
467*45916cd2Sjpk 			if ((newsize = alloc_string(&sstring, ssize, 'c')) ==
468*45916cd2Sjpk 			    0) {
469*45916cd2Sjpk 				/* Can't get more memory */
470*45916cd2Sjpk 				free(wstring);
471*45916cd2Sjpk 				return (NULL);
472*45916cd2Sjpk 			}
473*45916cd2Sjpk 			ssize += newsize;
474*45916cd2Sjpk 		}
475*45916cd2Sjpk 		if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
476*45916cd2Sjpk 			free(wstring);
477*45916cd2Sjpk 			return (NULL);
478*45916cd2Sjpk 		}
479*45916cd2Sjpk 	}
480*45916cd2Sjpk 	free(wstring);
481*45916cd2Sjpk 
482*45916cd2Sjpk 	return (sstring);
483*45916cd2Sjpk }  /* sbcleartos */
484