1 /*
2  * Portions copyright 2002, 2003 Richard Laager.
3  * Copyright (c) 1996, 1997, 1998, 1999, Marc Horowitz.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Marc Horowitz.
17  * 4. The name of the author may not be used to endorse or promote
18  *    products derived from this software without specific prior written
19  *    permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY MARC HOROWITZ ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.  IN NO EVENT SHALL MARC HOROWITZ BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 const char rcsid_util_c[] =
39   "$Id: util.c,v 1.4 2003/03/01 19:43:12 rlaager Exp $";
40 
41 #if HAVE_SYS_TYPES_H
42 #include <sys/types.h>
43 #endif
44 
45 #if HAVE_CTYPE_H
46 #include <ctype.h>
47 #endif
48 
49 #if HAVE_ERRNO_H
50 #include <errno.h>
51 #endif
52 
53 #if HAVE_STDIO_H
54 #include <stdio.h>
55 #endif
56 
57 #if HAVE_STDLIB_H
58 #include <stdlib.h>
59 #endif
60 
61 #if HAVE_STRING_H
62 #include <string.h>
63 #endif
64 
65 #include "util.h"
66 
67 #if HAVE_MMAP
68 
69 #if HAVE_SYS_MMAN_H
70 #include <sys/mman.h>
71 #endif
72 
73 #if HAVE_SYS_STAT_H
74 #include <sys/stat.h>
75 #endif
76 
77 #if HAVE_UNISTD_H
78 #include <unistd.h>
79 #endif
80 
81 #endif /* HAVE_MMAP */
82 
83 const unsigned char zeros[1024];	/* globals are initialized to zero */
84 
85 void
xbuffer_alloc(xbuffer * xb)86 xbuffer_alloc (xbuffer * xb)
87 {
88   xb->alloclen = 0;
89   xb->len = 0;
90   xb->buf = NULL;
91 }
92 
93 void
xbuffer_free(xbuffer * xb)94 xbuffer_free (xbuffer * xb)
95 {
96   if (xb->buf)
97     {
98       free (xb->buf);
99       xb->alloclen = 0;
100       xb->len = 0;
101       xb->buf = NULL;
102     }
103 }
104 
105 int
xbuffer_append(xbuffer * xb,const unsigned char * data,long len)106 xbuffer_append (xbuffer * xb, const unsigned char *data, long len)
107 {
108   if (len == 0)
109     return (1);
110 
111   if (xb->alloclen < (xb->len + len))
112     {
113       if (xb->alloclen == 0)
114 	{
115 	  xb->alloclen = (len > 512) ? len : 512;
116 
117 	  if ((xb->buf = (unsigned char *) malloc (xb->alloclen)) == NULL)
118 	    return (0);
119 	}
120       else
121 	{
122 	  unsigned char *tmp;
123 
124 	  xb->alloclen = (((xb->alloclen * 3 / 2) > (xb->alloclen + len)) ?
125 			  xb->alloclen * 3 / 2 : xb->alloclen + len);
126 
127 	  if ((tmp =
128 	       (unsigned char *) realloc (xb->buf, xb->alloclen)) == NULL)
129 	    return (0);
130 
131 	  xb->buf = tmp;
132 	}
133     }
134 
135   memcpy ((void *) (xb->buf + xb->len), (const void *) data, (size_t) len);
136 
137   xb->len += len;
138 
139   return (1);
140 }
141 
142 int
xbuffer_append_str(xbuffer * xb,const char * data)143 xbuffer_append_str (xbuffer * xb, const char *data)
144 {
145   return (xbuffer_append (xb, (unsigned char *) data, (long) strlen (data)));
146 }
147 
148 int
xfilecontents_get(xfilecontents * xfc,FILE * f)149 xfilecontents_get (xfilecontents * xfc, FILE * f)
150 {
151 #if HAVE_MMAP
152   int fd;
153   struct stat fst;
154 #endif
155   unsigned char buf[1024];
156   int cnt;
157 
158   xbuffer_alloc (&(xfc->xb));
159 
160 #if HAVE_MMAP
161   fd = fileno (f);
162 
163   if (fstat (fd, &fst))
164     return (0);
165 
166   xfc->len = fst.st_size;
167 
168   xfc->buf = (unsigned char *) mmap (0, xfc->len, PROT_READ, MAP_SHARED,
169 				     fd, 0);
170 
171   if (xfc->buf != ((void *) -1))
172     {
173       xfc->mmapped = 1;
174 
175 #if HAVE_MADVISE && defined(MADV_SEQUENTIAL)
176       madvise ((char *) xfc->buf, xfc->len, MADV_SEQUENTIAL);
177       /* ignore the error.  some systems don't support all the kinds of
178          advice, and there's nothing to do, anyway. */
179 #endif
180 
181       return (1);
182     }
183 
184   if ((errno != ENODEV) && (errno != EINVAL))
185     {
186       xbuffer_free (&(xfc->xb));
187       return (0);
188     }
189 #endif
190 
191   while (!feof (f))
192     {
193       cnt = fread ((void *) buf, 1, sizeof (buf), f);
194 
195       if (cnt)
196 	if (!xbuffer_append (&(xfc->xb), buf, cnt))
197 	  {
198 	    xbuffer_free (&(xfc->xb));
199 	    return (0);
200 	  }
201 
202       if (cnt < 1024)
203 	break;
204     }
205 
206   if (ferror (f))
207     {
208       xbuffer_free (&(xfc->xb));
209       return (0);
210     }
211 
212   xfc->len = xfc->xb.len;
213   xfc->buf = xfc->xb.buf;
214 
215 #if HAVE_MMAP
216   xfc->mmapped = 0;
217 #endif
218   return (1);
219 }
220 
221 void
xfilecontents_free(xfilecontents * xfc)222 xfilecontents_free (xfilecontents * xfc)
223 {
224 #if HAVE_MMAP
225   if (xfc->mmapped)
226     munmap ((char *) xfc->buf, xfc->len);
227 #endif
228   xbuffer_free (&(xfc->xb));
229 }
230 
231 char *
my_strdup(const char * s)232 my_strdup (const char *s)
233 {
234   char *ns;
235 
236   if ((ns = (char *) malloc (strlen (s) + 1)) == NULL)
237     return (NULL);
238 
239   strcpy (ns, s);
240 
241   return (ns);
242 }
243 
244 int
my_strncasecmp(const char * s1,const char * s2,int n)245 my_strncasecmp (const char *s1, const char *s2, int n)
246 {
247   int tmp;
248 
249   for (; n && *s1 && *s2; n--, s1++, s2++)
250     {
251       if (*s1 == *s2)
252 	continue;
253       if ((tmp = (tolower (*s1) - tolower (*s2))) != 0)
254 	return (tmp);
255     }
256 
257   return (0);
258 }
259 
260 void *
my_memmem(const void * mem,const void * s,size_t memn,size_t mems)261 my_memmem (const void *mem, const void *s, size_t memn, size_t mems)
262 {
263   const char *cmem = (const char *) mem;
264   const char *cs = (const char *) s;
265 
266   char *cptr;
267 
268   for (cptr = (char *) memchr (mem, (int) cs[0], memn);
269        cptr;
270        cptr = (char *) memchr (((void *) (cptr + 1)), (int) cs[0],
271 			       memn - (cptr + 1 - cmem)))
272     {
273       if ((memn - (cptr - cmem)) < mems)
274 	return (NULL);
275       if (memcmp (cptr, cs, mems) == 0)
276 	break;
277     }
278 
279   return ((void *) cptr);
280 }
281 
282 void *
my_memcasemem(const void * mem,const void * s,size_t memn,size_t mems)283 my_memcasemem (const void *mem, const void *s, size_t memn, size_t mems)
284 {
285   const char *cmem = (const char *) mem;
286   const char *cs = (const char *) s;
287 
288   char *cptr;
289 
290   for (cptr = (char *) memchr (mem, toupper ((int) cs[0]), memn);
291        cptr;
292        cptr = (char *) memchr (((void *) (cptr + 1)), toupper ((int) cs[0]),
293 			       memn - (cptr + 1 - cmem)))
294     {
295       if ((memn - (cptr - cmem)) < mems)
296 	return (NULL);
297       if (my_strncasecmp (cptr, cs, mems) == 0)
298 	break;
299     }
300 
301   if (!cptr && isalpha ((int) cs[0]))
302     {
303       for (cptr = (char *) memchr (mem, (int) tolower ((int) cs[0]), memn);
304 	   cptr;
305 	   cptr =
306 	   (char *) memchr (((void *) (cptr + 1)), tolower ((int) cs[0]),
307 			    memn - (cptr + 1 - cmem)))
308 	{
309 	  if ((memn - (cptr - cmem)) < mems)
310 	    return (NULL);
311 	  if (my_strncasecmp (cptr, cs, mems) == 0)
312 	    break;
313 	}
314     }
315 
316   return ((void *) cptr);
317 }
318 
319 void *
my_memstr(const void * mem,const char * s,size_t n)320 my_memstr (const void *mem, const char *s, size_t n)
321 {
322   return (my_memmem (mem, (const void *) s, n, strlen (s)));
323 }
324