190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266692SgshapiroSM_RCSID("@(#)$Id: snprintf.c,v 1.25 2013-11-22 20:51:43 ca Exp $") 1790792Sgshapiro#include <limits.h> 1890792Sgshapiro#include <sm/varargs.h> 1990792Sgshapiro#include <sm/io.h> 20168515Sgshapiro#include <sm/string.h> 2190792Sgshapiro#include "local.h" 2290792Sgshapiro 2390792Sgshapiro/* 2490792Sgshapiro** SM_SNPRINTF -- format a string to a memory location of restricted size 2590792Sgshapiro** 2690792Sgshapiro** Parameters: 2790792Sgshapiro** str -- memory location to place formatted string 2890792Sgshapiro** n -- size of buffer pointed to by str, capped to 2990792Sgshapiro** a maximum of INT_MAX 3090792Sgshapiro** fmt -- the formatting directives 3190792Sgshapiro** ... -- the data to satisfy the formatting 3290792Sgshapiro** 3390792Sgshapiro** Returns: 3490792Sgshapiro** Failure: -1 3590792Sgshapiro** Success: number of bytes that would have been written 3690792Sgshapiro** to str, not including the trailing '\0', 3790792Sgshapiro** up to a maximum of INT_MAX, as if there was 3890792Sgshapiro** no buffer size limitation. If the result >= n 3990792Sgshapiro** then the output was truncated. 4090792Sgshapiro** 4190792Sgshapiro** Side Effects: 4290792Sgshapiro** If n > 0, then between 0 and n-1 bytes of formatted output 4390792Sgshapiro** are written into 'str', followed by a '\0'. 4490792Sgshapiro*/ 4590792Sgshapiro 4690792Sgshapiroint 4790792Sgshapiro#if SM_VA_STD 4890792Sgshapirosm_snprintf(char *str, size_t n, char const *fmt, ...) 4990792Sgshapiro#else /* SM_VA_STD */ 5090792Sgshapirosm_snprintf(str, n, fmt, va_alist) 5190792Sgshapiro char *str; 5290792Sgshapiro size_t n; 5390792Sgshapiro char *fmt; 5490792Sgshapiro va_dcl 5590792Sgshapiro#endif /* SM_VA_STD */ 5690792Sgshapiro{ 5790792Sgshapiro int ret; 5890792Sgshapiro SM_VA_LOCAL_DECL 5990792Sgshapiro SM_FILE_T fake; 6090792Sgshapiro 6190792Sgshapiro /* While snprintf(3) specifies size_t stdio uses an int internally */ 6290792Sgshapiro if (n > INT_MAX) 6390792Sgshapiro n = INT_MAX; 6490792Sgshapiro SM_VA_START(ap, fmt); 6590792Sgshapiro 6690792Sgshapiro /* XXX put this into a static? */ 6790792Sgshapiro fake.sm_magic = SmFileMagic; 6890792Sgshapiro fake.f_file = -1; 6990792Sgshapiro fake.f_flags = SMWR | SMSTR; 7090792Sgshapiro fake.f_cookie = &fake; 7190792Sgshapiro fake.f_bf.smb_base = fake.f_p = (unsigned char *)str; 7290792Sgshapiro fake.f_bf.smb_size = fake.f_w = n ? n - 1 : 0; 7390792Sgshapiro fake.f_timeout = SM_TIME_FOREVER; 7490792Sgshapiro fake.f_timeoutstate = SM_TIME_BLOCK; 7590792Sgshapiro fake.f_close = NULL; 7690792Sgshapiro fake.f_open = NULL; 7790792Sgshapiro fake.f_read = NULL; 7890792Sgshapiro fake.f_write = NULL; 7990792Sgshapiro fake.f_seek = NULL; 8090792Sgshapiro fake.f_setinfo = fake.f_getinfo = NULL; 8190792Sgshapiro fake.f_type = "sm_snprintf:fake"; 8290792Sgshapiro ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); 8390792Sgshapiro if (n > 0) 8490792Sgshapiro *fake.f_p = '\0'; 8590792Sgshapiro SM_VA_END(ap); 8690792Sgshapiro return ret; 8790792Sgshapiro} 88