source: trunk/third/sendmail/libsm/strl.c @ 19204

Revision 19204, 7.5 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 1999-2002 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#include <sm/gen.h>
12SM_RCSID("@(#)$Id: strl.c,v 1.1.1.1 2003-04-08 15:06:50 zacheiss Exp $")
13#include <sm/config.h>
14#include <sm/string.h>
15
16/*
17**  Notice: this file is used by libmilter. Please try to avoid
18**      using libsm specific functions.
19*/
20
21/*
22**  XXX the type of the length parameter has been changed
23**  from size_t to ssize_t to avoid theoretical problems with negative
24**  numbers passed into these functions.
25**  The real solution to this problem is to make sure that this doesn't
26**  happen, but for now we'll use this workaround.
27*/
28
29/*
30**  SM_STRLCPY -- size bounded string copy
31**
32**      This is a bounds-checking variant of strcpy.
33**      If size > 0, copy up to size-1 characters from the nul terminated
34**      string src to dst, nul terminating the result.  If size == 0,
35**      the dst buffer is not modified.
36**      Additional note: this function has been "tuned" to run fast and tested
37**      as such (versus versions in some OS's libc).
38**
39**      The result is strlen(src).  You can detect truncation (not all
40**      of the characters in the source string were copied) using the
41**      following idiom:
42**
43**              char *s, buf[BUFSIZ];
44**              ...
45**              if (sm_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
46**                      goto overflow;
47**
48**      Parameters:
49**              dst -- destination buffer
50**              src -- source string
51**              size -- size of destination buffer
52**
53**      Returns:
54**              strlen(src)
55*/
56
57size_t
58sm_strlcpy(dst, src, size)
59        register char *dst;
60        register const char *src;
61        ssize_t size;
62{
63        register ssize_t i;
64
65        if (size-- <= 0)
66                return strlen(src);
67        for (i = 0; i < size && (dst[i] = src[i]) != 0; i++)
68                continue;
69        dst[i] = '\0';
70        if (src[i] == '\0')
71                return i;
72        else
73                return i + strlen(src + i);
74}
75
76/*
77**  SM_STRLCAT -- size bounded string concatenation
78**
79**      This is a bounds-checking variant of strcat.
80**      If strlen(dst) < size, then append at most size - strlen(dst) - 1
81**      characters from the source string to the destination string,
82**      nul terminating the result.  Otherwise, dst is not modified.
83**
84**      The result is the initial length of dst + the length of src.
85**      You can detect overflow (not all of the characters in the
86**      source string were copied) using the following idiom:
87**
88**              char *s, buf[BUFSIZ];
89**              ...
90**              if (sm_strlcat(buf, s, sizeof(buf)) >= sizeof(buf))
91**                      goto overflow;
92**
93**      Parameters:
94**              dst -- nul-terminated destination string buffer
95**              src -- nul-terminated source string
96**              size -- size of destination buffer
97**
98**      Returns:
99**              total length of the string tried to create
100**              (= initial length of dst + length of src)
101*/
102
103size_t
104sm_strlcat(dst, src, size)
105        register char *dst;
106        register const char *src;
107        ssize_t size;
108{
109        register ssize_t i, j, o;
110
111        o = strlen(dst);
112        if (size < o + 1)
113                return o + strlen(src);
114        size -= o + 1;
115        for (i = 0, j = o; i < size && (dst[j] = src[i]) != 0; i++, j++)
116                continue;
117        dst[j] = '\0';
118        if (src[i] == '\0')
119                return j;
120        else
121                return j + strlen(src + i);
122}
123/*
124**  SM_STRLCAT2 -- append two strings to dst obeying length and
125**              '\0' terminate it
126**
127**              strlcat2 will append at most len - strlen(dst) - 1 chars.
128**              terminates with '\0' if len > 0
129**              dst = dst "+" src1 "+" src2
130**              use this instead of sm_strlcat(dst,src1); sm_strlcat(dst,src2);
131**              for better speed.
132**
133**      Parameters:
134**              dst -- "destination" string.
135**              src1 -- "from" string 1.
136**              src2 -- "from" string 2.
137**              len -- max. length of "destination" string.
138**
139**      Returns:
140**              total length of the string tried to create
141**              (= initial length of dst + length of src)
142**              if this is greater than len then an overflow would have
143**              occurred.
144**
145*/
146
147size_t
148sm_strlcat2(dst, src1, src2, len)
149        register char *dst;
150        register const char *src1;
151        register const char *src2;
152        ssize_t len;
153{
154        register ssize_t i, j, o;
155
156        /* current size of dst */
157        o = strlen(dst);
158
159        /* max. size is less than current? */
160        if (len < o + 1)
161                return o + strlen(src1) + strlen(src2);
162
163        len -= o + 1;   /* space left in dst */
164
165        /* copy the first string; i: index in src1; j: index in dst */
166        for (i = 0, j = o; i < len && (dst[j] = src1[i]) != 0; i++, j++)
167                continue;
168
169        /* src1: end reached? */
170        if (src1[i] != '\0')
171        {
172                /* no: terminate dst; there is space since i < len */
173                dst[j] = '\0';
174                return j + strlen(src1 + i) + strlen(src2);
175        }
176
177        len -= i;       /* space left in dst */
178
179        /* copy the second string; i: index in src2; j: index in dst */
180        for (i = 0; i < len && (dst[j] = src2[i]) != 0; i++, j++)
181                continue;
182        dst[j] = '\0';  /* terminate dst; there is space since i < len */
183        if (src2[i] == '\0')
184                return j;
185        else
186                return j + strlen(src2 + i);
187}
188
189/*
190**  SM_STRLCPYN -- concatenate n strings and assign the result to dst
191**              while obeying length and '\0' terminate it
192**
193**              dst = src1 "+" src2 "+" ...
194**              use this instead of sm_snprintf() for string values
195**              and repeated sm_strlc*() calls for better speed.
196**
197**      Parameters:
198**              dst -- "destination" string.
199**              len -- max. length of "destination" string.
200**              n -- number of strings
201**              strings...
202**
203**      Returns:
204**              total length of the string tried to create
205**              (= initial length of dst + length of src)
206**              if this is greater than len then an overflow would have
207**              occurred.
208*/
209
210size_t
211#ifdef __STDC__
212sm_strlcpyn(char *dst, ssize_t len, int n, ...)
213#else /* __STDC__ */
214sm_strlcpyn(dst, len, n, va_alist)
215        register char *dst;
216        ssize_t len;
217        int n;
218        va_dcl
219#endif /* __STDC__ */
220{
221        register ssize_t i, j;
222        char *str;
223        SM_VA_LOCAL_DECL
224
225        SM_VA_START(ap, n);
226
227        if (len-- <= 0) /* This allows space for the terminating '\0' */
228        {
229                i = 0;
230                while (n-- > 0)
231                        i += strlen(SM_VA_ARG(ap, char *));
232                SM_VA_END(ap);
233                return i;
234        }
235
236        j = 0;  /* index in dst */
237
238        /* loop through all source strings */
239        while (n-- > 0)
240        {
241                str = SM_VA_ARG(ap, char *);
242
243                /* copy string; i: index in str; j: index in dst */
244                for (i = 0; j < len && (dst[j] = str[i]) != 0; i++, j++)
245                        continue;
246
247                /* str: end reached? */
248                if (str[i] != '\0')
249                {
250                        /* no: terminate dst; there is space since j < len */
251                        dst[j] = '\0';
252                        j += strlen(str + i);
253                        while (n-- > 0)
254                                j += strlen(SM_VA_ARG(ap, char *));
255                        SM_VA_END(ap);
256                        return j;
257                }
258        }
259        SM_VA_END(ap);
260
261        dst[j] = '\0';  /* terminate dst; there is space since j < len */
262        return j;
263}
264
265#if 0
266/*
267**  SM_STRLAPP -- append string if it fits into buffer.
268**
269**      If size > 0, copy up to size-1 characters from the nul terminated
270**      string src to dst, nul terminating the result.  If size == 0,
271**      the dst buffer is not modified.
272**
273**      This routine is useful for appending strings in a loop, e.g, instead of
274**      s = buf;
275**      for (ptr, ptr != NULL, ptr = next->ptr)
276**      {
277**              (void) sm_strlcpy(s, ptr->string, sizeof buf - (s - buf));
278**              s += strlen(s);
279**      }
280**      replace the loop body with:
281**              if (!sm_strlapp(*s, ptr->string, sizeof buf - (s - buf)))
282**                      break;
283**      it's faster...
284**
285**      XXX interface isn't completely clear (yet), hence this code is
286**      not available.
287**
288**
289**      Parameters:
290**              dst -- (pointer to) destination buffer
291**              src -- source string
292**              size -- size of destination buffer
293**
294**      Returns:
295**              true if strlen(src) < size
296**
297**      Side Effects:
298**              modifies dst if append succeeds (enough space).
299*/
300
301bool
302sm_strlapp(dst, src, size)
303        register char **dst;
304        register const char *src;
305        ssize_t size;
306{
307        register size_t i;
308
309        if (size-- <= 0)
310                return false;
311        for (i = 0; i < size && ((*dst)[i] = src[i]) != '\0'; i++)
312                continue;
313        (*dst)[i] = '\0';
314        if (src[i] == '\0')
315        {
316                *dst += i;
317                return true;
318        }
319
320        /* undo */
321        (*dst)[0] = '\0';
322        return false;
323}
324#endif /* 0 */
Note: See TracBrowser for help on using the repository browser.