1 /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <stdarg.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <wchar.h>
23 #include <libioP.h>
24 
25 static int
locked_vfxprintf(FILE * fp,const char * fmt,va_list ap,unsigned int mode_flags)26 locked_vfxprintf (FILE *fp, const char *fmt, va_list ap,
27 		  unsigned int mode_flags)
28 {
29   if (_IO_fwide (fp, 0) <= 0)
30     return __vfprintf_internal (fp, fmt, ap, mode_flags);
31 
32   /* We must convert the narrow format string to a wide one.
33      Each byte can produce at most one wide character.  */
34   wchar_t *wfmt;
35   mbstate_t mbstate;
36   int res;
37   int used_malloc = 0;
38   size_t len = strlen (fmt) + 1;
39 
40   if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t)))
41     {
42       __set_errno (EOVERFLOW);
43       return -1;
44     }
45   if (__libc_use_alloca (len * sizeof (wchar_t)))
46     wfmt = alloca (len * sizeof (wchar_t));
47   else if ((wfmt = malloc (len * sizeof (wchar_t))) == NULL)
48     return -1;
49   else
50     used_malloc = 1;
51 
52   memset (&mbstate, 0, sizeof mbstate);
53   res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
54 
55   if (res != -1)
56     res = __vfwprintf_internal (fp, wfmt, ap, mode_flags);
57 
58   if (used_malloc)
59     free (wfmt);
60 
61   return res;
62 }
63 
64 int
__vfxprintf(FILE * fp,const char * fmt,va_list ap,unsigned int mode_flags)65 __vfxprintf (FILE *fp, const char *fmt, va_list ap,
66 	     unsigned int mode_flags)
67 {
68   if (fp == NULL)
69     fp = stderr;
70   _IO_flockfile (fp);
71   int res = locked_vfxprintf (fp, fmt, ap, mode_flags);
72   _IO_funlockfile (fp);
73   return res;
74 }
75 
76 int
__fxprintf(FILE * fp,const char * fmt,...)77 __fxprintf (FILE *fp, const char *fmt, ...)
78 {
79   va_list ap;
80   va_start (ap, fmt);
81   int res = __vfxprintf (fp, fmt, ap, 0);
82   va_end (ap);
83   return res;
84 }
85 
86 int
__fxprintf_nocancel(FILE * fp,const char * fmt,...)87 __fxprintf_nocancel (FILE *fp, const char *fmt, ...)
88 {
89   if (fp == NULL)
90     fp = stderr;
91 
92   va_list ap;
93   va_start (ap, fmt);
94   _IO_flockfile (fp);
95   int save_flags2 = fp->_flags2;
96   fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
97 
98   int res = locked_vfxprintf (fp, fmt, ap, 0);
99 
100   fp->_flags2 = save_flags2;
101   _IO_funlockfile (fp);
102   va_end (ap);
103   return res;
104 }
105