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