Annotation of libaitio/src/tools.c, revision 1.15.2.1
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.15.2.1! misho 6: * $Id: tools.c,v 1.15 2012/07/03 08:51:05 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: /*
1.11 misho 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
1.11 misho 57: io_LTrimStr(char * __restrict psLine)
1.2 misho 58: {
59: int pos = 0;
1.11 misho 60: char *s;
1.2 misho 61:
62: if (!psLine || !*psLine)
63: return 0;
64:
1.11 misho 65: for (s = psLine; isspace((u_char) *s); s++);
1.2 misho 66: pos = s - psLine;
67:
1.11 misho 68: memmove(psLine, s, (strlen(psLine) - pos) + 1);
1.2 misho 69: return pos;
70: }
71:
72: /*
1.11 misho 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
1.11 misho 79: io_RTrimStr(char * __restrict psLine)
1.2 misho 80: {
1.11 misho 81: char *t, *pos;
1.2 misho 82:
83: if (!psLine || !*psLine)
84: return 0;
85:
1.11 misho 86: pos = psLine + strlen(psLine);
87: for (t = pos - 1; t > psLine && isspace((u_char) *t); t--);
1.2 misho 88: *++t = 0;
89:
90: return pos - t;
91: }
92:
93: /*
1.11 misho 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
1.11 misho 100: io_TrimStr(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: /*
1.11 misho 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
1.11 misho 117: io_UnquotStr(char * __restrict psLine)
1.2 misho 118: {
119: char *pos, *str = NULL;
120: int flg;
121:
122: if (!psLine)
123: return 0;
124:
1.11 misho 125: if (*psLine == '"' || *psLine == '\'') {
1.15 misho 126: str = io_strdup(psLine + 1);
1.11 misho 127: for (pos = str, flg = 0; *pos; flg = ('\\' == *pos), pos++) {
128: if (!flg && *pos == *psLine) {
129: *pos = 0;
130: strlcpy(psLine, str, strlen(psLine) + 1);
131: break;
1.2 misho 132: }
1.11 misho 133: }
1.15 misho 134: io_free(str);
1.11 misho 135: return 1;
1.2 misho 136: }
137:
138: return 0;
139: }
140:
141: /*
1.11 misho 142: * io_Ch2Hex() - Convert from Char string to Hex string
1.10 misho 143: *
1.2 misho 144: * @psLine = Text string
145: * @lineLen = Length of Text string
1.15 misho 146: * return: NULL nothing to do or error; !=0 Allocated new converted data without term\0 (must be io_free)
1.2 misho 147: */
1.5 misho 148: inline u_char *
149: io_Ch2Hex(u_char *psLine, int lineLen)
1.2 misho 150: {
151: register int i;
1.3 misho 152: char szWork[3];
153: u_char *str;
1.2 misho 154:
155: if (!psLine || !*psLine || !lineLen)
156: return NULL;
157:
1.15 misho 158: str = io_malloc(lineLen / 2);
1.2 misho 159: if (!str) {
160: LOGERR;
161: return NULL;
162: } else
1.3 misho 163: memset(str, 0, lineLen / 2);
1.2 misho 164:
1.3 misho 165: for (i = 0; i < lineLen && psLine[i * 2]; i++) {
166: strlcpy(szWork, (char*) &psLine[i * 2], 3);
167: str[i] = (u_char) strtol(szWork, NULL, 16);
1.2 misho 168: }
169:
170: return str;
171: }
172:
173:
174: /*
1.11 misho 175: * io_Hex2Ch() - Convert from Hex string to Char string
1.10 misho 176: *
1.2 misho 177: * @psLine = Text string
178: * @lineLen = Length of Text string
1.15 misho 179: * return: NULL nothing to do or error; !=0 Allocated new converted string(must be io_free)
1.2 misho 180: */
1.5 misho 181: inline char *
182: io_Hex2Ch(u_char *psLine, int lineLen)
1.2 misho 183: {
184: register int i;
185: char szWork[3], *str;
186:
187: if (!psLine || !*psLine || !lineLen)
188: return NULL;
189:
1.15 misho 190: str = io_malloc(lineLen * 2 + 1);
1.2 misho 191: if (!str) {
192: LOGERR;
193: return NULL;
194: } else
1.3 misho 195: memset(str, 0, lineLen * 2 + 1);
1.2 misho 196:
1.3 misho 197: for (i = 0; i <= lineLen; i++) {
198: memset(szWork, 0, 3);
199: snprintf(szWork, 3, "%02X", (u_char) psLine[i]);
200: strncat(str, szWork, 2);
1.2 misho 201: }
202:
203: return str;
204: }
1.5 misho 205:
206: /*
1.11 misho 207: * io_CopyEnv() - Copy environment to new environment array;
1.10 misho 208: *
1.5 misho 209: * @oldenv = Environment array
1.15 misho 210: * return: NULL error; !=NULL Allocated new environment array(must be io_free)
1.5 misho 211: */
212: char **
213: io_CopyEnv(const char **oldenv)
214: {
215: char **newenv, **el;
216: register int i, num;
217:
218: if (!oldenv)
219: return NULL;
220: else
221: newenv = el = NULL;
222:
223: /* count items environment */
224: for (i = num = 0; oldenv[i]; i++)
225: if (*strchr(oldenv[i], '='))
226: num++;
227:
228: /* create and copy new environment */
1.15 misho 229: newenv = io_calloc(num + 1, sizeof(char*));
1.5 misho 230: if (!newenv) {
231: LOGERR;
232: return NULL;
233: } else
234: el = newenv;
235:
236: for (i = 0; oldenv[i]; i++)
237: if (*strchr(oldenv[i], '=')) {
1.15 misho 238: *el = io_strdup(oldenv[i]);
1.5 misho 239: el++;
240: }
241: *el = NULL;
242:
243: return newenv;
244: }
245:
246: /*
1.11 misho 247: * io_ExecArgs() - Build exec arguments from other array
1.10 misho 248: *
1.5 misho 249: * @psProg = Program name for execute
250: * @oldarg = Arguments array
1.15 misho 251: * return: NULL error; !=NULL Allocated execution array(must be io_free)
1.5 misho 252: */
253: char **
254: io_ExecArgs(const char *psProg, const char **oldarg)
255: {
256: char **newarg, **el;
257: register int i, num;
258:
259: if (!psProg || !oldarg)
260: return NULL;
261: else
262: newarg = el = NULL;
263:
264: /* count items arguments */
265: for (num = 0; oldarg[num]; num++);
266:
267: /* create and copy new arguments */
1.15 misho 268: newarg = io_calloc(num + 2, sizeof(char*));
1.5 misho 269: if (!newarg) {
270: LOGERR;
271: return NULL;
272: } else
273: el = newarg;
274:
1.15 misho 275: *el = io_strdup(psProg);
1.5 misho 276: el++;
277:
278: for (i = 0; oldarg[i]; i++, el++)
1.15 misho 279: *el = io_strdup(oldarg[i]);
1.5 misho 280: *el = NULL;
281:
282: return newarg;
283: }
284:
285: /*
1.11 misho 286: * io_FreeNullTerm() - Free dynamic allocated null terminated array with strings
1.10 misho 287: *
1.5 misho 288: * @arr = Pointer to array for free
289: * return: none
290: */
291: inline void
292: io_FreeNullTerm(char *** __restrict arr)
293: {
294: char **a;
295:
296: if (arr && *arr) {
297: a = *arr;
298: while (a && *a)
1.15 misho 299: io_free(*a++);
300: io_free(*arr);
1.5 misho 301: *arr = NULL;
302: }
303: }
1.6 misho 304:
305: /*
1.9 misho 306: * io_Path2File() - Parse and make path/filename pair
307: *
308: * @csArgs = Input argument line
309: * @psPath = Output Path, if ==NULL path not returned
310: * @pathLen = Size of path array
311: * @psFile = Output File
312: * @fileLen = Size of file array
313: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
314: */
315: inline int
316: io_Path2File(const char * __restrict csArgs, char * __restrict psPath,
317: int pathLen, char * __restrict psFile, int fileLen)
318: {
319: char *pos, *psBuf;
320:
321: if (!csArgs || !psFile || !fileLen)
322: return -1;
323: if (psPath && !pathLen)
324: return -1;
325:
1.15 misho 326: psBuf = io_strdup(csArgs);
1.9 misho 327: if (!psBuf) {
328: LOGERR;
329: return -1;
330: }
331:
332: pos = strrchr(psBuf, '/');
333: if (!pos) {
334: strlcpy(psFile, psBuf, fileLen);
335:
1.15 misho 336: io_free(psBuf);
1.9 misho 337: return 1;
338: } else
339: *pos++ = 0;
340:
341: strlcpy(psFile, pos, fileLen);
342: if (psPath)
343: strlcpy(psPath, psBuf, pathLen);
344:
1.15 misho 345: io_free(psBuf);
1.9 misho 346: return 2;
347: }
348:
349: /*
1.11 misho 350: * io_ether_ntoa() - Convert ethernet address to string
1.10 misho 351: *
1.6 misho 352: * @n = ethernet address structure, like struct ether_addr
353: * @a = string
354: * @len = string length
355: * return: NULL error or !=NULL string a
356: */
357: inline char *
358: io_ether_ntoa(const struct io_ether_addr *n, char * __restrict a, int len)
359: {
360: if (!n || !a)
361: return NULL;
362:
363: memset(a, 0, len);
364: if (snprintf(a, len, "%02x:%02x:%02x:%02x:%02x:%02x",
365: n->ether_addr_octet[0], n->ether_addr_octet[1],
366: n->ether_addr_octet[2], n->ether_addr_octet[3],
367: n->ether_addr_octet[4], n->ether_addr_octet[5]) < 17)
368: return NULL;
369:
370: return a;
371: }
372:
373: /*
1.11 misho 374: * io_ether_aton() - Convert string to ethernet address
1.10 misho 375: *
1.6 misho 376: * @a = string
377: * @e = ethernet address structure, like struct ether_addr
378: * return: NULL error or !=NULL ethernet address structure
379: */
380: inline struct io_ether_addr *
381: io_ether_aton(const char *a, struct io_ether_addr *e)
382: {
383: int i;
384: u_int o0, o1, o2, o3, o4, o5;
385:
386: if (!a || !e)
387: return NULL;
388:
389: i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
390: if (i != 6)
391: return NULL;
392:
393: e->ether_addr_octet[0] = o0;
394: e->ether_addr_octet[1] = o1;
395: e->ether_addr_octet[2] = o2;
396: e->ether_addr_octet[3] = o3;
397: e->ether_addr_octet[4] = o4;
398: e->ether_addr_octet[5] = o5;
399:
400: return e;
401: }
1.7 misho 402:
403: /*
1.11 misho 404: * io_n2port() - Extract port from network structure
1.10 misho 405: *
1.7 misho 406: * @addr = Address
407: * return: 0 not supported family type or port number
408: */
409: inline u_short
410: io_n2port(io_sockaddr_t * __restrict addr)
411: {
412: u_short port = 0;
413:
414: if (!addr)
415: return port;
416:
417: switch (addr->sa.sa_family) {
418: case AF_INET:
419: return ntohs(addr->sin.sin_port);
420: case AF_INET6:
421: return ntohs(addr->sin6.sin6_port);
422: default:
423: break;
424: }
425:
426: return port;
427: }
428:
429: /*
1.11 misho 430: * io_n2addr() - Extract address from network structure
1.10 misho 431: *
1.7 misho 432: * @addr = Address
433: * @val = Value for store string address
434: * return: NULL error or !=NULL string address from val
435: */
436: const char *
437: io_n2addr(io_sockaddr_t * __restrict addr, ait_val_t * __restrict val)
438: {
439: char str[INET6_ADDRSTRLEN] = { 0 };
440: const char *ret = NULL;
441:
442: if (!addr || !val)
443: return ret;
444:
1.13 misho 445: AIT_INIT_VAL(val);
1.7 misho 446: switch (addr->sa.sa_family) {
447: case AF_INET:
448: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
449: LOGERR;
450: return ret;
451: } else
452: ret = str;
453: break;
454: case AF_INET6:
455: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
456: LOGERR;
457: return ret;
458: } else
459: ret = str;
460: break;
1.13 misho 461: case AF_LOCAL:
462: ret = addr->sun.sun_path;
463: break;
1.7 misho 464: default:
465: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
466: addr->sa.sa_family);
467: return ret;
468: }
469:
470: AIT_SET_STR(val, ret);
1.8 misho 471: return (const char*) AIT_GET_STR(val);
1.7 misho 472: }
473:
474: /*
1.11 misho 475: * io_gethostbyname() - Get host and port and make network structure
1.10 misho 476: *
1.7 misho 477: * @psHost = Hostname
478: * @port = Port
479: * @addr = Network address structure
480: * return: NULL error or !=NULL network structure
481: */
482: io_sockaddr_t *
483: io_gethostbyname(const char *psHost, u_short port, io_sockaddr_t * __restrict addr)
484: {
1.12 misho 485: struct hostent *host = NULL;
1.7 misho 486:
487: if (!psHost || !addr)
488: return NULL;
489:
1.12 misho 490: if (*psHost != '/') {
491: /* resolver */
492: if (!addr->sa.sa_family)
493: host = gethostbyname(psHost);
494: else
495: host = gethostbyname2(psHost, addr->sa.sa_family);
496: if (!host) {
497: io_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
498: return NULL;
1.15.2.1! misho 499: } else {
! 500: memset(addr, 0, sizeof(io_sockaddr_t));
1.12 misho 501: addr->sa.sa_family = host->h_addrtype;
1.15.2.1! misho 502: }
! 503: } else {
! 504: memset(addr, 0, sizeof(io_sockaddr_t));
1.12 misho 505: addr->sa.sa_family = AF_LOCAL;
1.15.2.1! misho 506: }
! 507:
1.7 misho 508:
1.12 misho 509: switch (addr->sa.sa_family) {
1.7 misho 510: case AF_INET:
511: addr->sin.sin_len = sizeof(struct sockaddr_in);
512: addr->sin.sin_family = AF_INET;
513: addr->sin.sin_port = htons(port);
514: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
515: return addr;
516: case AF_INET6:
517: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
518: addr->sin6.sin6_family = AF_INET6;
519: addr->sin6.sin6_port = htons(port);
520: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
521: return addr;
1.12 misho 522: case AF_LOCAL:
523: addr->sun.sun_len = sizeof(struct sockaddr_un);
524: addr->sun.sun_family = AF_LOCAL;
525: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
526: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
527: return addr;
1.7 misho 528: default:
1.12 misho 529: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
1.7 misho 530: break;
531: }
532:
533: return NULL;
534: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>