1 /**************************************************************************************************
2 	$Id: string.c,v 1.22 2005/04/20 16:49:11 bboy Exp $
3 
4 	string.c: Typical generic string manipulation routines.
5 
6 	Copyright (C) 2002-2005  Don Moore <bboy@bboy.net>
7 
8 	This program is free software; you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation; either version 2 of the License, or
11 	(at Your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with this program; if not, write to the Free Software
20 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 **************************************************************************************************/
22 
23 #include "mydnsutil.h"
24 
25 
26 /**************************************************************************************************
27 	STRTRIMLEAD
28 	Remove trailing spaces, etc.
29 **************************************************************************************************/
30 char *
strtrimlead(char * str)31 strtrimlead(char *str)
32 {
33 	char *obuf;
34 
35 	if (str)
36 	{
37 		for (obuf = str; *obuf && isspace((int)(*obuf)); ++obuf)
38 			;
39 		if (str != obuf)
40 			memmove(str, obuf, strlen(obuf) + 1);
41 	}
42 	return (str);
43 }
44 /*--- strtrimlead() -----------------------------------------------------------------------------*/
45 
46 
47 /**************************************************************************************************
48 	STRTRIMTRAIL
49 **************************************************************************************************/
50 char *
strtrimtrail(char * str)51 strtrimtrail(char *str)
52 {
53 	int i;
54 
55 	if (str && 0 != (i = strlen(str)))
56 	{
57 		while (--i >= 0)
58 		{
59 			if (!isspace((int)(str[i])))
60 				break;
61 		}
62 		str[++i] = '\0';
63 	}
64 	return (str);
65 }
66 /*--- strtrimtrail() ----------------------------------------------------------------------------*/
67 
68 
69 /**************************************************************************************************
70 	STRTRIM
71 	Removes leading and trailing whitespace from a string.  Converts tabs and newlines to spaces.
72 **************************************************************************************************/
73 char *
strtrim(char * str)74 strtrim(char *str)
75 {
76 	strtrimlead(str);
77 	strtrimtrail(str);
78 	return (str);
79 }
80 /*--- strtrim() ---------------------------------------------------------------------------------*/
81 
82 
83 /**************************************************************************************************
84 	STRTOUPPER
85 	Converts a string to uppercase.
86 **************************************************************************************************/
87 char *
strtoupper(char * str)88 strtoupper(char *str)
89 {
90 	register char *c;
91 
92 	if (!str || !*str)
93 		return (NULL);
94 	for (c = str; *c; c++)
95 		*c = toupper(*c);
96 	return (str);
97 }
98 /*--- strtoupper() ------------------------------------------------------------------------------*/
99 
100 
101 /**************************************************************************************************
102 	STRTOLOWER
103 	Converts a string to lowercase.
104 **************************************************************************************************/
105 char *
strtolower(char * str)106 strtolower(char *str)
107 {
108 	register char *c;
109 
110 	if (!str || !*str)
111 		return (NULL);
112 	for (c = str; *c; c++)
113 		*c = tolower(*c);
114 	return (str);
115 }
116 /*--- strtolower() ------------------------------------------------------------------------------*/
117 
118 
119 /**************************************************************************************************
120 	STRSECS
121 	Outputs a number of seconds in a more human-friendly format.
122 **************************************************************************************************/
123 char *
strsecs(time_t seconds)124 strsecs(time_t seconds)
125 {
126 	int weeks, days, hours, minutes;
127 	static char str[40];
128 	char *s;
129 
130 	weeks = seconds / 604800; seconds -= (weeks * 604800);
131 	days = seconds / 86400; seconds -= (days * 86400);
132 	hours = seconds / 3600; seconds -= (hours * 3600);
133 	minutes = seconds / 60; seconds -= (minutes * 60);
134 
135 	s = str;
136 	if (weeks) s += snprintf(s, sizeof(str) - strlen(str), "%dw", weeks);
137 	if (days) s += snprintf(s, sizeof(str) - strlen(str), "%dd", days);
138 	if (hours) s += snprintf(s, sizeof(str) - strlen(str), "%dh", hours);
139 	if (minutes) s += snprintf(s, sizeof(str) - strlen(str), "%dm", minutes);
140 	if (seconds || s == str) s += snprintf(s, sizeof(str) - strlen(str), "%ds", (int)seconds);
141 	return (str);
142 }
143 /*--- strsecs() ---------------------------------------------------------------------------------*/
144 
145 
146 /**************************************************************************************************
147 	STRDCAT
148 	Dynamically-allocated strcat(3).
149 **************************************************************************************************/
150 char *
strdcat(char ** dest,const char * src)151 strdcat(char **dest, const char *src)
152 {
153 	register int	srclen,									/* Length of src */
154 						destlen;									/* Length of dest */
155 	char				*d = *dest;								/* Ptr to dest */
156 
157 	/* If we pass a length of 0 to realloc, it frees memory: just return */
158 	if ((srclen = strlen(src)) == 0)
159 		return (d);
160 	destlen = (d) ? strlen(d) : 0;
161 
162 	/* Allocate/reallocate the storage in dest */
163 	if (!d)
164 	{
165 		if (!(d = malloc(destlen + srclen + 1)))
166 			Err("malloc");
167 	}
168 	else
169 	{
170 		if (!(d = realloc(d, destlen + srclen + 1)))
171 			Err("realloc");
172 	}
173 
174 	memcpy(d + destlen, src, srclen);
175 	d[destlen + srclen] = '\0';
176 
177 	*dest = d;
178 	return (d);
179 }
180 /*--- strdcat() ---------------------------------------------------------------------------------*/
181 
182 
183 /**************************************************************************************************
184 	SDPRINTF
185 	Dynamically-allocated sprintf(3).
186 **************************************************************************************************/
187 int
sdprintf(char ** dest,const char * fmt,...)188 sdprintf(char **dest, const char *fmt, ...)
189 {
190 #if HAVE_VASPRINTF
191 	char	*buf = NULL;
192 #else
193 	char	buf[BUFSIZ];
194 #endif
195 	va_list ap;
196 	int len;
197 
198 	va_start(ap, fmt);
199 #if HAVE_VASPRINTF
200 	vasprintf(&buf, fmt, ap);
201 	len = strlen(buf);
202 #else
203 	len = vsnprintf(buf, sizeof(buf), fmt, ap);
204 #endif
205 	va_end(ap);
206 
207 	strdcat(dest, buf);
208 
209 #if HAVE_VASPRINTF
210 	Free(buf);
211 #endif
212 	return (len);
213 }
214 /*--- sdprintf() --------------------------------------------------------------------------------*/
215 
216 
217 /**************************************************************************************************
218 	Given a string such as "10MB" returns the size represented, in bytes.
219 **************************************************************************************************/
220 size_t
human_file_size(const char * str)221 human_file_size(const char *str)
222 {
223 	size_t numeric = 0;											/* Numeric part of `str' */
224 	register char *c;												/* Ptr to first nonalpha char */
225 
226 	numeric = (size_t)strtoul(str, (char **)NULL, 10);
227 
228 	for (c = (char *)str; *c && isdigit((int)(*c)); c++)
229 		/* DONOTHING */;
230 
231 	if (!*c)
232 		return (numeric);
233 
234 	switch (tolower(*c))
235 	{
236 		case 'k': return (numeric * 1024);
237 		case 'm': return (numeric * 1048576);
238 		case 'g': return (numeric * 1073741824);
239 		default:
240 			break;
241 	}
242 	return (numeric);
243 }
244 /*--- human_file_size() -------------------------------------------------------------------------*/
245 
246 
247 /**************************************************************************************************
248 	ESCDATA
249 	(for debugging) Outputs a received packet.
250 **************************************************************************************************/
251 void
escdata(char * data,int len)252 escdata(char *data, int len)
253 {
254 	register int n, ct;
255 
256 	for (ct = 0; ct < len; ct += 8)
257 	{
258 		for (n = ct; n < ct + 8; n++)
259 		{
260 			printf("%c", n < len ? (isprint(data[n]) ? data[n] : '.') : ' ');
261 			if (n == ct+3)
262 				printf(" ");
263 		}
264 		printf("   ");
265 		for (n = ct; n < ct + 8 && n < len; n++)
266 			printf("%02x%s", data[n], (n == ct+3) ? "  " : " ");
267 		printf(" %d-%d %d-%d\n", ct, ct+3, ct+4, ct+7);
268 	}
269 }
270 /*--- escdata() ---------------------------------------------------------------------------------*/
271 
272 
273 /**************************************************************************************************
274 	BYTESTR
275 	(for debugging) Return a static string containing `byte' shown as binary.
276 **************************************************************************************************/
277 char *
bytestr(unsigned char byte)278 bytestr(unsigned char byte)
279 {
280 	register int i, j;
281 	int bits = 8;
282 	int strwid = 9;
283 	static char str[80], *s;
284 
285 	s = str;
286 	j = strwid - (bits + (bits >> 2)- (bits % 4 ? 0 : 1));
287 	for (i = 0; i < j; i++)
288 		*s++ = ' ';
289 	while (--bits >= 0)
290 	{
291 		*s++ = ((byte >> bits) & 1) + '0';
292 		if (!(bits % 4) && bits)
293 			*s++ = ' ';
294 	}
295 	*s = '\0';
296 	return (str);
297 }
298 /*--- bytestr() ---------------------------------------------------------------------------------*/
299 
300 
301 /**************************************************************************************************
302 	ESCSTR
303 	(for debugging)
304 **************************************************************************************************/
305 char *
escstr(char * str,size_t len)306 escstr(char *str, size_t len)
307 {
308 	static char buf[BUFSIZ];
309 	register char *s, *d;
310 
311 	for (s = str, d = buf; s < str + len; s++)
312 		*(d++) = (isprint(*s)) ? *s : '?';
313 	return ((char *)buf);
314 }
315 /*--- escstr() ----------------------------------------------------------------------------------*/
316 
317 
318 /**************************************************************************************************
319 	COMMAFMT
320 	Copies the numeric value of N into buffer 'buf' of size 'bufsiz', inserting commas where
321 	appropriate.
322 **************************************************************************************************/
323 static size_t
commafmt(char * buf,size_t bufsiz,unsigned long N)324 commafmt(char *buf, size_t bufsiz, unsigned long N)
325 {
326 	unsigned int len = 1, posn = 1;
327 	char *ptr = buf + bufsiz - 1;
328 
329 	if (bufsiz < 2)
330 	{
331 		*buf = '\0';
332 		return 0;
333 	}
334 	*ptr-- = '\0';
335 	--bufsiz;
336 	for ( ; len <= bufsiz; ++len, ++posn)
337 	{
338 		*ptr-- = (char)((N % 10L) + '0');
339 		if (0L == (N /= 10L))
340 			break;
341 		if (0 == (posn % 3))
342 		{
343 			*ptr-- = ',';
344 			++len;
345 		}
346 		if (len >= bufsiz)
347 		{
348 			*buf = '\0';
349 			return 0;
350 		}
351 	}
352 	strcpy(buf, ++ptr);
353 	return (size_t)len;
354 }
355 /*--- commafmt() --------------------------------------------------------------------------------*/
356 
357 
358 /**************************************************************************************************
359 	COMMA1-3
360 	Making printf life easy for Don at the expense of repetition and a few hundred bytes of RAM.
361 **************************************************************************************************/
comma(unsigned long num)362 char *comma(unsigned long num)
363 { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
comma1(unsigned long num)364 char *comma1(unsigned long num)
365 { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
comma2(unsigned long num)366 char *comma2(unsigned long num)
367 { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
comma3(unsigned long num)368 char *comma3(unsigned long num)
369 { static char cbuf[81];  commafmt(cbuf, 80, num); return (cbuf); }
370 /*--- comma1-3() --------------------------------------------------------------------------------*/
371 
372 
373 
374 /* vi:set ts=3: */
375