1 /**
2  * @file
3  *
4  * @section DESCRIPTION
5  *
6  * These functions provide a portable implementation of the common (but not
7  * yet universal) asprintf & vasprintf routines to allocate a buffer big
8  * enough to sprintf the arguments to.  The XNF variants terminate the server
9  * if the allocation fails.
10  */
11 /*
12  * Copyright (c) 2004 Alexander Gottwald
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in
22  * all copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
28  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  * DEALINGS IN THE SOFTWARE.
31  *
32  * Except as contained in this notice, the name(s) of the above copyright
33  * holders shall not be used in advertising or otherwise to promote the sale,
34  * use or other dealings in this Software without prior written authorization.
35  */
36 /*
37  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
38  *
39  * Permission is hereby granted, free of charge, to any person obtaining a
40  * copy of this software and associated documentation files (the "Software"),
41  * to deal in the Software without restriction, including without limitation
42  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
43  * and/or sell copies of the Software, and to permit persons to whom the
44  * Software is furnished to do so, subject to the following conditions:
45  *
46  * The above copyright notice and this permission notice (including the next
47  * paragraph) shall be included in all copies or substantial portions of the
48  * Software.
49  *
50  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
53  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
55  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56  * DEALINGS IN THE SOFTWARE.
57  */
58 
59 #ifdef HAVE_DIX_CONFIG_H
60 #include <dix-config.h>
61 #endif
62 
63 #include <X11/Xos.h>
64 #include "os.h"
65 #include <stdarg.h>
66 #include <stdio.h>
67 #include <errno.h>
68 #include <string.h>
69 
70 #ifdef asprintf
71 #undef asprintf
72 #endif
73 #ifdef vasprintf
74 #undef vasprintf
75 #endif
76 
77 #ifndef va_copy
78 #ifdef __va_copy
79 #define va_copy __va_copy
80 #else
81 #error "no working va_copy was found"
82 #endif
83 #endif
84 
85 /**
86  * Varargs sprintf that allocates a string buffer the right size for
87  * the pattern & data provided and prints the requested data to it.
88  *
89  * @param ret     Pointer to which the newly allocated buffer is written
90  *                (contents undefined on error)
91  * @param format  printf style format string
92  * @param va      variable argument list
93  * @return        size of allocated buffer, or -1 on error.
94  */
95 int
Xvasprintf(char ** ret,const char * _X_RESTRICT_KYWD format,va_list va)96 Xvasprintf(char **ret, const char *_X_RESTRICT_KYWD format, va_list va)
97 {
98 #ifdef HAVE_VASPRINTF
99     return vasprintf(ret, format, va);
100 #else
101     int size;
102     va_list va2;
103 
104     va_copy(va2, va);
105     size = vsnprintf(NULL, 0, format, va2);
106     va_end(va2);
107 
108     *ret = malloc(size + 1);
109     if (*ret == NULL)
110         return -1;
111 
112     vsnprintf(*ret, size + 1, format, va);
113     (*ret)[size] = 0;
114     return size;
115 #endif
116 }
117 
118 #ifndef HAVE_VASPRINTF
119 #define vasprintf Xvasprintf
120 #endif
121 
122 /**
123  * sprintf that allocates a string buffer the right size for
124  * the pattern & data provided and prints the requested data to it.
125  *
126  * @param ret     Pointer to which the newly allocated buffer is written
127  *                (contents undefined on error)
128  * @param format  printf style format string
129  * @param ...     arguments for specified format
130  * @return        size of allocated buffer, or -1 on error.
131  */
132 int
Xasprintf(char ** ret,const char * _X_RESTRICT_KYWD format,...)133 Xasprintf(char **ret, const char *_X_RESTRICT_KYWD format, ...)
134 {
135     int size;
136     va_list va;
137 
138     va_start(va, format);
139     size = vasprintf(ret, format, va);
140     va_end(va);
141     return size;
142 }
143 
144 /**
145  * Varargs sprintf that allocates a string buffer the right size for
146  * the pattern & data provided and prints the requested data to it.
147  * On failure, issues a FatalError message and aborts the server.
148  *
149  * @param ret     Pointer to which the newly allocated buffer is written
150  *                (contents undefined on error)
151  * @param format  printf style format string
152  * @param va      variable argument list
153  * @return        size of allocated buffer
154  */
155 int
XNFvasprintf(char ** ret,const char * _X_RESTRICT_KYWD format,va_list va)156 XNFvasprintf(char **ret, const char *_X_RESTRICT_KYWD format, va_list va)
157 {
158     int size = vasprintf(ret, format, va);
159 
160     if ((size == -1) || (*ret == NULL)) {
161         FatalError("XNFvasprintf failed: %s", strerror(errno));
162     }
163     return size;
164 }
165 
166 /**
167  * sprintf that allocates a string buffer the right size for
168  * the pattern & data provided and prints the requested data to it.
169  * On failure, issues a FatalError message and aborts the server.
170  *
171  * @param ret     Pointer to which the newly allocated buffer is written
172  *                (contents undefined on error)
173  * @param format  printf style format string
174  * @param ...     arguments for specified format
175  * @return        size of allocated buffer
176  */
177 int
XNFasprintf(char ** ret,const char * _X_RESTRICT_KYWD format,...)178 XNFasprintf(char **ret, const char *_X_RESTRICT_KYWD format, ...)
179 {
180     int size;
181     va_list va;
182 
183     va_start(va, format);
184     size = XNFvasprintf(ret, format, va);
185     va_end(va);
186     return size;
187 }
188 
189 /**
190  * Varargs snprintf that returns the actual number of bytes (excluding final
191  * '\0') that were copied into the buffer.
192  * This is opposed to the normal sprintf() usually returns the number of bytes
193  * that would have been written.
194  *
195  * @param s       buffer to copy into
196  * @param n       size of buffer s
197  * @param format  printf style format string
198  * @param va      variable argument list
199  * @return        number of bytes actually copied, excluding final '\0'
200  */
201 int
Xvscnprintf(char * s,int n,const char * format,va_list args)202 Xvscnprintf(char *s, int n, const char *format, va_list args)
203 {
204     int x;
205     if (n == 0)
206         return 0;
207     x = vsnprintf(s, n , format, args);
208     return (x >= n) ? (n - 1) : x;
209 }
210 
211 /**
212  * snprintf that returns the actual number of bytes (excluding final '\0') that
213  * were copied into the buffer.
214  * This is opposed to the normal sprintf() usually returns the number of bytes
215  * that would have been written.
216  *
217  * @param s       buffer to copy into
218  * @param n       size of buffer s
219  * @param format  printf style format string
220  * @param ...     arguments for specified format
221  * @return        number of bytes actually copied, excluding final '\0'
222  */
Xscnprintf(char * s,int n,const char * format,...)223 int Xscnprintf(char *s, int n, const char *format, ...)
224 {
225     int x;
226     va_list ap;
227     va_start(ap, format);
228     x = Xvscnprintf(s, n, format, ap);
229     va_end(ap);
230     return x;
231 }
232 
233 /* Old api, now deprecated, may be removed in the future */
234 char *
Xvprintf(const char * format,va_list va)235 Xvprintf(const char *format, va_list va)
236 {
237     char *ret;
238 
239     if (vasprintf(&ret, format, va) == -1)
240         ret = NULL;
241 
242     return ret;
243 }
244 
245 char *
Xprintf(const char * format,...)246 Xprintf(const char *format, ...)
247 {
248     char *ret;
249     va_list va;
250 
251     va_start(va, format);
252     if (vasprintf(&ret, format, va) == -1)
253         ret = NULL;
254     va_end(va);
255     return ret;
256 }
257 
258 char *
XNFvprintf(const char * format,va_list va)259 XNFvprintf(const char *format, va_list va)
260 {
261     char *ret;
262 
263     XNFvasprintf(&ret, format, va);
264 
265     return ret;
266 }
267 
268 char *
XNFprintf(const char * format,...)269 XNFprintf(const char *format, ...)
270 {
271     char *ret;
272     va_list va;
273 
274     va_start(va, format);
275     XNFvasprintf(&ret, format, va);
276     va_end(va);
277     return ret;
278 }
279