Annotation of libaitio/src/tools.c, revision 1.12
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.12 ! misho 6: * $Id: tools.c,v 1.11.2.3 2012/05/14 15:26:50 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 == '\'') {
126: str = strdup(psLine + 1);
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: }
134: free(str);
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.3 misho 146: * return: NULL nothing to do or error; !=0 Allocated new converted data without term\0 (must be 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.3 misho 158: str = 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
179: * return: NULL nothing to do or error; !=0 Allocated new converted string(must be free)
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.3 misho 190: str = 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
210: * return: NULL error; !=NULL Allocated new environment array(must be free)
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 */
229: newenv = calloc(num + 1, sizeof(char*));
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], '=')) {
238: *el = strdup(oldenv[i]);
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
251: * return: NULL error; !=NULL Allocated execution array(must be free)
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 */
268: newarg = calloc(num + 2, sizeof(char*));
269: if (!newarg) {
270: LOGERR;
271: return NULL;
272: } else
273: el = newarg;
274:
275: *el = strdup(psProg);
276: el++;
277:
278: for (i = 0; oldarg[i]; i++, el++)
279: *el = strdup(oldarg[i]);
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)
299: free(*a++);
300: free(*arr);
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:
326: psBuf = strdup(csArgs);
327: if (!psBuf) {
328: LOGERR;
329: return -1;
330: }
331:
332: pos = strrchr(psBuf, '/');
333: if (!pos) {
334: strlcpy(psFile, psBuf, fileLen);
335:
336: free(psBuf);
337: return 1;
338: } else
339: *pos++ = 0;
340:
341: strlcpy(psFile, pos, fileLen);
342: if (psPath)
343: strlcpy(psPath, psBuf, pathLen);
344:
345: free(psBuf);
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: io_SetErr(ESOCKTNOSUPPORT, "Unsuported address family %d",
424: addr->sa.sa_family);
425: break;
426: }
427:
428: return port;
429: }
430:
431: /*
1.11 misho 432: * io_n2addr() - Extract address from network structure
1.10 misho 433: *
1.7 misho 434: * @addr = Address
435: * @val = Value for store string address
436: * return: NULL error or !=NULL string address from val
437: */
438: const char *
439: io_n2addr(io_sockaddr_t * __restrict addr, ait_val_t * __restrict val)
440: {
441: char str[INET6_ADDRSTRLEN] = { 0 };
442: const char *ret = NULL;
443:
444: if (!addr || !val)
445: return ret;
446:
447: switch (addr->sa.sa_family) {
448: case AF_INET:
449: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
450: LOGERR;
451: return ret;
452: } else
453: ret = str;
454: break;
455: case AF_INET6:
456: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
457: LOGERR;
458: return ret;
459: } else
460: ret = str;
461: break;
462: default:
463: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
464: addr->sa.sa_family);
465: return ret;
466: }
467:
468: AIT_SET_STR(val, ret);
1.8 misho 469: return (const char*) AIT_GET_STR(val);
1.7 misho 470: }
471:
472: /*
1.11 misho 473: * io_gethostbyname() - Get host and port and make network structure
1.10 misho 474: *
1.7 misho 475: * @psHost = Hostname
476: * @port = Port
477: * @addr = Network address structure
478: * return: NULL error or !=NULL network structure
479: */
480: io_sockaddr_t *
481: io_gethostbyname(const char *psHost, u_short port, io_sockaddr_t * __restrict addr)
482: {
1.12 ! misho 483: struct hostent *host = NULL;
1.7 misho 484:
485: if (!psHost || !addr)
486: return NULL;
1.12 ! misho 487: else
! 488: memset(addr, 0, sizeof(io_sockaddr_t));
1.7 misho 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;
! 499: } else
! 500: addr->sa.sa_family = host->h_addrtype;
! 501: } else
! 502: addr->sa.sa_family = AF_LOCAL;
1.7 misho 503:
1.12 ! misho 504: switch (addr->sa.sa_family) {
1.7 misho 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;
1.12 ! misho 517: case AF_LOCAL:
! 518: addr->sun.sun_len = sizeof(struct sockaddr_un);
! 519: addr->sun.sun_family = AF_LOCAL;
! 520: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
! 521: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
! 522: return addr;
1.7 misho 523: default:
1.12 ! misho 524: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
1.7 misho 525: break;
526: }
527:
528: return NULL;
529: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>