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