Annotation of libaitio/src/tools.c, revision 1.10
1.2 misho 1: /*************************************************************************
1.4 misho 2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
1.2 misho 4: *
5: * $Author: misho $
1.10 ! misho 6: * $Id: tools.c,v 1.9.2.1 2012/03/27 21:37:56 misho Exp $
1.2 misho 7: *
1.4 misho 8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.9 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.4 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
1.2 misho 46: #include "global.h"
47: #include "aitio.h"
48:
49:
50: /*
51: * io_LTrimStr() Remove left whitespaces from text string
1.10 ! misho 52: *
1.2 misho 53: * @psLine = Text string
54: * return: 0 nothing to do; !=0 Removed bytes
55: */
1.5 misho 56: inline int
57: io_LTrimStr(u_char * __restrict psLine)
1.2 misho 58: {
59: int pos = 0;
60: u_char *s;
61:
62: if (!psLine || !*psLine)
63: return 0;
64:
65: for (s = psLine; isspace(*s); s++);
66: pos = s - psLine;
67:
68: memmove(psLine, s, (strlen((char*) psLine) - pos) + 1);
69: return pos;
70: }
71:
72: /*
73: * io_RTrimStr() Remove right whitespaces from text string
1.10 ! misho 74: *
1.2 misho 75: * @psLine = Text string
76: * return: 0 nothing to do; !=0 Removed bytes
77: */
1.5 misho 78: inline int
79: io_RTrimStr(u_char * __restrict psLine)
1.2 misho 80: {
81: u_char *t, *pos;
82:
83: if (!psLine || !*psLine)
84: return 0;
85:
86: pos = psLine + strlen((char*) psLine);
87: for (t = pos - 1; t > psLine && isspace(*t); t--);
88: *++t = 0;
89:
90: return pos - t;
91: }
92:
93: /*
94: * io_TrimStr() Remove left and right whitespaces from text string
1.10 ! misho 95: *
1.2 misho 96: * @psLine = Text string
97: * return: 0 nothing to do; !=0 Removed bytes
98: */
1.5 misho 99: inline int
100: io_TrimStr(u_char * __restrict psLine)
1.2 misho 101: {
102: int ret = 0;
103:
104: ret = io_LTrimStr(psLine);
105: ret += io_RTrimStr(psLine);
106:
107: return ret;
108: }
109:
110: /*
111: * io_UnquotStr() Remove quots from input text string
1.10 ! misho 112: *
1.2 misho 113: * @psLine = Text string
114: * return: 0 nothing to do; 1 successful unquoted string
115: */
1.5 misho 116: inline int
117: io_UnquotStr(u_char * __restrict psLine)
1.2 misho 118: {
119: char *pos, *str = NULL;
120: int flg;
121:
122: if (!psLine)
123: return 0;
124:
125: switch (*psLine) {
126: case '`':
127: case '"':
128: case '\'':
129: str = strdup((char*) psLine + 1);
130: for (pos = str, flg = 0; *pos; flg = ('\\' == *pos), pos++) {
131: if (!flg && *pos == *psLine) {
132: *pos = 0;
133: strlcpy((char*) psLine, str, strlen((char*) psLine) + 1);
134: break;
135: }
136: }
137: free(str);
138: return 1;
139: }
140:
141: return 0;
142: }
143:
144: /*
1.3 misho 145: * io_Ch2Hex() Convert from Char string to Hex string
1.10 ! misho 146: *
1.2 misho 147: * @psLine = Text string
148: * @lineLen = Length of Text string
1.3 misho 149: * return: NULL nothing to do or error; !=0 Allocated new converted data without term\0 (must be free)
1.2 misho 150: */
1.5 misho 151: inline u_char *
152: io_Ch2Hex(u_char *psLine, int lineLen)
1.2 misho 153: {
154: register int i;
1.3 misho 155: char szWork[3];
156: u_char *str;
1.2 misho 157:
158: if (!psLine || !*psLine || !lineLen)
159: return NULL;
160:
1.3 misho 161: str = malloc(lineLen / 2);
1.2 misho 162: if (!str) {
163: LOGERR;
164: return NULL;
165: } else
1.3 misho 166: memset(str, 0, lineLen / 2);
1.2 misho 167:
1.3 misho 168: for (i = 0; i < lineLen && psLine[i * 2]; i++) {
169: strlcpy(szWork, (char*) &psLine[i * 2], 3);
170: str[i] = (u_char) strtol(szWork, NULL, 16);
1.2 misho 171: }
172:
173: return str;
174: }
175:
176:
177: /*
1.3 misho 178: * io_Hex2Ch() Convert from Hex string to Char string
1.10 ! misho 179: *
1.2 misho 180: * @psLine = Text string
181: * @lineLen = Length of Text string
182: * return: NULL nothing to do or error; !=0 Allocated new converted string(must be free)
183: */
1.5 misho 184: inline char *
185: io_Hex2Ch(u_char *psLine, int lineLen)
1.2 misho 186: {
187: register int i;
188: char szWork[3], *str;
189:
190: if (!psLine || !*psLine || !lineLen)
191: return NULL;
192:
1.3 misho 193: str = malloc(lineLen * 2 + 1);
1.2 misho 194: if (!str) {
195: LOGERR;
196: return NULL;
197: } else
1.3 misho 198: memset(str, 0, lineLen * 2 + 1);
1.2 misho 199:
1.3 misho 200: for (i = 0; i <= lineLen; i++) {
201: memset(szWork, 0, 3);
202: snprintf(szWork, 3, "%02X", (u_char) psLine[i]);
203: strncat(str, szWork, 2);
1.2 misho 204: }
205:
206: return str;
207: }
1.5 misho 208:
209: /*
210: * io_CopyEnv() Copy environment to new environment array;
1.10 ! misho 211: *
1.5 misho 212: * @oldenv = Environment array
213: * return: NULL error; !=NULL Allocated new environment array(must be free)
214: */
215: char **
216: io_CopyEnv(const char **oldenv)
217: {
218: char **newenv, **el;
219: register int i, num;
220:
221: if (!oldenv)
222: return NULL;
223: else
224: newenv = el = NULL;
225:
226: /* count items environment */
227: for (i = num = 0; oldenv[i]; i++)
228: if (*strchr(oldenv[i], '='))
229: num++;
230:
231: /* create and copy new environment */
232: newenv = calloc(num + 1, sizeof(char*));
233: if (!newenv) {
234: LOGERR;
235: return NULL;
236: } else
237: el = newenv;
238:
239: for (i = 0; oldenv[i]; i++)
240: if (*strchr(oldenv[i], '=')) {
241: *el = strdup(oldenv[i]);
242: el++;
243: }
244: *el = NULL;
245:
246: return newenv;
247: }
248:
249: /*
250: * io_ExecArgs() Build exec arguments from other array
1.10 ! misho 251: *
1.5 misho 252: * @psProg = Program name for execute
253: * @oldarg = Arguments array
254: * return: NULL error; !=NULL Allocated execution array(must be free)
255: */
256: char **
257: io_ExecArgs(const char *psProg, const char **oldarg)
258: {
259: char **newarg, **el;
260: register int i, num;
261:
262: if (!psProg || !oldarg)
263: return NULL;
264: else
265: newarg = el = NULL;
266:
267: /* count items arguments */
268: for (num = 0; oldarg[num]; num++);
269:
270: /* create and copy new arguments */
271: newarg = calloc(num + 2, sizeof(char*));
272: if (!newarg) {
273: LOGERR;
274: return NULL;
275: } else
276: el = newarg;
277:
278: *el = strdup(psProg);
279: el++;
280:
281: for (i = 0; oldarg[i]; i++, el++)
282: *el = strdup(oldarg[i]);
283: *el = NULL;
284:
285: return newarg;
286: }
287:
288: /*
289: * io_FreeNullTerm() Free dynamic allocated null terminated array with strings
1.10 ! misho 290: *
1.5 misho 291: * @arr = Pointer to array for free
292: * return: none
293: */
294: inline void
295: io_FreeNullTerm(char *** __restrict arr)
296: {
297: char **a;
298:
299: if (arr && *arr) {
300: a = *arr;
301: while (a && *a)
302: free(*a++);
303: free(*arr);
304: *arr = NULL;
305: }
306: }
1.6 misho 307:
308: /*
1.9 misho 309: * io_Path2File() - Parse and make path/filename pair
310: *
311: * @csArgs = Input argument line
312: * @psPath = Output Path, if ==NULL path not returned
313: * @pathLen = Size of path array
314: * @psFile = Output File
315: * @fileLen = Size of file array
316: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
317: */
318: inline int
319: io_Path2File(const char * __restrict csArgs, char * __restrict psPath,
320: int pathLen, char * __restrict psFile, int fileLen)
321: {
322: char *pos, *psBuf;
323:
324: if (!csArgs || !psFile || !fileLen)
325: return -1;
326: if (psPath && !pathLen)
327: return -1;
328:
329: psBuf = strdup(csArgs);
330: if (!psBuf) {
331: LOGERR;
332: return -1;
333: }
334:
335: pos = strrchr(psBuf, '/');
336: if (!pos) {
337: strlcpy(psFile, psBuf, fileLen);
338:
339: free(psBuf);
340: return 1;
341: } else
342: *pos++ = 0;
343:
344: strlcpy(psFile, pos, fileLen);
345: if (psPath)
346: strlcpy(psPath, psBuf, pathLen);
347:
348: free(psBuf);
349: return 2;
350: }
351:
352: /*
1.6 misho 353: * io_ether_ntoa() Convert ethernet address to string
1.10 ! misho 354: *
1.6 misho 355: * @n = ethernet address structure, like struct ether_addr
356: * @a = string
357: * @len = string length
358: * return: NULL error or !=NULL string a
359: */
360: inline char *
361: io_ether_ntoa(const struct io_ether_addr *n, char * __restrict a, int len)
362: {
363: if (!n || !a)
364: return NULL;
365:
366: memset(a, 0, len);
367: if (snprintf(a, len, "%02x:%02x:%02x:%02x:%02x:%02x",
368: n->ether_addr_octet[0], n->ether_addr_octet[1],
369: n->ether_addr_octet[2], n->ether_addr_octet[3],
370: n->ether_addr_octet[4], n->ether_addr_octet[5]) < 17)
371: return NULL;
372:
373: return a;
374: }
375:
376: /*
377: * io_ether_aton() Convert string to ethernet address
1.10 ! misho 378: *
1.6 misho 379: * @a = string
380: * @e = ethernet address structure, like struct ether_addr
381: * return: NULL error or !=NULL ethernet address structure
382: */
383: inline struct io_ether_addr *
384: io_ether_aton(const char *a, struct io_ether_addr *e)
385: {
386: int i;
387: u_int o0, o1, o2, o3, o4, o5;
388:
389: if (!a || !e)
390: return NULL;
391:
392: i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
393: if (i != 6)
394: return NULL;
395:
396: e->ether_addr_octet[0] = o0;
397: e->ether_addr_octet[1] = o1;
398: e->ether_addr_octet[2] = o2;
399: e->ether_addr_octet[3] = o3;
400: e->ether_addr_octet[4] = o4;
401: e->ether_addr_octet[5] = o5;
402:
403: return e;
404: }
1.7 misho 405:
406: /*
407: * io_n2port() Extract port from network structure
1.10 ! misho 408: *
1.7 misho 409: * @addr = Address
410: * return: 0 not supported family type or port number
411: */
412: inline u_short
413: io_n2port(io_sockaddr_t * __restrict addr)
414: {
415: u_short port = 0;
416:
417: if (!addr)
418: return port;
419:
420: switch (addr->sa.sa_family) {
421: case AF_INET:
422: return ntohs(addr->sin.sin_port);
423: case AF_INET6:
424: return ntohs(addr->sin6.sin6_port);
425: default:
426: io_SetErr(ESOCKTNOSUPPORT, "Unsuported address family %d",
427: addr->sa.sa_family);
428: break;
429: }
430:
431: return port;
432: }
433:
434: /*
435: * io_n2addr() Extract address from network structure
1.10 ! misho 436: *
1.7 misho 437: * @addr = Address
438: * @val = Value for store string address
439: * return: NULL error or !=NULL string address from val
440: */
441: const char *
442: io_n2addr(io_sockaddr_t * __restrict addr, ait_val_t * __restrict val)
443: {
444: char str[INET6_ADDRSTRLEN] = { 0 };
445: const char *ret = NULL;
446:
447: if (!addr || !val)
448: return ret;
449:
450: switch (addr->sa.sa_family) {
451: case AF_INET:
452: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
453: LOGERR;
454: return ret;
455: } else
456: ret = str;
457: break;
458: case AF_INET6:
459: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
460: LOGERR;
461: return ret;
462: } else
463: ret = str;
464: break;
465: default:
466: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
467: addr->sa.sa_family);
468: return ret;
469: }
470:
1.8 misho 471: if (!AIT_ISEMPTY(val))
472: AIT_FREE_VAL(val);
1.7 misho 473: AIT_SET_STR(val, ret);
1.8 misho 474: return (const char*) AIT_GET_STR(val);
1.7 misho 475: }
476:
477: /*
478: * io_gethostbyname() Get host and port and make network structure
1.10 ! misho 479: *
1.7 misho 480: * @psHost = Hostname
481: * @port = Port
482: * @addr = Network address structure
483: * return: NULL error or !=NULL network structure
484: */
485: io_sockaddr_t *
486: io_gethostbyname(const char *psHost, u_short port, io_sockaddr_t * __restrict addr)
487: {
488: struct hostent *host;
489:
490: if (!psHost || !addr)
491: return NULL;
492:
493: /* resolver */
494: if (!addr->sa.sa_family)
495: host = gethostbyname(psHost);
496: else
497: host = gethostbyname2(psHost, addr->sa.sa_family);
498: if (!host) {
499: io_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
500: return NULL;
501: }
502:
503: memset(addr, 0, sizeof(io_sockaddr_t));
504: switch (host->h_addrtype) {
505: case AF_INET:
506: addr->sin.sin_len = sizeof(struct sockaddr_in);
507: addr->sin.sin_family = AF_INET;
508: addr->sin.sin_port = htons(port);
509: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
510: return addr;
511: case AF_INET6:
512: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
513: addr->sin6.sin6_family = AF_INET6;
514: addr->sin6.sin6_port = htons(port);
515: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
516: return addr;
517: default:
518: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
519: host->h_addrtype);
520: break;
521: }
522:
523: return NULL;
524: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>