├── .travis.yml ├── COPYING ├── Makefile.am ├── README ├── README.md ├── core_hep.h ├── hepipe ├── hepipe.c ├── hepipe.h ├── hepipe.ini ├── minIni ├── LICENSE ├── NOTICE ├── minGlue-FatFs.h ├── minGlue-ccs.h ├── minGlue-efsl.h ├── minGlue-ffs.h ├── minGlue-mdd.h ├── minGlue-stdio.h ├── minGlue.h ├── minIni.c ├── minIni.h ├── minIni.pdf ├── minini_12.zip ├── test.c ├── test.ini ├── test2.cc ├── testplain.ini └── wxMinIni.h └── run.sh /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | 6 | install: 7 | - sudo apt-get update || true 8 | - sudo apt-get install build-essential 9 | - sudo apt-get install libpcap-dev 10 | 11 | script: 12 | - sudo cc -o hepipe hepipe.c -lpcap 13 | - ./hepipe -h 14 | 15 | notifications: 16 | slack: qxip:WuEGMSIAa8KEX6iL2zN2bZbv 17 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 3 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # makefile 3 | # 4 | 5 | bin_PROGRAMS = hepipe 6 | 7 | hepipe_LDFLAGS = \ 8 | -lpcap -lsocket 9 | 10 | hepipe_CFLAGS = \ 11 | -g -Wall -DUSE_IPV6 -DUSE_HEP3 -DUSE_CONFFILE 12 | 13 | hepipe_SOURCES = \ 14 | minIni/minIni.c \ 15 | hepipe.c 16 | 17 | noinst_HEADERS = \ 18 | hepipe.h \ 19 | minIni/minGlue-ccs.h \ 20 | minIni/minGlue-efsl.h \ 21 | minIni/minGlue-FatFs.h \ 22 | minIni/minGlue-ffs.h \ 23 | minIni/minGlue.h \ 24 | minIni/minGlue-mdd.h \ 25 | minIni/minGlue-stdio.h \ 26 | minIni/minIni.h \ 27 | minIni/wxMinIni.h 28 | 29 | confdir = $(sysconfdir)/hepipe 30 | dist_conf_DATA = \ 31 | hepipe.ini 32 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Homer capturing agent. 2 | 3 | The agent will duplicate all SIP messages in HEP to the Homer capture server. 4 | 5 | At this time, only SIP UDP can be duplicate! Don't use it for TCP/SCTP/TLS SIP mirroring. 6 | 7 | IPv6 should works also. :-). If you don't need this, remove -DUSE_IPv6 from CFLAGS. 8 | 9 | All comments please send to alexandr.dubovikov@gmail.com 10 | 11 | URL: http://www.sipcapture.org 12 | 13 | # How to use: 14 | 15 | captagent -p 9060 -s homerserver -n -r 5060-5080 16 | 17 | or load a pcap file to Homer 18 | 19 | captagent -p 9060 -D test.pcap -s homerserver -n -r 5060-5080 -H 2 -i 101 20 | 21 | usage: captagent <-mvhnc> <-d dev> <-s host> <-p port> 22 | <-P pid file> <-r port|portrange> <-f filter file> 23 | <-i id> <-H 1|2> --config= 24 | -h is help/usage 25 | -v is version information 26 | -m is don't go into promiscuous mode 27 | -n is don't go into background 28 | -d is use specified device instead of the pcap default 29 | -D is use specified pcap file instead of a device 30 | -s is the capture server 31 | -p is use specified port of capture server. I.E. 9060 32 | -r is open specified capturing port or portrange instead of the default (5060) 33 | -P is open specified pid file instead of the default (/var/run/captagent.pid) 34 | -f is the file with specific pcap filter 35 | -c is checkout 36 | -i is capture identifity. Must be a 16-bit number. I.e: 101 37 | -H is HEP protocol version [1|2]. By default we use HEP version 1 38 | --config is config file to use to specify some options. Default location is [/usr/local/etc/captagent/captagent.ini] 39 | 40 | 41 | #Tipp: 42 | -p the port number where your capture server listen on. 43 | -r normaly it's 5060, but you can use ports range 5060-5090 too. 44 | -s this param can be an IP or FQDN 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Build_Status](https://travis-ci.org/sipcapture/hepipe.svg?branch=master) 2 | 3 | HEPipe 4 | ======= 5 | 6 | ## Description: 7 | 8 | HEPipe *(pronounced HEP-pipe)* is an application for logging arbitrary data *(ie: logs, cdrs, debug lines)* to a *HEP/EEP* capture server such as [HOMER](https://github.com/sipcapture/homer) or [HEPIC](http://hepic.tel) 9 | 10 | ## Compilation: 11 | 12 | ### Linux 13 | 14 | cc -o hepipe hepipe.c -lpcap 15 | 16 | ### Solaris 17 | 18 | cc -o hepipe hepipe.c -lpcap -lsocket 19 | NOTE: Please make sure that your compiler is gcc or understands the packet attribute for structure 20 | 21 | ## Format: 22 | 23 | ```csv 24 | timesec;timeusec;correlationid;source_ip;source_port;destination_ip;destinaton_port;payload in json 25 | ``` 26 | 27 | ## Usage Example: 28 | 29 | * `-t 100` - loging Protocol Type 30 | 31 | ```sh 32 | echo '1396362930;1003;fd8f48ea-b9aa-11e3-92f7-1803731b65be;127.0.0.1;5060;10.0.0.1;5060;{"pl": 10, "jt": 10}' | ./hepipe -s hepserver -p 9061 -t 100 33 | ``` 34 | -------------------------------------------------------------------------------- /core_hep.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id$ 3 | * 4 | * captagent - Homer capture agent. Modular 5 | * Duplicate SIP messages in Homer Encapulate Protocol [HEP] [ipv6 version] 6 | * 7 | * Author: Alexandr Dubovikov 8 | * (C) Homer Project 2012 (http://www.sipcapture.org) 9 | * 10 | * Homer capture agent is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 3 of the License, or 13 | * (at your option) any later version 14 | * 15 | * Homer capture agent is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | * 24 | */ 25 | 26 | #define USE_IPV6 27 | 28 | #ifdef USE_IPV6 29 | #include 30 | #endif /* USE_IPV6 */ 31 | 32 | int hep_version = 3; 33 | int usessl = 0; 34 | int pl_compress = 0; 35 | 36 | 37 | struct rc_info { 38 | uint8_t ip_family; /* IP family IPv6 IPv4 */ 39 | uint8_t ip_proto; /* IP protocol ID : tcp/udp */ 40 | uint8_t proto_type; /* SIP: 0x001, SDP: 0x03*/ 41 | char *src_ip; 42 | char *dst_ip; 43 | uint16_t src_port; 44 | uint16_t dst_port; 45 | uint32_t time_sec; 46 | uint32_t time_usec; 47 | uint16_t val1; 48 | uint16_t val2; 49 | } ; 50 | 51 | typedef struct rc_info rc_info_t; 52 | 53 | 54 | /* HEPv3 types */ 55 | 56 | struct hep_chunk { 57 | uint16_t vendor_id; 58 | uint16_t type_id; 59 | uint16_t length; 60 | } __attribute__((packed)); 61 | 62 | typedef struct hep_chunk hep_chunk_t; 63 | 64 | struct hep_chunk_uint8 { 65 | hep_chunk_t chunk; 66 | uint8_t data; 67 | } __attribute__((packed)); 68 | 69 | typedef struct hep_chunk_uint8 hep_chunk_uint8_t; 70 | 71 | struct hep_chunk_uint16 { 72 | hep_chunk_t chunk; 73 | uint16_t data; 74 | } __attribute__((packed)); 75 | 76 | typedef struct hep_chunk_uint16 hep_chunk_uint16_t; 77 | 78 | struct hep_chunk_uint32 { 79 | hep_chunk_t chunk; 80 | uint32_t data; 81 | } __attribute__((packed)); 82 | 83 | typedef struct hep_chunk_uint32 hep_chunk_uint32_t; 84 | 85 | struct hep_chunk_str { 86 | hep_chunk_t chunk; 87 | char *data; 88 | } __attribute__((packed)); 89 | 90 | typedef struct hep_chunk_str hep_chunk_str_t; 91 | 92 | struct hep_chunk_ip4 { 93 | hep_chunk_t chunk; 94 | struct in_addr data; 95 | } __attribute__((packed)); 96 | 97 | typedef struct hep_chunk_ip4 hep_chunk_ip4_t; 98 | 99 | struct hep_chunk_ip6 { 100 | hep_chunk_t chunk; 101 | struct in6_addr data; 102 | } __attribute__((packed)); 103 | 104 | typedef struct hep_chunk_ip6 hep_chunk_ip6_t; 105 | 106 | struct hep_ctrl { 107 | char id[4]; 108 | uint16_t length; 109 | } __attribute__((packed)); 110 | 111 | typedef struct hep_ctrl hep_ctrl_t; 112 | 113 | struct hep_chunk_payload { 114 | hep_chunk_t chunk; 115 | char *data; 116 | } __attribute__((packed)); 117 | 118 | typedef struct hep_chunk_payload hep_chunk_payload_t; 119 | 120 | /* Structure of HEP */ 121 | 122 | struct hep_generic { 123 | hep_ctrl_t header; 124 | hep_chunk_uint8_t ip_family; 125 | hep_chunk_uint8_t ip_proto; 126 | hep_chunk_uint16_t src_port; 127 | hep_chunk_uint16_t dst_port; 128 | hep_chunk_uint32_t time_sec; 129 | hep_chunk_uint32_t time_usec; 130 | hep_chunk_uint8_t proto_t; 131 | hep_chunk_uint32_t capt_id; 132 | } __attribute__((packed)); 133 | 134 | typedef struct hep_generic hep_generic_t; 135 | 136 | struct hep_hdr{ 137 | uint8_t hp_v; /* version */ 138 | uint8_t hp_l; /* length */ 139 | uint8_t hp_f; /* family */ 140 | uint8_t hp_p; /* protocol */ 141 | uint16_t hp_sport; /* source port */ 142 | uint16_t hp_dport; /* destination port */ 143 | }; 144 | 145 | struct hep_timehdr{ 146 | uint32_t tv_sec; /* seconds */ 147 | uint32_t tv_usec; /* useconds */ 148 | uint16_t captid; /* Capture ID node */ 149 | }; 150 | 151 | struct hep_iphdr{ 152 | struct in_addr hp_src; 153 | struct in_addr hp_dst; /* source and dest address */ 154 | }; 155 | 156 | #ifdef USE_IPV6 157 | struct hep_ip6hdr { 158 | struct in6_addr hp6_src; /* source address */ 159 | struct in6_addr hp6_dst; /* destination address */ 160 | }; 161 | #endif 162 | -------------------------------------------------------------------------------- /hepipe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipcapture/hepipe/e646842ba3501268e82db9b40e2962765391cbde/hepipe -------------------------------------------------------------------------------- /hepipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id$ 3 | * 4 | * hepipe - Homer Stream agent. 5 | * Duplicate LOGS messages in Homer Encapulate Protocol [HEP] [ipv6 version] 6 | * 7 | * Author: Alexandr Dubovikov 8 | * (C) 2014 (http://www.sipcapture.org) 9 | * Author: Lorenzo Mangani 10 | * (C) 2015 (http://www.sipcapture.org) 11 | * 12 | * Homer Stream agent is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation; either version 3 of the License, or 15 | * (at your option) any later version 16 | * 17 | * Homer capture agent is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program; if not, write to the Free Software 24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 | * 26 | */ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifndef __USE_BSD 35 | #define __USE_BSD 36 | #endif /* __USE_BSD */ 37 | 38 | #ifndef __FAVOR_BSD 39 | #define __FAVOR_BSD 40 | #endif /* __FAVOR_BSD */ 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifdef USE_IPV6 49 | #include 50 | #endif /* USE_IPV6 */ 51 | #define __FAVOR_BSD 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | /* Solaris */ 64 | #include 65 | #include 66 | 67 | #include "core_hep.h" 68 | #include "minIni/minIni.h" 69 | #include "hepipe.h" 70 | 71 | /* sender socket */ 72 | int sock; 73 | int captid = 0; 74 | int hepversion = 3; 75 | char *capt_password = NULL; 76 | char *correlation_id = NULL; 77 | uint8_t link_offset = 14; 78 | uint8_t chunk_vendor_id = 0; 79 | uint8_t val1_chunk = 0; 80 | uint8_t val2_chunk = 0; 81 | /* logging TYPE */ 82 | int proto_type = 100; 83 | int adv = 0; 84 | 85 | 86 | void usage(int8_t e) { 87 | #ifdef USE_CONFFILE 88 | printf("usage: hepipe <-vhc> <-s host> <-p port>\n" 89 | " <-t type> <-i id> <-H 1|2|3> --config=\n" 90 | " -h is help/usage\n" 91 | " -v is version information\n" 92 | " -a is advanced packet\n" 93 | " -t is protocol type packet\n" 94 | " -K is vendor chunk id\n" 95 | " -V is custom chunks id\n" 96 | " -s is the capture server\n" 97 | " -p is use specified port of capture server. i.e. 9060\n" 98 | " -P is the capture password\n" 99 | " -c is checkout\n" 100 | " -i is capture identifity. Must be a 16-bit number. I.e: 101\n" 101 | " -H is HEP protocol version [1|2|3]. By default we use HEP version 3\n" 102 | "--config is config file to use to specify some options. Default location is [%s]\n" 103 | "", DEFAULT_CONFIG); 104 | exit(e); 105 | #else 106 | printf("usage: hepipe <-vhc> <-d dev> <-s host> <-p port>\n" 107 | " <-t type> <-f filter file> <-i id> <-H 1|2|3>\n" 108 | " -h is help/usage\n" 109 | " -v is version information\n" 110 | " -a is advanced packet\n" 111 | " -t is protocol type packet\n" 112 | " -K is vendor chunk id\n" 113 | " -V is custom chunks id\n" 114 | " -s is the capture server\n" 115 | " -P is the capture password\n" 116 | " -p is use specified port of capture server. i.e. 9060\n" 117 | " -c is checkout\n" 118 | " -i is capture identifity. Must be a 16-bit number. I.e: 101\n" 119 | " -H is HEP protocol version [1|2|3]. By default we use HEP version 3\n" 120 | ""); 121 | exit(e); 122 | 123 | #endif 124 | } 125 | 126 | 127 | void handler(int value) 128 | { 129 | if(sock) close(sock); 130 | exit(0); 131 | } 132 | 133 | 134 | int main(int argc,char **argv) 135 | { 136 | int mode, c, checkout=0, heps=0; 137 | struct addrinfo *ai, hints[1] = {{ 0 }}; 138 | char *capt_host = NULL, *capt_port = NULL, *chunk_vals = NULL; 139 | uint16_t snaplen = 65535, promisc = 1, to = 100; 140 | char *dav = NULL; 141 | 142 | #ifdef USE_CONFFILE 143 | 144 | #define sizearray(a) (sizeof(a) / sizeof((a)[0])) 145 | 146 | char *conffile = NULL; 147 | 148 | static struct option long_options[] = { 149 | {"config", optional_argument, 0, 'C'}, 150 | {0, 0, 0, 0} 151 | }; 152 | 153 | while((c=getopt_long(argc, argv, "avhcp:s:c:f:i:H:C:K:V:P:", long_options, NULL))!=-1) { 154 | #else 155 | while((c=getopt(argc, argv, "avhcp:s:c:f:t:i:H:C:K:V:P:"))!=EOF) { 156 | #endif 157 | switch(c) { 158 | #ifdef USE_CONFFILE 159 | case 'C': 160 | conffile = optarg ? optarg : DEFAULT_CONFIG; 161 | break; 162 | #endif 163 | case 's': 164 | capt_host = optarg; 165 | break; 166 | case 'p': 167 | capt_port = optarg; 168 | break; 169 | case 'P': 170 | capt_password = optarg; 171 | break; 172 | case 'h': 173 | usage(0); 174 | break; 175 | case 'c': 176 | checkout=1; 177 | break; 178 | case 'a': 179 | adv=1; 180 | break; 181 | 182 | case 'v': 183 | printf("version: %s\n", VERSION); 184 | #ifdef USE_HEP2 185 | printf("HEP2 is enabled\n"); 186 | #endif 187 | exit(0); 188 | break; 189 | case 'i': 190 | captid = atoi(optarg); 191 | break; 192 | case 't': 193 | proto_type = atoi(optarg); 194 | break; 195 | case 'H': 196 | hepversion = atoi(optarg); 197 | heps=1; 198 | break; 199 | case 'K': 200 | chunk_vendor_id = atoi(optarg); 201 | break; 202 | case 'V': 203 | chunk_vals = optarg; 204 | break; 205 | default: 206 | abort(); 207 | } 208 | } 209 | 210 | #ifdef USE_CONFFILE 211 | 212 | long n; 213 | char ini[100]; 214 | char captport_ini[100]; 215 | char captportr_ini[100]; 216 | char captid_ini[10]; 217 | char hep_ini[2]; 218 | 219 | if(heps == 0) { 220 | n = ini_gets("main", "hep", "dummy", hep_ini, sizearray(hep_ini), conffile); 221 | if(strcmp(hep_ini, "dummy") != 0) { 222 | hepversion=atoi(hep_ini); 223 | } 224 | 225 | if(hepversion == 0) 226 | hepversion = 1; 227 | } 228 | 229 | if(captid == 0) { 230 | n = ini_gets("main", "identifier", "dummy", captid_ini, sizearray(captid_ini), conffile); 231 | if(strcmp(captid_ini, "dummy") != 0) { 232 | captid=atoi(captid_ini); 233 | } 234 | } 235 | 236 | if(capt_host == NULL) { 237 | n = ini_gets("main", "capture_server", "dummy", ini, sizearray(ini), conffile); 238 | if(strcmp(ini, "dummy") != 0) { 239 | capt_host=ini; 240 | } 241 | } 242 | 243 | if(capt_port == NULL) { 244 | n = ini_gets("main", "capture_server_port", "dummy", captport_ini, sizearray(captport_ini), conffile); 245 | if(strcmp(captport_ini, "dummy") != 0) { 246 | capt_port=captport_ini; 247 | } 248 | } 249 | 250 | #endif 251 | 252 | if(capt_host == NULL || capt_port == NULL) { 253 | fprintf(stderr,"capture server and capture port must be defined!\n"); 254 | usage(-1); 255 | } 256 | 257 | 258 | if(hepversion < 1 && hepversion > 3) { 259 | fprintf(stderr,"unsupported HEP version. Must be 1,2 or 3, but you have defined as [%i]!\n", hepversion); 260 | return 1; 261 | } 262 | 263 | hints->ai_flags = AI_NUMERICSERV; 264 | hints->ai_family = AF_UNSPEC; 265 | hints->ai_socktype = SOCK_DGRAM; 266 | hints->ai_protocol = IPPROTO_UDP; 267 | 268 | if (getaddrinfo(capt_host, capt_port, hints, &ai)) { 269 | fprintf(stderr,"capture: getaddrinfo() error"); 270 | return 2; 271 | } 272 | 273 | sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 274 | if (sock < 0) { 275 | fprintf(stderr,"Sender socket creation failed: %s\n", strerror(errno)); 276 | return 3; 277 | } 278 | 279 | /* not blocking */ 280 | mode = fcntl(sock, F_GETFL, 0); 281 | mode |= O_NDELAY | O_NONBLOCK; 282 | fcntl(sock, F_SETFL, mode); 283 | 284 | if (connect(sock, ai->ai_addr, (socklen_t)(ai->ai_addrlen)) == -1) { 285 | if (errno != EINPROGRESS) { 286 | fprintf(stderr,"Sender socket creation failed: %s\n", strerror(errno)); 287 | return 4; 288 | } 289 | } 290 | 291 | if(checkout) { 292 | fprintf(stdout,"Version : [%s]\n", VERSION); 293 | fprintf(stdout,"Capture host: [%s]\n", capt_host); 294 | fprintf(stdout,"Capture port: [%s]\n", capt_port); 295 | fprintf(stdout,"Capture ID : [%i]\n", captid); 296 | fprintf(stdout,"Capture pro : [%i]\n", proto_type); 297 | fprintf(stdout,"HEP version : [%i]\n", hepversion); 298 | #ifdef USE_CONFFILE 299 | fprintf(stdout,"Config file : [%s]\n", conffile); 300 | #endif 301 | return 0; 302 | } 303 | 304 | 305 | if(chunk_vals) 306 | { 307 | /* useconds */ 308 | dav = strtok(chunk_vals, ":"); 309 | if(dav) { 310 | val1_chunk = atoi(dav); 311 | chunk_vals+=(strlen(dav)+1); 312 | val2_chunk = atoi(chunk_vals); 313 | } 314 | else { 315 | val1_chunk = atoi(chunk_vals); 316 | } 317 | } 318 | 319 | read_from_pipe(); 320 | 321 | handler(1); 322 | /* we should never get here during normal operation */ 323 | return 0; 324 | } 325 | 326 | 327 | int read_from_pipe() { 328 | 329 | char buffer[BUF_SIZE]; 330 | char cid[256]; 331 | size_t contentSize = 1; // includes NULL 332 | char *pch = NULL, *tmpval = NULL; 333 | unsigned int offset; 334 | unsigned int tsec=0, tusec=0; 335 | char src_ip[256], dst_ip[256]; 336 | uint16_t sport = 1, dport=2, val1=0, val2=0; 337 | struct timeval tv; 338 | 339 | char *content = malloc(sizeof(char) * BUF_SIZE); 340 | if(content == NULL) 341 | { 342 | perror("Failed to allocate content"); 343 | exit(1); 344 | } 345 | 346 | content[0] = '\0'; // make null-terminated 347 | cid[0] = '\0'; 348 | 349 | correlation_id = NULL; 350 | 351 | while(fgets(buffer, BUF_SIZE, stdin)) 352 | { 353 | char *old = content; 354 | contentSize += strlen(buffer); 355 | content = realloc(content, contentSize); 356 | if(content == NULL) 357 | { 358 | perror("Failed to reallocate content"); 359 | free(old); 360 | exit(2); 361 | } 362 | strcat(content, buffer); 363 | } 364 | 365 | if(content && adv == 0) { 366 | 367 | /* seconds */ 368 | pch = strtok(content, ";"); 369 | if(pch) tsec = atoi(pch); 370 | else goto error; 371 | 372 | /* useconds */ 373 | pch = strtok(NULL, ";"); 374 | if(pch) tusec = atoi(pch); 375 | else goto error; 376 | 377 | /* correlation id */ 378 | pch = strtok(NULL, ";"); 379 | if(pch) snprintf(cid, 256, "%s", pch); 380 | else goto error; 381 | 382 | /* src ip */ 383 | pch = strtok(NULL, ";"); 384 | if(pch) snprintf(src_ip, 256, "%s", pch); 385 | else goto error; 386 | 387 | /* sport */ 388 | pch = strtok(NULL, ";"); 389 | if(pch) sport = atoi(pch); 390 | else goto error; 391 | 392 | /* dst ip */ 393 | pch = strtok(NULL, ";"); 394 | if(pch) snprintf(dst_ip, 256, "%s", pch); 395 | else goto error; 396 | 397 | /* dport */ 398 | pch = strtok(NULL, ";"); 399 | if(pch) dport = atoi(pch); 400 | else goto error; 401 | 402 | /* data */ 403 | pch = strtok(NULL, ";"); 404 | if(!pch) goto error; 405 | } 406 | else if(content && adv == 1) 407 | { 408 | /* gettimeofday(&tv,NULL); 409 | tsec = tv.tv_sec; 410 | tusec = tv.tv_usec 411 | */ 412 | 413 | /* seconds */ 414 | pch = strtok(content, ";"); 415 | if(pch) tsec = atoi(pch); 416 | else goto error; 417 | 418 | /* useconds */ 419 | pch = strtok(NULL, ";"); 420 | if(pch) tusec = atoi(pch); 421 | else goto error; 422 | 423 | /* correlation id */ 424 | pch = strtok(NULL, ";"); 425 | if(pch) snprintf(cid, 256, "%s", pch); 426 | else goto error; 427 | 428 | pch = strtok(NULL, ";"); 429 | if(pch) val1= atoi(pch); 430 | else goto error; 431 | 432 | pch = strtok(NULL, ";"); 433 | if(pch) val2=atoi(pch); 434 | else goto error; 435 | 436 | snprintf(src_ip, 256, "127.0.0.20"); 437 | snprintf(dst_ip, 256, "127.0.0.30"); 438 | 439 | } 440 | 441 | if(ferror(stdin)) 442 | { 443 | free(content); 444 | perror("Error reading from stdin."); 445 | } 446 | 447 | 448 | printf("\nTIME: %d.%d | ", tsec, tusec); 449 | printf("\nCID: %s | ", cid ? cid : "NULL"); 450 | printf("\nPort: source: %d, destination: %d", sport, dport); 451 | printf("\nDATA: %d/%d | STATUS: ", val1, val2); 452 | 453 | /* check our correlation */ 454 | if(cid && strlen(cid) > 0) correlation_id = cid; 455 | 456 | if(dump_proto_packet(pch, strlen(pch), tsec, tusec, src_ip, dst_ip, sport, dport, val1, val2)) { 457 | printf("SENT\n"); 458 | } 459 | 460 | return 1; 461 | 462 | 463 | 464 | error: 465 | if(content) free(content); 466 | return 1; 467 | } 468 | 469 | 470 | int dump_proto_packet(unsigned char *data, uint32_t len, uint32_t tsec, uint32_t tusec, const char *ip_src, const char *ip_dst, uint16_t sport, uint16_t dport, uint16_t val1, uint16_t val2) { 471 | 472 | char timebuffer[30]; 473 | rc_info_t *rcinfo = NULL; 474 | 475 | rcinfo = malloc(sizeof(rc_info_t)); 476 | memset(rcinfo, 0, sizeof(rc_info_t)); 477 | 478 | rcinfo->src_port = sport; 479 | rcinfo->dst_port = dport; 480 | rcinfo->src_ip = (char *)ip_src; 481 | rcinfo->dst_ip = (char *)ip_dst; 482 | rcinfo->ip_family = AF_INET; 483 | rcinfo->ip_proto = 17; 484 | rcinfo->time_sec = tsec; 485 | rcinfo->time_usec = tusec; 486 | rcinfo->proto_type = proto_type; 487 | rcinfo->val1 = val1; 488 | rcinfo->val2 = val2; 489 | 490 | /* Duplcate */ 491 | if(!send_hep_basic(rcinfo, data, (unsigned int) len)) { 492 | printf("FAILED\n"); 493 | } 494 | 495 | if(rcinfo) free(rcinfo); 496 | 497 | return 1; 498 | } 499 | 500 | 501 | 502 | int send_hep_basic (rc_info_t *rcinfo, unsigned char *data, unsigned int len) { 503 | 504 | switch(hep_version) { 505 | 506 | case 3: 507 | return send_hepv3(rcinfo, data , len); 508 | break; 509 | 510 | case 2: 511 | case 1: 512 | return send_hepv2(rcinfo, data, len); 513 | break; 514 | 515 | default: 516 | fprintf(stderr, "Unsupported HEP version [%d]\n", hep_version); 517 | break; 518 | } 519 | 520 | return 0; 521 | } 522 | 523 | int send_hepv3 (rc_info_t *rcinfo, unsigned char *data, unsigned int len) { 524 | 525 | struct hep_generic *hg=NULL; 526 | void* buffer; 527 | unsigned int buflen=0, iplen=0,tlen=0; 528 | hep_chunk_ip4_t src_ip4, dst_ip4; 529 | #ifdef USE_IPV6 530 | hep_chunk_ip6_t src_ip6, dst_ip6; 531 | #endif 532 | hep_chunk_t payload_chunk; 533 | hep_chunk_t authkey_chunk; 534 | hep_chunk_t correlation_chunk; 535 | hep_chunk_uint16_t chunk_val1, chunk_val2; 536 | static int errors = 0; 537 | 538 | hg = malloc(sizeof(struct hep_generic)); 539 | memset(hg, 0, sizeof(struct hep_generic)); 540 | 541 | /* header set */ 542 | memcpy(hg->header.id, "\x48\x45\x50\x33", 4); 543 | 544 | /* IP proto */ 545 | hg->ip_family.chunk.vendor_id = htons(0x0000); 546 | hg->ip_family.chunk.type_id = htons(0x0001); 547 | hg->ip_family.data = rcinfo->ip_family; 548 | hg->ip_family.chunk.length = htons(sizeof(hg->ip_family)); 549 | 550 | /* Proto ID */ 551 | hg->ip_proto.chunk.vendor_id = htons(0x0000); 552 | hg->ip_proto.chunk.type_id = htons(0x0002); 553 | hg->ip_proto.data = rcinfo->ip_proto; 554 | hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto)); 555 | 556 | 557 | /* IPv4 */ 558 | if(rcinfo->ip_family == AF_INET) { 559 | /* SRC IP */ 560 | src_ip4.chunk.vendor_id = htons(0x0000); 561 | src_ip4.chunk.type_id = htons(0x0003); 562 | inet_pton(AF_INET, rcinfo->src_ip, &src_ip4.data); 563 | src_ip4.chunk.length = htons(sizeof(src_ip4)); 564 | 565 | /* DST IP */ 566 | dst_ip4.chunk.vendor_id = htons(0x0000); 567 | dst_ip4.chunk.type_id = htons(0x0004); 568 | inet_pton(AF_INET, rcinfo->dst_ip, &dst_ip4.data); 569 | dst_ip4.chunk.length = htons(sizeof(dst_ip4)); 570 | 571 | iplen = sizeof(dst_ip4) + sizeof(src_ip4); 572 | } 573 | #ifdef USE_IPV6 574 | /* IPv6 */ 575 | else if(rcinfo->ip_family == AF_INET6) { 576 | /* SRC IPv6 */ 577 | src_ip6.chunk.vendor_id = htons(0x0000); 578 | src_ip6.chunk.type_id = htons(0x0005); 579 | inet_pton(AF_INET6, rcinfo->src_ip, &src_ip6.data); 580 | src_ip6.chunk.length = htons(sizeof(src_ip6)); 581 | 582 | /* DST IPv6 */ 583 | dst_ip6.chunk.vendor_id = htons(0x0000); 584 | dst_ip6.chunk.type_id = htons(0x0006); 585 | inet_pton(AF_INET6, rcinfo->dst_ip, &dst_ip6.data); 586 | dst_ip6.chunk.length = htons(sizeof(dst_ip6)); 587 | 588 | iplen = sizeof(dst_ip6) + sizeof(src_ip6); 589 | } 590 | #endif 591 | 592 | /* SRC PORT */ 593 | hg->src_port.chunk.vendor_id = htons(0x0000); 594 | hg->src_port.chunk.type_id = htons(0x0007); 595 | hg->src_port.data = rcinfo->src_port; 596 | hg->src_port.chunk.length = htons(sizeof(hg->src_port)); 597 | 598 | /* DST PORT */ 599 | hg->dst_port.chunk.vendor_id = htons(0x0000); 600 | hg->dst_port.chunk.type_id = htons(0x0008); 601 | hg->dst_port.data = rcinfo->dst_port; 602 | hg->dst_port.chunk.length = htons(sizeof(hg->dst_port)); 603 | 604 | 605 | /* TIMESTAMP SEC */ 606 | hg->time_sec.chunk.vendor_id = htons(0x0000); 607 | hg->time_sec.chunk.type_id = htons(0x0009); 608 | hg->time_sec.data = htonl(rcinfo->time_sec); 609 | hg->time_sec.chunk.length = htons(sizeof(hg->time_sec)); 610 | 611 | 612 | /* TIMESTAMP USEC */ 613 | hg->time_usec.chunk.vendor_id = htons(0x0000); 614 | hg->time_usec.chunk.type_id = htons(0x000a); 615 | hg->time_usec.data = htonl(rcinfo->time_usec); 616 | hg->time_usec.chunk.length = htons(sizeof(hg->time_usec)); 617 | 618 | /* Protocol TYPE */ 619 | hg->proto_t.chunk.vendor_id = htons(0x0000); 620 | hg->proto_t.chunk.type_id = htons(0x000b); 621 | hg->proto_t.data = rcinfo->proto_type; 622 | hg->proto_t.chunk.length = htons(sizeof(hg->proto_t)); 623 | 624 | /* Capture ID */ 625 | hg->capt_id.chunk.vendor_id = htons(0x0000); 626 | hg->capt_id.chunk.type_id = htons(0x000c); 627 | hg->capt_id.data = htonl(captid); 628 | hg->capt_id.chunk.length = htons(sizeof(hg->capt_id)); 629 | 630 | /* Payload */ 631 | payload_chunk.vendor_id = htons(0x0000); 632 | payload_chunk.type_id = htons(0x000f); 633 | payload_chunk.length = htons(sizeof(payload_chunk) + len); 634 | 635 | tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t); 636 | 637 | /* auth key */ 638 | if(capt_password != NULL) { 639 | 640 | tlen += sizeof(hep_chunk_t); 641 | /* Auth key */ 642 | authkey_chunk.vendor_id = htons(0x0000); 643 | authkey_chunk.type_id = htons(0x000e); 644 | authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(capt_password)); 645 | tlen += strlen(capt_password); 646 | } 647 | 648 | /* correlation id */ 649 | if(correlation_id != NULL) { 650 | tlen += sizeof(hep_chunk_t); 651 | /* Auth key */ 652 | correlation_chunk.vendor_id = htons(0x0000); 653 | correlation_chunk.type_id = htons(0x0011); 654 | correlation_chunk.length = htons(sizeof(correlation_chunk) + strlen(correlation_id)); 655 | tlen += strlen(correlation_id); 656 | } 657 | 658 | /* val1 */ 659 | if(chunk_vendor_id != 0 && val1_chunk != 0) { 660 | tlen += sizeof(hep_chunk_uint16_t); 661 | chunk_val1.chunk.vendor_id = htons(chunk_vendor_id); 662 | chunk_val1.chunk.type_id = htons(val1_chunk); 663 | chunk_val1.data = htons(rcinfo->val1); 664 | chunk_val1.chunk.length = htons(sizeof(hep_chunk_uint16_t)); 665 | } 666 | 667 | /* val2 */ 668 | if(chunk_vendor_id != 0 && val2_chunk != 0) { 669 | tlen += sizeof(hep_chunk_uint16_t); 670 | chunk_val2.chunk.vendor_id = htons(chunk_vendor_id); 671 | chunk_val2.chunk.type_id = htons(val2_chunk); 672 | chunk_val2.data = htons(rcinfo->val2); 673 | chunk_val2.chunk.length = htons(sizeof(hep_chunk_uint16_t)); 674 | } 675 | 676 | /* total */ 677 | hg->header.length = htons(tlen); 678 | 679 | buffer = (void*)malloc(tlen); 680 | if (buffer==0){ 681 | fprintf(stderr,"ERROR: out of memory\n"); 682 | free(hg); 683 | return 1; 684 | } 685 | 686 | memcpy((void*) buffer, hg, sizeof(struct hep_generic)); 687 | buflen = sizeof(struct hep_generic); 688 | 689 | /* IPv4 */ 690 | if(rcinfo->ip_family == AF_INET) { 691 | /* SRC IP */ 692 | memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip4)); 693 | buflen += sizeof(struct hep_chunk_ip4); 694 | 695 | memcpy((void*) buffer+buflen, &dst_ip4, sizeof(struct hep_chunk_ip4)); 696 | buflen += sizeof(struct hep_chunk_ip4); 697 | } 698 | #ifdef USE_IPV6 699 | /* IPv6 */ 700 | else if(rcinfo->ip_family == AF_INET6) { 701 | /* SRC IPv6 */ 702 | memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6)); 703 | buflen += sizeof(struct hep_chunk_ip6); 704 | 705 | memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6)); 706 | buflen += sizeof(struct hep_chunk_ip6); 707 | } 708 | #endif 709 | 710 | /* AUTH KEY CHUNK */ 711 | if(capt_password != NULL) { 712 | 713 | memcpy((void*) buffer+buflen, &authkey_chunk, sizeof(struct hep_chunk)); 714 | buflen += sizeof(struct hep_chunk); 715 | 716 | /* Now copying payload self */ 717 | memcpy((void*) buffer+buflen, capt_password, strlen(capt_password)); 718 | buflen+=strlen(capt_password); 719 | } 720 | 721 | /* AUTH KEY CHUNK */ 722 | if(correlation_id != NULL) { 723 | 724 | memcpy((void*) buffer+buflen, &correlation_chunk, sizeof(struct hep_chunk)); 725 | buflen += sizeof(struct hep_chunk); 726 | 727 | /* Now copying payload self */ 728 | memcpy((void*) buffer+buflen, correlation_id, strlen(correlation_id)); 729 | buflen+=strlen(correlation_id); 730 | } 731 | 732 | 733 | /* val1 */ 734 | if(chunk_vendor_id != 0 && val1_chunk != 0) { 735 | 736 | memcpy((void*) buffer+buflen, &chunk_val1, sizeof(chunk_val1)); 737 | buflen += sizeof(hep_chunk_uint16_t); 738 | } 739 | 740 | /* val2 */ 741 | if(chunk_vendor_id != 0 && val2_chunk != 0) { 742 | 743 | memcpy((void*) buffer+buflen, &chunk_val2, sizeof(chunk_val2)); 744 | buflen += sizeof(hep_chunk_uint16_t); 745 | } 746 | 747 | /* PAYLOAD CHUNK */ 748 | memcpy((void*) buffer+buflen, &payload_chunk, sizeof(struct hep_chunk)); 749 | buflen += sizeof(struct hep_chunk); 750 | 751 | /* Now copying payload self */ 752 | memcpy((void*) buffer+buflen, data, len); 753 | buflen+=len; 754 | 755 | /* send this packet out of our socket */ 756 | send(sock, buffer, buflen, 0); 757 | 758 | /* FREE */ 759 | if(buffer) free(buffer); 760 | if(hg) free(hg); 761 | 762 | return 1; 763 | } 764 | 765 | 766 | int send_hepv2 (rc_info_t *rcinfo, unsigned char *data, unsigned int len) { 767 | 768 | void* buffer; 769 | struct hep_hdr hdr; 770 | struct hep_timehdr hep_time; 771 | struct hep_iphdr hep_ipheader; 772 | unsigned int totlen=0, buflen=0; 773 | static int errors=0; 774 | #ifdef USE_IPV6 775 | struct hep_ip6hdr hep_ip6header; 776 | #endif /* USE IPV6 */ 777 | 778 | /* Version && proto */ 779 | hdr.hp_v = hep_version; 780 | hdr.hp_f = rcinfo->ip_family; 781 | hdr.hp_p = rcinfo->ip_proto; 782 | hdr.hp_sport = htons(rcinfo->src_port); /* src port */ 783 | hdr.hp_dport = htons(rcinfo->dst_port); /* dst port */ 784 | 785 | /* IP version */ 786 | switch (hdr.hp_f) { 787 | case AF_INET: 788 | totlen = sizeof(struct hep_iphdr); 789 | break; 790 | #ifdef USE_IPV6 791 | case AF_INET6: 792 | totlen = sizeof(struct hep_ip6hdr); 793 | break; 794 | #endif /* USE IPV6 */ 795 | 796 | } 797 | 798 | hdr.hp_l = totlen + sizeof(struct hep_hdr); 799 | 800 | /* COMPLETE LEN */ 801 | totlen += sizeof(struct hep_hdr); 802 | totlen += len; 803 | 804 | if(hep_version == 2) { 805 | totlen += sizeof(struct hep_timehdr); 806 | hep_time.tv_sec = rcinfo->time_sec; 807 | hep_time.tv_usec = rcinfo->time_usec; 808 | hep_time.captid = captid; 809 | } 810 | 811 | /*buffer for ethernet frame*/ 812 | buffer = (void*)malloc(totlen); 813 | if (buffer==0){ 814 | fprintf(stderr,"ERROR: out of memory\n"); 815 | goto error; 816 | } 817 | 818 | /* copy hep_hdr */ 819 | memcpy((void*) buffer, &hdr, sizeof(struct hep_hdr)); 820 | buflen = sizeof(struct hep_hdr); 821 | 822 | switch (hdr.hp_f) { 823 | 824 | case AF_INET: 825 | /* Source && Destination ipaddresses*/ 826 | inet_pton(AF_INET, rcinfo->src_ip, &hep_ipheader.hp_src); 827 | inet_pton(AF_INET, rcinfo->dst_ip, &hep_ipheader.hp_dst); 828 | 829 | /* copy hep ipheader */ 830 | memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); 831 | buflen += sizeof(struct hep_iphdr); 832 | 833 | break; 834 | #ifdef USE_IPV6 835 | case AF_INET6: 836 | 837 | inet_pton(AF_INET6, rcinfo->src_ip, &hep_ip6header.hp6_src); 838 | inet_pton(AF_INET6, rcinfo->dst_ip, &hep_ip6header.hp6_dst); 839 | 840 | /* copy hep6 ipheader */ 841 | memcpy((void*)buffer + buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); 842 | buflen += sizeof(struct hep_ip6hdr); 843 | break; 844 | #endif /* USE_IPV6 */ 845 | } 846 | 847 | /* Version 2 has timestamp, captnode ID */ 848 | if(hep_version == 2) { 849 | /* TIMING */ 850 | memcpy((void*)buffer + buflen, &hep_time, sizeof(struct hep_timehdr)); 851 | buflen += sizeof(struct hep_timehdr); 852 | } 853 | 854 | memcpy((void *)(buffer + buflen) , (void*)(data), len); 855 | buflen +=len; 856 | 857 | send(sock, buffer, buflen, 0); 858 | 859 | /* FREE */ 860 | if(buffer) free(buffer); 861 | 862 | return 1; 863 | 864 | error: 865 | if(buffer) free(buffer); 866 | return 0; 867 | } 868 | -------------------------------------------------------------------------------- /hepipe.h: -------------------------------------------------------------------------------- 1 | #define VERSION "1.0.3 dev" 2 | #define DEFAULT_CONFIG "/usr/local/etc/hepipe/hepipe.ini" 3 | 4 | #define PROTO_SIP 0x01 5 | #define ETH_P_IP 0x0800 6 | #define BUF_SIZE 1024 7 | 8 | /* functions */ 9 | int read_from_pipe(); 10 | 11 | int dump_proto_packet(unsigned char *data, uint32_t len, uint32_t tsec, uint32_t tusec, const char *ip_src, const char *ip_dst, uint16_t sport, uint16_t dport, uint16_t val1, uint16_t val2); 12 | int send_hep_basic (rc_info_t *rcinfo, unsigned char *data, unsigned int len); 13 | int send_hepv3 (rc_info_t *rcinfo, unsigned char *data, unsigned int len); 14 | int send_hepv2 (rc_info_t *rcinfo, unsigned char *data, unsigned int len); 15 | -------------------------------------------------------------------------------- /hepipe.ini: -------------------------------------------------------------------------------- 1 | [main] 2 | capture_server = 127.0.0.1 3 | capture_server_port = 5060 4 | identifier = 101 5 | hep = 3 6 | -------------------------------------------------------------------------------- /minIni/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | 7 | EXCEPTION TO THE APACHE 2.0 LICENSE 8 | 9 | As a special exception to the Apache License 2.0 (and referring to the 10 | definitions in Section 1 of this license), you may link, statically or 11 | dynamically, the "Work" to other modules to produce an executable file 12 | containing portions of the "Work", and distribute that executable file 13 | in "Object" form under the terms of your choice, without any of the 14 | additional requirements listed in Section 4 of the Apache License 2.0. 15 | This exception applies only to redistributions in "Object" form (not 16 | "Source" form) and only if no modifications have been made to the "Work". 17 | 18 | 19 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 20 | 21 | 1. Definitions. 22 | 23 | "License" shall mean the terms and conditions for use, reproduction, 24 | and distribution as defined by Sections 1 through 9 of this document. 25 | 26 | "Licensor" shall mean the copyright owner or entity authorized by 27 | the copyright owner that is granting the License. 28 | 29 | "Legal Entity" shall mean the union of the acting entity and all 30 | other entities that control, are controlled by, or are under common 31 | control with that entity. For the purposes of this definition, 32 | "control" means (i) the power, direct or indirect, to cause the 33 | direction or management of such entity, whether by contract or 34 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 35 | outstanding shares, or (iii) beneficial ownership of such entity. 36 | 37 | "You" (or "Your") shall mean an individual or Legal Entity 38 | exercising permissions granted by this License. 39 | 40 | "Source" form shall mean the preferred form for making modifications, 41 | including but not limited to software source code, documentation 42 | source, and configuration files. 43 | 44 | "Object" form shall mean any form resulting from mechanical 45 | transformation or translation of a Source form, including but 46 | not limited to compiled object code, generated documentation, 47 | and conversions to other media types. 48 | 49 | "Work" shall mean the work of authorship, whether in Source or 50 | Object form, made available under the License, as indicated by a 51 | copyright notice that is included in or attached to the work 52 | (an example is provided in the Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object 55 | form, that is based on (or derived from) the Work and for which the 56 | editorial revisions, annotations, elaborations, or other modifications 57 | represent, as a whole, an original work of authorship. For the purposes 58 | of this License, Derivative Works shall not include works that remain 59 | separable from, or merely link (or bind by name) to the interfaces of, 60 | the Work and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any work of authorship, including 63 | the original version of the Work and any modifications or additions 64 | to that Work or Derivative Works thereof, that is intentionally 65 | submitted to Licensor for inclusion in the Work by the copyright owner 66 | or by an individual or Legal Entity authorized to submit on behalf of 67 | the copyright owner. For the purposes of this definition, "submitted" 68 | means any form of electronic, verbal, or written communication sent 69 | to the Licensor or its representatives, including but not limited to 70 | communication on electronic mailing lists, source code control systems, 71 | and issue tracking systems that are managed by, or on behalf of, the 72 | Licensor for the purpose of discussing and improving the Work, but 73 | excluding communication that is conspicuously marked or otherwise 74 | designated in writing by the copyright owner as "Not a Contribution." 75 | 76 | "Contributor" shall mean Licensor and any individual or Legal Entity 77 | on behalf of whom a Contribution has been received by Licensor and 78 | subsequently incorporated within the Work. 79 | 80 | 2. Grant of Copyright License. Subject to the terms and conditions of 81 | this License, each Contributor hereby grants to You a perpetual, 82 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 83 | copyright license to reproduce, prepare Derivative Works of, 84 | publicly display, publicly perform, sublicense, and distribute the 85 | Work and such Derivative Works in Source or Object form. 86 | 87 | 3. Grant of Patent License. Subject to the terms and conditions of 88 | this License, each Contributor hereby grants to You a perpetual, 89 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 90 | (except as stated in this section) patent license to make, have made, 91 | use, offer to sell, sell, import, and otherwise transfer the Work, 92 | where such license applies only to those patent claims licensable 93 | by such Contributor that are necessarily infringed by their 94 | Contribution(s) alone or by combination of their Contribution(s) 95 | with the Work to which such Contribution(s) was submitted. If You 96 | institute patent litigation against any entity (including a 97 | cross-claim or counterclaim in a lawsuit) alleging that the Work 98 | or a Contribution incorporated within the Work constitutes direct 99 | or contributory patent infringement, then any patent licenses 100 | granted to You under this License for that Work shall terminate 101 | as of the date such litigation is filed. 102 | 103 | 4. Redistribution. You may reproduce and distribute copies of the 104 | Work or Derivative Works thereof in any medium, with or without 105 | modifications, and in Source or Object form, provided that You 106 | meet the following conditions: 107 | 108 | (a) You must give any other recipients of the Work or 109 | Derivative Works a copy of this License; and 110 | 111 | (b) You must cause any modified files to carry prominent notices 112 | stating that You changed the files; and 113 | 114 | (c) You must retain, in the Source form of any Derivative Works 115 | that You distribute, all copyright, patent, trademark, and 116 | attribution notices from the Source form of the Work, 117 | excluding those notices that do not pertain to any part of 118 | the Derivative Works; and 119 | 120 | (d) If the Work includes a "NOTICE" text file as part of its 121 | distribution, then any Derivative Works that You distribute must 122 | include a readable copy of the attribution notices contained 123 | within such NOTICE file, excluding those notices that do not 124 | pertain to any part of the Derivative Works, in at least one 125 | of the following places: within a NOTICE text file distributed 126 | as part of the Derivative Works; within the Source form or 127 | documentation, if provided along with the Derivative Works; or, 128 | within a display generated by the Derivative Works, if and 129 | wherever such third-party notices normally appear. The contents 130 | of the NOTICE file are for informational purposes only and 131 | do not modify the License. You may add Your own attribution 132 | notices within Derivative Works that You distribute, alongside 133 | or as an addendum to the NOTICE text from the Work, provided 134 | that such additional attribution notices cannot be construed 135 | as modifying the License. 136 | 137 | You may add Your own copyright statement to Your modifications and 138 | may provide additional or different license terms and conditions 139 | for use, reproduction, or distribution of Your modifications, or 140 | for any such Derivative Works as a whole, provided Your use, 141 | reproduction, and distribution of the Work otherwise complies with 142 | the conditions stated in this License. 143 | 144 | 5. Submission of Contributions. Unless You explicitly state otherwise, 145 | any Contribution intentionally submitted for inclusion in the Work 146 | by You to the Licensor shall be under the terms and conditions of 147 | this License, without any additional terms or conditions. 148 | Notwithstanding the above, nothing herein shall supersede or modify 149 | the terms of any separate license agreement you may have executed 150 | with Licensor regarding such Contributions. 151 | 152 | 6. Trademarks. This License does not grant permission to use the trade 153 | names, trademarks, service marks, or product names of the Licensor, 154 | except as required for reasonable and customary use in describing the 155 | origin of the Work and reproducing the content of the NOTICE file. 156 | 157 | 7. Disclaimer of Warranty. Unless required by applicable law or 158 | agreed to in writing, Licensor provides the Work (and each 159 | Contributor provides its Contributions) on an "AS IS" BASIS, 160 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 161 | implied, including, without limitation, any warranties or conditions 162 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 163 | PARTICULAR PURPOSE. You are solely responsible for determining the 164 | appropriateness of using or redistributing the Work and assume any 165 | risks associated with Your exercise of permissions under this License. 166 | 167 | 8. Limitation of Liability. In no event and under no legal theory, 168 | whether in tort (including negligence), contract, or otherwise, 169 | unless required by applicable law (such as deliberate and grossly 170 | negligent acts) or agreed to in writing, shall any Contributor be 171 | liable to You for damages, including any direct, indirect, special, 172 | incidental, or consequential damages of any character arising as a 173 | result of this License or out of the use or inability to use the 174 | Work (including but not limited to damages for loss of goodwill, 175 | work stoppage, computer failure or malfunction, or any and all 176 | other commercial damages or losses), even if such Contributor 177 | has been advised of the possibility of such damages. 178 | 179 | 9. Accepting Warranty or Additional Liability. While redistributing 180 | the Work or Derivative Works thereof, You may choose to offer, 181 | and charge a fee for, acceptance of support, warranty, indemnity, 182 | or other liability obligations and/or rights consistent with this 183 | License. However, in accepting such obligations, You may act only 184 | on Your own behalf and on Your sole responsibility, not on behalf 185 | of any other Contributor, and only if You agree to indemnify, 186 | defend, and hold each Contributor harmless for any liability 187 | incurred by, or claims asserted against, such Contributor by reason 188 | of your accepting any such warranty or additional liability. 189 | 190 | -------------------------------------------------------------------------------- /minIni/NOTICE: -------------------------------------------------------------------------------- 1 | minIni is a programmer's library to read and write "INI" files in embedded 2 | systems. The library takes little resources and can be configured for various 3 | kinds of file I/O libraries. 4 | 5 | The method for portable INI file management in minIni is, in part based, on the 6 | article "Multiplatform .INI Files" by Joseph J. Graf in the March 1994 issue of 7 | Dr. Dobb's Journal. 8 | 9 | The C++ class in minIni.h was contributed by Steven Van Ingelgem. 10 | 11 | The option to compile minIni as a read-only library was contributed by Luca 12 | Bassanello. 13 | -------------------------------------------------------------------------------- /minIni/minGlue-FatFs.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the FatFs and Petit-FatFs 2 | * libraries, see http://elm-chan.org/fsw/ff/00index_e.html 3 | * 4 | * Copyright (c) CompuPhase, 2008-2012 5 | * (The FatFs and Petit-FatFs libraries are copyright by ChaN and licensed at 6 | * its own terms.) 7 | * 8 | * This "glue file" is licensed under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | #define INI_BUFFERSIZE 256 /* maximum line length, maximum path length */ 22 | 23 | /* You must set _USE_STRFUNC to 1 or 2 in the include file ff.h (or tff.h) 24 | * to enable the "string functions" fgets() and fputs(). 25 | */ 26 | #include "ff.h" /* include tff.h for Tiny-FatFs */ 27 | 28 | #define INI_FILETYPE FIL 29 | #define ini_openread(filename,file) (f_open((file), (filename), FA_READ+FA_OPEN_EXISTING) == FR_OK) 30 | #define ini_openwrite(filename,file) (f_open((file), (filename), FA_WRITE+FA_CREATE_ALWAYS) == FR_OK) 31 | #define ini_close(file) (f_close(file) == FR_OK) 32 | #define ini_read(buffer,size,file) f_gets((buffer), (size),(file)) 33 | #define ini_write(buffer,file) f_puts((buffer), (file)) 34 | #define ini_remove(filename) (f_unlink(filename) == FR_OK) 35 | 36 | #define INI_FILEPOS DWORD 37 | #define ini_tell(file,pos) (*(pos) = f_tell((file))) 38 | #define ini_seek(file,pos) (f_lseek((file), *(pos)) == FR_OK) 39 | 40 | static int ini_rename(TCHAR *source, const TCHAR *dest) 41 | { 42 | /* Function f_rename() does not allow drive letters in the destination file */ 43 | char *drive = strchr(dest, ':'); 44 | drive = (drive == NULL) ? dest : drive + 1; 45 | return (f_rename(source, drive) == FR_OK); 46 | } 47 | -------------------------------------------------------------------------------- /minIni/minGlue-ccs.h: -------------------------------------------------------------------------------- 1 | /* minIni glue functions for FAT library by CCS, Inc. (as provided with their 2 | * PIC MCU compiler) 3 | * 4 | * Copyright (c) CompuPhase, 2011-2012 5 | * (The FAT library is copyright (c) 2007 Custom Computer Services, and 6 | * licensed at its own terms.) 7 | * 8 | * This "glue file" is licensed under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | #define INI_BUFFERSIZE 256 /* maximum line length, maximum path length */ 22 | 23 | #ifndef FAT_PIC_C 24 | #error FAT library must be included before this module 25 | #endif 26 | #define const /* keyword not supported by CCS */ 27 | 28 | #define INI_FILETYPE FILE 29 | #define ini_openread(filename,file) (fatopen((filename), "r", (file)) == GOODEC) 30 | #define ini_openwrite(filename,file) (fatopen((filename), "w", (file)) == GOODEC) 31 | #define ini_close(file) (fatclose((file)) == 0) 32 | #define ini_read(buffer,size,file) (fatgets((buffer), (size), (file)) != NULL) 33 | #define ini_write(buffer,file) (fatputs((buffer), (file)) == GOODEC) 34 | #define ini_remove(filename) (rm_file((filename)) == 0) 35 | 36 | #define INI_FILEPOS fatpos_t 37 | #define ini_tell(file,pos) (fatgetpos((file), (pos)) == 0) 38 | #define ini_seek(file,pos) (fatsetpos((file), (pos)) == 0) 39 | 40 | #ifndef INI_READONLY 41 | /* CCS FAT library lacks a rename function, so instead we copy the file to the 42 | * new name and delete the old file 43 | */ 44 | static int ini_rename(char *source, char *dest) 45 | { 46 | FILE fr, fw; 47 | int n; 48 | 49 | if (fatopen(source, "r", &fr) != GOODEC) 50 | return 0; 51 | if (rm_file(dest) != 0) 52 | return 0; 53 | if (fatopen(dest, "w", &fw) != GOODEC) 54 | return 0; 55 | 56 | /* With some "insider knowledge", we can save some memory: the "source" 57 | * parameter holds a filename that was built from the "dest" parameter. It 58 | * was built in a local buffer with the size INI_BUFFERSIZE. We can reuse 59 | * this buffer for copying the file. 60 | */ 61 | while (n=fatread(source, 1, INI_BUFFERSIZE, &fr)) 62 | fatwrite(source, 1, n, &fw); 63 | 64 | fatclose(&fr); 65 | fatclose(&fw); 66 | 67 | /* Now we need to delete the source file. However, we have garbled the buffer 68 | * that held the filename of the source. So we need to build it again. 69 | */ 70 | ini_tempname(source, dest, INI_BUFFERSIZE); 71 | return rm_file(source) == 0; 72 | } 73 | #endif 74 | -------------------------------------------------------------------------------- /minIni/minGlue-efsl.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the EFS Library, see 2 | * http://www.efsl.be/ 3 | * 4 | * Copyright (c) CompuPhase, 2008-2012 5 | * (EFSL is copyright 2005-2006 Lennart Ysboodt and Michael De Nil, and 6 | * licensed under the GPL with an exception clause for statit linking.) 7 | * 8 | * This "glue file" is licensed under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | #define INI_BUFFERSIZE 256 /* maximum line length, maximum path length */ 22 | #define INI_LINETERM "\r\n" /* set line termination explicitly */ 23 | 24 | #include "efs.h" 25 | extern EmbeddedFileSystem g_efs; 26 | 27 | #define INI_FILETYPE EmbeddedFile 28 | #define ini_openread(filename,file) (file_fopen((file), &g_efs.myFs, (char*)(filename), 'r') == 0) 29 | #define ini_openwrite(filename,file) (file_fopen((file), &g_efs.myFs, (char*)(filename), 'w') == 0) 30 | #define ini_close(file) file_fclose(file) 31 | #define ini_read(buffer,size,file) (file_read((file), (size), (buffer)) > 0) 32 | #define ini_write(buffer,file) (file_write((file), strlen(buffer), (char*)(buffer)) > 0) 33 | #define ini_remove(filename) rmfile(&g_efs.myFs, (char*)(filename)) 34 | 35 | #define INI_FILEPOS euint32 36 | #define ini_tell(file,pos) (*(pos) = (file)->FilePtr)) 37 | #define ini_seek(file,pos) file_setpos((file), (*pos)) 38 | 39 | #if ! defined INI_READONLY 40 | /* EFSL lacks a rename function, so instead we copy the file to the new name 41 | * and delete the old file 42 | */ 43 | static int ini_rename(char *source, const char *dest) 44 | { 45 | EmbeddedFile fr, fw; 46 | int n; 47 | 48 | if (file_fopen(&fr, &g_efs.myFs, source, 'r') != 0) 49 | return 0; 50 | if (rmfile(&g_efs.myFs, (char*)dest) != 0) 51 | return 0; 52 | if (file_fopen(&fw, &g_efs.myFs, (char*)dest, 'w') != 0) 53 | return 0; 54 | 55 | /* With some "insider knowledge", we can save some memory: the "source" 56 | * parameter holds a filename that was built from the "dest" parameter. It 57 | * was built in buffer and this buffer has the size INI_BUFFERSIZE. We can 58 | * reuse this buffer for copying the file. 59 | */ 60 | while (n=file_read(&fr, INI_BUFFERSIZE, source)) 61 | file_write(&fw, n, source); 62 | 63 | file_fclose(&fr); 64 | file_fclose(&fw); 65 | 66 | /* Now we need to delete the source file. However, we have garbled the buffer 67 | * that held the filename of the source. So we need to build it again. 68 | */ 69 | ini_tempname(source, dest, INI_BUFFERSIZE); 70 | return rmfile(&g_efs.myFs, source) == 0; 71 | } 72 | #endif 73 | -------------------------------------------------------------------------------- /minIni/minGlue-ffs.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the "FAT Filing System" 2 | * library by embedded-code.com 3 | * 4 | * Copyright (c) CompuPhase, 2008-2012 5 | * (The "FAT Filing System" library itself is copyright embedded-code.com, and 6 | * licensed at its own terms.) 7 | * 8 | * This "glue file" is licensed under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | #define INI_BUFFERSIZE 256 /* maximum line length, maximum path length */ 22 | #include 23 | 24 | #define INI_FILETYPE FFS_FILE* 25 | #define ini_openread(filename,file) ((*(file) = ffs_fopen((filename),"r")) != NULL) 26 | #define ini_openwrite(filename,file) ((*(file) = ffs_fopen((filename),"w")) != NULL) 27 | #define ini_close(file) (ffs_fclose(*(file)) == 0) 28 | #define ini_read(buffer,size,file) (ffs_fgets((buffer),(size),*(file)) != NULL) 29 | #define ini_write(buffer,file) (ffs_fputs((buffer),*(file)) >= 0) 30 | #define ini_rename(source,dest) (ffs_rename((source), (dest)) == 0) 31 | #define ini_remove(filename) (ffs_remove(filename) == 0) 32 | 33 | #define INI_FILEPOS long 34 | #define ini_tell(file,pos) (ffs_fgetpos(*(file), (pos)) == 0) 35 | #define ini_seek(file,pos) (ffs_fsetpos(*(file), (pos)) == 0) 36 | -------------------------------------------------------------------------------- /minIni/minGlue-mdd.h: -------------------------------------------------------------------------------- 1 | /* minIni glue functions for Microchip's "Memory Disk Drive" file system 2 | * library, as presented in Microchip application note AN1045. 3 | * 4 | * Copyright (c) CompuPhase, 2011-2012 5 | * (The "Microchip Memory Disk Drive File System" is copyright (c) Microchip 6 | * Technology Incorporated, and licensed at its own terms.) 7 | * 8 | * This "glue file" is licensed under the Apache License, Version 2.0 (the 9 | * "License"); you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | #define INI_BUFFERSIZE 256 /* maximum line length, maximum path length */ 22 | 23 | #include "MDD File System\fsio.h" 24 | #include 25 | 26 | #define INI_FILETYPE FSFILE* 27 | #define ini_openread(filename,file) ((*(file) = FSfopen((filename), FS_READ)) != NULL) 28 | #define ini_openwrite(filename,file) ((*(file) = FSfopen((filename), FS_WRITE)) != NULL) 29 | #define ini_close(file) (FSfclose(*(file)) == 0) 30 | #define ini_write(buffer,file) (FSfwrite((buffer), 1, strlen(buffer), (*file)) > 0) 31 | #define ini_remove(filename) (FSremove((filename)) == 0) 32 | 33 | #define INI_FILEPOS long 34 | #define ini_tell(file,pos) (*(pos) = FSftell(*(file))) 35 | #define ini_seek(file,pos) (FSfseek(*(file), *(pos), SEEK_SET) == 0) 36 | 37 | /* Since the Memory Disk Drive file system library reads only blocks of files, 38 | * the function to read a text line does so by "over-reading" a block of the 39 | * of the maximum size and truncating it behind the end-of-line. 40 | */ 41 | static int ini_read(char *buffer, int size, INI_FILETYPE *file) 42 | { 43 | size_t numread = size; 44 | char *eol; 45 | 46 | if ((numread = FSfread(buffer, 1, size, *file)) == 0) 47 | return 0; /* at EOF */ 48 | if ((eol = strchr(buffer, '\n')) == NULL) 49 | eol = strchr(buffer, '\r'); 50 | if (eol != NULL) { 51 | /* terminate the buffer */ 52 | *++eol = '\0'; 53 | /* "unread" the data that was read too much */ 54 | FSfseek(*file, - (int)(numread - (size_t)(eol - buffer)), SEEK_CUR); 55 | } /* if */ 56 | return 1; 57 | } 58 | 59 | #ifndef INI_READONLY 60 | static int ini_rename(const char *source, const char *dest) 61 | { 62 | FSFILE* ftmp = FSfopen((source), FS_READ); 63 | FSrename((dest), ftmp); 64 | return FSfclose(ftmp) == 0; 65 | } 66 | #endif 67 | -------------------------------------------------------------------------------- /minIni/minGlue-stdio.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the C/C++ stdio library 2 | * 3 | * Or better said: this file contains macros that maps the function interface 4 | * used by minIni to the standard C/C++ file I/O functions. 5 | * 6 | * Copyright (c) CompuPhase, 2008-2012 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 | * use this file except in compliance with the License. You may obtain a copy 10 | * of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | /* map required file I/O types and functions to the standard C library */ 22 | #include 23 | 24 | #define INI_FILETYPE FILE* 25 | #define ini_openread(filename,file) ((*(file) = fopen((filename),"r")) != NULL) 26 | #define ini_openwrite(filename,file) ((*(file) = fopen((filename),"w")) != NULL) 27 | #define ini_close(file) (fclose(*(file)) == 0) 28 | #define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL) 29 | #define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0) 30 | #define ini_rename(source,dest) (rename((source), (dest)) == 0) 31 | #define ini_remove(filename) (remove(filename) == 0) 32 | 33 | #define INI_FILEPOS fpos_t 34 | #define ini_tell(file,pos) (fgetpos(*(file), (pos)) == 0) 35 | #define ini_seek(file,pos) (fsetpos(*(file), (pos)) == 0) 36 | 37 | /* for floating-point support, define additional types and functions */ 38 | #define INI_REAL float 39 | #define ini_ftoa(string,value) sprintf((string),"%f",(value)) 40 | #define ini_atof(string) (INI_REAL)strtod((string),NULL) 41 | -------------------------------------------------------------------------------- /minIni/minGlue.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the C/C++ stdio library 2 | * 3 | * Or better said: this file contains macros that maps the function interface 4 | * used by minIni to the standard C/C++ file I/O functions. 5 | * 6 | * Copyright (c) CompuPhase, 2008-2012 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 | * use this file except in compliance with the License. You may obtain a copy 10 | * of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | */ 20 | 21 | /* map required file I/O types and functions to the standard C library */ 22 | #include 23 | 24 | #define INI_FILETYPE FILE* 25 | #define ini_openread(filename,file) ((*(file) = fopen((filename),"r")) != NULL) 26 | #define ini_openwrite(filename,file) ((*(file) = fopen((filename),"w")) != NULL) 27 | #define ini_close(file) (fclose(*(file)) == 0) 28 | #define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL) 29 | #define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0) 30 | #define ini_rename(source,dest) (rename((source), (dest)) == 0) 31 | #define ini_remove(filename) (remove(filename) == 0) 32 | 33 | #define INI_FILEPOS fpos_t 34 | #define ini_tell(file,pos) (fgetpos(*(file), (pos)) == 0) 35 | #define ini_seek(file,pos) (fsetpos(*(file), (pos)) == 0) 36 | 37 | /* for floating-point support, define additional types and functions */ 38 | #define INI_REAL float 39 | #define ini_ftoa(string,value) sprintf((string),"%f",(value)) 40 | #define ini_atof(string) (INI_REAL)strtod((string),NULL) 41 | -------------------------------------------------------------------------------- /minIni/minIni.c: -------------------------------------------------------------------------------- 1 | /* minIni - Multi-Platform INI file parser, suitable for embedded systems 2 | * 3 | * These routines are in part based on the article "Multiplatform .INI Files" 4 | * by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal. 5 | * 6 | * Copyright (c) CompuPhase, 2008-2012 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 | * use this file except in compliance with the License. You may obtain a copy 10 | * of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 17 | * License for the specific language governing permissions and limitations 18 | * under the License. 19 | * 20 | * Version: $Id: minIni.c 42 2012-01-04 12:14:54Z thiadmer.riemersma $ 21 | */ 22 | 23 | #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined MININI_ANSI 24 | # if !defined UNICODE /* for Windows */ 25 | # define UNICODE 26 | # endif 27 | # if !defined _UNICODE /* for C library */ 28 | # define _UNICODE 29 | # endif 30 | #endif 31 | 32 | #define MININI_IMPLEMENTATION 33 | #include "minIni.h" 34 | #if defined NDEBUG 35 | #define assert(e) 36 | #else 37 | #include 38 | #endif 39 | 40 | #if !defined __T 41 | #include 42 | #include 43 | #include 44 | /* definition of TCHAR already in minIni.h */ 45 | #define __T(s) s 46 | #define _tcscat strcat 47 | #define _tcschr strchr 48 | #define _tcscmp strcmp 49 | #define _tcscpy strcpy 50 | #define _tcsicmp stricmp 51 | #define _tcslen strlen 52 | #define _tcsncmp strncmp 53 | #define _tcsnicmp strnicmp 54 | #define _tcsrchr strrchr 55 | #define _tcstol strtol 56 | #define _tcstod strtod 57 | #define _totupper toupper 58 | #define _stprintf sprintf 59 | #define _tfgets fgets 60 | #define _tfputs fputs 61 | #define _tfopen fopen 62 | #define _tremove remove 63 | #define _trename rename 64 | #endif 65 | 66 | #if defined __linux || defined __linux__ 67 | #define __LINUX__ 68 | #endif 69 | #if defined FREEBSD && !defined __FreeBSD__ 70 | #define __FreeBSD__ 71 | #endif 72 | #if !defined strnicmp 73 | #if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ 74 | #define strnicmp strncasecmp 75 | #endif 76 | #endif 77 | 78 | #if !defined INI_LINETERM 79 | #define INI_LINETERM __T("\n") 80 | #endif 81 | #if !defined INI_FILETYPE 82 | #error Missing definition for INI_FILETYPE. 83 | #endif 84 | 85 | #if !defined sizearray 86 | #define sizearray(a) (sizeof(a) / sizeof((a)[0])) 87 | #endif 88 | 89 | enum quote_option { 90 | QUOTE_NONE, 91 | QUOTE_ENQUOTE, 92 | QUOTE_DEQUOTE, 93 | }; 94 | 95 | static TCHAR *skipleading(const TCHAR *str) 96 | { 97 | assert(str != NULL); 98 | while (*str != '\0' && *str <= ' ') 99 | str++; 100 | return (TCHAR *)str; 101 | } 102 | 103 | static TCHAR *skiptrailing(const TCHAR *str, const TCHAR *base) 104 | { 105 | assert(str != NULL); 106 | assert(base != NULL); 107 | while (str > base && *(str-1) <= ' ') 108 | str--; 109 | return (TCHAR *)str; 110 | } 111 | 112 | static TCHAR *striptrailing(TCHAR *str) 113 | { 114 | TCHAR *ptr = skiptrailing(_tcschr(str, '\0'), str); 115 | assert(ptr != NULL); 116 | *ptr = '\0'; 117 | return str; 118 | } 119 | 120 | static TCHAR *save_strncpy(TCHAR *dest, const TCHAR *source, size_t maxlen, enum quote_option option) 121 | { 122 | size_t d, s; 123 | 124 | assert(maxlen>0); 125 | assert(dest <= source || dest >= source + maxlen); 126 | if (option == QUOTE_ENQUOTE && maxlen < 3) 127 | option = QUOTE_NONE; /* cannot store two quotes and a terminating zero in less than 3 characters */ 128 | 129 | switch (option) { 130 | case QUOTE_NONE: 131 | for (d = 0; d < maxlen - 1 && source[d] != '\0'; d++) 132 | dest[d] = source[d]; 133 | assert(d < maxlen); 134 | dest[d] = '\0'; 135 | break; 136 | case QUOTE_ENQUOTE: 137 | d = 0; 138 | dest[d++] = '"'; 139 | for (s = 0; source[s] != '\0' && d < maxlen - 2; s++, d++) { 140 | if (source[s] == '"') { 141 | if (d >= maxlen - 3) 142 | break; /* no space to store the escape character plus the one that follows it */ 143 | dest[d++] = '\\'; 144 | } /* if */ 145 | dest[d] = source[s]; 146 | } /* for */ 147 | dest[d++] = '"'; 148 | dest[d] = '\0'; 149 | break; 150 | case QUOTE_DEQUOTE: 151 | for (d = s = 0; source[s] != '\0' && d < maxlen - 1; s++, d++) { 152 | if ((source[s] == '"' || source[s] == '\\') && source[s + 1] == '"') 153 | s++; 154 | dest[d] = source[s]; 155 | } /* for */ 156 | dest[d] = '\0'; 157 | break; 158 | default: 159 | assert(0); 160 | } /* switch */ 161 | 162 | return dest; 163 | } 164 | 165 | static TCHAR *cleanstring(TCHAR *string, enum quote_option *quotes) 166 | { 167 | int isstring; 168 | TCHAR *ep; 169 | 170 | assert(string != NULL); 171 | assert(quotes != NULL); 172 | 173 | /* Remove a trailing comment */ 174 | isstring = 0; 175 | for (ep = string; *ep != '\0' && ((*ep != ';' && *ep != '#') || isstring); ep++) { 176 | if (*ep == '"') { 177 | if (*(ep + 1) == '"') 178 | ep++; /* skip "" (both quotes) */ 179 | else 180 | isstring = !isstring; /* single quote, toggle isstring */ 181 | } else if (*ep == '\\' && *(ep + 1) == '"') { 182 | ep++; /* skip \" (both quotes */ 183 | } /* if */ 184 | } /* for */ 185 | assert(ep != NULL && (*ep == '\0' || *ep == ';' || *ep == '#')); 186 | *ep = '\0'; /* terminate at a comment */ 187 | striptrailing(string); 188 | /* Remove double quotes surrounding a value */ 189 | *quotes = QUOTE_NONE; 190 | if (*string == '"' && (ep = _tcschr(string, '\0')) != NULL && *(ep - 1) == '"') { 191 | string++; 192 | *--ep = '\0'; 193 | *quotes = QUOTE_DEQUOTE; /* this is a string, so remove escaped characters */ 194 | } /* if */ 195 | return string; 196 | } 197 | 198 | static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key, 199 | int idxSection, int idxKey, TCHAR *Buffer, int BufferSize) 200 | { 201 | TCHAR *sp, *ep; 202 | int len, idx; 203 | enum quote_option quotes; 204 | TCHAR LocalBuffer[INI_BUFFERSIZE]; 205 | 206 | assert(fp != NULL); 207 | /* Move through file 1 line at a time until a section is matched or EOF. If 208 | * parameter Section is NULL, only look at keys above the first section. If 209 | * idxSection is postive, copy the relevant section name. 210 | */ 211 | len = (Section != NULL) ? _tcslen(Section) : 0; 212 | if (len > 0 || idxSection >= 0) { 213 | idx = -1; 214 | do { 215 | if (!ini_read(LocalBuffer, INI_BUFFERSIZE, fp)) 216 | return 0; 217 | sp = skipleading(LocalBuffer); 218 | ep = _tcschr(sp, ']'); 219 | } while (*sp != '[' || ep == NULL || (((int)(ep-sp-1) != len || _tcsnicmp(sp+1,Section,len) != 0) && ++idx != idxSection)); 220 | if (idxSection >= 0) { 221 | if (idx == idxSection) { 222 | assert(ep != NULL); 223 | assert(*ep == ']'); 224 | *ep = '\0'; 225 | save_strncpy(Buffer, sp + 1, BufferSize, QUOTE_NONE); 226 | return 1; 227 | } /* if */ 228 | return 0; /* no more section found */ 229 | } /* if */ 230 | } /* if */ 231 | 232 | /* Now that the section has been found, find the entry. 233 | * Stop searching upon leaving the section's area. 234 | */ 235 | assert(Key != NULL || idxKey >= 0); 236 | len = (Key != NULL) ? (int)_tcslen(Key) : 0; 237 | idx = -1; 238 | do { 239 | if (!ini_read(LocalBuffer,INI_BUFFERSIZE,fp) || *(sp = skipleading(LocalBuffer)) == '[') 240 | return 0; 241 | sp = skipleading(LocalBuffer); 242 | ep = _tcschr(sp, '='); /* Parse out the equal sign */ 243 | if (ep == NULL) 244 | ep = _tcschr(sp, ':'); 245 | } while (*sp == ';' || *sp == '#' || ep == NULL || (((int)(skiptrailing(ep,sp)-sp) != len || _tcsnicmp(sp,Key,len) != 0) && ++idx != idxKey)); 246 | if (idxKey >= 0) { 247 | if (idx == idxKey) { 248 | assert(ep != NULL); 249 | assert(*ep == '=' || *ep == ':'); 250 | *ep = '\0'; 251 | striptrailing(sp); 252 | save_strncpy(Buffer, sp, BufferSize, QUOTE_NONE); 253 | return 1; 254 | } /* if */ 255 | return 0; /* no more key found (in this section) */ 256 | } /* if */ 257 | 258 | /* Copy up to BufferSize chars to buffer */ 259 | assert(ep != NULL); 260 | assert(*ep == '=' || *ep == ':'); 261 | sp = skipleading(ep + 1); 262 | sp = cleanstring(sp, "es); /* Remove a trailing comment */ 263 | save_strncpy(Buffer, sp, BufferSize, quotes); 264 | return 1; 265 | } 266 | 267 | /** ini_gets() 268 | * \param Section the name of the section to search for 269 | * \param Key the name of the entry to find the value of 270 | * \param DefValue default string in the event of a failed read 271 | * \param Buffer a pointer to the buffer to copy into 272 | * \param BufferSize the maximum number of characters to copy 273 | * \param Filename the name and full path of the .ini file to read from 274 | * 275 | * \return the number of characters copied into the supplied buffer 276 | */ 277 | int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue, 278 | TCHAR *Buffer, int BufferSize, const TCHAR *Filename) 279 | { 280 | INI_FILETYPE fp; 281 | int ok = 0; 282 | 283 | if (Buffer == NULL || BufferSize <= 0 || Key == NULL) 284 | return 0; 285 | if (ini_openread(Filename, &fp)) { 286 | ok = getkeystring(&fp, Section, Key, -1, -1, Buffer, BufferSize); 287 | (void)ini_close(&fp); 288 | } /* if */ 289 | if (!ok) 290 | save_strncpy(Buffer, DefValue, BufferSize, QUOTE_NONE); 291 | return _tcslen(Buffer); 292 | } 293 | 294 | /** ini_getl() 295 | * \param Section the name of the section to search for 296 | * \param Key the name of the entry to find the value of 297 | * \param DefValue the default value in the event of a failed read 298 | * \param Filename the name of the .ini file to read from 299 | * 300 | * \return the value located at Key 301 | */ 302 | long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename) 303 | { 304 | TCHAR LocalBuffer[64]; 305 | int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); 306 | return (len == 0) ? DefValue 307 | : ((len >= 2 && _totupper(LocalBuffer[1]) == 'X') ? _tcstol(LocalBuffer, NULL, 16) 308 | : _tcstol(LocalBuffer, NULL, 10)); 309 | } 310 | 311 | #if defined INI_REAL 312 | /** ini_getf() 313 | * \param Section the name of the section to search for 314 | * \param Key the name of the entry to find the value of 315 | * \param DefValue the default value in the event of a failed read 316 | * \param Filename the name of the .ini file to read from 317 | * 318 | * \return the value located at Key 319 | */ 320 | INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename) 321 | { 322 | TCHAR LocalBuffer[64]; 323 | int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); 324 | return (len == 0) ? DefValue : ini_atof(LocalBuffer); 325 | } 326 | #endif 327 | 328 | /** ini_getbool() 329 | * \param Section the name of the section to search for 330 | * \param Key the name of the entry to find the value of 331 | * \param DefValue default value in the event of a failed read; it should 332 | * zero (0) or one (1). 333 | * \param Buffer a pointer to the buffer to copy into 334 | * \param BufferSize the maximum number of characters to copy 335 | * \param Filename the name and full path of the .ini file to read from 336 | * 337 | * A true boolean is found if one of the following is matched: 338 | * - A string starting with 'y' or 'Y' 339 | * - A string starting with 't' or 'T' 340 | * - A string starting with '1' 341 | * 342 | * A false boolean is found if one of the following is matched: 343 | * - A string starting with 'n' or 'N' 344 | * - A string starting with 'f' or 'F' 345 | * - A string starting with '0' 346 | * 347 | * \return the true/false flag as interpreted at Key 348 | */ 349 | int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename) 350 | { 351 | TCHAR LocalBuffer[2]; 352 | int ret; 353 | 354 | ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); 355 | LocalBuffer[0] = toupper(LocalBuffer[0]); 356 | if (LocalBuffer[0] == 'Y' || LocalBuffer[0] == '1' || LocalBuffer[0] == 'T') 357 | ret = 1; 358 | else if (LocalBuffer[0] == 'N' || LocalBuffer[0] == '0' || LocalBuffer[0] == 'F') 359 | ret = 0; 360 | else 361 | ret = DefValue; 362 | 363 | return(ret); 364 | } 365 | 366 | /** ini_getsection() 367 | * \param idx the zero-based sequence number of the section to return 368 | * \param Buffer a pointer to the buffer to copy into 369 | * \param BufferSize the maximum number of characters to copy 370 | * \param Filename the name and full path of the .ini file to read from 371 | * 372 | * \return the number of characters copied into the supplied buffer 373 | */ 374 | int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename) 375 | { 376 | INI_FILETYPE fp; 377 | int ok = 0; 378 | 379 | if (Buffer == NULL || BufferSize <= 0 || idx < 0) 380 | return 0; 381 | if (ini_openread(Filename, &fp)) { 382 | ok = getkeystring(&fp, NULL, NULL, idx, -1, Buffer, BufferSize); 383 | (void)ini_close(&fp); 384 | } /* if */ 385 | if (!ok) 386 | *Buffer = '\0'; 387 | return _tcslen(Buffer); 388 | } 389 | 390 | /** ini_getkey() 391 | * \param Section the name of the section to browse through, or NULL to 392 | * browse through the keys outside any section 393 | * \param idx the zero-based sequence number of the key to return 394 | * \param Buffer a pointer to the buffer to copy into 395 | * \param BufferSize the maximum number of characters to copy 396 | * \param Filename the name and full path of the .ini file to read from 397 | * 398 | * \return the number of characters copied into the supplied buffer 399 | */ 400 | int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename) 401 | { 402 | INI_FILETYPE fp; 403 | int ok = 0; 404 | 405 | if (Buffer == NULL || BufferSize <= 0 || idx < 0) 406 | return 0; 407 | if (ini_openread(Filename, &fp)) { 408 | ok = getkeystring(&fp, Section, NULL, -1, idx, Buffer, BufferSize); 409 | (void)ini_close(&fp); 410 | } /* if */ 411 | if (!ok) 412 | *Buffer = '\0'; 413 | return _tcslen(Buffer); 414 | } 415 | 416 | 417 | #if !defined INI_NOBROWSE 418 | /** ini_browse() 419 | * \param Callback a pointer to a function that will be called for every 420 | * setting in the INI file. 421 | * \param UserData arbitrary data, which the function passes on the the 422 | * \c Callback function 423 | * \param Filename the name and full path of the .ini file to read from 424 | * 425 | * \return 1 on success, 0 on failure (INI file not found) 426 | * 427 | * \note The \c Callback function must return 1 to continue 428 | * browsing through the INI file, or 0 to stop. Even when the 429 | * callback stops the browsing, this function will return 1 430 | * (for success). 431 | */ 432 | int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filename) 433 | { 434 | TCHAR LocalBuffer[INI_BUFFERSIZE]; 435 | TCHAR *sp, *ep; 436 | int lenSec, lenKey; 437 | enum quote_option quotes; 438 | INI_FILETYPE fp; 439 | 440 | if (Callback == NULL) 441 | return 0; 442 | if (!ini_openread(Filename, &fp)) 443 | return 0; 444 | 445 | LocalBuffer[0] = '\0'; /* copy an empty section in the buffer */ 446 | lenSec = _tcslen(LocalBuffer) + 1; 447 | for ( ;; ) { 448 | if (!ini_read(LocalBuffer + lenSec, INI_BUFFERSIZE - lenSec, &fp)) 449 | break; 450 | sp = skipleading(LocalBuffer + lenSec); 451 | /* ignore empty strings and comments */ 452 | if (*sp == '\0' || *sp == ';' || *sp == '#') 453 | continue; 454 | /* see whether we reached a new section */ 455 | ep = _tcschr(sp, ']'); 456 | if (*sp == '[' && ep != NULL) { 457 | *ep = '\0'; 458 | save_strncpy(LocalBuffer, sp + 1, INI_BUFFERSIZE, QUOTE_NONE); 459 | lenSec = _tcslen(LocalBuffer) + 1; 460 | continue; 461 | } /* if */ 462 | /* not a new section, test for a key/value pair */ 463 | ep = _tcschr(sp, '='); /* test for the equal sign or colon */ 464 | if (ep == NULL) 465 | ep = _tcschr(sp, ':'); 466 | if (ep == NULL) 467 | continue; /* invalid line, ignore */ 468 | *ep++ = '\0'; /* split the key from the value */ 469 | striptrailing(sp); 470 | save_strncpy(LocalBuffer + lenSec, sp, INI_BUFFERSIZE - lenSec, QUOTE_NONE); 471 | lenKey = _tcslen(LocalBuffer + lenSec) + 1; 472 | /* clean up the value */ 473 | sp = skipleading(ep); 474 | sp = cleanstring(sp, "es); /* Remove a trailing comment */ 475 | save_strncpy(LocalBuffer + lenSec + lenKey, sp, INI_BUFFERSIZE - lenSec - lenKey, quotes); 476 | /* call the callback */ 477 | if (!Callback(LocalBuffer, LocalBuffer + lenSec, LocalBuffer + lenSec + lenKey, UserData)) 478 | break; 479 | } /* for */ 480 | 481 | (void)ini_close(&fp); 482 | return 1; 483 | } 484 | #endif /* INI_NOBROWSE */ 485 | 486 | #if ! defined INI_READONLY 487 | static void ini_tempname(TCHAR *dest, const TCHAR *source, int maxlength) 488 | { 489 | TCHAR *p; 490 | 491 | save_strncpy(dest, source, maxlength, QUOTE_NONE); 492 | p = _tcsrchr(dest, '\0'); 493 | assert(p != NULL); 494 | *(p - 1) = '~'; 495 | } 496 | 497 | static enum quote_option check_enquote(const TCHAR *Value) 498 | { 499 | const TCHAR *p; 500 | 501 | /* run through the value, if it has trailing spaces, or '"', ';' or '#' 502 | * characters, enquote it 503 | */ 504 | assert(Value != NULL); 505 | for (p = Value; *p != '\0' && *p != '"' && *p != ';' && *p != '#'; p++) 506 | /* nothing */; 507 | return (*p != '\0' || (p > Value && *(p - 1) == ' ')) ? QUOTE_ENQUOTE : QUOTE_NONE; 508 | } 509 | 510 | static void writesection(TCHAR *LocalBuffer, const TCHAR *Section, INI_FILETYPE *fp) 511 | { 512 | TCHAR *p; 513 | 514 | if (Section != NULL && _tcslen(Section) > 0) { 515 | LocalBuffer[0] = '['; 516 | save_strncpy(LocalBuffer + 1, Section, INI_BUFFERSIZE - 4, QUOTE_NONE); /* -1 for '[', -1 for ']', -2 for '\r\n' */ 517 | p = _tcsrchr(LocalBuffer, '\0'); 518 | assert(p != NULL); 519 | *p++ = ']'; 520 | _tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */ 521 | (void)ini_write(LocalBuffer, fp); 522 | } /* if */ 523 | } 524 | 525 | static void writekey(TCHAR *LocalBuffer, const TCHAR *Key, const TCHAR *Value, INI_FILETYPE *fp) 526 | { 527 | TCHAR *p; 528 | enum quote_option option = check_enquote(Value); 529 | save_strncpy(LocalBuffer, Key, INI_BUFFERSIZE - 3, QUOTE_NONE); /* -1 for '=', -2 for '\r\n' */ 530 | p = _tcsrchr(LocalBuffer, '\0'); 531 | assert(p != NULL); 532 | *p++ = '='; 533 | save_strncpy(p, Value, INI_BUFFERSIZE - (p - LocalBuffer) - 2, option); /* -2 for '\r\n' */ 534 | p = _tcsrchr(LocalBuffer, '\0'); 535 | assert(p != NULL); 536 | _tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */ 537 | (void)ini_write(LocalBuffer, fp); 538 | } 539 | 540 | static int cache_accum(const TCHAR *string, int *size, int max) 541 | { 542 | int len = _tcslen(string); 543 | if (*size + len >= max) 544 | return 0; 545 | *size += len; 546 | return 1; 547 | } 548 | 549 | static int cache_flush(TCHAR *buffer, int *size, 550 | INI_FILETYPE *rfp, INI_FILETYPE *wfp, INI_FILEPOS *mark) 551 | { 552 | int pos = 0; 553 | 554 | (void)ini_seek(rfp, mark); 555 | assert(buffer != NULL); 556 | buffer[0] = '\0'; 557 | assert(size != NULL); 558 | while (pos < *size) { 559 | (void)ini_read(buffer + pos, INI_BUFFERSIZE - pos, rfp); 560 | pos += _tcslen(buffer + pos); 561 | assert(pos <= *size); 562 | } /* while */ 563 | if (buffer[0] != '\0') 564 | (void)ini_write(buffer, wfp); 565 | (void)ini_tell(rfp, mark); /* update mark */ 566 | *size = 0; 567 | /* return whether the buffer ended with a line termination */ 568 | return (_tcscmp(buffer + pos - _tcslen(INI_LINETERM), INI_LINETERM) == 0); 569 | } 570 | 571 | static int close_rename(INI_FILETYPE *rfp, INI_FILETYPE *wfp, const TCHAR *filename, TCHAR *buffer) 572 | { 573 | (void)ini_close(rfp); 574 | (void)ini_close(wfp); 575 | (void)ini_remove(filename); 576 | (void)ini_tempname(buffer, filename, INI_BUFFERSIZE); 577 | (void)ini_rename(buffer, filename); 578 | return 1; 579 | } 580 | 581 | /** ini_puts() 582 | * \param Section the name of the section to write the string in 583 | * \param Key the name of the entry to write, or NULL to erase all keys in the section 584 | * \param Value a pointer to the buffer the string, or NULL to erase the key 585 | * \param Filename the name and full path of the .ini file to write to 586 | * 587 | * \return 1 if successful, otherwise 0 588 | */ 589 | int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename) 590 | { 591 | INI_FILETYPE rfp; 592 | INI_FILETYPE wfp; 593 | INI_FILEPOS mark; 594 | TCHAR *sp, *ep; 595 | TCHAR LocalBuffer[INI_BUFFERSIZE]; 596 | int len, match, flag, cachelen; 597 | 598 | assert(Filename != NULL); 599 | if (!ini_openread(Filename, &rfp)) { 600 | /* If the .ini file doesn't exist, make a new file */ 601 | if (Key != NULL && Value != NULL) { 602 | if (!ini_openwrite(Filename, &wfp)) 603 | return 0; 604 | writesection(LocalBuffer, Section, &wfp); 605 | writekey(LocalBuffer, Key, Value, &wfp); 606 | (void)ini_close(&wfp); 607 | } /* if */ 608 | return 1; 609 | } /* if */ 610 | 611 | /* If parameters Key and Value are valid (so this is not an "erase" request) 612 | * and the setting already exists and it already has the correct value, do 613 | * nothing. This early bail-out avoids rewriting the INI file for no reason. 614 | */ 615 | if (Key != NULL && Value != NULL) { 616 | (void)ini_tell(&rfp, &mark); 617 | match = getkeystring(&rfp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer)); 618 | if (match && _tcscmp(LocalBuffer,Value) == 0) { 619 | (void)ini_close(&rfp); 620 | return 1; 621 | } /* if */ 622 | /* key not found, or different value -> proceed (but rewind the input file first) */ 623 | (void)ini_seek(&rfp, &mark); 624 | } /* if */ 625 | 626 | /* Get a temporary file name to copy to. Use the existing name, but with 627 | * the last character set to a '~'. 628 | */ 629 | ini_tempname(LocalBuffer, Filename, INI_BUFFERSIZE); 630 | if (!ini_openwrite(LocalBuffer, &wfp)) { 631 | (void)ini_close(&rfp); 632 | return 0; 633 | } /* if */ 634 | (void)ini_tell(&rfp, &mark); 635 | cachelen = 0; 636 | 637 | /* Move through the file one line at a time until a section is 638 | * matched or until EOF. Copy to temp file as it is read. 639 | */ 640 | len = (Section != NULL) ? _tcslen(Section) : 0; 641 | if (len > 0) { 642 | do { 643 | if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { 644 | /* Failed to find section, so add one to the end */ 645 | flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 646 | if (Key!=NULL && Value!=NULL) { 647 | if (!flag) 648 | (void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */ 649 | writesection(LocalBuffer, Section, &wfp); 650 | writekey(LocalBuffer, Key, Value, &wfp); 651 | } /* if */ 652 | return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ 653 | } /* if */ 654 | /* Copy the line from source to dest, but not if this is the section that 655 | * we are looking for and this section must be removed 656 | */ 657 | sp = skipleading(LocalBuffer); 658 | ep = _tcschr(sp, ']'); 659 | match = (*sp == '[' && ep != NULL && (int)(ep-sp-1) == len && _tcsnicmp(sp + 1,Section,len) == 0); 660 | if (!match || Key != NULL) { 661 | if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { 662 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 663 | (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); 664 | cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); 665 | } /* if */ 666 | } /* if */ 667 | } while (!match); 668 | } /* if */ 669 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 670 | /* when deleting a section, the section head that was just found has not been 671 | * copied to the output file, but because this line was not "accumulated" in 672 | * the cache, the position in the input file was reset to the point just 673 | * before the section; this must now be skipped (again) 674 | */ 675 | if (Key == NULL) { 676 | (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); 677 | (void)ini_tell(&rfp, &mark); 678 | } /* if */ 679 | 680 | /* Now that the section has been found, find the entry. Stop searching 681 | * upon leaving the section's area. Copy the file as it is read 682 | * and create an entry if one is not found. 683 | */ 684 | len = (Key!=NULL) ? _tcslen(Key) : 0; 685 | for( ;; ) { 686 | if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { 687 | /* EOF without an entry so make one */ 688 | flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 689 | if (Key!=NULL && Value!=NULL) { 690 | if (!flag) 691 | (void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */ 692 | writekey(LocalBuffer, Key, Value, &wfp); 693 | } /* if */ 694 | return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ 695 | } /* if */ 696 | sp = skipleading(LocalBuffer); 697 | ep = _tcschr(sp, '='); /* Parse out the equal sign */ 698 | if (ep == NULL) 699 | ep = _tcschr(sp, ':'); 700 | match = (ep != NULL && (int)(skiptrailing(ep,sp)-sp) == len && _tcsnicmp(sp,Key,len) == 0); 701 | if ((Key != NULL && match) || *sp == '[') 702 | break; /* found the key, or found a new section */ 703 | /* copy other keys in the section */ 704 | if (Key == NULL) { 705 | (void)ini_tell(&rfp, &mark); /* we are deleting the entire section, so update the read position */ 706 | } else { 707 | if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { 708 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 709 | (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); 710 | cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); 711 | } /* if */ 712 | } /* if */ 713 | } /* for */ 714 | /* the key was found, or we just dropped on the next section (meaning that it 715 | * wasn't found); in both cases we need to write the key, but in the latter 716 | * case, we also need to write the line starting the new section after writing 717 | * the key 718 | */ 719 | flag = (*sp == '['); 720 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 721 | if (Key != NULL && Value != NULL) 722 | writekey(LocalBuffer, Key, Value, &wfp); 723 | /* cache_flush() reset the "read pointer" to the start of the line with the 724 | * previous key or the new section; read it again (because writekey() destroyed 725 | * the buffer) 726 | */ 727 | (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); 728 | if (flag) { 729 | /* the new section heading needs to be copied to the output file */ 730 | cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); 731 | } else { 732 | /* forget the old key line */ 733 | (void)ini_tell(&rfp, &mark); 734 | } /* if */ 735 | /* Copy the rest of the INI file */ 736 | while (ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { 737 | if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { 738 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 739 | (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); 740 | cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); 741 | } /* if */ 742 | } /* while */ 743 | cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); 744 | return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ 745 | } 746 | 747 | /* Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C" book. */ 748 | #define ABS(v) ((v) < 0 ? -(v) : (v)) 749 | 750 | static void strreverse(TCHAR *str) 751 | { 752 | TCHAR t; 753 | int i, j; 754 | 755 | for (i = 0, j = _tcslen(str) - 1; i < j; i++, j--) { 756 | t = str[i]; 757 | str[i] = str[j]; 758 | str[j] = t; 759 | } /* for */ 760 | } 761 | 762 | static void long2str(long value, TCHAR *str) 763 | { 764 | int i = 0; 765 | long sign = value; 766 | int n; 767 | 768 | /* generate digits in reverse order */ 769 | do { 770 | n = (int)(value % 10); /* get next lowest digit */ 771 | str[i++] = (TCHAR)(ABS(n) + '0'); /* handle case of negative digit */ 772 | } while (value /= 10); /* delete the lowest digit */ 773 | if (sign < 0) 774 | str[i++] = '-'; 775 | str[i] = '\0'; 776 | 777 | strreverse(str); 778 | } 779 | 780 | /** ini_putl() 781 | * \param Section the name of the section to write the value in 782 | * \param Key the name of the entry to write 783 | * \param Value the value to write 784 | * \param Filename the name and full path of the .ini file to write to 785 | * 786 | * \return 1 if successful, otherwise 0 787 | */ 788 | int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename) 789 | { 790 | TCHAR LocalBuffer[32]; 791 | long2str(Value, LocalBuffer); 792 | return ini_puts(Section, Key, LocalBuffer, Filename); 793 | } 794 | 795 | #if defined INI_REAL 796 | /** ini_putf() 797 | * \param Section the name of the section to write the value in 798 | * \param Key the name of the entry to write 799 | * \param Value the value to write 800 | * \param Filename the name and full path of the .ini file to write to 801 | * 802 | * \return 1 if successful, otherwise 0 803 | */ 804 | int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename) 805 | { 806 | TCHAR LocalBuffer[64]; 807 | ini_ftoa(LocalBuffer, Value); 808 | return ini_puts(Section, Key, LocalBuffer, Filename); 809 | } 810 | #endif /* INI_REAL */ 811 | #endif /* !INI_READONLY */ 812 | 813 | 814 | #if defined PORTABLE_STRNICMP 815 | int strnicmp(const TCHAR *s1, const TCHAR *s2, size_t n) 816 | { 817 | register unsigned TCHAR c1, c2; 818 | 819 | while (n-- != 0 && (*s1 || *s2)) { 820 | c1 = *(const unsigned TCHAR *)s1++; 821 | if ('a' <= c1 && c1 <= 'z') 822 | c1 += ('A' - 'a'); 823 | c2 = *(const unsigned TCHAR *)s2++; 824 | if ('a' <= c2 && c2 <= 'z') 825 | c2 += ('A' - 'a'); 826 | if (c1 != c2) 827 | return c1 - c2; 828 | } /* while */ 829 | return 0; 830 | } 831 | #endif /* PORTABLE_STRNICMP */ 832 | -------------------------------------------------------------------------------- /minIni/minIni.h: -------------------------------------------------------------------------------- 1 | /* minIni - Multi-Platform INI file parser, suitable for embedded systems 2 | * 3 | * Copyright (c) CompuPhase, 2008-2012 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy 7 | * of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations 15 | * under the License. 16 | * 17 | * Version: $Id: minIni.h 42 2012-01-04 12:14:54Z thiadmer.riemersma $ 18 | */ 19 | #ifndef MININI_H 20 | #define MININI_H 21 | 22 | #include "minGlue.h" 23 | 24 | #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY 25 | #include 26 | #elif !defined __T 27 | typedef char TCHAR; 28 | #endif 29 | 30 | #if !defined INI_BUFFERSIZE 31 | #define INI_BUFFERSIZE 512 32 | #endif 33 | 34 | #if defined __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename); 39 | long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename); 40 | int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); 41 | int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); 42 | int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); 43 | 44 | #if defined INI_REAL 45 | INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename); 46 | #endif 47 | 48 | #if !defined INI_READONLY 49 | int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename); 50 | int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename); 51 | #if defined INI_REAL 52 | int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename); 53 | #endif 54 | #endif /* INI_READONLY */ 55 | 56 | #if !defined INI_NOBROWSE 57 | typedef int (*INI_CALLBACK)(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const void *UserData); 58 | int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filename); 59 | #endif /* INI_NOBROWSE */ 60 | 61 | #if defined __cplusplus 62 | } 63 | #endif 64 | 65 | 66 | #if defined __cplusplus 67 | 68 | #if defined __WXWINDOWS__ 69 | #include "wxMinIni.h" 70 | #else 71 | #include 72 | 73 | /* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */ 74 | class minIni 75 | { 76 | public: 77 | minIni(const std::string& filename) : iniFilename(filename) 78 | { } 79 | 80 | bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const 81 | { return static_cast(ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str())); } 82 | 83 | long getl(const std::string& Section, const std::string& Key, long DefValue=0) const 84 | { return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 85 | 86 | int geti(const std::string& Section, const std::string& Key, int DefValue=0) const 87 | { return static_cast(this->getl(Section, Key, long(DefValue))); } 88 | 89 | std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const 90 | { 91 | char buffer[INI_BUFFERSIZE]; 92 | ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str()); 93 | return buffer; 94 | } 95 | 96 | std::string getsection(int idx) const 97 | { 98 | char buffer[INI_BUFFERSIZE]; 99 | ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 100 | return buffer; 101 | } 102 | 103 | std::string getkey(const std::string& Section, int idx) const 104 | { 105 | char buffer[INI_BUFFERSIZE]; 106 | ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 107 | return buffer; 108 | } 109 | 110 | #if defined INI_REAL 111 | INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const 112 | { return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 113 | #endif 114 | 115 | #if ! defined INI_READONLY 116 | bool put(const std::string& Section, const std::string& Key, long Value) const 117 | { return (bool)ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } 118 | 119 | bool put(const std::string& Section, const std::string& Key, int Value) const 120 | { return (bool)ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()); } 121 | 122 | bool put(const std::string& Section, const std::string& Key, bool Value) const 123 | { return (bool)ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()); } 124 | 125 | bool put(const std::string& Section, const std::string& Key, const std::string& Value) const 126 | { return (bool)ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()); } 127 | 128 | bool put(const std::string& Section, const std::string& Key, const char* Value) const 129 | { return (bool)ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } 130 | 131 | #if defined INI_REAL 132 | bool put(const std::string& Section, const std::string& Key, INI_REAL Value) const 133 | { return (bool)ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } 134 | #endif 135 | 136 | bool del(const std::string& Section, const std::string& Key) const 137 | { return (bool)ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()); } 138 | 139 | bool del(const std::string& Section) const 140 | { return (bool)ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()); } 141 | #endif 142 | 143 | private: 144 | std::string iniFilename; 145 | }; 146 | 147 | #endif /* __WXWINDOWS__ */ 148 | #endif /* __cplusplus */ 149 | 150 | #endif /* MININI_H */ 151 | -------------------------------------------------------------------------------- /minIni/minIni.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipcapture/hepipe/e646842ba3501268e82db9b40e2962765391cbde/minIni/minIni.pdf -------------------------------------------------------------------------------- /minIni/minini_12.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipcapture/hepipe/e646842ba3501268e82db9b40e2962765391cbde/minIni/minini_12.zip -------------------------------------------------------------------------------- /minIni/test.c: -------------------------------------------------------------------------------- 1 | /* Simple test program 2 | * 3 | * gcc -o test test.c minIni.c 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include "minIni.h" 9 | 10 | #define sizearray(a) (sizeof(a) / sizeof((a)[0])) 11 | 12 | const char inifile[] = "test.ini"; 13 | const char inifile2[] = "testplain.ini"; 14 | 15 | int Callback(const char *section, const char *key, const char *value, const void *userdata) 16 | { 17 | printf(" [%s]\t%s=%s\n", section, key, value); 18 | return 1; 19 | } 20 | 21 | int main(void) 22 | { 23 | char str[100]; 24 | long n; 25 | int s, k; 26 | char section[50]; 27 | 28 | /* string reading */ 29 | n = ini_gets("first", "string", "dummy", str, sizearray(str), inifile); 30 | assert(n==4 && strcmp(str,"noot")==0); 31 | n = ini_gets("second", "string", "dummy", str, sizearray(str), inifile); 32 | assert(n==4 && strcmp(str,"mies")==0); 33 | n = ini_gets("first", "undefined", "dummy", str, sizearray(str), inifile); 34 | assert(n==5 && strcmp(str,"dummy")==0); 35 | /* ----- */ 36 | n = ini_gets("", "string", "dummy", str, sizearray(str), inifile2); 37 | assert(n==4 && strcmp(str,"noot")==0); 38 | n = ini_gets(NULL, "string", "dummy", str, sizearray(str), inifile2); 39 | assert(n==4 && strcmp(str,"noot")==0); 40 | /* ----- */ 41 | printf("1. String reading tests passed\n"); 42 | 43 | /* value reading */ 44 | n = ini_getl("first", "val", -1, inifile); 45 | assert(n==1); 46 | n = ini_getl("second", "val", -1, inifile); 47 | assert(n==2); 48 | n = ini_getl("first", "undefined", -1, inifile); 49 | assert(n==-1); 50 | /* ----- */ 51 | n = ini_getl(NULL, "val", -1, inifile2); 52 | assert(n==1); 53 | /* ----- */ 54 | printf("2. Value reading tests passed\n"); 55 | 56 | /* string writing */ 57 | n = ini_puts("first", "alt", "flagged as \"correct\"", inifile); 58 | assert(n==1); 59 | n = ini_gets("first", "alt", "dummy", str, sizearray(str), inifile); 60 | assert(n==20 && strcmp(str,"flagged as \"correct\"")==0); 61 | /* ----- */ 62 | n = ini_puts("second", "alt", "correct", inifile); 63 | assert(n==1); 64 | n = ini_gets("second", "alt", "dummy", str, sizearray(str), inifile); 65 | assert(n==7 && strcmp(str,"correct")==0); 66 | /* ----- */ 67 | n = ini_puts("third", "test", "correct", inifile); 68 | assert(n==1); 69 | n = ini_gets("third", "test", "dummy", str, sizearray(str), inifile); 70 | assert(n==7 && strcmp(str,"correct")==0); 71 | /* ----- */ 72 | n = ini_puts("second", "alt", "overwrite", inifile); 73 | assert(n==1); 74 | n = ini_gets("second", "alt", "dummy", str, sizearray(str), inifile); 75 | assert(n==9 && strcmp(str,"overwrite")==0); 76 | /* ----- */ 77 | n = ini_puts(NULL, "alt", "correct", inifile2); 78 | assert(n==1); 79 | n = ini_gets(NULL, "alt", "dummy", str, sizearray(str), inifile2); 80 | assert(n==7 && strcmp(str,"correct")==0); 81 | /* ----- */ 82 | printf("3. String writing tests passed\n"); 83 | 84 | /* section/key enumeration */ 85 | printf("4. Section/key enumertion, file contents follows\n"); 86 | for (s = 0; ini_getsection(s, section, sizearray(section), inifile) > 0; s++) { 87 | printf(" [%s]\n", section); 88 | for (k = 0; ini_getkey(section, k, str, sizearray(str), inifile) > 0; k++) { 89 | printf("\t%s\n", str); 90 | } /* for */ 91 | } /* for */ 92 | 93 | /* browsing through the file */ 94 | printf("5. browse through all settings, file contents follows\n"); 95 | ini_browse(Callback, NULL, inifile); 96 | 97 | /* string deletion */ 98 | n = ini_puts("first", "alt", NULL, inifile); 99 | assert(n==1); 100 | n = ini_puts("second", "alt", NULL, inifile); 101 | assert(n==1); 102 | n = ini_puts("third", NULL, NULL, inifile); 103 | assert(n==1); 104 | /* ----- */ 105 | n = ini_puts(NULL, "alt", NULL, inifile2); 106 | assert(n==1); 107 | printf("6. String deletion tests passed\n"); 108 | 109 | return 0; 110 | } 111 | 112 | -------------------------------------------------------------------------------- /minIni/test.ini: -------------------------------------------------------------------------------- 1 | [First] 2 | String=noot # trailing commment 3 | Val=1 4 | 5 | [Second] 6 | Val = 2 7 | #comment=3 8 | String = mies 9 | -------------------------------------------------------------------------------- /minIni/test2.cc: -------------------------------------------------------------------------------- 1 | /* 2 | gcc -o minIni.o -c minIni.c 3 | g++ -o test2.o -c test2.cc 4 | g++ -o test2 test2.o minIni.o 5 | ./test2 6 | */ 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | using namespace std ; 13 | 14 | #include "minIni.h" 15 | 16 | int main(void) 17 | { 18 | minIni ini("test.ini"); 19 | string s; 20 | 21 | /* string reading */ 22 | s = ini.gets( "first", "string" , "aap" ); 23 | assert(s == "noot"); 24 | s = ini.gets( "second", "string" , "aap" ); 25 | assert(s == "mies"); 26 | s = ini.gets( "first", "dummy" , "aap" ); 27 | assert(s == "aap"); 28 | cout << "1. String reading tests passed" << endl ; 29 | 30 | 31 | /* value reading */ 32 | long n; 33 | n = ini.getl("first", "val", -1 ); 34 | assert(n==1); 35 | n = ini.getl("second", "val", -1); 36 | assert(n==2); 37 | n = ini.getl("first", "dummy", -1); 38 | assert(n==-1); 39 | cout << "2. Value reading tests passed" << endl ; 40 | 41 | 42 | /* string writing */ 43 | bool b; 44 | b = ini.put("first", "alt", "flagged as \"correct\""); 45 | assert(b); 46 | s = ini.gets("first", "alt", "aap"); 47 | assert(s=="flagged as \"correct\""); 48 | 49 | b = ini.put("second", "alt", "correct"); 50 | assert(b); 51 | s = ini.gets("second", "alt", "aap"); 52 | assert(s=="correct"); 53 | 54 | n = ini.put("third", "alt", "correct"); 55 | assert(b); 56 | s = ini.gets("third", "alt", "aap" ); 57 | assert(s=="correct"); 58 | cout << "3. String writing tests passed" << endl; 59 | 60 | /* section/key enumeration */ 61 | cout << "4. section/key enumeration; file contents follows" << endl; 62 | string section; 63 | for (int is = 0; section = ini.getsection(is), section.length() > 0; is++) { 64 | cout << " [" << section.c_str() << "]" << endl; 65 | for (int ik = 0; s = ini.getkey(section, ik), s.length() > 0; ik++) { 66 | cout << "\t" << s.c_str() << endl; 67 | } 68 | } 69 | 70 | /* string deletion */ 71 | b = ini.del("first", "alt"); 72 | assert(b); 73 | b = ini.del("second", "alt"); 74 | assert(b); 75 | b = ini.del("third"); 76 | assert(b); 77 | cout << "5. string deletion passed " << endl; 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /minIni/testplain.ini: -------------------------------------------------------------------------------- 1 | String=noot # trailing commment 2 | #comment=3 3 | Val=1 4 | -------------------------------------------------------------------------------- /minIni/wxMinIni.h: -------------------------------------------------------------------------------- 1 | /* minIni - Multi-Platform INI file parser, wxWidgets interface 2 | * 3 | * Copyright (c) CompuPhase, 2008-2012 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy 7 | * of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations 15 | * under the License. 16 | * 17 | * Version: $Id: wxMinIni.h 42 2012-01-04 12:14:54Z thiadmer.riemersma $ 18 | */ 19 | #ifndef WXMININI_H 20 | #define WXMININI_H 21 | 22 | #include 23 | 24 | class minIni 25 | { 26 | public: 27 | minIni(const wxString& filename) : iniFilename(filename) 28 | { } 29 | 30 | bool getbool(const wxString& Section, const wxString& Key, bool DefValue=false) const 31 | { return static_cast(ini_getbool(Section.utf8_str(), Key.utf8_str(), int(DefValue), iniFilename.utf8_str())); } 32 | 33 | long getl(const wxString& Section, const wxString& Key, long DefValue=0) const 34 | { return ini_getl(Section.utf8_str(), Key.utf8_str(), DefValue, iniFilename.utf8_str()); } 35 | 36 | int geti(const wxString& Section, const wxString& Key, int DefValue=0) const 37 | { return static_castini_getl(Section.utf8_str(), Key.utf8_str(), (long)DefValue, iniFilename.utf8_str()); } 38 | 39 | wxString gets(const wxString& Section, const wxString& Key, const wxString& DefValue=wxT("")) const 40 | { 41 | char buffer[INI_BUFFERSIZE]; 42 | ini_gets(Section.utf8_str(), Key.utf8_str(), DefValue.utf8_str(), buffer, INI_BUFFERSIZE, iniFilename.utf8_str()); 43 | wxString result = wxString::FromUTF8(buffer); 44 | return result; 45 | } 46 | 47 | wxString getsection(int idx) const 48 | { 49 | char buffer[INI_BUFFERSIZE]; 50 | ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.utf8_str()); 51 | wxString result = wxString::FromUTF8(buffer); 52 | return result; 53 | } 54 | 55 | wxString getkey(const wxString& Section, int idx) const 56 | { 57 | char buffer[INI_BUFFERSIZE]; 58 | ini_getkey(Section.utf8_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.utf8_str()); 59 | wxString result = wxString::FromUTF8(buffer); 60 | return result; 61 | } 62 | 63 | #if defined INI_REAL 64 | INI_REAL getf(const wxString& Section, wxString& Key, INI_REAL DefValue=0) const 65 | { return ini_getf(Section.utf8_str(), Key.utf8_str(), DefValue, iniFilename.utf8_str()); } 66 | #endif 67 | 68 | #if ! defined INI_READONLY 69 | bool put(const wxString& Section, const wxString& Key, long Value) const 70 | { return (bool)ini_putl(Section.utf8_str(), Key.utf8_str(), Value, iniFilename.utf8_str()); } 71 | 72 | bool put(const wxString& Section, const wxString& Key, int Value) const 73 | { return (bool)ini_putl(Section.utf8_str(), Key.utf8_str(), (long)Value, iniFilename.utf8_str()); } 74 | 75 | bool put(const wxString& Section, const wxString& Key, bool Value) const 76 | { return (bool)ini_putl(Section.utf8_str(), Key.utf8_str(), (long)Value, iniFilename.utf8_str()); } 77 | 78 | bool put(const wxString& Section, const wxString& Key, const wxString& Value) const 79 | { return (bool)ini_puts(Section.utf8_str(), Key.utf8_str(), Value.utf8_str(), iniFilename.utf8_str()); } 80 | 81 | bool put(const wxString& Section, const wxString& Key, const char* Value) const 82 | { return (bool)ini_puts(Section.utf8_str(), Key.utf8_str(), Value, iniFilename.utf8_str()); } 83 | 84 | #if defined INI_REAL 85 | bool put(const wxString& Section, const wxString& Key, INI_REAL Value) const 86 | { return (bool)ini_putf(Section.utf8_str(), Key.utf8_str(), Value, iniFilename.utf8_str()); } 87 | #endif 88 | 89 | bool del(const wxString& Section, const wxString& Key) const 90 | { return (bool)ini_puts(Section.utf8_str(), Key.utf8_str(), 0, iniFilename.utf8_str()); } 91 | 92 | bool del(const wxString& Section) const 93 | { return (bool)ini_puts(Section.utf8_str(), 0, 0, iniFilename.utf8_str()); } 94 | #endif 95 | 96 | private: 97 | wxString iniFilename; 98 | }; 99 | 100 | #endif /* WXMININI_H */ 101 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #Linux 4 | cc -o hepipe hepipe.c -lpcap 5 | #-lsocket 6 | 7 | #Solaris. Please be sure that your compiler is gcc or understand the packet attribute for structure 8 | #cc -o hepipe hepipe.c -lpcap -lsocket --------------------------------------------------------------------------------