1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
6: * $Id: tools.c,v 1.11 2012/05/14 12:49:21 misho Exp $
7: *
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:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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: */
46: #include "global.h"
47: #include "aitio.h"
48:
49:
50: /*
51: * io_LTrimStr() - Remove left whitespaces from text string
52: *
53: * @psLine = Text string
54: * return: 0 nothing to do; !=0 Removed bytes
55: */
56: inline int
57: io_LTrimStr(char * __restrict psLine)
58: {
59: int pos = 0;
60: char *s;
61:
62: if (!psLine || !*psLine)
63: return 0;
64:
65: for (s = psLine; isspace((u_char) *s); s++);
66: pos = s - psLine;
67:
68: memmove(psLine, s, (strlen(psLine) - pos) + 1);
69: return pos;
70: }
71:
72: /*
73: * io_RTrimStr() - Remove right whitespaces from text string
74: *
75: * @psLine = Text string
76: * return: 0 nothing to do; !=0 Removed bytes
77: */
78: inline int
79: io_RTrimStr(char * __restrict psLine)
80: {
81: char *t, *pos;
82:
83: if (!psLine || !*psLine)
84: return 0;
85:
86: pos = psLine + strlen(psLine);
87: for (t = pos - 1; t > psLine && isspace((u_char) *t); t--);
88: *++t = 0;
89:
90: return pos - t;
91: }
92:
93: /*
94: * io_TrimStr() - Remove left and right whitespaces from text string
95: *
96: * @psLine = Text string
97: * return: 0 nothing to do; !=0 Removed bytes
98: */
99: inline int
100: io_TrimStr(char * __restrict psLine)
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
112: *
113: * @psLine = Text string
114: * return: 0 nothing to do; 1 successful unquoted string
115: */
116: inline int
117: io_UnquotStr(char * __restrict psLine)
118: {
119: char *pos, *str = NULL;
120: int flg;
121:
122: if (!psLine)
123: return 0;
124:
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;
132: }
133: }
134: free(str);
135: return 1;
136: }
137:
138: return 0;
139: }
140:
141: /*
142: * io_Ch2Hex() - Convert from Char string to Hex string
143: *
144: * @psLine = Text string
145: * @lineLen = Length of Text string
146: * return: NULL nothing to do or error; !=0 Allocated new converted data without term\0 (must be free)
147: */
148: inline u_char *
149: io_Ch2Hex(u_char *psLine, int lineLen)
150: {
151: register int i;
152: char szWork[3];
153: u_char *str;
154:
155: if (!psLine || !*psLine || !lineLen)
156: return NULL;
157:
158: str = malloc(lineLen / 2);
159: if (!str) {
160: LOGERR;
161: return NULL;
162: } else
163: memset(str, 0, lineLen / 2);
164:
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);
168: }
169:
170: return str;
171: }
172:
173:
174: /*
175: * io_Hex2Ch() - Convert from Hex string to Char string
176: *
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: */
181: inline char *
182: io_Hex2Ch(u_char *psLine, int lineLen)
183: {
184: register int i;
185: char szWork[3], *str;
186:
187: if (!psLine || !*psLine || !lineLen)
188: return NULL;
189:
190: str = malloc(lineLen * 2 + 1);
191: if (!str) {
192: LOGERR;
193: return NULL;
194: } else
195: memset(str, 0, lineLen * 2 + 1);
196:
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);
201: }
202:
203: return str;
204: }
205:
206: /*
207: * io_CopyEnv() - Copy environment to new environment array;
208: *
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: /*
247: * io_ExecArgs() - Build exec arguments from other array
248: *
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: /*
286: * io_FreeNullTerm() - Free dynamic allocated null terminated array with strings
287: *
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: }
304:
305: /*
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: /*
350: * io_ether_ntoa() - Convert ethernet address to string
351: *
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: /*
374: * io_ether_aton() - Convert string to ethernet address
375: *
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: }
402:
403: /*
404: * io_n2port() - Extract port from network structure
405: *
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: /*
432: * io_n2addr() - Extract address from network structure
433: *
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);
469: return (const char*) AIT_GET_STR(val);
470: }
471:
472: /*
473: * io_gethostbyname() - Get host and port and make network structure
474: *
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: {
483: struct hostent *host;
484:
485: if (!psHost || !addr)
486: return NULL;
487:
488: /* resolver */
489: if (!addr->sa.sa_family)
490: host = gethostbyname(psHost);
491: else
492: host = gethostbyname2(psHost, addr->sa.sa_family);
493: if (!host) {
494: io_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
495: return NULL;
496: }
497:
498: memset(addr, 0, sizeof(io_sockaddr_t));
499: switch (host->h_addrtype) {
500: case AF_INET:
501: addr->sin.sin_len = sizeof(struct sockaddr_in);
502: addr->sin.sin_family = AF_INET;
503: addr->sin.sin_port = htons(port);
504: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
505: return addr;
506: case AF_INET6:
507: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
508: addr->sin6.sin6_family = AF_INET6;
509: addr->sin6.sin6_port = htons(port);
510: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
511: return addr;
512: default:
513: io_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
514: host->h_addrtype);
515: break;
516: }
517:
518: return NULL;
519: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>