1 | /* |
---|
2 | * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. |
---|
3 | * All rights reserved. |
---|
4 | * |
---|
5 | * By using this file, you agree to the terms and conditions set |
---|
6 | * forth in the LICENSE file which can be found at the top level of |
---|
7 | * the sendmail distribution. |
---|
8 | */ |
---|
9 | |
---|
10 | /* |
---|
11 | * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> |
---|
12 | * All rights reserved. |
---|
13 | * |
---|
14 | * Redistribution and use in source and binary forms, with or without |
---|
15 | * modification, are permitted provided that the following conditions |
---|
16 | * are met: |
---|
17 | * 1. Redistributions of source code must retain the above copyright |
---|
18 | * notice, this list of conditions and the following disclaimer. |
---|
19 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
20 | * notice, this list of conditions and the following disclaimer in the |
---|
21 | * documentation and/or other materials provided with the distribution. |
---|
22 | * 3. The name of the author may not be used to endorse or promote products |
---|
23 | * derived from this software without specific prior written permission. |
---|
24 | * |
---|
25 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
---|
26 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
---|
27 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
---|
28 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
---|
31 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
---|
32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
---|
33 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
---|
34 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
35 | */ |
---|
36 | |
---|
37 | #include <sm/gen.h> |
---|
38 | SM_RCSID("@(#)$Id: vasprintf.c,v 1.1.1.1 2003-04-08 15:06:05 zacheiss Exp $") |
---|
39 | #include <stdlib.h> |
---|
40 | #include <errno.h> |
---|
41 | #include <sm/io.h> |
---|
42 | #include <sm/heap.h> |
---|
43 | #include "local.h" |
---|
44 | |
---|
45 | /* |
---|
46 | ** SM_VASPRINTF -- printf to a dynamically allocated string |
---|
47 | ** |
---|
48 | ** Write 'printf' output to a dynamically allocated string |
---|
49 | ** buffer which is returned to the caller. |
---|
50 | ** |
---|
51 | ** Parameters: |
---|
52 | ** str -- *str receives a pointer to the allocated string |
---|
53 | ** fmt -- format directives for printing |
---|
54 | ** ap -- variable argument list |
---|
55 | ** |
---|
56 | ** Results: |
---|
57 | ** On failure, set *str to NULL, set errno, and return -1. |
---|
58 | ** |
---|
59 | ** On success, set *str to a pointer to a nul-terminated |
---|
60 | ** string buffer containing printf output, and return the |
---|
61 | ** length of the string (not counting the nul). |
---|
62 | */ |
---|
63 | |
---|
64 | #define SM_VA_BUFSIZE 128 |
---|
65 | |
---|
66 | int |
---|
67 | sm_vasprintf(str, fmt, ap) |
---|
68 | char **str; |
---|
69 | const char *fmt; |
---|
70 | SM_VA_LOCAL_DECL |
---|
71 | { |
---|
72 | int ret; |
---|
73 | SM_FILE_T fake; |
---|
74 | unsigned char *base; |
---|
75 | |
---|
76 | fake.sm_magic = SmFileMagic; |
---|
77 | fake.f_timeout = SM_TIME_FOREVER; |
---|
78 | fake.f_timeoutstate = SM_TIME_BLOCK; |
---|
79 | fake.f_file = -1; |
---|
80 | fake.f_flags = SMWR | SMSTR | SMALC; |
---|
81 | fake.f_bf.smb_base = fake.f_p = (unsigned char *)sm_malloc(SM_VA_BUFSIZE); |
---|
82 | if (fake.f_bf.smb_base == NULL) |
---|
83 | goto err2; |
---|
84 | fake.f_close = NULL; |
---|
85 | fake.f_open = NULL; |
---|
86 | fake.f_read = NULL; |
---|
87 | fake.f_write = NULL; |
---|
88 | fake.f_seek = NULL; |
---|
89 | fake.f_setinfo = fake.f_getinfo = NULL; |
---|
90 | fake.f_type = "sm_vasprintf:fake"; |
---|
91 | fake.f_bf.smb_size = fake.f_w = SM_VA_BUFSIZE - 1; |
---|
92 | fake.f_timeout = SM_TIME_FOREVER; |
---|
93 | ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap); |
---|
94 | if (ret == -1) |
---|
95 | goto err; |
---|
96 | *fake.f_p = '\0'; |
---|
97 | |
---|
98 | /* use no more space than necessary */ |
---|
99 | base = (unsigned char *) sm_realloc(fake.f_bf.smb_base, ret + 1); |
---|
100 | if (base == NULL) |
---|
101 | goto err; |
---|
102 | *str = (char *)base; |
---|
103 | return ret; |
---|
104 | |
---|
105 | err: |
---|
106 | if (fake.f_bf.smb_base != NULL) |
---|
107 | { |
---|
108 | sm_free(fake.f_bf.smb_base); |
---|
109 | fake.f_bf.smb_base = NULL; |
---|
110 | } |
---|
111 | err2: |
---|
112 | *str = NULL; |
---|
113 | errno = ENOMEM; |
---|
114 | return -1; |
---|
115 | } |
---|