150276Speter/**************************************************************************** 2174993Srafan * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Thomas E. Dickey <dickey@clark.net> 1997 * 3150276Speter ****************************************************************************/ 3250276Speter 3350276Speter#include <curses.priv.h> 3450276Speter#include <ctype.h> 3550276Speter 36174993SrafanMODULE_ID("$Id: safe_sprintf.c,v 1.20 2007/04/21 22:28:06 tom Exp $") 3750276Speter 3850276Speter#if USE_SAFE_SPRINTF 3950276Speter 4076726Spetertypedef enum { 4176726Speter Flags, Width, Prec, Type, Format 4276726Speter} PRINTF; 4350276Speter 4450276Speter#define VA_INTGR(type) ival = va_arg(ap, type) 4550276Speter#define VA_FLOAT(type) fval = va_arg(ap, type) 4650276Speter#define VA_POINT(type) pval = (void *)va_arg(ap, type) 4750276Speter 4850276Speter/* 4950276Speter * Scan a variable-argument list for printf to determine the number of 5050276Speter * characters that would be emitted. 5150276Speter */ 5250276Speterstatic int 5350276Speter_nc_printf_length(const char *fmt, va_list ap) 5450276Speter{ 5576726Speter size_t length = BUFSIZ; 5676726Speter char *buffer; 5776726Speter char *format; 5876726Speter int len = 0; 59166124Srafan size_t fmt_len; 60166124Srafan char fmt_arg[BUFSIZ]; 6150276Speter 6276726Speter if (fmt == 0 || *fmt == '\0') 63166124Srafan return 0; 64166124Srafan fmt_len = strlen(fmt) + 1; 65166124Srafan if ((format = typeMalloc(char, fmt_len)) == 0) 6676726Speter return -1; 6776726Speter if ((buffer = typeMalloc(char, length)) == 0) { 6876726Speter free(format); 6976726Speter return -1; 7076726Speter } 7150276Speter 7276726Speter while (*fmt != '\0') { 7376726Speter if (*fmt == '%') { 7476726Speter static char dummy[] = ""; 7576726Speter PRINTF state = Flags; 7676726Speter char *pval = dummy; /* avoid const-cast */ 7776726Speter double fval = 0.0; 7876726Speter int done = FALSE; 7976726Speter int ival = 0; 8076726Speter int prec = -1; 8176726Speter int type = 0; 8276726Speter int used = 0; 8376726Speter int width = -1; 8476726Speter size_t f = 0; 8550276Speter 8676726Speter format[f++] = *fmt; 8776726Speter while (*++fmt != '\0' && len >= 0 && !done) { 8876726Speter format[f++] = *fmt; 8950276Speter 9097049Speter if (isdigit(UChar(*fmt))) { 9176726Speter int num = *fmt - '0'; 9276726Speter if (state == Flags && num != 0) 9376726Speter state = Width; 9476726Speter if (state == Width) { 9576726Speter if (width < 0) 9676726Speter width = 0; 9776726Speter width = (width * 10) + num; 9876726Speter } else if (state == Prec) { 9976726Speter if (prec < 0) 10076726Speter prec = 0; 10176726Speter prec = (prec * 10) + num; 10276726Speter } 10376726Speter } else if (*fmt == '*') { 10476726Speter VA_INTGR(int); 10576726Speter if (state == Flags) 10676726Speter state = Width; 10776726Speter if (state == Width) { 10876726Speter width = ival; 10976726Speter } else if (state == Prec) { 11076726Speter prec = ival; 11176726Speter } 112166124Srafan sprintf(fmt_arg, "%d", ival); 113166124Srafan fmt_len += strlen(fmt_arg); 114166124Srafan if ((format = realloc(format, fmt_len)) == 0) { 115166124Srafan return -1; 116166124Srafan } 117166124Srafan strcpy(&format[--f], fmt_arg); 11876726Speter f = strlen(format); 11997049Speter } else if (isalpha(UChar(*fmt))) { 12076726Speter done = TRUE; 12176726Speter switch (*fmt) { 12276726Speter case 'Z': /* FALLTHRU */ 12376726Speter case 'h': /* FALLTHRU */ 12476726Speter case 'l': /* FALLTHRU */ 12576726Speter done = FALSE; 12676726Speter type = *fmt; 12776726Speter break; 12876726Speter case 'i': /* FALLTHRU */ 12976726Speter case 'd': /* FALLTHRU */ 13076726Speter case 'u': /* FALLTHRU */ 13176726Speter case 'x': /* FALLTHRU */ 13276726Speter case 'X': /* FALLTHRU */ 13376726Speter if (type == 'l') 13476726Speter VA_INTGR(long); 13576726Speter else if (type == 'Z') 13676726Speter VA_INTGR(size_t); 13776726Speter else 13876726Speter VA_INTGR(int); 13976726Speter used = 'i'; 14076726Speter break; 14176726Speter case 'f': /* FALLTHRU */ 14276726Speter case 'e': /* FALLTHRU */ 14376726Speter case 'E': /* FALLTHRU */ 14476726Speter case 'g': /* FALLTHRU */ 14576726Speter case 'G': /* FALLTHRU */ 14676726Speter VA_FLOAT(double); 14776726Speter used = 'f'; 14876726Speter break; 14976726Speter case 'c': 15076726Speter VA_INTGR(int); 15176726Speter used = 'i'; 15276726Speter break; 15376726Speter case 's': 15476726Speter VA_POINT(char *); 15576726Speter if (prec < 0) 15676726Speter prec = strlen(pval); 15776726Speter if (prec > (int) length) { 15876726Speter length = length + prec; 15976726Speter buffer = typeRealloc(char, length, buffer); 16076726Speter if (buffer == 0) { 16176726Speter free(format); 16276726Speter return -1; 16376726Speter } 16450276Speter } 16576726Speter used = 'p'; 16676726Speter break; 16776726Speter case 'p': 16876726Speter VA_POINT(void *); 16976726Speter used = 'p'; 17076726Speter break; 17176726Speter case 'n': 17276726Speter VA_POINT(int *); 17376726Speter used = 0; 17476726Speter break; 17576726Speter default: 17676726Speter break; 17776726Speter } 17876726Speter } else if (*fmt == '.') { 17976726Speter state = Prec; 18076726Speter } else if (*fmt == '%') { 18176726Speter done = TRUE; 18276726Speter used = 'p'; 18350276Speter } 18476726Speter } 18576726Speter format[f] = '\0'; 18676726Speter switch (used) { 18776726Speter case 'i': 18876726Speter sprintf(buffer, format, ival); 18976726Speter break; 19076726Speter case 'f': 19176726Speter sprintf(buffer, format, fval); 19276726Speter break; 19376726Speter default: 19476726Speter sprintf(buffer, format, pval); 19576726Speter break; 19676726Speter } 19776726Speter len += (int) strlen(buffer); 19876726Speter } else { 19976726Speter fmt++; 20076726Speter len++; 20150276Speter } 20276726Speter } 20350276Speter 20476726Speter free(buffer); 20576726Speter free(format); 20676726Speter return len; 20750276Speter} 20850276Speter#endif 20950276Speter 210174993Srafan#define my_buffer _nc_globals.safeprint_buf 211174993Srafan#define my_length _nc_globals.safeprint_used 212174993Srafan 21350276Speter/* 21450276Speter * Wrapper for vsprintf that allocates a buffer big enough to hold the result. 21550276Speter */ 21676726SpeterNCURSES_EXPORT(char *) 217166124Srafan_nc_printf_string(const char *fmt, va_list ap) 21850276Speter{ 219166124Srafan char *result = 0; 220166124Srafan 221166124Srafan if (fmt != 0) { 22250276Speter#if USE_SAFE_SPRINTF 223166124Srafan int len = _nc_printf_length(fmt, ap); 22450276Speter 225174993Srafan if ((int) my_length < len + 1) { 226174993Srafan my_length = 2 * (len + 1); 227174993Srafan my_buffer = typeRealloc(char, my_length, my_buffer); 228166124Srafan } 229174993Srafan if (my_buffer != 0) { 230174993Srafan *my_buffer = '\0'; 231166124Srafan if (len >= 0) { 232174993Srafan vsprintf(my_buffer, fmt, ap); 233166124Srafan } 234174993Srafan result = my_buffer; 235166124Srafan } 23650276Speter#else 237174993Srafan#define MyCols _nc_globals.safeprint_cols 238174993Srafan#define MyRows _nc_globals.safeprint_rows 23950276Speter 240174993Srafan if (screen_lines > MyRows || screen_columns > MyCols) { 241174993Srafan if (screen_lines > MyRows) 242174993Srafan MyRows = screen_lines; 243174993Srafan if (screen_columns > MyCols) 244174993Srafan MyCols = screen_columns; 245174993Srafan my_length = (MyRows * (MyCols + 1)) + 1; 246174993Srafan my_buffer = typeRealloc(char, my_length, my_buffer); 24750276Speter } 24850276Speter 249174993Srafan if (my_buffer != 0) { 25050276Speter# if HAVE_VSNPRINTF 251174993Srafan vsnprintf(my_buffer, my_length, fmt, ap); /* GNU extension */ 25250276Speter# else 253174993Srafan vsprintf(my_buffer, fmt, ap); /* ANSI */ 25450276Speter# endif 255174993Srafan result = my_buffer; 256166124Srafan } 257166124Srafan#endif 258174993Srafan } else if (my_buffer != 0) { /* see _nc_freeall() */ 259174993Srafan free(my_buffer); 260174993Srafan my_buffer = 0; 261174993Srafan my_length = 0; 26276726Speter } 263166124Srafan return result; 26450276Speter} 265