14297a3b0SGarrett D'Amore /* 2*2d08521bSGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org> 34297a3b0SGarrett D'Amore * Copyright (c) 2002-2004 Tim J. Robbins. 44297a3b0SGarrett D'Amore * All rights reserved. 54297a3b0SGarrett D'Amore * 64297a3b0SGarrett D'Amore * Redistribution and use in source and binary forms, with or without 74297a3b0SGarrett D'Amore * modification, are permitted provided that the following conditions 84297a3b0SGarrett D'Amore * are met: 94297a3b0SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright 104297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer. 114297a3b0SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright 124297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer in the 134297a3b0SGarrett D'Amore * documentation and/or other materials provided with the distribution. 144297a3b0SGarrett D'Amore * 154297a3b0SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 164297a3b0SGarrett D'Amore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 174297a3b0SGarrett D'Amore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 184297a3b0SGarrett D'Amore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 194297a3b0SGarrett D'Amore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 204297a3b0SGarrett D'Amore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 214297a3b0SGarrett D'Amore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 224297a3b0SGarrett D'Amore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 234297a3b0SGarrett D'Amore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 244297a3b0SGarrett D'Amore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 254297a3b0SGarrett D'Amore * SUCH DAMAGE. 264297a3b0SGarrett D'Amore */ 274297a3b0SGarrett D'Amore 284297a3b0SGarrett D'Amore /* 294297a3b0SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 304297a3b0SGarrett D'Amore * Use is subject to license terms. 314297a3b0SGarrett D'Amore */ 324297a3b0SGarrett D'Amore 334297a3b0SGarrett D'Amore #include "lint.h" 344297a3b0SGarrett D'Amore #include "file64.h" 354297a3b0SGarrett D'Amore #include "mtlib.h" 364297a3b0SGarrett D'Amore #include "mse_int.h" 374297a3b0SGarrett D'Amore #include <errno.h> 384297a3b0SGarrett D'Amore #include <limits.h> 394297a3b0SGarrett D'Amore #include <stdio.h> 404297a3b0SGarrett D'Amore #include <stdlib.h> 414297a3b0SGarrett D'Amore #include <wchar.h> 424297a3b0SGarrett D'Amore #include <synch.h> 434297a3b0SGarrett D'Amore #include "mblocal.h" 444297a3b0SGarrett D'Amore #include "stdiom.h" 454297a3b0SGarrett D'Amore #include "mse.h" 464297a3b0SGarrett D'Amore 474297a3b0SGarrett D'Amore #pragma weak _putwc = putwc 484297a3b0SGarrett D'Amore 494297a3b0SGarrett D'Amore /* 504297a3b0SGarrett D'Amore * FreeBSD had both a MT safe and non-MT safe version. For whatever reason, 514297a3b0SGarrett D'Amore * we don't need the non-MT safe version. We do this because its faster, 524297a3b0SGarrett D'Amore * since we don't have to lock the file while doing the potentially expensive 534297a3b0SGarrett D'Amore * conversion from wide to mb. 544297a3b0SGarrett D'Amore * 554297a3b0SGarrett D'Amore * Solaris also has XPG5 and legacy semantics. The new standard requires 564297a3b0SGarrett D'Amore * that the stream orientation change, but legacy calls don't do that. 574297a3b0SGarrett D'Amore * 584297a3b0SGarrett D'Amore * Note that we had the source for the XPG5 version of this, but it relied 594297a3b0SGarrett D'Amore * on closed implementation bits that we lack, so we supply replacements 604297a3b0SGarrett D'Amore * here. 614297a3b0SGarrett D'Amore */ 624297a3b0SGarrett D'Amore static wint_t 634297a3b0SGarrett D'Amore __fputwc_impl(wchar_t wc, FILE *fp, int orient) 644297a3b0SGarrett D'Amore { 654297a3b0SGarrett D'Amore char buf[MB_LEN_MAX]; 664297a3b0SGarrett D'Amore size_t i, len; 674297a3b0SGarrett D'Amore rmutex_t *mx; 684297a3b0SGarrett D'Amore 694297a3b0SGarrett D'Amore /* If we are given WEOF, then we have to stop */ 704297a3b0SGarrett D'Amore if (wc == WEOF) 714297a3b0SGarrett D'Amore return (WEOF); 724297a3b0SGarrett D'Amore 734297a3b0SGarrett D'Amore if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { 744297a3b0SGarrett D'Amore /* 754297a3b0SGarrett D'Amore * Assume single-byte locale with no special encoding. 764297a3b0SGarrett D'Amore */ 774297a3b0SGarrett D'Amore *buf = (unsigned char)wc; 784297a3b0SGarrett D'Amore len = 1; 794297a3b0SGarrett D'Amore } else { 804297a3b0SGarrett D'Amore /* 814297a3b0SGarrett D'Amore * FreeBSD used restartable wcrtomb. I think we can use 824297a3b0SGarrett D'Amore * the simpler wctomb form here. We should have a complete 834297a3b0SGarrett D'Amore * decode. 844297a3b0SGarrett D'Amore */ 854297a3b0SGarrett D'Amore if ((len = wctomb(buf, wc)) == (size_t)-1) { 864297a3b0SGarrett D'Amore fp->_flag |= _IOERR; 874297a3b0SGarrett D'Amore errno = EILSEQ; 884297a3b0SGarrett D'Amore return (WEOF); 894297a3b0SGarrett D'Amore } 904297a3b0SGarrett D'Amore } 914297a3b0SGarrett D'Amore 924297a3b0SGarrett D'Amore FLOCKFILE(mx, fp); 934297a3b0SGarrett D'Amore /* 944297a3b0SGarrett D'Amore * This is used for XPG 5 semantics, which requires the stream 954297a3b0SGarrett D'Amore * orientation to be changed when the function is called. 964297a3b0SGarrett D'Amore */ 974297a3b0SGarrett D'Amore if (orient && GET_NO_MODE(fp)) { 984297a3b0SGarrett D'Amore _setorientation(fp, _WC_MODE); 994297a3b0SGarrett D'Amore } 1004297a3b0SGarrett D'Amore for (i = 0; i < len; i++) { 1014297a3b0SGarrett D'Amore if (PUTC((unsigned char)buf[i], fp) == EOF) { 1024297a3b0SGarrett D'Amore FUNLOCKFILE(mx); 1034297a3b0SGarrett D'Amore return (WEOF); 1044297a3b0SGarrett D'Amore } 1054297a3b0SGarrett D'Amore } 1064297a3b0SGarrett D'Amore FUNLOCKFILE(mx); 1074297a3b0SGarrett D'Amore return ((wint_t)wc); 1084297a3b0SGarrett D'Amore } 1094297a3b0SGarrett D'Amore 1104297a3b0SGarrett D'Amore wint_t 1114297a3b0SGarrett D'Amore fputwc(wchar_t wc, FILE *fp) 1124297a3b0SGarrett D'Amore { 1134297a3b0SGarrett D'Amore return (__fputwc_impl(wc, fp, 0)); 1144297a3b0SGarrett D'Amore } 1154297a3b0SGarrett D'Amore 1164297a3b0SGarrett D'Amore /* 1174297a3b0SGarrett D'Amore * Trivial functional form of the typical macro. 1184297a3b0SGarrett D'Amore */ 1194297a3b0SGarrett D'Amore #undef __putwc 1204297a3b0SGarrett D'Amore wint_t 1214297a3b0SGarrett D'Amore putwc(wchar_t wc, FILE *fp) 1224297a3b0SGarrett D'Amore { 1234297a3b0SGarrett D'Amore return (__fputwc_impl(wc, fp, 0)); 1244297a3b0SGarrett D'Amore } 1254297a3b0SGarrett D'Amore 1264297a3b0SGarrett D'Amore wint_t 1274297a3b0SGarrett D'Amore __fputwc_xpg5(wint_t wc, FILE *fp) 1284297a3b0SGarrett D'Amore { 1294297a3b0SGarrett D'Amore return (__fputwc_impl(wc, fp, 1)); 1304297a3b0SGarrett D'Amore } 1314297a3b0SGarrett D'Amore 1324297a3b0SGarrett D'Amore #undef __putwc_xpg5 1334297a3b0SGarrett D'Amore wint_t 1344297a3b0SGarrett D'Amore __putwc_xpg5(wint_t wc, FILE *fp) 1354297a3b0SGarrett D'Amore { 1364297a3b0SGarrett D'Amore return (__fputwc_impl(wc, fp, 1)); 1374297a3b0SGarrett D'Amore } 138