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 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 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 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 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 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 * 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 * 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