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