1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Kernel iconv code conversion module (kiconv_emea) for Europe, Middle East,
  28  * and South East Asia (PSARC/2007/173).
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/param.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/systm.h>
  35 #include <sys/debug.h>
  36 #include <sys/kmem.h>
  37 #include <sys/cmn_err.h>
  38 #include <sys/ddi.h>
  39 #include <sys/sunddi.h>
  40 #include <sys/ksynch.h>
  41 #include <sys/modctl.h>
  42 #include <sys/byteorder.h>
  43 #include <sys/errno.h>
  44 #include <sys/kiconv.h>
  45 #include <sys/kiconv_emea1.h>
  46 #include <sys/kiconv_emea2.h>
  47 
  48 
  49 /*
  50  * The following macros indicate ids to the correct code conversion mapping
  51  * data tables to use. The actual tables are coming from <sys/kiconv_emea1.h>
  52  * and <sys/kiconv_emea2.h>. If you update the header files, then, you might
  53  * also need to update the table ids at below.
  54  *
  55  * The table for KICONV_TBLID_720 is a special case and should come from
  56  * a separate header file than others at <sys/kiconv_emea1.h> hence it has
  57  * an id that is rather unusual distinguishing itself from others. (And,
  58  * the ids much be of uint8_t.)
  59  */
  60 #define KICONV_TBLID_720                (0xFFU)
  61 #define KICONV_TBLID_RANGE1_START       KICONV_TBLID_720
  62 #define KICONV_TBLID_RANGE1_END         KICONV_TBLID_720
  63 
  64 #define KICONV_TBLID_737                (0)
  65 #define KICONV_TBLID_852                (1)
  66 #define KICONV_TBLID_857                (2)
  67 #define KICONV_TBLID_862                (3)
  68 #define KICONV_TBLID_866                (4)
  69 #define KICONV_TBLID_1250               (5)
  70 #define KICONV_TBLID_1251               (6)
  71 #define KICONV_TBLID_1253               (7)
  72 #define KICONV_TBLID_1254               (8)
  73 #define KICONV_TBLID_1255               (9)
  74 #define KICONV_TBLID_1256               (10)
  75 #define KICONV_TBLID_1257               (11)
  76 #define KICONV_TBLID_8859_2             (12)
  77 #define KICONV_TBLID_8859_3             (13)
  78 #define KICONV_TBLID_8859_4             (14)
  79 #define KICONV_TBLID_8859_5             (15)
  80 #define KICONV_TBLID_8859_6             (16)
  81 #define KICONV_TBLID_8859_7             (17)
  82 #define KICONV_TBLID_8859_8             (18)
  83 #define KICONV_TBLID_8859_9             (19)
  84 #define KICONV_TBLID_8859_10            (20)
  85 #define KICONV_TBLID_8859_11            (21)
  86 #define KICONV_TBLID_8859_13            (22)
  87 #define KICONV_TBLID_KOI8_R             (23)
  88 
  89 #define KICONV_MAX_MAPPING_TBLID        KICONV_TBLID_KOI8_R
  90 
  91 /*
  92  * The following tables are coming from u8_textprep.c. We use them to
  93  * check on validity of UTF-8 characters and their bytes.
  94  */
  95 extern const int8_t u8_number_of_bytes[];
  96 extern const uint8_t u8_valid_min_2nd_byte[];
  97 extern const uint8_t u8_valid_max_2nd_byte[];
  98 
  99 
 100 /*
 101  * The following 25 open_to_xxxx() functions are kiconv_open functions for
 102  * the conversions from UTF-8 to xxxx single byte codesets.
 103  */
 104 static void *
 105 open_to_720()
 106 {
 107         kiconv_state_t s;
 108 
 109         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 110         s->id = KICONV_TBLID_720;
 111         s->bom_processed = 0;
 112 
 113         return ((void *)s);
 114 }
 115 
 116 static void *
 117 open_to_737()
 118 {
 119         kiconv_state_t s;
 120 
 121         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 122         s->id = KICONV_TBLID_737;
 123         s->bom_processed = 0;
 124 
 125         return ((void *)s);
 126 }
 127 
 128 static void *
 129 open_to_852()
 130 {
 131         kiconv_state_t s;
 132 
 133         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 134         s->id = KICONV_TBLID_852;
 135         s->bom_processed = 0;
 136 
 137         return ((void *)s);
 138 }
 139 
 140 static void *
 141 open_to_857()
 142 {
 143         kiconv_state_t s;
 144 
 145         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 146         s->id = KICONV_TBLID_857;
 147         s->bom_processed = 0;
 148 
 149         return ((void *)s);
 150 }
 151 
 152 static void *
 153 open_to_862()
 154 {
 155         kiconv_state_t s;
 156 
 157         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 158         s->id = KICONV_TBLID_862;
 159         s->bom_processed = 0;
 160 
 161         return ((void *)s);
 162 }
 163 
 164 static void *
 165 open_to_866()
 166 {
 167         kiconv_state_t s;
 168 
 169         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 170         s->id = KICONV_TBLID_866;
 171         s->bom_processed = 0;
 172 
 173         return ((void *)s);
 174 }
 175 
 176 static void *
 177 open_to_1250()
 178 {
 179         kiconv_state_t s;
 180 
 181         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 182         s->id = KICONV_TBLID_1250;
 183         s->bom_processed = 0;
 184 
 185         return ((void *)s);
 186 }
 187 
 188 static void *
 189 open_to_1251()
 190 {
 191         kiconv_state_t s;
 192 
 193         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 194         s->id = KICONV_TBLID_1251;
 195         s->bom_processed = 0;
 196 
 197         return ((void *)s);
 198 }
 199 
 200 static void *
 201 open_to_1253()
 202 {
 203         kiconv_state_t s;
 204 
 205         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 206         s->id = KICONV_TBLID_1253;
 207         s->bom_processed = 0;
 208 
 209         return ((void *)s);
 210 }
 211 
 212 static void *
 213 open_to_1254()
 214 {
 215         kiconv_state_t s;
 216 
 217         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 218         s->id = KICONV_TBLID_1254;
 219         s->bom_processed = 0;
 220 
 221         return ((void *)s);
 222 }
 223 
 224 static void *
 225 open_to_1255()
 226 {
 227         kiconv_state_t s;
 228 
 229         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 230         s->id = KICONV_TBLID_1255;
 231         s->bom_processed = 0;
 232 
 233         return ((void *)s);
 234 }
 235 
 236 static void *
 237 open_to_1256()
 238 {
 239         kiconv_state_t s;
 240 
 241         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 242         s->id = KICONV_TBLID_1256;
 243         s->bom_processed = 0;
 244 
 245         return ((void *)s);
 246 }
 247 
 248 static void *
 249 open_to_1257()
 250 {
 251         kiconv_state_t s;
 252 
 253         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 254         s->id = KICONV_TBLID_1257;
 255         s->bom_processed = 0;
 256 
 257         return ((void *)s);
 258 }
 259 
 260 static void *
 261 open_to_88592()
 262 {
 263         kiconv_state_t s;
 264 
 265         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 266         s->id = KICONV_TBLID_8859_2;
 267         s->bom_processed = 0;
 268 
 269         return ((void *)s);
 270 }
 271 
 272 static void *
 273 open_to_88593()
 274 {
 275         kiconv_state_t s;
 276 
 277         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 278         s->id = KICONV_TBLID_8859_3;
 279         s->bom_processed = 0;
 280 
 281         return ((void *)s);
 282 }
 283 
 284 static void *
 285 open_to_88594()
 286 {
 287         kiconv_state_t s;
 288 
 289         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 290         s->id = KICONV_TBLID_8859_4;
 291         s->bom_processed = 0;
 292 
 293         return ((void *)s);
 294 }
 295 
 296 static void *
 297 open_to_88595()
 298 {
 299         kiconv_state_t s;
 300 
 301         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 302         s->id = KICONV_TBLID_8859_5;
 303         s->bom_processed = 0;
 304 
 305         return ((void *)s);
 306 }
 307 
 308 static void *
 309 open_to_88596()
 310 {
 311         kiconv_state_t s;
 312 
 313         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 314         s->id = KICONV_TBLID_8859_6;
 315         s->bom_processed = 0;
 316 
 317         return ((void *)s);
 318 }
 319 
 320 static void *
 321 open_to_88597()
 322 {
 323         kiconv_state_t s;
 324 
 325         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 326         s->id = KICONV_TBLID_8859_7;
 327         s->bom_processed = 0;
 328 
 329         return ((void *)s);
 330 }
 331 
 332 static void *
 333 open_to_88598()
 334 {
 335         kiconv_state_t s;
 336 
 337         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 338         s->id = KICONV_TBLID_8859_8;
 339         s->bom_processed = 0;
 340 
 341         return ((void *)s);
 342 }
 343 
 344 static void *
 345 open_to_88599()
 346 {
 347         kiconv_state_t s;
 348 
 349         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 350         s->id = KICONV_TBLID_8859_9;
 351         s->bom_processed = 0;
 352 
 353         return ((void *)s);
 354 }
 355 
 356 static void *
 357 open_to_885910()
 358 {
 359         kiconv_state_t s;
 360 
 361         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 362         s->id = KICONV_TBLID_8859_10;
 363         s->bom_processed = 0;
 364 
 365         return ((void *)s);
 366 }
 367 
 368 static void *
 369 open_to_885911()
 370 {
 371         kiconv_state_t s;
 372 
 373         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 374         s->id = KICONV_TBLID_8859_11;
 375         s->bom_processed = 0;
 376 
 377         return ((void *)s);
 378 }
 379 
 380 static void *
 381 open_to_885913()
 382 {
 383         kiconv_state_t s;
 384 
 385         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 386         s->id = KICONV_TBLID_8859_13;
 387         s->bom_processed = 0;
 388 
 389         return ((void *)s);
 390 }
 391 
 392 static void *
 393 open_to_koi8r()
 394 {
 395         kiconv_state_t s;
 396 
 397         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 398         s->id = KICONV_TBLID_KOI8_R;
 399         s->bom_processed = 0;
 400 
 401         return ((void *)s);
 402 }
 403 
 404 /*
 405  * The following 25 open_fr_xxxx() functions are kiconv_open functions for
 406  * the conversions from xxxx single byte codeset to UTF-8.
 407  */
 408 static void *
 409 open_fr_720()
 410 {
 411         return ((void *)KICONV_TBLID_720);
 412 }
 413 
 414 static void *
 415 open_fr_737()
 416 {
 417         return ((void *)KICONV_TBLID_737);
 418 }
 419 
 420 static void *
 421 open_fr_852()
 422 {
 423         return ((void *)KICONV_TBLID_852);
 424 }
 425 
 426 static void *
 427 open_fr_857()
 428 {
 429         return ((void *)KICONV_TBLID_857);
 430 }
 431 
 432 static void *
 433 open_fr_862()
 434 {
 435         return ((void *)KICONV_TBLID_862);
 436 }
 437 
 438 static void *
 439 open_fr_866()
 440 {
 441         return ((void *)KICONV_TBLID_866);
 442 }
 443 
 444 static void *
 445 open_fr_1250()
 446 {
 447         return ((void *)KICONV_TBLID_1250);
 448 }
 449 
 450 static void *
 451 open_fr_1251()
 452 {
 453         return ((void *)KICONV_TBLID_1251);
 454 }
 455 
 456 static void *
 457 open_fr_1253()
 458 {
 459         return ((void *)KICONV_TBLID_1253);
 460 }
 461 
 462 static void *
 463 open_fr_1254()
 464 {
 465         return ((void *)KICONV_TBLID_1254);
 466 }
 467 
 468 static void *
 469 open_fr_1255()
 470 {
 471         return ((void *)KICONV_TBLID_1255);
 472 }
 473 
 474 static void *
 475 open_fr_1256()
 476 {
 477         return ((void *)KICONV_TBLID_1256);
 478 }
 479 
 480 static void *
 481 open_fr_1257()
 482 {
 483         return ((void *)KICONV_TBLID_1257);
 484 }
 485 
 486 static void *
 487 open_fr_88592()
 488 {
 489         return ((void *)KICONV_TBLID_8859_2);
 490 }
 491 
 492 static void *
 493 open_fr_88593()
 494 {
 495         return ((void *)KICONV_TBLID_8859_3);
 496 }
 497 
 498 static void *
 499 open_fr_88594()
 500 {
 501         return ((void *)KICONV_TBLID_8859_4);
 502 }
 503 
 504 static void *
 505 open_fr_88595()
 506 {
 507         return ((void *)KICONV_TBLID_8859_5);
 508 }
 509 
 510 static void *
 511 open_fr_88596()
 512 {
 513         return ((void *)KICONV_TBLID_8859_6);
 514 }
 515 
 516 static void *
 517 open_fr_88597()
 518 {
 519         return ((void *)KICONV_TBLID_8859_7);
 520 }
 521 
 522 static void *
 523 open_fr_88598()
 524 {
 525         return ((void *)KICONV_TBLID_8859_8);
 526 }
 527 
 528 static void *
 529 open_fr_88599()
 530 {
 531         return ((void *)KICONV_TBLID_8859_9);
 532 }
 533 
 534 static void *
 535 open_fr_885910()
 536 {
 537         return ((void *)KICONV_TBLID_8859_10);
 538 }
 539 
 540 static void *
 541 open_fr_885911()
 542 {
 543         return ((void *)KICONV_TBLID_8859_11);
 544 }
 545 
 546 static void *
 547 open_fr_885913()
 548 {
 549         return ((void *)KICONV_TBLID_8859_13);
 550 }
 551 
 552 static void *
 553 open_fr_koi8r()
 554 {
 555         return ((void *)KICONV_TBLID_KOI8_R);
 556 }
 557 
 558 /*
 559  * The following is the common kiconv_close function for the conversions from
 560  * UTF-8 to single byte codesets.
 561  */
 562 static int
 563 close_to_sb(void *s)
 564 {
 565         if (! s || s == (void *)-1)
 566                 return (EBADF);
 567 
 568         kmem_free(s, sizeof (kiconv_state_data_t));
 569 
 570         return (0);
 571 }
 572 
 573 /*
 574  * The following is the common kiconv_close function for the conversions from
 575  * single byte codesets to UTF-8.
 576  */
 577 static int
 578 close_fr_sb(void *s)
 579 {
 580         if ((ulong_t)s > KICONV_MAX_MAPPING_TBLID &&
 581             ((ulong_t)s < KICONV_TBLID_RANGE1_START ||
 582             (ulong_t)s > KICONV_TBLID_RANGE1_END))
 583                 return (EBADF);
 584 
 585         return (0);
 586 }
 587 
 588 /*
 589  * The following is the common kiconv function for the conversions from
 590  * UTF-8 to single byte codesets. (This may look a lot similar to
 591  * kiconvstr_to_sb() but they do have different features to cover and
 592  * it's not really worth to try to merge them into a single function since
 593  * you'll have to add performance penalty for both per each character
 594  * conversion as you will have to figure out if this is kiconv_to_sb() or
 595  * kiconvstr_to_sb().)
 596  */
 597 static size_t
 598 kiconv_to_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
 599         size_t *outbytesleft, int *errno)
 600 {
 601         kiconv_to_sb_tbl_comp_t *tbl;
 602         size_t id;
 603         size_t ret_val;
 604         uchar_t *ib;
 605         uchar_t *oldib;
 606         uchar_t *ob;
 607         uchar_t *ibtail;
 608         uchar_t *obtail;
 609         uint32_t u8;
 610         size_t i;
 611         size_t l;
 612         size_t h;
 613         size_t init_h;
 614         int8_t sz;
 615         boolean_t second;
 616 
 617         /* Check on the kiconv code conversion descriptor. */
 618         if (! kcd || kcd == (void *)-1) {
 619                 *errno = EBADF;
 620                 return ((size_t)-1);
 621         }
 622 
 623         /* Get the table id and check on it. */
 624         id = ((kiconv_state_t)kcd)->id;
 625         if (id > KICONV_MAX_MAPPING_TBLID &&
 626             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
 627                 *errno = EBADF;
 628                 return ((size_t)-1);
 629         }
 630 
 631         /* If this is a state reset request, process and return. */
 632         if (! inbuf || ! (*inbuf)) {
 633                 ((kiconv_state_t)kcd)->bom_processed = 0;
 634                 return ((size_t)0);
 635         }
 636 
 637         ret_val = 0;
 638         ib = (uchar_t *)*inbuf;
 639         ob = (uchar_t *)*outbuf;
 640         ibtail = ib + *inbytesleft;
 641         obtail = ob + *outbytesleft;
 642 
 643         /*
 644          * Get the table we want to use and also calculate the "init_h"
 645          * which is the initial high index for the binary search that we will
 646          * use. While the table sizes are all the same at the moment, to be
 647          * ready for future cases where tables could be in different sizes,
 648          * we separately calculate the init_h at here.
 649          */
 650         if (id == KICONV_TBLID_720) {
 651                 tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
 652                 init_h = sizeof (u8_to_cp720_tbl);
 653         } else {
 654                 tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
 655                 init_h = sizeof (to_sb_tbl[id]);
 656         }
 657         init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
 658 
 659         /*
 660          * If we haven't checked on the UTF-8 signature BOM character in
 661          * the beginning of the conversion data stream, we check it and if
 662          * find one, we skip it since we have no use for it.
 663          */
 664         if (((kiconv_state_t)kcd)->bom_processed == 0 && (ibtail - ib) >= 3 &&
 665             *ib == 0xef && *(ib + 1) == 0xbb && *(ib + 2) == 0xbf)
 666                         ib += 3;
 667         ((kiconv_state_t)kcd)->bom_processed = 1;
 668 
 669         while (ib < ibtail) {
 670                 sz = u8_number_of_bytes[*ib];
 671                 if (sz <= 0) {
 672                         *errno = EILSEQ;
 673                         ret_val = (size_t)-1;
 674                         break;
 675                 }
 676 
 677                 /*
 678                  * If there is no room to write at the output buffer,
 679                  * we issue E2BIG and let the caller knows about it.
 680                  */
 681                 if (ob >= obtail) {
 682                         *errno = E2BIG;
 683                         ret_val = (size_t)-1;
 684                         break;
 685                 }
 686 
 687                 /*
 688                  * If it is a 7-bit ASCII character, we don't need to
 689                  * process further and we just copy the character over.
 690                  *
 691                  * If not, we collect the character bytes up to four bytes,
 692                  * validate the bytes, and binary search for the corresponding
 693                  * single byte codeset character byte. If we find it from
 694                  * the mapping table, we put that into the output buffer;
 695                  * otherwise, we put a replacement character instead as
 696                  * a non-identical conversion.
 697                  */
 698                 if (sz == 1) {
 699                         *ob++ = *ib++;
 700                         continue;
 701                 }
 702 
 703                 /*
 704                  * Issue EINVAL if the last character at the input buffer
 705                  * is an incomplete character missing a byte or more.
 706                  */
 707                 if ((ibtail - ib) < sz) {
 708                         *errno = EINVAL;
 709                         ret_val = (size_t)-1;
 710                         break;
 711                 }
 712 
 713                 /*
 714                  * We collect UTF-8 character bytes and at the same time,
 715                  * check on if the bytes are valid bytes or not. This follows
 716                  * the latest UTF-8 byte representation.
 717                  */
 718                 oldib = ib;
 719                 u8 = *ib++;
 720                 second = B_TRUE;
 721                 for (i = 1; i < sz; i++) {
 722                         if (second) {
 723                                 if (*ib < u8_valid_min_2nd_byte[u8] ||
 724                                     *ib > u8_valid_max_2nd_byte[u8]) {
 725                                         *errno = EILSEQ;
 726                                         ret_val = (size_t)-1;
 727                                         ib = oldib;
 728                                         goto TO_SB_ILLEGAL_CHAR_ERR;
 729                                 }
 730                                 second = B_FALSE;
 731                         } else if (*ib < 0x80 || *ib > 0xbf) {
 732                                 *errno = EILSEQ;
 733                                 ret_val = (size_t)-1;
 734                                 ib = oldib;
 735                                 goto TO_SB_ILLEGAL_CHAR_ERR;
 736                         }
 737                         u8 = (u8 << 8) | ((uint32_t)*ib);
 738                         ib++;
 739                 }
 740 
 741                 i = l = 0;
 742                 h = init_h;
 743                 while (l <= h) {
 744                         i = (l + h) / 2;
 745                         if (tbl[i].u8 == u8)
 746                                 break;
 747                         else if (tbl[i].u8 < u8)
 748                                 l = i + 1;
 749                         else
 750                                 h = i - 1;
 751                 }
 752 
 753                 if (tbl[i].u8 == u8) {
 754                         *ob++ = tbl[i].sb;
 755                 } else {
 756                         /*
 757                          * What this means is that we encountered
 758                          * a non-identical conversion. In other words,
 759                          * input buffer contains a valid character in
 760                          * the fromcode but the tocode doesn't have
 761                          * any character that can be mapped to.
 762                          *
 763                          * In this case, we insert an ASCII replacement
 764                          * character instead at the output buffer and
 765                          * count such non-identical conversions by
 766                          * increasing the ret_val.
 767                          *
 768                          * If the return value of the function is bigger
 769                          * than zero, that means we had such non-identical
 770                          * conversion(s).
 771                          */
 772                         *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
 773                         ret_val++;
 774                 }
 775         }
 776 
 777 TO_SB_ILLEGAL_CHAR_ERR:
 778         *inbuf = (char *)ib;
 779         *inbytesleft = ibtail - ib;
 780         *outbuf = (char *)ob;
 781         *outbytesleft = obtail - ob;
 782 
 783         return (ret_val);
 784 }
 785 
 786 /*
 787  * The following is the common kiconv function for the conversions from
 788  * single byte codesets to UTf-8.
 789  */
 790 static size_t
 791 kiconv_fr_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
 792         size_t *outbytesleft, int *errno)
 793 {
 794         kiconv_to_utf8_tbl_comp_t *tbl;
 795         size_t ret_val;
 796         uchar_t *ib;
 797         uchar_t *ob;
 798         uchar_t *ibtail;
 799         uchar_t *obtail;
 800         size_t i;
 801         size_t k;
 802         int8_t sz;
 803 
 804         /* Validate the kiconv code conversion descriptor. */
 805         if ((ulong_t)kcd > KICONV_MAX_MAPPING_TBLID &&
 806             ((ulong_t)kcd < KICONV_TBLID_RANGE1_START ||
 807             (ulong_t)kcd > KICONV_TBLID_RANGE1_END)) {
 808                 *errno = EBADF;
 809                 return ((size_t)-1);
 810         }
 811 
 812         /*
 813          * If this is a state reset request, there is nothing to do and so
 814          * we just return.
 815          */
 816         if (! inbuf || ! (*inbuf))
 817                 return ((size_t)0);
 818 
 819         ret_val = 0;
 820         ib = (uchar_t *)*inbuf;
 821         ob = (uchar_t *)*outbuf;
 822         ibtail = ib + *inbytesleft;
 823         obtail = ob + *outbytesleft;
 824 
 825         tbl = ((ulong_t)kcd == KICONV_TBLID_720) ?
 826             (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
 827             (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[(ulong_t)kcd];
 828 
 829         while (ib < ibtail) {
 830                 /*
 831                  * If this is a 7-bit ASCII character, we just copy over and
 832                  * that's all we need to do for this character.
 833                  */
 834                 if (*ib < 0x80) {
 835                         if (ob >= obtail) {
 836                                 *errno = E2BIG;
 837                                 ret_val = (size_t)-1;
 838                                 break;
 839                         }
 840 
 841                         *ob++ = *ib++;
 842                         continue;
 843                 }
 844 
 845                 /*
 846                  * Otherwise, we get the corresponding UTF-8 character bytes
 847                  * from the mapping table and copy them over.
 848                  *
 849                  * We don't need to worry about if the UTF-8 character bytes
 850                  * at the mapping tables are valid or not since they are good.
 851                  */
 852                 k = *ib - 0x80;
 853                 sz = u8_number_of_bytes[tbl[k].u8[0]];
 854 
 855                 /*
 856                  * If (sz <= 0), that means the character in the input buffer
 857                  * is an illegal character possibly unassigned or non-character
 858                  * at the fromcode single byte codeset.
 859                  */
 860                 if (sz <= 0) {
 861                         *errno = EILSEQ;
 862                         ret_val = (size_t)-1;
 863                         break;
 864                 }
 865 
 866                 if ((obtail - ob) < sz) {
 867                         *errno = E2BIG;
 868                         ret_val = (size_t)-1;
 869                         break;
 870                 }
 871 
 872                 for (i = 0; i < sz; i++)
 873                         *ob++ = tbl[k].u8[i];
 874 
 875                 ib++;
 876         }
 877 
 878         *inbuf = (char *)ib;
 879         *inbytesleft = ibtail - ib;
 880         *outbuf = (char *)ob;
 881         *outbytesleft = obtail - ob;
 882 
 883         return (ret_val);
 884 }
 885 
 886 /*
 887  * The following is the common kiconvstr function for the conversions from
 888  * UTF-8 to single byte codeset.
 889  */
 890 static size_t
 891 kiconvstr_to_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
 892         size_t *outlen, int flag, int *errno)
 893 {
 894         kiconv_to_sb_tbl_comp_t *tbl;
 895         size_t ret_val;
 896         uchar_t *oldib;
 897         uchar_t *ibtail;
 898         uchar_t *obtail;
 899         uint32_t u8;
 900         size_t i;
 901         size_t l;
 902         size_t h;
 903         size_t init_h;
 904         int8_t sz;
 905         boolean_t second;
 906         boolean_t do_not_ignore_null;
 907 
 908         /* Let's double check on the table id. */
 909         if (id > KICONV_MAX_MAPPING_TBLID &&
 910             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
 911                 *errno = EBADF;
 912                 return ((size_t)-1);
 913         }
 914 
 915         ret_val = 0;
 916         ibtail = ib + *inlen;
 917         obtail = ob + *outlen;
 918         do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
 919 
 920         if (id == KICONV_TBLID_720) {
 921                 tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
 922                 init_h = sizeof (u8_to_cp720_tbl);
 923         } else {
 924                 tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
 925                 init_h = sizeof (to_sb_tbl[id]);
 926         }
 927         init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
 928 
 929         /* Skip any UTF-8 signature BOM character in the beginning. */
 930         if ((ibtail - ib) >= 3 && *ib == 0xef && *(ib + 1) == 0xbb &&
 931             *(ib + 2) == 0xbf)
 932                         ib += 3;
 933 
 934         /*
 935          * Basically this is pretty much the same as kiconv_to_sb() except
 936          * that we are now accepting two flag values and doing the processing
 937          * accordingly.
 938          */
 939         while (ib < ibtail) {
 940                 sz = u8_number_of_bytes[*ib];
 941                 if (sz <= 0) {
 942                         if (flag & KICONV_REPLACE_INVALID) {
 943                                 if (ob >= obtail) {
 944                                         *errno = E2BIG;
 945                                         ret_val = (size_t)-1;
 946                                         break;
 947                                 }
 948 
 949                                 ib++;
 950                                 goto STR_TO_SB_REPLACE_INVALID;
 951                         }
 952 
 953                         *errno = EILSEQ;
 954                         ret_val = (size_t)-1;
 955                         break;
 956                 }
 957 
 958                 if (*ib == '\0' && do_not_ignore_null)
 959                         break;
 960 
 961                 if (ob >= obtail) {
 962                         *errno = E2BIG;
 963                         ret_val = (size_t)-1;
 964                         break;
 965                 }
 966 
 967                 if (sz == 1) {
 968                         *ob++ = *ib++;
 969                         continue;
 970                 }
 971 
 972                 if ((ibtail - ib) < sz) {
 973                         if (flag & KICONV_REPLACE_INVALID) {
 974                                 ib = ibtail;
 975                                 goto STR_TO_SB_REPLACE_INVALID;
 976                         }
 977 
 978                         *errno = EINVAL;
 979                         ret_val = (size_t)-1;
 980                         break;
 981                 }
 982 
 983                 oldib = ib;
 984                 u8 = *ib++;
 985                 second = B_TRUE;
 986                 for (i = 1; i < sz; i++) {
 987                         if (second) {
 988                                 if (*ib < u8_valid_min_2nd_byte[u8] ||
 989                                     *ib > u8_valid_max_2nd_byte[u8]) {
 990                                         if (flag & KICONV_REPLACE_INVALID) {
 991                                                 ib = oldib + sz;
 992                                                 goto STR_TO_SB_REPLACE_INVALID;
 993                                         }
 994 
 995                                         *errno = EILSEQ;
 996                                         ret_val = (size_t)-1;
 997                                         ib = oldib;
 998                                         goto STR_TO_SB_ILLEGAL_CHAR_ERR;
 999                                 }
1000                                 second = B_FALSE;
1001                         } else if (*ib < 0x80 || *ib > 0xbf) {
1002                                 if (flag & KICONV_REPLACE_INVALID) {
1003                                         ib = oldib + sz;
1004                                         goto STR_TO_SB_REPLACE_INVALID;
1005                                 }
1006 
1007                                 *errno = EILSEQ;
1008                                 ret_val = (size_t)-1;
1009                                 ib = oldib;
1010                                 goto STR_TO_SB_ILLEGAL_CHAR_ERR;
1011                         }
1012                         u8 = (u8 << 8) | ((uint32_t)*ib);
1013                         ib++;
1014                 }
1015 
1016                 i = l = 0;
1017                 h = init_h;
1018                 while (l <= h) {
1019                         i = (l + h) / 2;
1020                         if (tbl[i].u8 == u8)
1021                                 break;
1022                         else if (tbl[i].u8 < u8)
1023                                 l = i + 1;
1024                         else
1025                                 h = i - 1;
1026                 }
1027 
1028                 if (tbl[i].u8 == u8) {
1029                         *ob++ = tbl[i].sb;
1030                 } else {
1031 STR_TO_SB_REPLACE_INVALID:
1032                         *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
1033                         ret_val++;
1034                 }
1035         }
1036 
1037 STR_TO_SB_ILLEGAL_CHAR_ERR:
1038         *inlen = ibtail - ib;
1039         *outlen = obtail - ob;
1040 
1041         return (ret_val);
1042 }
1043 
1044 /*
1045  * The following 25 functions are the real entry points that will be
1046  * given to the kiconv framework at the genunix.
1047  */
1048 static size_t
1049 kiconvstr_to_720(char *inarray, size_t *inlen, char *outarray,
1050         size_t *outlen, int flag, int *errno)
1051 {
1052         return (kiconvstr_to_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1053             inlen, (uchar_t *)outarray, outlen, flag, errno));
1054 }
1055 
1056 static size_t
1057 kiconvstr_to_737(char *inarray, size_t *inlen, char *outarray,
1058         size_t *outlen, int flag, int *errno)
1059 {
1060         return (kiconvstr_to_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1061             inlen, (uchar_t *)outarray, outlen, flag, errno));
1062 }
1063 
1064 static size_t
1065 kiconvstr_to_852(char *inarray, size_t *inlen, char *outarray,
1066         size_t *outlen, int flag, int *errno)
1067 {
1068         return (kiconvstr_to_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1069             inlen, (uchar_t *)outarray, outlen, flag, errno));
1070 }
1071 
1072 static size_t
1073 kiconvstr_to_857(char *inarray, size_t *inlen, char *outarray,
1074         size_t *outlen, int flag, int *errno)
1075 {
1076         return (kiconvstr_to_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1077             inlen, (uchar_t *)outarray, outlen, flag, errno));
1078 }
1079 
1080 static size_t
1081 kiconvstr_to_862(char *inarray, size_t *inlen, char *outarray,
1082         size_t *outlen, int flag, int *errno)
1083 {
1084         return (kiconvstr_to_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1085             inlen, (uchar_t *)outarray, outlen, flag, errno));
1086 }
1087 
1088 static size_t
1089 kiconvstr_to_866(char *inarray, size_t *inlen, char *outarray,
1090         size_t *outlen, int flag, int *errno)
1091 {
1092         return (kiconvstr_to_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1093             inlen, (uchar_t *)outarray, outlen, flag, errno));
1094 }
1095 
1096 static size_t
1097 kiconvstr_to_1250(char *inarray, size_t *inlen, char *outarray,
1098         size_t *outlen, int flag, int *errno)
1099 {
1100         return (kiconvstr_to_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1101             inlen, (uchar_t *)outarray, outlen, flag, errno));
1102 }
1103 
1104 static size_t
1105 kiconvstr_to_1251(char *inarray, size_t *inlen, char *outarray,
1106         size_t *outlen, int flag, int *errno)
1107 {
1108         return (kiconvstr_to_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1109             inlen, (uchar_t *)outarray, outlen, flag, errno));
1110 }
1111 
1112 static size_t
1113 kiconvstr_to_1253(char *inarray, size_t *inlen, char *outarray,
1114         size_t *outlen, int flag, int *errno)
1115 {
1116         return (kiconvstr_to_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1117             inlen, (uchar_t *)outarray, outlen, flag, errno));
1118 }
1119 
1120 static size_t
1121 kiconvstr_to_1254(char *inarray, size_t *inlen, char *outarray,
1122         size_t *outlen, int flag, int *errno)
1123 {
1124         return (kiconvstr_to_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1125             inlen, (uchar_t *)outarray, outlen, flag, errno));
1126 }
1127 
1128 static size_t
1129 kiconvstr_to_1255(char *inarray, size_t *inlen, char *outarray,
1130         size_t *outlen, int flag, int *errno)
1131 {
1132         return (kiconvstr_to_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1133             inlen, (uchar_t *)outarray, outlen, flag, errno));
1134 }
1135 
1136 static size_t
1137 kiconvstr_to_1256(char *inarray, size_t *inlen, char *outarray,
1138         size_t *outlen, int flag, int *errno)
1139 {
1140         return (kiconvstr_to_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1141             inlen, (uchar_t *)outarray, outlen, flag, errno));
1142 }
1143 
1144 static size_t
1145 kiconvstr_to_1257(char *inarray, size_t *inlen, char *outarray,
1146         size_t *outlen, int flag, int *errno)
1147 {
1148         return (kiconvstr_to_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1149             inlen, (uchar_t *)outarray, outlen, flag, errno));
1150 }
1151 
1152 static size_t
1153 kiconvstr_to_88592(char *inarray, size_t *inlen, char *outarray,
1154         size_t *outlen, int flag, int *errno)
1155 {
1156         return (kiconvstr_to_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1157             inlen, (uchar_t *)outarray, outlen, flag, errno));
1158 }
1159 
1160 static size_t
1161 kiconvstr_to_88593(char *inarray, size_t *inlen, char *outarray,
1162         size_t *outlen, int flag, int *errno)
1163 {
1164         return (kiconvstr_to_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1165             inlen, (uchar_t *)outarray, outlen, flag, errno));
1166 }
1167 
1168 static size_t
1169 kiconvstr_to_88594(char *inarray, size_t *inlen, char *outarray,
1170         size_t *outlen, int flag, int *errno)
1171 {
1172         return (kiconvstr_to_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1173             inlen, (uchar_t *)outarray, outlen, flag, errno));
1174 }
1175 
1176 static size_t
1177 kiconvstr_to_88595(char *inarray, size_t *inlen, char *outarray,
1178         size_t *outlen, int flag, int *errno)
1179 {
1180         return (kiconvstr_to_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1181             inlen, (uchar_t *)outarray, outlen, flag, errno));
1182 }
1183 
1184 static size_t
1185 kiconvstr_to_88596(char *inarray, size_t *inlen, char *outarray,
1186         size_t *outlen, int flag, int *errno)
1187 {
1188         return (kiconvstr_to_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1189             inlen, (uchar_t *)outarray, outlen, flag, errno));
1190 }
1191 
1192 static size_t
1193 kiconvstr_to_88597(char *inarray, size_t *inlen, char *outarray,
1194         size_t *outlen, int flag, int *errno)
1195 {
1196         return (kiconvstr_to_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1197             inlen, (uchar_t *)outarray, outlen, flag, errno));
1198 }
1199 
1200 static size_t
1201 kiconvstr_to_88598(char *inarray, size_t *inlen, char *outarray,
1202         size_t *outlen, int flag, int *errno)
1203 {
1204         return (kiconvstr_to_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1205             inlen, (uchar_t *)outarray, outlen, flag, errno));
1206 }
1207 
1208 static size_t
1209 kiconvstr_to_88599(char *inarray, size_t *inlen, char *outarray,
1210         size_t *outlen, int flag, int *errno)
1211 {
1212         return (kiconvstr_to_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1213             inlen, (uchar_t *)outarray, outlen, flag, errno));
1214 }
1215 
1216 static size_t
1217 kiconvstr_to_885910(char *inarray, size_t *inlen, char *outarray,
1218         size_t *outlen, int flag, int *errno)
1219 {
1220         return (kiconvstr_to_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1221             inlen, (uchar_t *)outarray, outlen, flag, errno));
1222 }
1223 
1224 static size_t
1225 kiconvstr_to_885911(char *inarray, size_t *inlen, char *outarray,
1226         size_t *outlen, int flag, int *errno)
1227 {
1228         return (kiconvstr_to_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1229             inlen, (uchar_t *)outarray, outlen, flag, errno));
1230 }
1231 
1232 static size_t
1233 kiconvstr_to_885913(char *inarray, size_t *inlen, char *outarray,
1234         size_t *outlen, int flag, int *errno)
1235 {
1236         return (kiconvstr_to_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1237             inlen, (uchar_t *)outarray, outlen, flag, errno));
1238 }
1239 
1240 static size_t
1241 kiconvstr_to_koi8r(char *inarray, size_t *inlen, char *outarray,
1242         size_t *outlen, int flag, int *errno)
1243 {
1244         return (kiconvstr_to_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1245             inlen, (uchar_t *)outarray, outlen, flag, errno));
1246 }
1247 
1248 /*
1249  * The following is the common kiconvstr function for the conversions from
1250  * single byte codeset to UTF-8.
1251  */
1252 static size_t
1253 kiconvstr_fr_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
1254         size_t *outlen, int flag, int *errno)
1255 {
1256         kiconv_to_utf8_tbl_comp_t *tbl;
1257         size_t ret_val;
1258         uchar_t *ibtail;
1259         uchar_t *obtail;
1260         size_t i;
1261         size_t k;
1262         int8_t sz;
1263         boolean_t do_not_ignore_null;
1264 
1265         if (id > KICONV_MAX_MAPPING_TBLID &&
1266             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
1267                 *errno = EBADF;
1268                 return ((size_t)-1);
1269         }
1270 
1271         ret_val = 0;
1272         ibtail = ib + *inlen;
1273         obtail = ob + *outlen;
1274         do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
1275 
1276         tbl = (id == KICONV_TBLID_720) ?
1277             (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
1278             (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[id];
1279 
1280         while (ib < ibtail) {
1281                 if (*ib == '\0' && do_not_ignore_null)
1282                         break;
1283 
1284                 if (*ib < 0x80) {
1285                         if (ob >= obtail) {
1286                                 *errno = E2BIG;
1287                                 ret_val = (size_t)-1;
1288                                 break;
1289                         }
1290                         *ob++ = *ib++;
1291                         continue;
1292                 }
1293 
1294                 k = *ib - 0x80;
1295                 sz = u8_number_of_bytes[tbl[k].u8[0]];
1296 
1297                 if (sz <= 0) {
1298                         if (flag & KICONV_REPLACE_INVALID) {
1299                                 if ((obtail - ob) < 3) {
1300                                         *errno = E2BIG;
1301                                         ret_val = (size_t)-1;
1302                                         break;
1303                                 }
1304 
1305                                 /* Save KICONV_UTF8_REPLACEMENT_CHAR. */
1306                                 *ob++ = 0xef;
1307                                 *ob++ = 0xbf;
1308                                 *ob++ = 0xbd;
1309                                 ret_val++;
1310                                 ib++;
1311 
1312                                 continue;
1313                         }
1314 
1315                         *errno = EILSEQ;
1316                         ret_val = (size_t)-1;
1317                         break;
1318                 }
1319 
1320                 if ((obtail - ob) < sz) {
1321                         *errno = E2BIG;
1322                         ret_val = (size_t)-1;
1323                         break;
1324                 }
1325 
1326                 for (i = 0; i < sz; i++)
1327                         *ob++ = tbl[k].u8[i];
1328 
1329                 ib++;
1330         }
1331 
1332         *inlen = ibtail - ib;
1333         *outlen = obtail - ob;
1334 
1335         return (ret_val);
1336 }
1337 
1338 /*
1339  * The following 25 functions are the real entry points that will be
1340  * given to kiconv framework at the genunix.
1341  */
1342 static size_t
1343 kiconvstr_fr_720(char *inarray, size_t *inlen, char *outarray,
1344         size_t *outlen, int flag, int *errno)
1345 {
1346         return (kiconvstr_fr_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1347             inlen, (uchar_t *)outarray, outlen, flag, errno));
1348 }
1349 
1350 static size_t
1351 kiconvstr_fr_737(char *inarray, size_t *inlen, char *outarray,
1352         size_t *outlen, int flag, int *errno)
1353 {
1354         return (kiconvstr_fr_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1355             inlen, (uchar_t *)outarray, outlen, flag, errno));
1356 }
1357 
1358 static size_t
1359 kiconvstr_fr_852(char *inarray, size_t *inlen, char *outarray,
1360         size_t *outlen, int flag, int *errno)
1361 {
1362         return (kiconvstr_fr_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1363             inlen, (uchar_t *)outarray, outlen, flag, errno));
1364 }
1365 
1366 static size_t
1367 kiconvstr_fr_857(char *inarray, size_t *inlen, char *outarray,
1368         size_t *outlen, int flag, int *errno)
1369 {
1370         return (kiconvstr_fr_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1371             inlen, (uchar_t *)outarray, outlen, flag, errno));
1372 }
1373 
1374 static size_t
1375 kiconvstr_fr_862(char *inarray, size_t *inlen, char *outarray,
1376         size_t *outlen, int flag, int *errno)
1377 {
1378         return (kiconvstr_fr_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1379             inlen, (uchar_t *)outarray, outlen, flag, errno));
1380 }
1381 
1382 static size_t
1383 kiconvstr_fr_866(char *inarray, size_t *inlen, char *outarray,
1384         size_t *outlen, int flag, int *errno)
1385 {
1386         return (kiconvstr_fr_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1387             inlen, (uchar_t *)outarray, outlen, flag, errno));
1388 }
1389 
1390 static size_t
1391 kiconvstr_fr_1250(char *inarray, size_t *inlen, char *outarray,
1392         size_t *outlen, int flag, int *errno)
1393 {
1394         return (kiconvstr_fr_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1395             inlen, (uchar_t *)outarray, outlen, flag, errno));
1396 }
1397 
1398 static size_t
1399 kiconvstr_fr_1251(char *inarray, size_t *inlen, char *outarray,
1400         size_t *outlen, int flag, int *errno)
1401 {
1402         return (kiconvstr_fr_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1403             inlen, (uchar_t *)outarray, outlen, flag, errno));
1404 }
1405 
1406 static size_t
1407 kiconvstr_fr_1253(char *inarray, size_t *inlen, char *outarray,
1408         size_t *outlen, int flag, int *errno)
1409 {
1410         return (kiconvstr_fr_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1411             inlen, (uchar_t *)outarray, outlen, flag, errno));
1412 }
1413 
1414 static size_t
1415 kiconvstr_fr_1254(char *inarray, size_t *inlen, char *outarray,
1416         size_t *outlen, int flag, int *errno)
1417 {
1418         return (kiconvstr_fr_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1419             inlen, (uchar_t *)outarray, outlen, flag, errno));
1420 }
1421 
1422 static size_t
1423 kiconvstr_fr_1255(char *inarray, size_t *inlen, char *outarray,
1424         size_t *outlen, int flag, int *errno)
1425 {
1426         return (kiconvstr_fr_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1427             inlen, (uchar_t *)outarray, outlen, flag, errno));
1428 }
1429 
1430 static size_t
1431 kiconvstr_fr_1256(char *inarray, size_t *inlen, char *outarray,
1432         size_t *outlen, int flag, int *errno)
1433 {
1434         return (kiconvstr_fr_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1435             inlen, (uchar_t *)outarray, outlen, flag, errno));
1436 }
1437 
1438 static size_t
1439 kiconvstr_fr_1257(char *inarray, size_t *inlen, char *outarray,
1440         size_t *outlen, int flag, int *errno)
1441 {
1442         return (kiconvstr_fr_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1443             inlen, (uchar_t *)outarray, outlen, flag, errno));
1444 }
1445 
1446 static size_t
1447 kiconvstr_fr_88592(char *inarray, size_t *inlen, char *outarray,
1448         size_t *outlen, int flag, int *errno)
1449 {
1450         return (kiconvstr_fr_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1451             inlen, (uchar_t *)outarray, outlen, flag, errno));
1452 }
1453 
1454 static size_t
1455 kiconvstr_fr_88593(char *inarray, size_t *inlen, char *outarray,
1456         size_t *outlen, int flag, int *errno)
1457 {
1458         return (kiconvstr_fr_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1459             inlen, (uchar_t *)outarray, outlen, flag, errno));
1460 }
1461 
1462 static size_t
1463 kiconvstr_fr_88594(char *inarray, size_t *inlen, char *outarray,
1464         size_t *outlen, int flag, int *errno)
1465 {
1466         return (kiconvstr_fr_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1467             inlen, (uchar_t *)outarray, outlen, flag, errno));
1468 }
1469 
1470 static size_t
1471 kiconvstr_fr_88595(char *inarray, size_t *inlen, char *outarray,
1472         size_t *outlen, int flag, int *errno)
1473 {
1474         return (kiconvstr_fr_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1475             inlen, (uchar_t *)outarray, outlen, flag, errno));
1476 }
1477 
1478 static size_t
1479 kiconvstr_fr_88596(char *inarray, size_t *inlen, char *outarray,
1480         size_t *outlen, int flag, int *errno)
1481 {
1482         return (kiconvstr_fr_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1483             inlen, (uchar_t *)outarray, outlen, flag, errno));
1484 }
1485 
1486 static size_t
1487 kiconvstr_fr_88597(char *inarray, size_t *inlen, char *outarray,
1488         size_t *outlen, int flag, int *errno)
1489 {
1490         return (kiconvstr_fr_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1491             inlen, (uchar_t *)outarray, outlen, flag, errno));
1492 }
1493 
1494 static size_t
1495 kiconvstr_fr_88598(char *inarray, size_t *inlen, char *outarray,
1496         size_t *outlen, int flag, int *errno)
1497 {
1498         return (kiconvstr_fr_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1499             inlen, (uchar_t *)outarray, outlen, flag, errno));
1500 }
1501 
1502 static size_t
1503 kiconvstr_fr_88599(char *inarray, size_t *inlen, char *outarray,
1504         size_t *outlen, int flag, int *errno)
1505 {
1506         return (kiconvstr_fr_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1507             inlen, (uchar_t *)outarray, outlen, flag, errno));
1508 }
1509 
1510 static size_t
1511 kiconvstr_fr_885910(char *inarray, size_t *inlen, char *outarray,
1512         size_t *outlen, int flag, int *errno)
1513 {
1514         return (kiconvstr_fr_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1515             inlen, (uchar_t *)outarray, outlen, flag, errno));
1516 }
1517 
1518 static size_t
1519 kiconvstr_fr_885911(char *inarray, size_t *inlen, char *outarray,
1520         size_t *outlen, int flag, int *errno)
1521 {
1522         return (kiconvstr_fr_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1523             inlen, (uchar_t *)outarray, outlen, flag, errno));
1524 }
1525 
1526 static size_t
1527 kiconvstr_fr_885913(char *inarray, size_t *inlen, char *outarray,
1528         size_t *outlen, int flag, int *errno)
1529 {
1530         return (kiconvstr_fr_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1531             inlen, (uchar_t *)outarray, outlen, flag, errno));
1532 }
1533 
1534 static size_t
1535 kiconvstr_fr_koi8r(char *inarray, size_t *inlen, char *outarray,
1536         size_t *outlen, int flag, int *errno)
1537 {
1538         return (kiconvstr_fr_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1539             inlen, (uchar_t *)outarray, outlen, flag, errno));
1540 }
1541 
1542 
1543 /*
1544  * The following are the supported code conversions that will be passed to
1545  * and registered from this module. The tocode and fromcode names are
1546  * normalized.
1547  */
1548 #define KICONV_MAX_EMEA_OPS             50
1549 
1550 static kiconv_ops_t kiconv_emea_ops[KICONV_MAX_EMEA_OPS] = {
1551         {
1552                 "utf8", "cp1250",
1553                 open_fr_1250, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1250
1554         },
1555         {
1556                 "cp1250", "utf8",
1557                 open_to_1250, kiconv_to_sb, close_to_sb, kiconvstr_to_1250
1558         },
1559         {
1560                 "utf8", "iso88592",
1561                 open_fr_88592, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88592
1562         },
1563         {
1564                 "iso88592", "utf8",
1565                 open_to_88592, kiconv_to_sb, close_to_sb, kiconvstr_to_88592
1566         },
1567         {
1568                 "utf8", "cp852",
1569                 open_fr_852, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_852
1570         },
1571         {
1572                 "cp852", "utf8",
1573                 open_to_852, kiconv_to_sb, close_to_sb, kiconvstr_to_852
1574         },
1575         {
1576                 "utf8", "cp1251",
1577                 open_fr_1251, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1251
1578         },
1579         {
1580                 "cp1251", "utf8",
1581                 open_to_1251, kiconv_to_sb, close_to_sb, kiconvstr_to_1251
1582         },
1583         {
1584                 "utf8", "iso88595",
1585                 open_fr_88595, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88595
1586         },
1587         {
1588                 "iso88595", "utf8",
1589                 open_to_88595, kiconv_to_sb, close_to_sb, kiconvstr_to_88595
1590         },
1591         {
1592                 "utf8", "koi8r",
1593                 open_fr_koi8r, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_koi8r
1594         },
1595         {
1596                 "koi8r", "utf8",
1597                 open_to_koi8r, kiconv_to_sb, close_to_sb, kiconvstr_to_koi8r
1598         },
1599         {
1600                 "utf8", "cp866",
1601                 open_fr_866, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_866
1602         },
1603         {
1604                 "cp866", "utf8",
1605                 open_to_866, kiconv_to_sb, close_to_sb, kiconvstr_to_866
1606         },
1607         {
1608                 "utf8", "cp1253",
1609                 open_fr_1253, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1253
1610         },
1611         {
1612                 "cp1253", "utf8",
1613                 open_to_1253, kiconv_to_sb, close_to_sb, kiconvstr_to_1253
1614         },
1615         {
1616                 "utf8", "iso88597",
1617                 open_fr_88597, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88597
1618         },
1619         {
1620                 "iso88597", "utf8",
1621                 open_to_88597, kiconv_to_sb, close_to_sb, kiconvstr_to_88597
1622         },
1623         {
1624                 "utf8", "cp737",
1625                 open_fr_737, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_737
1626         },
1627         {
1628                 "cp737", "utf8",
1629                 open_to_737, kiconv_to_sb, close_to_sb, kiconvstr_to_737
1630         },
1631         {
1632                 "utf8", "cp1254",
1633                 open_fr_1254, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1254
1634         },
1635         {
1636                 "cp1254", "utf8",
1637                 open_to_1254, kiconv_to_sb, close_to_sb, kiconvstr_to_1254
1638         },
1639         {
1640                 "utf8", "iso88599",
1641                 open_fr_88599, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88599
1642         },
1643         {
1644                 "iso88599", "utf8",
1645                 open_to_88599, kiconv_to_sb, close_to_sb, kiconvstr_to_88599
1646         },
1647         {
1648                 "utf8", "cp857",
1649                 open_fr_857, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_857
1650         },
1651         {
1652                 "cp857", "utf8",
1653                 open_to_857, kiconv_to_sb, close_to_sb, kiconvstr_to_857
1654         },
1655         {
1656                 "utf8", "cp1256",
1657                 open_fr_1256, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1256
1658         },
1659         {
1660                 "cp1256", "utf8",
1661                 open_to_1256, kiconv_to_sb, close_to_sb, kiconvstr_to_1256
1662         },
1663         {
1664                 "utf8", "iso88596",
1665                 open_fr_88596, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88596
1666         },
1667         {
1668                 "iso88596", "utf8",
1669                 open_to_88596, kiconv_to_sb, close_to_sb, kiconvstr_to_88596
1670         },
1671         {
1672                 "utf8", "cp720",
1673                 open_fr_720, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_720
1674         },
1675         {
1676                 "cp720", "utf8",
1677                 open_to_720, kiconv_to_sb, close_to_sb, kiconvstr_to_720
1678         },
1679         {
1680                 "utf8", "cp1255",
1681                 open_fr_1255, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1255
1682         },
1683         {
1684                 "cp1255", "utf8",
1685                 open_to_1255, kiconv_to_sb, close_to_sb, kiconvstr_to_1255
1686         },
1687         {
1688                 "utf8", "iso88598",
1689                 open_fr_88598, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88598
1690         },
1691         {
1692                 "iso88598", "utf8",
1693                 open_to_88598, kiconv_to_sb, close_to_sb, kiconvstr_to_88598
1694         },
1695         {
1696                 "utf8", "cp862",
1697                 open_fr_862, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_862
1698         },
1699         {
1700                 "cp862", "utf8",
1701                 open_to_862, kiconv_to_sb, close_to_sb, kiconvstr_to_862
1702         },
1703         {
1704                 "utf8", "cp1257",
1705                 open_fr_1257, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1257
1706         },
1707         {
1708                 "cp1257", "utf8",
1709                 open_to_1257, kiconv_to_sb, close_to_sb, kiconvstr_to_1257
1710         },
1711         {
1712                 "utf8", "iso885913",
1713                 open_fr_885913, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885913
1714         },
1715         {
1716                 "iso885913", "utf8",
1717                 open_to_885913, kiconv_to_sb, close_to_sb, kiconvstr_to_885913
1718         },
1719         {
1720                 "utf8", "iso885910",
1721                 open_fr_885910, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885910
1722         },
1723         {
1724                 "iso885910", "utf8",
1725                 open_to_885910, kiconv_to_sb, close_to_sb, kiconvstr_to_885910
1726         },
1727         {
1728                 "utf8", "iso885911",
1729                 open_fr_885911, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885911
1730         },
1731         {
1732                 "iso885911", "utf8",
1733                 open_to_885911, kiconv_to_sb, close_to_sb, kiconvstr_to_885911
1734         },
1735         {
1736                 "utf8", "iso88593",
1737                 open_fr_88593, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88593
1738         },
1739         {
1740                 "iso88593", "utf8",
1741                 open_to_88593, kiconv_to_sb, close_to_sb, kiconvstr_to_88593
1742         },
1743         {
1744                 "utf8", "iso88594",
1745                 open_fr_88594, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88594
1746         },
1747         {
1748                 "iso88594", "utf8",
1749                 open_to_88594, kiconv_to_sb, close_to_sb, kiconvstr_to_88594
1750         },
1751 };
1752 
1753 static kiconv_module_info_t kiconv_emea_modinfo = {
1754         "kiconv_emea",          /* Must be the same as in kiconv framework. */
1755         KICONV_MAX_EMEA_OPS,    /* size_t kiconv_num_convs */
1756         kiconv_emea_ops,        /* kiconv_ops_t *kiconv_ops_tbl */
1757         0,                      /* size_t kiconv_num_aliases */
1758         NULL,                   /* char **aliases */
1759         NULL,                   /* char **canonicals */
1760         0                       /* int nowait */
1761 };
1762 
1763 static struct modlkiconv kiconv_emea = {
1764         &mod_kiconvops,
1765         "kiconv module for EMEA",
1766         &kiconv_emea_modinfo
1767 };
1768 
1769 static struct modlinkage linkage = {
1770         MODREV_1,
1771         { (void *)&kiconv_emea, NULL }
1772 };
1773 
1774 int
1775 _init()
1776 {
1777         int err;
1778 
1779         err = mod_install(&linkage);
1780         if (err)
1781                 cmn_err(CE_WARN, "kiconv_emea: failed to load kernel module");
1782 
1783         return (err);
1784 }
1785 
1786 int
1787 _info(struct modinfo *modinfop)
1788 {
1789         return (mod_info(&linkage, modinfop));
1790 }
1791 
1792 int
1793 _fini()
1794 {
1795         int err;
1796 
1797         /*
1798          * If this module is being used, then, we cannot remove the module.
1799          * The following checking will catch pretty much all usual cases.
1800          *
1801          * Any remaining will be catached by the kiconv_unregister_module()
1802          * during mod_remove() at below.
1803          */
1804         if (kiconv_module_ref_count(KICONV_MODULE_ID_EMEA))
1805                 return (EBUSY);
1806 
1807         err = mod_remove(&linkage);
1808         if (err)
1809                 cmn_err(CE_WARN, "kiconv_emea: failed to remove kernel module");
1810 
1811         return (err);
1812 }