| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-01-06 16:53:44 -08:00
										 |  |  |  *  Copyright (C) 2013-2022 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-01-25 10:15:50 -05:00
										 |  |  |  *  Copyright (C) 2007-2013 Sourcefire, Inc. | 
					
						
							| 
									
										
										
										
											2008-04-02 15:24:51 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  Authors: Tomasz Kojm, Nigel Horne, Török Edvin | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-03-05 16:34:35 -05:00
										 |  |  |  *  Acknowledgements: cli_strcasestr() contains a public domain code from: | 
					
						
							|  |  |  |  *                    http://unixpapa.com/incnote/string.html
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  This program is free software; you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2007-03-31 20:31:04 +00:00
										 |  |  |  *  it under the terms of the GNU General Public License version 2 as | 
					
						
							|  |  |  |  *  published by the Free Software Foundation. | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  *  GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  *  along with this program; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-04-09 19:59:28 +00:00
										 |  |  |  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | 
					
						
							|  |  |  |  *  MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-06 13:46:08 +00:00
										 |  |  | #if HAVE_CONFIG_H
 | 
					
						
							|  |  |  | #include "clamav-config.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-03-09 22:46:28 +00:00
										 |  |  | #include "str.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  | #include <limits.h>
 | 
					
						
							| 
									
										
										
										
											2008-10-13 11:17:35 +00:00
										 |  |  | #ifdef HAVE_STRINGS_H
 | 
					
						
							|  |  |  | #include <strings.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "clamav.h"
 | 
					
						
							|  |  |  | #include "others.h"
 | 
					
						
							| 
									
										
										
										
											2007-03-28 21:38:07 +00:00
										 |  |  | #include "matcher.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | #include "jsparse/textbuf.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  | #include "platform.h"
 | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:37:58 -05:00
										 |  |  | // clang-format off
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 08:15:26 +00:00
										 |  |  | static const int hex_chars[256] = { | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |      0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  |     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:37:58 -05:00
										 |  |  | // clang-format on
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-16 08:15:26 +00:00
										 |  |  | static inline int cli_hex2int(const char c) | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     return hex_chars[(const unsigned char)c]; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | int cli_realhex2ui(const char *hex, uint16_t *ptr, unsigned int len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint16_t val; | 
					
						
							|  |  |  |     unsigned int i; | 
					
						
							|  |  |  |     int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i += 2) { | 
					
						
							|  |  |  |         val = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hex[i] == '?' && hex[i + 1] == '?') { | 
					
						
							|  |  |  |             val |= CLI_MATCH_IGNORE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else if (hex[i + 1] == '?') { | 
					
						
							|  |  |  |             if ((c = cli_hex2int(hex[i])) >= 0) { | 
					
						
							|  |  |  |                 val = c << 4; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             val |= CLI_MATCH_NIBBLE_HIGH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else if (hex[i] == '?') { | 
					
						
							|  |  |  |             if ((c = cli_hex2int(hex[i + 1])) >= 0) { | 
					
						
							|  |  |  |                 val = c; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             val |= CLI_MATCH_NIBBLE_LOW; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         } else if (hex[i] == '(') { | 
					
						
							|  |  |  |             val |= CLI_MATCH_SPECIAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if ((c = cli_hex2int(hex[i])) >= 0) { | 
					
						
							|  |  |  |                 val = c; | 
					
						
							|  |  |  |                 if ((c = cli_hex2int(hex[i + 1])) >= 0) { | 
					
						
							|  |  |  |                     val = (val << 4) + c; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     return 0; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *ptr++ = val; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-11-04 21:45:49 +00:00
										 |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint16_t *cli_hex2ui(const char *hex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     uint16_t *str; | 
					
						
							|  |  |  |     unsigned int len; | 
					
						
							| 
									
										
										
										
											2008-11-04 21:45:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     len = strlen(hex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (len % 2 != 0) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         cli_errmsg("cli_hex2ui(): Malformed hexstring: %s (length: %u)\n", hex, | 
					
						
							|  |  |  |                    len); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2008-11-04 21:45:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     str = cli_calloc((len / 2) + 1, sizeof(uint16_t)); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!str) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (cli_realhex2ui(hex, str, len)) | 
					
						
							| 
									
										
										
										
											2008-11-04 21:45:49 +00:00
										 |  |  |         return str; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-04 21:45:49 +00:00
										 |  |  |     free(str); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  | char *cli_hex2str(const char *hex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-19 16:10:37 +01:00
										 |  |  |     char *str; | 
					
						
							| 
									
										
										
										
											2009-03-09 11:22:57 +00:00
										 |  |  |     size_t len; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     len = strlen(hex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (len % 2 != 0) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         cli_errmsg("cli_hex2str(): Malformed hexstring: %s (length: %u)\n", hex, | 
					
						
							|  |  |  |                    (unsigned)len); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     str = cli_calloc((len / 2) + 1, sizeof(char)); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!str) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-09 11:22:57 +00:00
										 |  |  |     if (cli_hex2str_to(hex, str, len) == -1) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         free(str); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2009-03-09 11:22:57 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     return str; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-19 16:10:37 +01:00
										 |  |  | int cli_hex2str_to(const char *hex, char *ptr, size_t len) | 
					
						
							| 
									
										
										
										
											2009-03-09 11:22:57 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t i; | 
					
						
							|  |  |  |     int c; | 
					
						
							| 
									
										
										
										
											2010-02-19 16:10:37 +01:00
										 |  |  |     char val; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; i < len; i += 2) { | 
					
						
							|  |  |  |         if ((c = cli_hex2int(hex[i])) >= 0) { | 
					
						
							|  |  |  |             val = c; | 
					
						
							|  |  |  |             if ((c = cli_hex2int(hex[i + 1])) >= 0) { | 
					
						
							|  |  |  |                 val = (val << 4) + c; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *ptr++ = val; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-09 11:22:57 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2004-07-13 03:30:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-20 04:14:06 +00:00
										 |  |  | int cli_hex2num(const char *hex) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     int hexval, ret = 0, len, i; | 
					
						
							| 
									
										
										
										
											2005-02-20 04:14:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     len = strlen(hex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (len % 2 != 0) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         cli_errmsg("cli_hex2num(): Malformed hexstring: %s (length: %d)\n", hex, | 
					
						
							|  |  |  |                    len); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2005-02-20 04:14:06 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         if ((hexval = cli_hex2int(hex[i])) < 0) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         ret = (ret << 4) | hexval; | 
					
						
							| 
									
										
										
										
											2005-02-20 04:14:06 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-23 17:17:08 -05:00
										 |  |  | int cli_xtoi(const char *hex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int len, val, i; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     char *hexbuf; | 
					
						
							| 
									
										
										
										
											2015-02-23 17:17:08 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     len = strlen(hex); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (len % 2 == 0) | 
					
						
							| 
									
										
										
										
											2015-02-23 17:17:08 -05:00
										 |  |  |         return cli_hex2num(hex); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     hexbuf = cli_calloc(len + 2, sizeof(char)); | 
					
						
							| 
									
										
										
										
											2015-02-23 17:17:08 -05:00
										 |  |  |     if (hexbuf == NULL) { | 
					
						
							|  |  |  |         cli_errmsg("cli_xtoi(): cli_malloc fails.\n"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < len; i++) | 
					
						
							|  |  |  |         hexbuf[i + 1] = hex[i]; | 
					
						
							| 
									
										
										
										
											2015-02-23 17:17:08 -05:00
										 |  |  |     val = cli_hex2num(hexbuf); | 
					
						
							|  |  |  |     free(hexbuf); | 
					
						
							|  |  |  |     return val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-19 17:54:40 +00:00
										 |  |  | char *cli_str2hex(const char *string, unsigned int len) | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     char *hexstr; | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |     char HEX[] = {'0', '1', '2', '3', '4', '5', '6', '7', | 
					
						
							|  |  |  |                   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     unsigned int i, j; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if ((hexstr = (char *)cli_calloc(2 * len + 1, sizeof(char))) == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0, j = 0; i < len; i++, j += 2) { | 
					
						
							|  |  |  |         hexstr[j]     = HEX[(string[i] >> 4) & 0xf]; | 
					
						
							|  |  |  |         hexstr[j + 1] = HEX[string[i] & 0xf]; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return hexstr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int cli_strbcasestr(const char *haystack, const char *needle) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     const char *pt = haystack; | 
					
						
							|  |  |  |     int i, j; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     i = strlen(haystack); | 
					
						
							|  |  |  |     j = strlen(needle); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (i < j) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     pt += i - j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return !strcasecmp(pt, needle); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 15:09:52 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief Remove trailing NL and CR characters from the end of the given string. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param string    string input | 
					
						
							|  |  |  |  * @return int      the new length of the string (ala strlen) | 
					
						
							|  |  |  |  * @return int      -1 if string was NULL. | 
					
						
							| 
									
										
										
										
											2004-06-22 10:58:58 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | int cli_chomp(char *string) | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     int l; | 
					
						
							| 
									
										
										
										
											2003-11-23 22:42:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (string == NULL) | 
					
						
							|  |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2003-11-24 16:19:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     l = strlen(string); | 
					
						
							| 
									
										
										
										
											2003-12-12 20:09:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (l == 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2003-12-12 20:09:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     --l; | 
					
						
							| 
									
										
										
										
											2004-06-22 10:58:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     while ((l >= 0) && ((string[l] == '\n') || (string[l] == '\r'))) | 
					
						
							|  |  |  |         string[l--] = '\0'; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     return l + 1; | 
					
						
							| 
									
										
										
										
											2004-06-22 10:58:58 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2003-12-12 20:09:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * char *cli_strok(const char *line, int fieldno, char *delim) | 
					
						
							|  |  |  |  * Return a copy of field <fieldno> from the string <line>, where | 
					
						
							|  |  |  |  * fields are delimited by any char from <delim>, or NULL if <line> | 
					
						
							|  |  |  |  * doesn't have <fieldno> fields or not enough memory is available. | 
					
						
							|  |  |  |  * The caller has to free() the result afterwards. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2004-03-09 22:46:28 +00:00
										 |  |  | char *cli_strtok(const char *line, int fieldno, const char *delim) | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     int counter  = 0, i, j; | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  |     char *buffer = NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 16:19:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  |     /* step to arg # <fieldno> */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; line[i] && counter != fieldno; i++) { | 
					
						
							|  |  |  |         if (strchr(delim, line[i])) { | 
					
						
							|  |  |  |             counter++; | 
					
						
							|  |  |  |             while (line[i + 1] && strchr(delim, line[i + 1])) { | 
					
						
							|  |  |  |                 i++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (!line[i]) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         /* end of buffer before field reached */ | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (j = i; line[j]; j++) { | 
					
						
							|  |  |  |         if (strchr(delim, line[j])) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (i == j) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2003-11-24 16:19:39 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     buffer = cli_malloc(j - i + 1); | 
					
						
							|  |  |  |     if (!buffer) { | 
					
						
							| 
									
										
										
										
											2013-03-01 13:51:15 -05:00
										 |  |  |         cli_errmsg("cli_strtok: Unable to allocate memory for buffer\n"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     strncpy(buffer, line + i, j - i); | 
					
						
							|  |  |  |     buffer[j - i] = '\0'; | 
					
						
							| 
									
										
										
										
											2003-12-02 22:48:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return buffer; | 
					
						
							| 
									
										
										
										
											2003-07-29 15:48:06 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Like cli_strtok, but this puts the output into a given argument, rather | 
					
						
							|  |  |  |  * than allocating fresh memory | 
					
						
							|  |  |  |  * Returns NULL for error, or a pointer to output | 
					
						
							|  |  |  |  * njh@bandsman.co.uk | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | char *cli_strtokbuf(const char *input, int fieldno, const char *delim, | 
					
						
							|  |  |  |                     char *output) | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     int counter = 0, i, j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* step to arg # <fieldno> */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; input[i] && counter != fieldno; i++) { | 
					
						
							|  |  |  |         if (strchr(delim, input[i])) { | 
					
						
							|  |  |  |             counter++; | 
					
						
							|  |  |  |             while (input[i + 1] && strchr(delim, input[i + 1])) { | 
					
						
							|  |  |  |                 i++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (input[i] == '\0') { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         /* end of buffer before field reached */ | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (j = i; input[j]; j++) { | 
					
						
							|  |  |  |         if (strchr(delim, input[j])) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (i == j) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     strncpy(output, input + i, j - i); | 
					
						
							|  |  |  |     output[j - i] = '\0'; | 
					
						
							| 
									
										
										
										
											2004-10-13 20:23:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return output; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-05 21:15:41 -05:00
										 |  |  | const char *cli_memstr(const char *haystack, size_t hs, const char *needle, size_t ns) | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-05 21:15:41 -05:00
										 |  |  |     size_t i, s1, s2; | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!hs || !ns || hs < ns) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (needle == haystack) | 
					
						
							|  |  |  |         return haystack; | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (ns == 1) | 
					
						
							|  |  |  |         return memchr(haystack, needle[0], hs); | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (needle[0] == needle[1]) { | 
					
						
							|  |  |  |         s1 = 2; | 
					
						
							|  |  |  |         s2 = 1; | 
					
						
							| 
									
										
										
										
											2009-08-24 22:09:38 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         s1 = 1; | 
					
						
							|  |  |  |         s2 = 2; | 
					
						
							| 
									
										
										
										
											2009-08-24 22:09:38 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; i <= hs - ns;) { | 
					
						
							|  |  |  |         if (needle[1] != haystack[i + 1]) { | 
					
						
							|  |  |  |             i += s1; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |             if ((needle[0] == haystack[i]) && | 
					
						
							|  |  |  |                 !memcmp(needle + 2, haystack + i + 2, ns - 2)) | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                 return &haystack[i]; | 
					
						
							|  |  |  |             i += s2; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2005-01-15 17:36:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-06-20 16:54:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | char *cli_strrcpy(char *dest, const char *source) /* by NJH */ | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!dest || !source) { | 
					
						
							|  |  |  |         cli_errmsg("cli_strrcpy: NULL argument\n"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2006-06-20 16:54:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |     while ((*dest++ = *source++)) | 
					
						
							|  |  |  |         ; | 
					
						
							| 
									
										
										
										
											2006-06-20 16:54:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return --dest; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  | const char *__cli_strcasestr(const char *haystack, const char *needle) | 
					
						
							| 
									
										
										
										
											2007-12-28 15:13:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     size_t l; | 
					
						
							|  |  |  |     char f[3]; | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     const size_t strlen_a = strlen(haystack); | 
					
						
							|  |  |  |     const size_t strlen_b = strlen(needle); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     f[0] = tolower(*needle); | 
					
						
							|  |  |  |     f[1] = toupper(*needle); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     f[2] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     for (l = strcspn(haystack, f); l != strlen_a; l += strcspn(haystack + l + 1, f) + 1) | 
					
						
							|  |  |  |         if (strncasecmp(haystack + l, needle, strlen_b) == 0) | 
					
						
							|  |  |  |             return (haystack + l); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     return (NULL); | 
					
						
							| 
									
										
										
										
											2007-12-28 15:13:12 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-16 17:03:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  | char *__cli_strndup(const char *s, size_t n) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:03:39 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     char *alloc; | 
					
						
							|  |  |  |     size_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!s) { | 
					
						
							| 
									
										
										
										
											2017-08-16 17:03:39 -04:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     len   = CLI_STRNLEN(s, n); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     alloc = malloc(len + 1); | 
					
						
							| 
									
										
										
										
											2017-08-16 17:03:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!alloc) { | 
					
						
							| 
									
										
										
										
											2017-08-16 17:03:39 -04:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |         memcpy(alloc, s, len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     alloc[len] = '\0'; | 
					
						
							|  |  |  |     return alloc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  | size_t __cli_strnlen(const char *s, size_t n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     size_t i = 0; | 
					
						
							|  |  |  |     for (; (i < n) && s[i] != '\0'; ++i) | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  |     return i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-02 13:05:17 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * @brief Find the first occurrence of find in s. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The search is limited to the first slen characters of s. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> | 
					
						
							|  |  |  |  * Copyright (c) 1990, 1993 | 
					
						
							|  |  |  |  * The Regents of the University of California.  All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This code is derived from software contributed to Berkeley by | 
					
						
							|  |  |  |  * Chris Torek. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 1990 The Regents of the University of California. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param s      haystack | 
					
						
							|  |  |  |  * @param find   needle | 
					
						
							|  |  |  |  * @param slen   haystack length | 
					
						
							|  |  |  |  * @return char* Address of the needle, if found, else NULL. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  | char *__cli_strnstr(const char *s, const char *find, size_t slen) | 
					
						
							| 
									
										
										
										
											2019-03-02 13:05:17 -05:00
										 |  |  | { | 
					
						
							|  |  |  |     char c, sc; | 
					
						
							|  |  |  |     size_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((c = *find++) != '\0') { | 
					
						
							|  |  |  |         len = strlen(find); | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             do { | 
					
						
							|  |  |  |                 if (slen-- < 1 || (sc = *s++) == '\0') | 
					
						
							|  |  |  |                     return (NULL); | 
					
						
							|  |  |  |             } while (sc != c); | 
					
						
							|  |  |  |             if (len > slen) | 
					
						
							|  |  |  |                 return (NULL); | 
					
						
							|  |  |  |         } while (strncmp(s, find, len) != 0); | 
					
						
							|  |  |  |         s--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return ((char *)s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | size_t cli_strtokenize(char *buffer, const char delim, const size_t token_count, | 
					
						
							|  |  |  |                        const char **tokens) | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     size_t tokens_found, i; | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (tokens_found = 0; tokens_found < token_count;) { | 
					
						
							|  |  |  |         tokens[tokens_found++] = buffer; | 
					
						
							|  |  |  |         buffer                 = strchr(buffer, delim); | 
					
						
							|  |  |  |         if (buffer) { | 
					
						
							|  |  |  |             *buffer++ = '\0'; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             i = tokens_found; | 
					
						
							|  |  |  |             while (i < token_count) | 
					
						
							|  |  |  |                 tokens[i++] = NULL; | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |             return tokens_found; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-01-05 19:57:47 +00:00
										 |  |  |     return tokens_found; | 
					
						
							| 
									
										
										
										
											2007-03-26 12:57:02 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-01-30 20:04:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief The strntol() function converts the string in str to a long value. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * Modifications made to validate the length of the string for non-null term | 
					
						
							|  |  |  |  * strings. | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 1990 The Regents of the University of California. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  |  * @param nptr          Pointer to start of string. | 
					
						
							|  |  |  |  * @param n             Max length of buffer in bytes. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * @param[out] endptr   [optional] If endptr is not NULL, strtol() stores the | 
					
						
							|  |  |  |  * address of the first invalid character in *endptr. If there were no digits at | 
					
						
							|  |  |  |  * all, however, strtol() stores the original value of str in *endptr. Nota | 
					
						
							|  |  |  |  * Bene:  If the buffer is non-null terminated and the number comprises the | 
					
						
							|  |  |  |  * entire buffer, endptr will point past the end of the buffer, and the caller | 
					
						
							|  |  |  |  * should check if endptr >= nptr + n. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param int           The conversion is done according to the given base, | 
					
						
							|  |  |  |  * which must be between 2 and 36 inclusive, or be the special value 0. | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  |  * @return long         The signed long value. | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | long cli_strntol(const char *nptr, size_t n, char **endptr, register int base) | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     register const char *s     = nptr; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     register unsigned long acc = 0; | 
					
						
							|  |  |  |     register int c; | 
					
						
							|  |  |  |     register unsigned long cutoff; | 
					
						
							|  |  |  |     register int neg = 0, any = 0, cutlim; | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (0 == n) { | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         goto done; | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     /*
 | 
					
						
							| 
									
										
										
										
											2022-02-16 00:13:55 +01:00
										 |  |  |      * Skip white space and pick up leading +/- sign if any. | 
					
						
							|  |  |  |      * If base is 0, allow 0x for hex and 0 for octal, else | 
					
						
							|  |  |  |      * assume decimal; if base is already 16, allow 0x. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     do { | 
					
						
							|  |  |  |         c = *s; | 
					
						
							|  |  |  |     } while (isspace(c) && (++s < nptr + n)); | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s >= nptr + n) { | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         goto done; | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     if (c == '-') { | 
					
						
							|  |  |  |         neg = 1; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         c   = *s++; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         if (s >= nptr + n) { | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (c == '+') { | 
					
						
							|  |  |  |         c = *s++; | 
					
						
							|  |  |  |         if (s >= nptr + n) { | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     if (base == 0 || base == 16) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (c == '0' && (s + 1 < nptr + n) && | 
					
						
							|  |  |  |             (*(s + 1) == 'x' || *(s + 1) == 'X')) { | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |             if (s + 2 >= nptr + n) { | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |                 goto done; | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |             c = s[1]; | 
					
						
							|  |  |  |             s += 2; | 
					
						
							|  |  |  |             base = 16; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     if (base == 0) | 
					
						
							|  |  |  |         base = c == '0' ? 8 : 10; | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     /*
 | 
					
						
							| 
									
										
										
										
											2022-02-16 00:13:55 +01:00
										 |  |  |      * Compute the cutoff value between legal numbers and illegal | 
					
						
							|  |  |  |      * numbers.  That is the largest legal value, divided by the | 
					
						
							|  |  |  |      * base.  An input number that is greater than this value, if | 
					
						
							|  |  |  |      * followed by a legal input character, is too big.  One that | 
					
						
							|  |  |  |      * is equal to this value may be valid or not; the limit | 
					
						
							|  |  |  |      * between valid and invalid numbers is then based on the last | 
					
						
							|  |  |  |      * digit.  For instance, if the range for longs is | 
					
						
							|  |  |  |      * [-2147483648..2147483647] and the input base is 10, | 
					
						
							|  |  |  |      * cutoff will be set to 214748364 and cutlim to either | 
					
						
							|  |  |  |      * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated | 
					
						
							|  |  |  |      * a value > 214748364, or equal but the next digit is > 7 (or 8), | 
					
						
							|  |  |  |      * the number is too big, and we will return a range error. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Set any if any `digits' consumed; make it negative to indicate | 
					
						
							|  |  |  |      * overflow. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; | 
					
						
							|  |  |  |     cutlim = cutoff % (unsigned long)base; | 
					
						
							|  |  |  |     cutoff /= (unsigned long)base; | 
					
						
							|  |  |  |     for (acc = 0, any = 0; s < nptr + n; s++) { | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  |         c = *s; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         if (isdigit(c)) | 
					
						
							|  |  |  |             c -= '0'; | 
					
						
							|  |  |  |         else if (isalpha(c)) | 
					
						
							|  |  |  |             c -= isupper(c) ? 'A' - 10 : 'a' - 10; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (c >= base) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) | 
					
						
							|  |  |  |             any = -1; | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             any = 1; | 
					
						
							|  |  |  |             acc *= base; | 
					
						
							|  |  |  |             acc += c; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (any < 0) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         acc   = neg ? LONG_MIN : LONG_MAX; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         errno = ERANGE; | 
					
						
							|  |  |  |     } else if (neg) | 
					
						
							|  |  |  |         acc = -acc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     if (endptr != 0) | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         *endptr = (char *)(any ? s : nptr); | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     return (acc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * @brief The strntoul() function converts the string in str to an unsigned long | 
					
						
							|  |  |  |  * value. Modifications made to validate the length of the string for non-null | 
					
						
							|  |  |  |  * term strings. | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 1990 The Regents of the University of California. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param nptr          Pointer to start of string. | 
					
						
							|  |  |  |  * @param n             Max length of buffer in bytes. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * @param[out] endptr   [optional] If endptr is not NULL, strtol() stores the | 
					
						
							|  |  |  |  * address of the first invalid character in *endptr. If there were no digits at | 
					
						
							|  |  |  |  * all, however, strtol() stores the original value of str in *endptr. Nota | 
					
						
							|  |  |  |  * Bene:  If the buffer is non-null terminated and the number comprises the | 
					
						
							|  |  |  |  * entire buffer, endptr will point past the end of the buffer, and the caller | 
					
						
							|  |  |  |  * should check if endptr >= nptr + n. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param int           The conversion is done according to the given base, | 
					
						
							|  |  |  |  * which must be between 2 and 36 inclusive, or be the special value 0. | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |  * @return unsigned long The unsigned long value. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | unsigned long cli_strntoul(const char *nptr, size_t n, char **endptr, | 
					
						
							|  |  |  |                            register int base) | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     register const char *s     = nptr; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     register unsigned long acc = 0; | 
					
						
							|  |  |  |     register int c; | 
					
						
							|  |  |  |     register unsigned long cutoff; | 
					
						
							|  |  |  |     register int neg = 0, any = 0, cutlim; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							| 
									
										
										
										
											2022-02-16 00:13:55 +01:00
										 |  |  |      * See cli_strntol for comments as to the logic used. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     do { | 
					
						
							|  |  |  |         c = *s; | 
					
						
							|  |  |  |     } while (isspace(c) && (++s < nptr + n)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s >= nptr + n) { | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (c == '-') { | 
					
						
							|  |  |  |         neg = 1; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         c   = *s++; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         if (s >= nptr + n) { | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (c == '+') { | 
					
						
							|  |  |  |         c = *s++; | 
					
						
							|  |  |  |         if (s >= nptr + n) { | 
					
						
							|  |  |  |             goto done; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (base == 0 || base == 16) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (c == '0' && (s + 1 < nptr + n) && | 
					
						
							|  |  |  |             (*(s + 1) == 'x' || *(s + 1) == 'X')) { | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |             if (s + 2 >= nptr + n) { | 
					
						
							|  |  |  |                 goto done; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             c = s[1]; | 
					
						
							|  |  |  |             s += 2; | 
					
						
							|  |  |  |             base = 16; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (base == 0) | 
					
						
							|  |  |  |         base = c == '0' ? 8 : 10; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; | 
					
						
							|  |  |  |     cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; | 
					
						
							|  |  |  |     for (acc = 0, any = 0; s < nptr + n; s++) { | 
					
						
							|  |  |  |         c = *s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (isdigit(c)) | 
					
						
							|  |  |  |             c -= '0'; | 
					
						
							|  |  |  |         else if (isalpha(c)) | 
					
						
							|  |  |  |             c -= isupper(c) ? 'A' - 10 : 'a' - 10; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (c >= base) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) | 
					
						
							|  |  |  |             any = -1; | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             any = 1; | 
					
						
							|  |  |  |             acc *= base; | 
					
						
							|  |  |  |             acc += c; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (any < 0) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         acc   = ULONG_MAX; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         errno = ERANGE; | 
					
						
							|  |  |  |     } else if (neg) | 
					
						
							|  |  |  |         acc = -acc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     if (endptr != 0) | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         *endptr = (char *)(any ? s : nptr); | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |     return (acc); | 
					
						
							| 
									
										
										
										
											2018-06-01 14:23:25 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |  * @brief 	cli_strntol_wrap() converts the string in str to a long value. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  |  * Wrapper for cli_strntol() that provides incentive to check for failure. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @param buf               Pointer to start of string. | 
					
						
							|  |  |  |  * @param buf_size 			Max length of buffer to convert to | 
					
						
							|  |  |  |  * integer. | 
					
						
							|  |  |  |  * @param fail_at_nondigit  If 1, fail out if the a non-digit character is found | 
					
						
							|  |  |  |  * before the end of the buffer. If 0, non-digit character represents end of | 
					
						
							|  |  |  |  * number and is not a failure. | 
					
						
							|  |  |  |  * @param base              The conversion is done according to the given base, | 
					
						
							|  |  |  |  * which must be between 2 and 36 inclusive, or be the special value 0. | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  |  * @param[out] result 	    Long integer value of ascii number. | 
					
						
							|  |  |  |  * @return CL_SUCCESS       Success | 
					
						
							|  |  |  |  * @return CL_EPARSE        Failure | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | cl_error_t cli_strntol_wrap(const char *buf, size_t buf_size, | 
					
						
							|  |  |  |                             int fail_at_nondigit, int base, long *result) | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     char *endptr = NULL; | 
					
						
							|  |  |  |     long num; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (buf_size == 0 || !buf || !result) { | 
					
						
							|  |  |  |         /* invalid parameter */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     errno = 0; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     num   = cli_strntol(buf, buf_size, &endptr, base); | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  |     if ((num == LONG_MIN || num == LONG_MAX) && errno == ERANGE) { | 
					
						
							|  |  |  |         /* under- or overflow */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (endptr == buf) { | 
					
						
							|  |  |  |         /* no digits */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (fail_at_nondigit && (endptr < (buf + buf_size)) && (*endptr != '\0')) { | 
					
						
							|  |  |  |         /* non-digit encountered */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* success */ | 
					
						
							|  |  |  |     *result = num; | 
					
						
							|  |  |  |     return CL_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief 	cli_strntoul_wrap() converts the string in str to a long value. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |  * Wrapper for cli_strntoul() that provides incentive to check for failure. | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @param buf               Pointer to start of string. | 
					
						
							|  |  |  |  * @param buf_size 			Max length of buffer to convert to | 
					
						
							|  |  |  |  * integer. | 
					
						
							|  |  |  |  * @param fail_at_nondigit  If 1, fail out if the a non-digit character is found | 
					
						
							|  |  |  |  * before the end of the buffer. If 0, non-digit character represents end of | 
					
						
							|  |  |  |  * number and is not a failure. | 
					
						
							|  |  |  |  * @param base              The conversion is done according to the given base, | 
					
						
							|  |  |  |  * which must be between 2 and 36 inclusive, or be the special value 0. | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |  * @param[out] result 	    Unsigned long integer value of ascii number. | 
					
						
							|  |  |  |  * @return CL_SUCCESS       Success | 
					
						
							|  |  |  |  * @return CL_EPARSE        Failure | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | cl_error_t cli_strntoul_wrap(const char *buf, size_t buf_size, | 
					
						
							|  |  |  |                              int fail_at_nondigit, int base, | 
					
						
							|  |  |  |                              unsigned long *result) | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     char *endptr = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-03 18:25:17 -04:00
										 |  |  |     unsigned long num; | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (buf_size == 0 || !buf || !result) { | 
					
						
							|  |  |  |         /* invalid parameter */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     errno = 0; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     num   = cli_strntoul(buf, buf_size, &endptr, base); | 
					
						
							| 
									
										
										
										
											2019-05-03 18:25:17 -04:00
										 |  |  |     if ((num == ULONG_MAX) && (errno == ERANGE)) { | 
					
						
							| 
									
										
										
										
											2018-06-12 20:47:21 -04:00
										 |  |  |         /* under- or overflow */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (endptr == buf) { | 
					
						
							|  |  |  |         /* no digits */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (fail_at_nondigit && (endptr < (buf + buf_size)) && (*endptr != '\0')) { | 
					
						
							|  |  |  |         /* non-digit encountered */ | 
					
						
							|  |  |  |         return CL_EPARSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* success */ | 
					
						
							|  |  |  |     *result = num; | 
					
						
							|  |  |  |     return CL_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-06-02 20:58:35 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | size_t cli_ldbtokenize(char *buffer, const char delim, const size_t token_count, | 
					
						
							| 
									
										
										
										
											2019-05-03 18:25:17 -04:00
										 |  |  |                        const char **tokens, size_t token_skip) | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |     size_t tokens_found = 0; | 
					
						
							|  |  |  |     size_t token_index  = 0; | 
					
						
							|  |  |  |     size_t buffer_index = 0; | 
					
						
							|  |  |  |     bool within_pcre    = false; | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |     while (tokens_found < token_count) { | 
					
						
							|  |  |  |         tokens[tokens_found++] = &buffer[buffer_index]; | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |         while (buffer[buffer_index] != '\0') { | 
					
						
							|  |  |  |             if (!within_pcre && (buffer[buffer_index] == delim)) { | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2022-07-25 12:56:03 -07:00
										 |  |  |             } else if ((tokens_found > token_skip) && | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |                        // LDB PCRE rules must escape the '/' character with a '\'.
 | 
					
						
							|  |  |  |                        // If the character sequence is "\/", then we are still within the PCRE string.
 | 
					
						
							|  |  |  |                        ((buffer_index > 0) && (buffer[buffer_index - 1] != '\\')) && (buffer[buffer_index] == '/')) { | 
					
						
							|  |  |  |                 within_pcre = !within_pcre; | 
					
						
							| 
									
										
										
										
											2022-07-25 12:56:03 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |             buffer_index++; | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |         if (buffer[buffer_index] != '\0') { | 
					
						
							|  |  |  |             buffer[buffer_index] = '\0'; | 
					
						
							|  |  |  |             buffer_index++; | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  |             token_index = tokens_found; | 
					
						
							|  |  |  |             while (token_index < token_count) { | 
					
						
							|  |  |  |                 tokens[token_index] = NULL; | 
					
						
							|  |  |  |                 token_index++; | 
					
						
							| 
									
										
										
										
											2022-07-25 12:56:03 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  |             return tokens_found; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-09 16:00:02 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-21 17:29:23 -04:00
										 |  |  |     return tokens_found; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-30 20:04:02 +00:00
										 |  |  | int cli_isnumber(const char *str) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-08 14:25:42 -05:00
										 |  |  |     if (NULL == str) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     while (*str) | 
					
						
							|  |  |  |         if (!strchr("0123456789", *str++)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							| 
									
										
										
										
											2008-01-30 20:04:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* encodes the unicode character as utf-8 */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | static inline size_t output_utf8(uint16_t u, unsigned char *dst) | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     if (!u) { | 
					
						
							|  |  |  |         *dst = 0x1; /* don't add \0, add \1 instead */ | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (u < 0x80) { | 
					
						
							|  |  |  |         *dst = u & 0xff; | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (u < 0x800) { | 
					
						
							|  |  |  |         *dst++ = 0xc0 | (u >> 6);   /* 110yyyyy */ | 
					
						
							|  |  |  |         *dst   = 0x80 | (u & 0x3f); /* 10zzzzzz */ | 
					
						
							|  |  |  |         return 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* u < 0x10000 because we only handle utf-16,
 | 
					
						
							| 
									
										
										
										
											2022-02-16 00:13:55 +01:00
										 |  |  |      * values in range 0xd800 - 0xdfff aren't valid, but we don't check for | 
					
						
							|  |  |  |      * that*/ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     *dst++ = 0xe0 | (u >> 12);         /* 1110xxxx */ | 
					
						
							|  |  |  |     *dst++ = 0x80 | ((u >> 6) & 0x3f); /* 10yyyyyy */ | 
					
						
							|  |  |  |     *dst   = 0x80 | (u & 0x3f);        /* 10zzzzzz */ | 
					
						
							|  |  |  |     return 3; | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* javascript-like unescape() function */ | 
					
						
							|  |  |  | char *cli_unescape(const char *str) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     char *R; | 
					
						
							|  |  |  |     size_t k, i = 0; | 
					
						
							|  |  |  |     const size_t len = strlen(str); | 
					
						
							|  |  |  |     /* unescaped string is at most as long as original,
 | 
					
						
							| 
									
										
										
										
											2022-02-16 00:13:55 +01:00
										 |  |  |      * it will usually be shorter */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     R = cli_malloc(len + 1); | 
					
						
							|  |  |  |     if (!R) { | 
					
						
							| 
									
										
										
										
											2013-03-01 13:51:15 -05:00
										 |  |  |         cli_errmsg("cli_unescape: Unable to allocate memory for string\n"); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (k = 0; k < len; k++) { | 
					
						
							|  |  |  |         unsigned char c = str[k]; | 
					
						
							|  |  |  |         if (str[k] == '%') { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |             if (k + 5 >= len || str[k + 1] != 'u' || !isxdigit(str[k + 2]) || | 
					
						
							|  |  |  |                 !isxdigit(str[k + 3]) || !isxdigit(str[k + 4]) || | 
					
						
							|  |  |  |                 !isxdigit(str[k + 5])) { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                 if (k + 2 < len && isxdigit(str[k + 1]) && isxdigit(str[k + 2])) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |                     c = ((cli_hex2int(str[k + 1]) < 0 ? 0 : cli_hex2int(str[k + 1])) | 
					
						
							|  |  |  |                          << 4) | | 
					
						
							|  |  |  |                         cli_hex2int(str[k + 2]); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                     k += 2; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |                 uint16_t u = | 
					
						
							|  |  |  |                     ((cli_hex2int(str[k + 2]) < 0 ? 0 : cli_hex2int(str[k + 2])) | 
					
						
							|  |  |  |                      << 12) | | 
					
						
							|  |  |  |                     ((cli_hex2int(str[k + 3]) < 0 ? 0 : cli_hex2int(str[k + 3])) << 8) | | 
					
						
							|  |  |  |                     ((cli_hex2int(str[k + 4]) < 0 ? 0 : cli_hex2int(str[k + 4])) << 4) | | 
					
						
							|  |  |  |                     cli_hex2int(str[k + 5]); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                 i += output_utf8(u, (unsigned char *)&R[i]); | 
					
						
							|  |  |  |                 k += 5; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (!c) | 
					
						
							|  |  |  |             c = 1; /* don't add \0 */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         R[i++] = c; | 
					
						
							| 
									
										
										
										
											2013-03-01 13:51:15 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     R[i++] = '\0'; | 
					
						
							|  |  |  |     R      = cli_realloc2(R, i); | 
					
						
							|  |  |  |     return R; | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* handle javascript's escape sequences inside strings */ | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | int cli_textbuffer_append_normalize(struct text_buffer *buf, const char *str, | 
					
						
							|  |  |  |                                     size_t len) | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     size_t i; | 
					
						
							|  |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         char c = str[i]; | 
					
						
							|  |  |  |         if (c == '\\' && i + 1 < len) { | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  |             switch (str[i]) { | 
					
						
							|  |  |  |                 case '0': | 
					
						
							|  |  |  |                     c = 0; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'b': | 
					
						
							|  |  |  |                     c = 8; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 't': | 
					
						
							|  |  |  |                     c = 9; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'n': | 
					
						
							|  |  |  |                     c = 10; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'v': | 
					
						
							|  |  |  |                     c = 11; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'f': | 
					
						
							|  |  |  |                     c = 12; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'r': | 
					
						
							|  |  |  |                     c = 13; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'x': | 
					
						
							|  |  |  |                     if (i + 2 < len) | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |                         c = ((cli_hex2int(str[i + 1]) < 0 ? 0 : cli_hex2int(str[i + 1])) | 
					
						
							|  |  |  |                              << 4) | | 
					
						
							|  |  |  |                             cli_hex2int(str[i + 2]); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                     i += 2; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case 'u': | 
					
						
							|  |  |  |                     if (i + 4 < len) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |                         uint16_t u = | 
					
						
							|  |  |  |                             ((cli_hex2int(str[i + 1]) < 0 ? 0 : cli_hex2int(str[i + 1])) | 
					
						
							|  |  |  |                              << 12) | | 
					
						
							|  |  |  |                             ((cli_hex2int(str[i + 2]) < 0 ? 0 : cli_hex2int(str[i + 2])) | 
					
						
							|  |  |  |                              << 8) | | 
					
						
							|  |  |  |                             ((cli_hex2int(str[i + 3]) < 0 ? 0 : cli_hex2int(str[i + 3])) | 
					
						
							|  |  |  |                              << 4) | | 
					
						
							|  |  |  |                             cli_hex2int(str[i + 4]); | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |                         if (textbuffer_ensure_capacity(buf, 4) == -1) | 
					
						
							|  |  |  |                             return -1; | 
					
						
							|  |  |  |                         buf->pos += output_utf8(u, (unsigned char *)&buf->data[buf->pos]); | 
					
						
							|  |  |  |                         i += 4; | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     c = str[i]; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (!c) | 
					
						
							|  |  |  |             c = 1; /* we don't insert \0 */ | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         if (textbuffer_putc(buf, c) == -1) | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2008-07-10 10:29:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-07 18:54:09 +01:00
										 |  |  | int cli_hexnibbles(char *str, int len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |     for (i = 0; i < len; i++) { | 
					
						
							|  |  |  |         int c = cli_hex2int(str[i]); | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (c < 0) | 
					
						
							|  |  |  |             return 1; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  |         str[i] = c; | 
					
						
							| 
									
										
										
										
											2009-12-07 18:54:09 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-11-14 21:23:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  | cl_error_t cli_basename(const char *filepath, size_t filepath_len, | 
					
						
							|  |  |  |                         char **filebase) | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     cl_error_t status = CL_EARG; | 
					
						
							|  |  |  |     const char *index = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-03 12:40:13 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  |     if (NULL == filepath || NULL == filebase || filepath_len == 0) { | 
					
						
							|  |  |  |         cli_dbgmsg("cli_basename: Invalid arguments.\n"); | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     index = filepath + filepath_len - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (index > filepath) { | 
					
						
							| 
									
										
										
										
											2019-02-19 13:02:55 -05:00
										 |  |  |         if (index[0] == PATHSEP[0]) | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  |         index--; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((index != filepath) || (index[0] == PATHSEP[0])) | 
					
						
							|  |  |  |         index++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     if (0 == CLI_STRNLEN(index, filepath_len - (index - filepath))) { | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  |         cli_dbgmsg("cli_basename: Provided path does not include a file name.\n"); | 
					
						
							|  |  |  |         status = CL_EFORMAT; | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-22 16:51:01 -04:00
										 |  |  |     *filebase = CLI_STRNDUP(index, filepath_len - (index - filepath)); | 
					
						
							| 
									
										
										
										
											2018-07-30 20:19:28 -04:00
										 |  |  |     if (NULL == *filebase) { | 
					
						
							|  |  |  |         cli_errmsg("cli_basename: Failed to allocate memory for file basename.\n"); | 
					
						
							|  |  |  |         status = CL_EMEM; | 
					
						
							|  |  |  |         goto done; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     status = CL_SUCCESS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  |     return status; | 
					
						
							|  |  |  | } |