140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro * All rights reserved.
440266059SGregory Neil Shapiro * Copyright (c) 1990, 1993
540266059SGregory Neil Shapiro * The Regents of the University of California. All rights reserved.
640266059SGregory Neil Shapiro *
740266059SGregory Neil Shapiro * This code is derived from software contributed to Berkeley by
840266059SGregory Neil Shapiro * Chris Torek.
940266059SGregory Neil Shapiro *
1040266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
1140266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
1240266059SGregory Neil Shapiro * the sendmail distribution.
1340266059SGregory Neil Shapiro */
1440266059SGregory Neil Shapiro
1540266059SGregory Neil Shapiro #include <sm/gen.h>
16*4313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: snprintf.c,v 1.25 2013-11-22 20:51:43 ca Exp $")
1740266059SGregory Neil Shapiro #include <limits.h>
1840266059SGregory Neil Shapiro #include <sm/varargs.h>
1940266059SGregory Neil Shapiro #include <sm/io.h>
20d0cef73dSGregory Neil Shapiro #include <sm/string.h>
2140266059SGregory Neil Shapiro #include "local.h"
2240266059SGregory Neil Shapiro
2340266059SGregory Neil Shapiro /*
2440266059SGregory Neil Shapiro ** SM_SNPRINTF -- format a string to a memory location of restricted size
2540266059SGregory Neil Shapiro **
2640266059SGregory Neil Shapiro ** Parameters:
2740266059SGregory Neil Shapiro ** str -- memory location to place formatted string
2840266059SGregory Neil Shapiro ** n -- size of buffer pointed to by str, capped to
2940266059SGregory Neil Shapiro ** a maximum of INT_MAX
3040266059SGregory Neil Shapiro ** fmt -- the formatting directives
3140266059SGregory Neil Shapiro ** ... -- the data to satisfy the formatting
3240266059SGregory Neil Shapiro **
3340266059SGregory Neil Shapiro ** Returns:
3440266059SGregory Neil Shapiro ** Failure: -1
3540266059SGregory Neil Shapiro ** Success: number of bytes that would have been written
3640266059SGregory Neil Shapiro ** to str, not including the trailing '\0',
3740266059SGregory Neil Shapiro ** up to a maximum of INT_MAX, as if there was
3840266059SGregory Neil Shapiro ** no buffer size limitation. If the result >= n
3940266059SGregory Neil Shapiro ** then the output was truncated.
4040266059SGregory Neil Shapiro **
4140266059SGregory Neil Shapiro ** Side Effects:
4240266059SGregory Neil Shapiro ** If n > 0, then between 0 and n-1 bytes of formatted output
4340266059SGregory Neil Shapiro ** are written into 'str', followed by a '\0'.
4440266059SGregory Neil Shapiro */
4540266059SGregory Neil Shapiro
4640266059SGregory Neil Shapiro int
4740266059SGregory Neil Shapiro #if SM_VA_STD
sm_snprintf(char * str,size_t n,char const * fmt,...)4840266059SGregory Neil Shapiro sm_snprintf(char *str, size_t n, char const *fmt, ...)
4940266059SGregory Neil Shapiro #else /* SM_VA_STD */
5040266059SGregory Neil Shapiro sm_snprintf(str, n, fmt, va_alist)
5140266059SGregory Neil Shapiro char *str;
5240266059SGregory Neil Shapiro size_t n;
5340266059SGregory Neil Shapiro char *fmt;
5440266059SGregory Neil Shapiro va_dcl
5540266059SGregory Neil Shapiro #endif /* SM_VA_STD */
5640266059SGregory Neil Shapiro {
5740266059SGregory Neil Shapiro int ret;
5840266059SGregory Neil Shapiro SM_VA_LOCAL_DECL
5940266059SGregory Neil Shapiro SM_FILE_T fake;
6040266059SGregory Neil Shapiro
6140266059SGregory Neil Shapiro /* While snprintf(3) specifies size_t stdio uses an int internally */
6240266059SGregory Neil Shapiro if (n > INT_MAX)
6340266059SGregory Neil Shapiro n = INT_MAX;
6440266059SGregory Neil Shapiro SM_VA_START(ap, fmt);
6540266059SGregory Neil Shapiro
6640266059SGregory Neil Shapiro /* XXX put this into a static? */
6740266059SGregory Neil Shapiro fake.sm_magic = SmFileMagic;
6840266059SGregory Neil Shapiro fake.f_file = -1;
6940266059SGregory Neil Shapiro fake.f_flags = SMWR | SMSTR;
7040266059SGregory Neil Shapiro fake.f_cookie = &fake;
7140266059SGregory Neil Shapiro fake.f_bf.smb_base = fake.f_p = (unsigned char *)str;
7240266059SGregory Neil Shapiro fake.f_bf.smb_size = fake.f_w = n ? n - 1 : 0;
7340266059SGregory Neil Shapiro fake.f_timeout = SM_TIME_FOREVER;
7440266059SGregory Neil Shapiro fake.f_timeoutstate = SM_TIME_BLOCK;
7540266059SGregory Neil Shapiro fake.f_close = NULL;
7640266059SGregory Neil Shapiro fake.f_open = NULL;
7740266059SGregory Neil Shapiro fake.f_read = NULL;
7840266059SGregory Neil Shapiro fake.f_write = NULL;
7940266059SGregory Neil Shapiro fake.f_seek = NULL;
8040266059SGregory Neil Shapiro fake.f_setinfo = fake.f_getinfo = NULL;
8140266059SGregory Neil Shapiro fake.f_type = "sm_snprintf:fake";
8240266059SGregory Neil Shapiro ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
8340266059SGregory Neil Shapiro if (n > 0)
8440266059SGregory Neil Shapiro *fake.f_p = '\0';
8540266059SGregory Neil Shapiro SM_VA_END(ap);
8640266059SGregory Neil Shapiro return ret;
8740266059SGregory Neil Shapiro }
88