1 /* 2 * Copyright 2013 Garrett D'Amore <garrett@damore.org> 3 * Copyright (c) 2002-2004 Tim J. Robbins. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 30 * Use is subject to license terms. 31 */ 32 33 #include "lint.h" 34 #include "file64.h" 35 #include "mtlib.h" 36 #include "mse_int.h" 37 #include <errno.h> 38 #include <limits.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <wchar.h> 42 #include <synch.h> 43 #include "mblocal.h" 44 #include "stdiom.h" 45 #include "mse.h" 46 47 #pragma weak _putwc = putwc 48 49 /* 50 * FreeBSD had both a MT safe and non-MT safe version. For whatever reason, 51 * we don't need the non-MT safe version. We do this because its faster, 52 * since we don't have to lock the file while doing the potentially expensive 53 * conversion from wide to mb. 54 * 55 * Solaris also has XPG5 and legacy semantics. The new standard requires 56 * that the stream orientation change, but legacy calls don't do that. 57 * 58 * Note that we had the source for the XPG5 version of this, but it relied 59 * on closed implementation bits that we lack, so we supply replacements 60 * here. 61 */ 62 static wint_t 63 __fputwc_impl(wchar_t wc, FILE *fp, int orient) 64 { 65 char buf[MB_LEN_MAX]; 66 size_t i, len; 67 rmutex_t *mx; 68 69 /* If we are given WEOF, then we have to stop */ 70 if (wc == WEOF) 71 return (WEOF); 72 73 if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { 74 /* 75 * Assume single-byte locale with no special encoding. 76 */ 77 *buf = (unsigned char)wc; 78 len = 1; 79 } else { 80 /* 81 * FreeBSD used restartable wcrtomb. I think we can use 82 * the simpler wctomb form here. We should have a complete 83 * decode. 84 */ 85 if ((len = wctomb(buf, wc)) == (size_t)-1) { 86 fp->_flag |= _IOERR; 87 errno = EILSEQ; 88 return (WEOF); 89 } 90 } 91 92 FLOCKFILE(mx, fp); 93 /* 94 * This is used for XPG 5 semantics, which requires the stream 95 * orientation to be changed when the function is called. 96 */ 97 if (orient && GET_NO_MODE(fp)) { 98 _setorientation(fp, _WC_MODE); 99 } 100 for (i = 0; i < len; i++) { 101 if (PUTC((unsigned char)buf[i], fp) == EOF) { 102 FUNLOCKFILE(mx); 103 return (WEOF); 104 } 105 } 106 FUNLOCKFILE(mx); 107 return ((wint_t)wc); 108 } 109 110 wint_t 111 fputwc(wchar_t wc, FILE *fp) 112 { 113 return (__fputwc_impl(wc, fp, 0)); 114 } 115 116 /* 117 * Trivial functional form of the typical macro. 118 */ 119 #undef __putwc 120 wint_t 121 putwc(wchar_t wc, FILE *fp) 122 { 123 return (__fputwc_impl(wc, fp, 0)); 124 } 125 126 wint_t 127 __fputwc_xpg5(wint_t wc, FILE *fp) 128 { 129 return (__fputwc_impl(wc, fp, 1)); 130 } 131 132 #undef __putwc_xpg5 133 wint_t 134 __putwc_xpg5(wint_t wc, FILE *fp) 135 { 136 return (__fputwc_impl(wc, fp, 1)); 137 }