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 */
95int
96Xvasprintf(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 */
132int
133Xasprintf(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 */
155int
156XNFvasprintf(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 */
177int
178XNFasprintf(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 */
201int
202Xvscnprintf(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 */
223int 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 */
234char *
235Xvprintf(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
245char *
246Xprintf(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
258char *
259XNFvprintf(const char *format, va_list va)
260{
261    char *ret;
262
263    XNFvasprintf(&ret, format, va);
264
265    return ret;
266}
267
268char *
269XNFprintf(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