1 /*
2 ** safestr.c - Buffer overrun safe string functions
3 **
4 ** Copyright (c) 1997-2000 Peter Eriksson <pen@lysator.liu.se>
5 **
6 ** This program is free software; you can redistribute it and/or
7 ** modify it as you wish - as long as you don't claim that you wrote
8 ** it.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 */
14
15 #define PLIB_IN_SAFESTR_C
16
17 #include "plib/config.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <syslog.h>
25
26 #include "plib/threads.h"
27 #include "plib/safeio.h"
28 #include "plib/safestr.h"
29
30
31
32
33
34 int
s_vsnprintf(char * buf,size_t bufsize,const char * format,va_list ap)35 s_vsnprintf(char *buf,
36 size_t bufsize,
37 const char *format,
38 va_list ap)
39 {
40 int retcode;
41
42
43 if (bufsize < 1)
44 {
45 syslog(LOG_ERR, "s_snprintf(..., %d, ...): illegal bufsize",
46 bufsize);
47 s_abort();
48 }
49
50 buf[bufsize-1] = '\0';
51 #ifdef HAVE_VSNPRINTF
52 retcode = vsnprintf(buf, bufsize, format, ap);
53 #else
54 #ifdef SPRINTF_RETVAL_POINTER
55 /* XXX: The reason we check for sprintf()'s return type and not
56 vsprintf() (which we should) is that SunOS 4 doesn't declare
57 vsprintf() in any header files, but it does have the same return
58 value as sprintf(). So expect a compiler warning here unless
59 we use the (uncesserary) '(char *)' cast - *Sigh* */
60 {
61 char *cp = (char *) vsprintf(buf, format, ap);
62 if (cp == NULL)
63 retcode = -1;
64 else
65 retcode = strlen(cp);
66 }
67 #else
68 retcode = vsprintf(buf, format, ap);
69 #endif
70 #endif
71 if (retcode > 0 && (buf[bufsize-1] != '\0' ||
72 retcode > bufsize-1))
73 {
74 syslog(LOG_ERR, "s_snprintf(..., %d, ...) = %d: buffer overrun\n",
75 bufsize, retcode);
76
77 s_abort();
78 }
79
80 return retcode;
81 }
82
83
84
85 int
s_snprintf(char * buf,size_t bufsize,const char * format,...)86 s_snprintf(char *buf,
87 size_t bufsize,
88 const char *format,
89 ...)
90 {
91 va_list ap;
92 int retcode;
93
94
95 va_start(ap, format);
96 retcode = s_vsnprintf(buf, bufsize, format, ap);
97 va_end(ap);
98
99 return retcode;
100 }
101
102
103 /*
104 ** A slightly safer strtok_r() function
105 */
106 char *
s_strtok_r(char * s,const char * d,char ** bp)107 s_strtok_r(char *s, const char *d, char **bp)
108 {
109 char *cp;
110
111
112 if (d == NULL || bp == NULL)
113 return NULL;
114
115 if (s == NULL)
116 s = *bp;
117
118 if (s == NULL)
119 return NULL;
120
121 s += strspn(s, d);
122 if (*s == '\0')
123 return NULL;
124
125 cp = s;
126 s = strpbrk(cp, d);
127 if (s == NULL)
128 *bp = strchr(cp, 0);
129 else
130 {
131 *s++ = '\0';
132 *bp = s;
133 }
134
135 return cp;
136 }
137
138
139 int
s_strcasecmp(const char * s1,const char * s2)140 s_strcasecmp(const char *s1, const char *s2)
141 {
142 int i;
143
144 while ((i = (toupper((unsigned char) *s1) - toupper((unsigned char) *s2))) == 0 && *s1)
145 {
146 ++s1;
147 ++s2;
148 }
149
150 return i;
151 }
152
153