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