191094Sdes/* 2115619Sdes * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 3228690Sdes * All rights reserved. 491094Sdes * Copyright (c) 1990, 1993 591094Sdes * The Regents of the University of California. All rights reserved. 691094Sdes * 799158Sdes * This code is derived from software contributed to Berkeley by 899158Sdes * Chris Torek. 999158Sdes * 1091094Sdes * By using this file, you agree to the terms and conditions set 1191094Sdes * forth in the LICENSE file which can be found at the top level of 1291094Sdes * the sendmail distribution. 1391094Sdes */ 1491094Sdes 1591094Sdes#include <sm/gen.h> 1691094SdesSM_RCSID("@(#)$Id: snprintf.c,v 1.25 2013-11-22 20:51:43 ca Exp $") 1791094Sdes#include <limits.h> 1891094Sdes#include <sm/varargs.h> 1991094Sdes#include <sm/io.h> 2091094Sdes#include <sm/string.h> 2191094Sdes#include "local.h" 2291094Sdes 2391094Sdes/* 2491094Sdes** SM_SNPRINTF -- format a string to a memory location of restricted size 2591094Sdes** 2691094Sdes** Parameters: 2791094Sdes** str -- memory location to place formatted string 2891094Sdes** n -- size of buffer pointed to by str, capped to 2991094Sdes** a maximum of INT_MAX 3091094Sdes** fmt -- the formatting directives 3191094Sdes** ... -- the data to satisfy the formatting 3291094Sdes** 3391094Sdes** Returns: 3491094Sdes** Failure: -1 35255376Sdes** Success: number of bytes that would have been written 3691094Sdes** to str, not including the trailing '\0', 3791094Sdes** up to a maximum of INT_MAX, as if there was 38228690Sdes** no buffer size limitation. If the result >= n 39228690Sdes** then the output was truncated. 40228690Sdes** 41228690Sdes** Side Effects: 4291094Sdes** If n > 0, then between 0 and n-1 bytes of formatted output 4391094Sdes** are written into 'str', followed by a '\0'. 4491094Sdes*/ 4591094Sdes 4691094Sdesint 4791094Sdes#if SM_VA_STD 4891094Sdessm_snprintf(char *str, size_t n, char const *fmt, ...) 4991094Sdes#else /* SM_VA_STD */ 5091094Sdessm_snprintf(str, n, fmt, va_alist) 5191094Sdes char *str; 5291094Sdes size_t n; 5391094Sdes char *fmt; 5491094Sdes va_dcl 5591094Sdes#endif /* SM_VA_STD */ 5691094Sdes{ 5791094Sdes int ret; 5891094Sdes SM_VA_LOCAL_DECL 5991094Sdes SM_FILE_T fake; 6091094Sdes 6191094Sdes /* While snprintf(3) specifies size_t stdio uses an int internally */ 62107937Sdes if (n > INT_MAX) 6391094Sdes n = INT_MAX; 64107937Sdes SM_VA_START(ap, fmt); 6591094Sdes 6691094Sdes /* XXX put this into a static? */ 6791094Sdes fake.sm_magic = SmFileMagic; 6891094Sdes fake.f_file = -1; 6991094Sdes fake.f_flags = SMWR | SMSTR; 7091094Sdes fake.f_cookie = &fake; 71115619Sdes fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; 72115619Sdes fake.f_bf.smb_size = fake.f_w = n ? n - 1 : 0; 7391094Sdes fake.f_timeout = SM_TIME_FOREVER; 7491094Sdes fake.f_timeoutstate = SM_TIME_BLOCK; 7591094Sdes fake.f_close = NULL; 76116520Sdes fake.f_open = NULL; 77116520Sdes fake.f_read = NULL; 78116520Sdes fake.f_write = NULL; 79116520Sdes fake.f_seek = NULL; 80115619Sdes fake.f_setinfo = fake.f_getinfo = NULL; 8191094Sdes fake.f_type = "sm_snprintf:fake"; 8291094Sdes ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); 8395908Sdes if (n > 0) 8491094Sdes *fake.f_p = '\0'; 8591094Sdes SM_VA_END(ap); 8691094Sdes return ret; 8791094Sdes} 8891094Sdes