Annotation of libaitio/src/tools.c, revision 1.16.4.2
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.16.4.2! misho 6: * $Id: tools.c,v 1.16.4.1 2012/07/30 11:49:46 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.16.4.2! misho 306: * io_argsNum() Parse and calculate number of arguments
! 307: *
! 308: * @csArgs = Input arguments line
! 309: * @csDelim = Delimiter(s) for separate
! 310: * return: 0 error format; -1 error:: can`t read; >0 ok, number of items
! 311: */
! 312: inline int
! 313: io_argsNum(const char *csArgs, const char *csDelim)
! 314: {
! 315: register int res;
! 316: char *pos;
! 317:
! 318: assert(csArgs);
! 319: assert(csDelim);
! 320: if (!csArgs || !csDelim)
! 321: return -1;
! 322:
! 323: for (res = 1, pos = (char*) csArgs; (pos = strpbrk(pos, csDelim)); res++, pos++);
! 324: return res;
! 325: }
! 326:
! 327: /*
1.16.4.1 misho 328: * io_MakeAV() Parse and make attribute/value pair
329: *
330: * @csArgs = Input argument line
331: * @csDelim = Delimiter for separate
332: * @psAttr = Output Attribute
333: * @attrLen = Size of attribute array
334: * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
335: * @valLen = Size of value array
336: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
337: */
338: int
339: io_MakeAV(const char * __restrict csArgs, const char *csDelim,
340: char * __restrict psAttr, int attrLen, char * __restrict psValue, int valLen)
341: {
342: register int ret = 0;
343: char *pos, *psBuf;
344:
345: if (!csArgs || !csDelim || !psAttr || !attrLen)
346: return -1;
347: if (psValue && !valLen)
348: return -1;
349: else
350: memset(psValue, 0, valLen);
351: psBuf = io_strdup(csArgs);
352: if (!psBuf) {
353: LOGERR;
354: return -1;
355: }
356:
357: pos = strpbrk(psBuf, csDelim);
358: if (pos)
359: *pos++ = 0;
360: ret++;
361: strlcpy(psAttr, psBuf, attrLen);
362:
363: if (pos && *pos) {
364: ret++;
365: if (psValue)
366: strlcpy(psValue, pos, valLen);
367: }
368:
369: io_free(psBuf);
370: return ret;
371: }
372:
373: /*
374: * io_MakeAV2() Parse and make attribute/value pair over input string
375: *
376: * @csArgs = Input argument line, will be modified!
377: * @csDelim = Delimiter for separate
378: * @psAttr = Output Attribute
379: * @psValue = Output Value, if ==NULL this element not present value or not wanted for return
380: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
381: */
382: int
383: io_MakeAV2(char * __restrict psArgs, const char *csDelim,
384: char ** __restrict psAttr, char ** __restrict psValue)
385: {
386: register int ret = 0;
387: char *pos;
388:
389: if (!psArgs || !csDelim)
390: return -1;
391:
392: pos = strpbrk(psArgs, csDelim);
393: if (pos) {
394: *pos++ = 0;
395: ret++;
396: if (psAttr)
397: *psAttr = psArgs;
398: } else
399: return 0;
400:
401: if (psValue) {
402: if (pos && *pos) {
403: ret++;
404: *psValue = pos;
405: } else
406: *psValue = NULL;
407: }
408:
409: return ret;
410: }
411:
412: /*
1.9 misho 413: * io_Path2File() - Parse and make path/filename pair
414: *
415: * @csArgs = Input argument line
416: * @psPath = Output Path, if ==NULL path not returned
417: * @pathLen = Size of path array
418: * @psFile = Output File
419: * @fileLen = Size of file array
420: * return: 0 error format; -1 error:: can`t read; >0 ok, number of readed items
421: */
422: inline int
423: io_Path2File(const char * __restrict csArgs, char * __restrict psPath,
424: int pathLen, char * __restrict psFile, int fileLen)
425: {
426: char *pos, *psBuf;
427:
428: if (!csArgs || !psFile || !fileLen)
429: return -1;
430: if (psPath && !pathLen)
431: return -1;
432:
1.15 misho 433: psBuf = io_strdup(csArgs);
1.9 misho 434: if (!psBuf) {
435: LOGERR;
436: return -1;
437: }
438:
439: pos = strrchr(psBuf, '/');
440: if (!pos) {
441: strlcpy(psFile, psBuf, fileLen);
442:
1.15 misho 443: io_free(psBuf);
1.9 misho 444: return 1;
445: } else
446: *pos++ = 0;
447:
448: strlcpy(psFile, pos, fileLen);
449: if (psPath)
450: strlcpy(psPath, psBuf, pathLen);
451:
1.15 misho 452: io_free(psBuf);
1.9 misho 453: return 2;
454: }
455:
456: /*
1.11 misho 457: * io_ether_ntoa() - Convert ethernet address to string
1.10 misho 458: *
1.6 misho 459: * @n = ethernet address structure, like struct ether_addr
460: * @a = string
461: * @len = string length
462: * return: NULL error or !=NULL string a
463: */
464: inline char *
465: io_ether_ntoa(const struct io_ether_addr *n, char * __restrict a, int len)
466: {
467: if (!n || !a)
468: return NULL;
469:
470: memset(a, 0, len);
471: if (snprintf(a, len, "%02x:%02x:%02x:%02x:%02x:%02x",
472: n->ether_addr_octet[0], n->ether_addr_octet[1],
473: n->ether_addr_octet[2], n->ether_addr_octet[3],
474: n->ether_addr_octet[4], n->ether_addr_octet[5]) < 17)
475: return NULL;
476:
477: return a;
478: }
479:
480: /*
1.11 misho 481: * io_ether_aton() - Convert string to ethernet address
1.10 misho 482: *
1.6 misho 483: * @a = string
484: * @e = ethernet address structure, like struct ether_addr
485: * return: NULL error or !=NULL ethernet address structure
486: */
487: inline struct io_ether_addr *
488: io_ether_aton(const char *a, struct io_ether_addr *e)
489: {
490: int i;
491: u_int o0, o1, o2, o3, o4, o5;
492:
493: if (!a || !e)
494: return NULL;
495:
496: i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
497: if (i != 6)
498: return NULL;
499:
500: e->ether_addr_octet[0] = o0;
501: e->ether_addr_octet[1] = o1;
502: e->ether_addr_octet[2] = o2;
503: e->ether_addr_octet[3] = o3;
504: e->ether_addr_octet[4] = o4;
505: e->ether_addr_octet[5] = o5;
506:
507: return e;
508: }
1.7 misho 509:
510: /*
1.11 misho 511: * io_n2port() - Extract port from network structure
1.10 misho 512: *
1.7 misho 513: * @addr = Address
514: * return: 0 not supported family type or port number
515: */
516: inline u_short
517: io_n2port(io_sockaddr_t * __restrict addr)
518: {
519: u_short port = 0;
520:
521: if (!addr)
522: return port;
523:
524: switch (addr->sa.sa_family) {
525: case AF_INET:
526: return ntohs(addr->sin.sin_port);
527: case AF_INET6:
528: return ntohs(addr->sin6.sin6_port);
529: default:
530: break;
531: }
532:
533: return port;
534: }
535:
536: /*
1.11 misho 537: * io_n2addr() - Extract address from network structure
1.10 misho 538: *
1.7 misho 539: * @addr = Address
540: * @val = Value for store string address
541: * return: NULL error or !=NULL string address from val
542: */
543: const char *
544: io_n2addr(io_sockaddr_t * __restrict addr, ait_val_t * __restrict val)
545: {
546: char str[INET6_ADDRSTRLEN] = { 0 };
547: const char *ret = NULL;
548:
549: if (!addr || !val)
550: return ret;
551:
1.13 misho 552: AIT_INIT_VAL(val);
1.7 misho 553: switch (addr->sa.sa_family) {
554: case AF_INET:
555: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
556: LOGERR;
557: return ret;
558: } else
559: ret = str;
560: break;
561: case AF_INET6:
562: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
563: LOGERR;
564: return ret;
565: } else
566: ret = str;
567: break;
1.13 misho 568: case AF_LOCAL:
569: ret = addr->sun.sun_path;
570: break;
1.7 misho 571: default:
572: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
573: addr->sa.sa_family);
574: return ret;
575: }
576:
577: AIT_SET_STR(val, ret);
1.8 misho 578: return (const char*) AIT_GET_STR(val);
1.7 misho 579: }
580:
581: /*
1.11 misho 582: * io_gethostbyname() - Get host and port and make network structure
1.10 misho 583: *
1.7 misho 584: * @psHost = Hostname
585: * @port = Port
586: * @addr = Network address structure
587: * return: NULL error or !=NULL network structure
588: */
589: io_sockaddr_t *
590: io_gethostbyname(const char *psHost, u_short port, io_sockaddr_t * __restrict addr)
591: {
1.12 misho 592: struct hostent *host = NULL;
1.7 misho 593:
594: if (!psHost || !addr)
595: return NULL;
596:
1.12 misho 597: if (*psHost != '/') {
598: /* resolver */
599: if (!addr->sa.sa_family)
600: host = gethostbyname(psHost);
601: else
602: host = gethostbyname2(psHost, addr->sa.sa_family);
603: if (!host) {
604: io_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
605: return NULL;
1.16 misho 606: } else {
607: memset(addr, 0, sizeof(io_sockaddr_t));
1.12 misho 608: addr->sa.sa_family = host->h_addrtype;
1.16 misho 609: }
610: } else {
611: memset(addr, 0, sizeof(io_sockaddr_t));
1.12 misho 612: addr->sa.sa_family = AF_LOCAL;
1.16 misho 613: }
614:
1.7 misho 615:
1.12 misho 616: switch (addr->sa.sa_family) {
1.7 misho 617: case AF_INET:
618: addr->sin.sin_len = sizeof(struct sockaddr_in);
619: addr->sin.sin_family = AF_INET;
620: addr->sin.sin_port = htons(port);
621: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
622: return addr;
623: case AF_INET6:
624: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
625: addr->sin6.sin6_family = AF_INET6;
626: addr->sin6.sin6_port = htons(port);
627: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
628: return addr;
1.12 misho 629: case AF_LOCAL:
630: addr->sun.sun_len = sizeof(struct sockaddr_un);
631: addr->sun.sun_family = AF_LOCAL;
632: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
633: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
634: return addr;
1.7 misho 635: default:
1.12 misho 636: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
1.7 misho 637: break;
638: }
639:
640: return NULL;
641: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>