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