diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cf3504 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +**/*~ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..218a17b --- /dev/null +++ b/Changelog @@ -0,0 +1,20 @@ +Version 1.2.1 +- import into GitHub (Alex Peuchert) +- added .gemspec for automatic GEM creation + +Version 1.2 +- All IP addresses (v4 and v6) are ipaddr objects now. +- Rework unit tests to run from rake + +Version 1.1 +- New features courtesy of Jeremy Tregunna +* Fixed "command not found" error when executing "netstat" on some of the BSD's +* Added support for Darwin and DragonFly BSD +* Added unit tests for Darwin and DragonFly as well as ifconfig examples +* Added three methods (1 public, 2 private) to common/ifconfig.rb: + - valid_addr? - Checks the supplied type and executes one of two private + methods to verify that the specified address is valid. Returns false if not. + + - valid_v4? and valid_v6? private methods will return true if the supplied + address is a valid ipv4 or ipv6 address (respectfully). + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..5f74e65 --- /dev/null +++ b/INSTALL @@ -0,0 +1,239 @@ +$Id: INSTALL,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ + +Requirements +------------ + +Ruby-Ifconfig depends on Ruby 1.8.0 or later. + +Installation +------------ + +Minero Aoki's setup.rb script is included. Extensive documentation for this +script can be found at the end of this document. + +Basically, however, the following should be enough to install the package: + + $ ruby setup.rb config + $ ruby setup.rb setup + # ruby setup.rb install + + ("#" line may require root privilege) + + +Documentation +------------- + +To create documentation for Ruby-Ifconfig, use rdoc as follows: + + $ rdoc -x CVS lib + +rdoc has been bundled with Ruby since 1.8.1, but you may care to use +a newer version from Ruby's CVS. Information on that can be found here: + + http://www.ruby-lang.org/en/20020106.html + + + +----------------------------------------------------------------------------- + +Full instructions for setup.rb: + +Details +------- + + Usage of install.rb/setup.rb is: + + ruby install.rb + ruby install.rb [] [] + + + -q,--quiet + suppress message outputs + --verbose + output messages verbosely (default) + -h,--help + prints help and quit + -v,--version + prints version and quit + --copyright + prints copyright and quit + + These are acceptable tasks: + config + saves configurations + show + prints current configurations + setup + compiles extentions + install + installs files + clean + cleans created files + + Task Options for Config + ----------------------- + + --prefix=PATH + a prefix of the installing directory path + --std-ruby=PATH + the directory for standard ruby libraries + --site-ruby-common=PATH + the directory for version-independent non-standard + ruby libraries + --site-ruby=PATH + the directory for non-standard ruby libraries + --bin-dir=PATH + the directory for commands + --rb-dir=PATH + the directory for ruby scripts + --so-dir=PATH + the directory for ruby extentions + --data-dir=PATH + the directory for shared data + --ruby-path=PATH + path to set to #! line + --ruby-prog=PATH + the ruby program using for installation + --make-prog=NAME + the make program to compile ruby extentions + --without-ext + forces to install.rb never to compile/install + ruby extentions. + --rbconfig=PATH + your rbconfig.rb to load + + You can view default values of these options by typing + + $ ruby install.rb --help + + + In addition, setup.rb accepts these options: + --with=NAME,NAME,NAME... + package names which you want to install + --without=NAME,NAME,NAME... + package names which you do not want to install + + [NOTE] You can pass options for extconf.rb like this: + + ruby install.rb config -- --with-tklib=/usr/lib/libtk-ja.so.8.0 + + + Task Options for Install + ------------------------ + + --no-harm + prints what to do and done nothing really. + --prefix=PATH + a prefix of the installing directory path. + This option may help binary package maintainers. + A default value is an empty string. + +Installing Programs with setup.rb +================================= + +Quick Start +----------- + + Type these lines on command line: + ("#" line may require root privilege) + + $ ruby setup.rb config + $ ruby setup.rb setup + # ruby setup.rb install + + +Details +------- + + Usage of setup.rb is: + + ruby setup.rb + ruby setup.rb [] [] + + + Global Options + -------------- + + -q,--quiet + suppress message outputs + --verbose + output messages verbosely (default) + -h,--help + prints help and quit + -v,--version + prints version and quit + --copyright + prints copyright and quit + + These are acceptable tasks: + config + Checks and saves configurations. + show + Prints current configurations. + setup + Compiles ruby extentions. + install + Installs files. + clean + Cleans created files. + distclean + Cleans created files. + + Task Options for CONFIG + ----------------------- + + --prefix=PATH + a prefix of the installing directory path + --std-ruby=PATH + the directory for standard ruby libraries + --site-ruby-common=PATH + the directory for version-independent non-standard + ruby libraries + --site-ruby=PATH + the directory for non-standard ruby libraries + --bin-dir=PATH + the directory for commands + --rb-dir=PATH + the directory for ruby scripts + --so-dir=PATH + the directory for ruby extentions + --data-dir=PATH + the directory for shared data + --ruby-path=PATH + path to set to #! line + --ruby-prog=PATH + the ruby program using for installation + --make-prog=NAME + the make program to compile ruby extentions + --without-ext + forces to setup.rb never to compile/install + ruby extentions. + --rbconfig=PATH + your rbconfig.rb to load + + You can view default values of these options by typing + + $ ruby setup.rb --help + + + If there's the directory named "packages", + You can also use these options: + --with=NAME,NAME,NAME... + Package names which you want to install. + --without=NAME,NAME,NAME... + Package names which you do not want to install. + + [NOTE] You can pass options for extconf.rb like this: + + ruby setup.rb config -- --with-tklib=/usr/lib/libtk-ja.so.8.0 + + + Task Options for INSTALL + ------------------------ + + --no-harm + prints what to do and done nothing really. + --prefix=PATH + The prefix of the installing directory path. + This option may help binary package maintainers. + A default value is an empty string. diff --git a/README b/README new file mode 100644 index 0000000..bfaddb6 --- /dev/null +++ b/README @@ -0,0 +1,38 @@ +$Id: README,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ + +This is a Ruby wrapper around the ifconfig command. The goal is to make +getting any information that ifconfig provides easy to access. + +It was developed on Linux 2.6 with ifconfig from net-tools 1.60. It also has +support for SunOS, Darwin and Open, Free, Net, and DragonflyBSD. These have +not been thoroughly tested. Non Linux platforms call netstat for interface +packet information + +Please send me ifconfig / netstat output for platforms that don't work. + +see test/*.rb for usage examples. + +Thanks to Peter Johnson for the *BSD examples +Thanks to Jeremy Tregunna for Darwin and DragonflyBSD support + +INSTALLATION +------------ + +Please see the INSTALL file for details of how to install Ruby-Ifconfig + +TESTING +------- +> rake +to run all the unit tests. + +LICENCE +------- + +This software is offered under the GNU GENERAL PUBLIC LICENSE, a copy of which +is included. + +Section 2, paragraph b and section 5 of the GNU General Public License does not apply when the Software (Ruby/Ifconfig) is included in the program Corgi. + +-- +Daniel Hobe +daniel@nightrunner.com diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..845ddaf --- /dev/null +++ b/Rakefile @@ -0,0 +1,14 @@ +require 'rake' +require 'rake/testtask' + +$VERBOSE = true + +desc "Run all unit tests" +task :default => [ :test_units ] + +desc "Run the unit tests in test/" +task :test_units do + Dir.glob('test/unit/*').each do |t| + puts `/usr/bin/env ruby #{t}` + end +end diff --git a/TODO b/TODO new file mode 100644 index 0000000..aaaa6e7 --- /dev/null +++ b/TODO @@ -0,0 +1,8 @@ +$Id: TODO,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ + +Clean up code to reduce duplicate code as much as possible. + +Test on more platforms + +Add concept of 'sub platform'. For example BSD->NetBSD1.4 might be different +from BSD->NetBSD1.5 diff --git a/ifconfig_examples/darwin.txt b/ifconfig_examples/darwin.txt new file mode 100644 index 0000000..4d34f43 --- /dev/null +++ b/ifconfig_examples/darwin.txt @@ -0,0 +1,17 @@ +lo0: flags=8049 mtu 16384 + inet6 ::1 prefixlen 128 + inet6 fe80::1 prefixlen 64 scopeid 0x1 + inet 127.0.0.1 netmask 0xff000000 +gif0: flags=8010 mtu 1280 +stf0: flags=0<> mtu 1280 +en0: flags=8863 mtu 1500 + inet6 fe80::203:93ff:fe0a:1676 prefixlen 64 scopeid 0x4 + inet 192.168.0.14 netmask 0xffffff00 broadcast 192.168.0.255 + inet6 2001:5c0:8116::203:93ff:fe0a:1676 prefixlen 64 autoconf + ether 00:03:93:0a:16:76 + media: autoselect (100baseTX ) status: active + supported media: none autoselect 10baseT/UTP 10baseT/UTP 10baseT/UTP 100baseTX 100baseTX 100baseTX +fw0: flags=8822 mtu 2030 + lladdr 00:03:93:ff:fe:0a:16:76 + media: autoselect status: inactive + supported media: autoselect diff --git a/ifconfig_examples/dragonflybsd.txt b/ifconfig_examples/dragonflybsd.txt new file mode 100644 index 0000000..23f887a --- /dev/null +++ b/ifconfig_examples/dragonflybsd.txt @@ -0,0 +1,10 @@ +rl0: flags=8843 mtu 1500 + inet6 fe80::202:44ff:fe8f:bb15%rl0 prefixlen 64 scopeid 0x2 + inet 192.168.1.24 netmask 0xffffff00 broadcast 192.168.1.255 + ether 00:02:44:8f:bb:15 + media: Ethernet autoselect (100baseTX ) + status: active +lo0: flags=8049 mtu 16384 + inet6 ::1 prefixlen 128 + inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4 + inet 127.0.0.1 netmask 0xff000000 diff --git a/ifconfig_examples/dragonflybsd_netstat.txt b/ifconfig_examples/dragonflybsd_netstat.txt new file mode 100644 index 0000000..ea3622a --- /dev/null +++ b/ifconfig_examples/dragonflybsd_netstat.txt @@ -0,0 +1,14 @@ +ppp0: flags=8010 mtu 1500 +sl0: flags=c010 mtu 552 +faith0: flags=8002 mtu 1500 +Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll +rl0 1500 00:02:44:8f:bb:15 606 0 549 0 0 +rl0 1500 fe80:2::202 fe80:2::202:44ff: 0 - 0 - - +rl0 1500 192.168.1 192.168.1.24 605 - 544 - - +lo0 16384 0 0 0 0 0 +lo0 16384 ::1/128 ::1 0 - 0 - - +lo0 16384 fe80:4::1/6 fe80:4::1 0 - 0 - - +lo0 16384 127 127.0.0.1 0 - 0 - - +ppp0* 1500 0 0 0 0 0 +sl0* 552 0 0 0 0 0 +faith0* 1500 0 0 0 0 0 diff --git a/ifconfig_examples/freebsd.txt b/ifconfig_examples/freebsd.txt new file mode 100644 index 0000000..b3fd865 --- /dev/null +++ b/ifconfig_examples/freebsd.txt @@ -0,0 +1,17 @@ +xl0: flags=8843 mtu 1500 + options=3 + inet 192.168.0.2 netmask 0xffffff00 broadcast 192.168.0.255 + inet6 fe80::201:2ff:fec6:4bea%xl0 prefixlen 64 scopeid 0x1 + ether 00:01:02:c6:4b:ea + media: Ethernet autoselect (100baseTX ) + status: active +rl0: flags=8943 mtu 1500 + inet 10.0.0.10 netmask 0xffffff00 broadcast 10.0.0.255 + inet6 fe80::200:21ff:fe03:8e1%rl0 prefixlen 64 scopeid 0x1 + ether 00:00:21:03:08:e1 + media: Ethernet autoselect (100baseTX ) + status: active +lo0: flags=8049 mtu 16384 + inet6 ::1 prefixlen 128 + inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2 + inet 127.0.0.1 netmask 0xff000000 diff --git a/ifconfig_examples/freebsd_netstat.txt b/ifconfig_examples/freebsd_netstat.txt new file mode 100644 index 0000000..1f1add2 --- /dev/null +++ b/ifconfig_examples/freebsd_netstat.txt @@ -0,0 +1,24 @@ +Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Time Drop +xl0 1500 00:01:02:c6:4b:ea 7878752 2 404325088 5502452 0 1276760877 0 0 0 + 33:33:46:5d:24:5a + 33:33:00:00:00:01 + 33:33:ff:c6:4b:ea + 01:00:5e:00:00:01 +xl0 1500 192.168.0 beleriand 7865045 - 287935758 5496244 - 1199565347 - - - + ALL-SYSTEMS.MCAST.NET +xl0 1500 fe80:1::201 fe80:1::201:2ff:f 0 - 0 0 - 0 - - - + ff02:1::2:465d:245a(refs: 1) + ff02:1::1 (refs: 1) + ff02:1::1:ffc6:4bea(refs: 1) +lo0 16384 574 0 118916 574 0 118916 0 0 0 +lo0 16384 localhost ::1 0 - 0 0 - 0 - - - + ff01::1 (refs: 1) + ff02:2::1 (refs: 1) + ff02:2::1:ff00:1 (refs: 2) +lo0 16384 fe80:2::1 fe80:2::1 0 - 0 0 - 0 - - - + ff01::1 (refs: 1) + ff02:2::1 (refs: 1) + ff02:2::1:ff00:1 (refs: 2) +lo0 16384 your-net localhost 574 - 118916 574 - 118916 - - - + ALL-SYSTEMS.MCAST.NET + diff --git a/ifconfig_examples/linux.txt b/ifconfig_examples/linux.txt new file mode 100644 index 0000000..2841267 --- /dev/null +++ b/ifconfig_examples/linux.txt @@ -0,0 +1,60 @@ +eth0 Link encap:Ethernet HWaddr 00:50:DA:C1:C3:45 + inet addr:216.87.223.240 Bcast:216.87.223.255 Mask:255.255.255.0 + inet6 addr: fe80::250:daff:fec1:c345/10 Scope:Link + inet6 addr: 3ffe:b00:c18:1fff::2bd/0 Scope:Global + IPX/Ethernet II addr:CA008137:00204808C79B + IPX/Ethernet SNAP addr:00204808C79B + IPX/Ethernet 802.2 addr:00204808C79B + IPX/Ethernet 802.3 addr:00204808C79B + EtherTalk Phase 2 addr:7349/195 + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:90170 errors:0 dropped:0 overruns:0 frame:0 + TX packets:2854 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:100 + RX bytes:1037052545 (989.0 MiB) TX bytes:32859376 (31.3 MiB) + Interrupt:10 Base address:0xe400 + +eth0:0 Link encap:Ethernet HWaddr 00:50:DA:C1:C3:45 + inet addr:172.16.0.93 Bcast:172.16.0.255 Mask:255.255.255.0 + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + Interrupt:10 Base address:0xe400 + +ppp0 Link encap:Point-to-Point Protocol + inet addr:213.8.120.98 P-t-P:213.8.120.1 Mask:255.255.255.255 + UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1452 Metric:1 + RX packets:49753 errors:0 dropped:0 overruns:0 frame:0 + TX packets:26973 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:10 + +sl0 Link encap:Serial Line IP + inet addr:192.168.1.1 P-t-P:192.168.1.2 Mask:255.255.255.0 + UP POINTOPOINT RUNNING MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 + TX packets:40 errors:0 dropped:0 overruns:0 + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + EtherTalk Phase 2 addr:0/0 + UP LOOPBACK RUNNING MTU:3924 Metric:1 + RX packets:43 errors:0 dropped:0 overruns:0 frame:0 + TX packets:43 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:14564572 (13.8 MiB) TX bytes:14564572 (13.8 MiB) + +sit0 Link encap:IPv6-in-IPv4 + inet6 addr: ::127.0.0.1/96 Scope:Unknown + inet6 addr: ::216.87.223.240/96 Scope:Compat + inet6 addr: ::172.16.0.93/96 Scope:Compat + UP RUNNING NOARP MTU:1480 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + +sit1 Link encap:IPv6-in-IPv4 + inet6 addr: fe80::d857:dff0/10 Scope:Link + inet6 addr: fe80::ac10:5d/10 Scope:Link + UP POINTOPOINT RUNNING NOARP MTU:1480 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:25 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 diff --git a/ifconfig_examples/linux_ethernet.txt b/ifconfig_examples/linux_ethernet.txt new file mode 100644 index 0000000..5d22e52 --- /dev/null +++ b/ifconfig_examples/linux_ethernet.txt @@ -0,0 +1,20 @@ +eth0 Link encap:Ethernet HWaddr 00:50:DA:C1:C3:45 + inet addr:216.87.223.240 Bcast:216.87.223.255 Mask:255.255.255.0 + inet6 addr: fe80::250:daff:fec1:c345/10 Scope:Link + inet6 addr: 3ffe:b00:c18:1fff::2bd/0 Scope:Global + IPX/Ethernet II addr:CA008137:00204808C79B + IPX/Ethernet SNAP addr:00204808C79B + IPX/Ethernet 802.2 addr:00204808C79B + IPX/Ethernet 802.3 addr:00204808C79B + EtherTalk Phase 2 addr:7349/195 + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:90170 errors:0 dropped:0 overruns:0 frame:0 + TX packets:2854 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:100 + RX bytes:1037052545 (989.0 MiB) TX bytes:32859376 (31.3 MiB) + Interrupt:10 Base address:0xe400 + +eth0:0 Link encap:Ethernet HWaddr 00:50:DA:C1:C3:45 + inet addr:172.16.0.93 Bcast:172.16.0.255 Mask:255.255.255.0 + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + Interrupt:10 Base address:0xe400 diff --git a/ifconfig_examples/netbsd.txt b/ifconfig_examples/netbsd.txt new file mode 100644 index 0000000..544ef44 --- /dev/null +++ b/ifconfig_examples/netbsd.txt @@ -0,0 +1,10 @@ +cs0: flags=8863 mtu 1500 + address: 08:00:2b:81:62:ca + media: Ethernet 10baseT + status: active + inet 192.168.0.3 netmask 0xffffff00 broadcast 192.168.0.255 + inet6 fe80::a00:2bff:fe81:62ca%cs0 prefixlen 64 scopeid 0x1 +lo0: flags=8009 mtu 33220 + inet 127.0.0.1 netmask 0xff000000 + inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2 + inet6 ::1 prefixlen 128 diff --git a/ifconfig_examples/openbsd.txt b/ifconfig_examples/openbsd.txt new file mode 100644 index 0000000..7b4c699 --- /dev/null +++ b/ifconfig_examples/openbsd.txt @@ -0,0 +1,36 @@ +lo0: flags=8049 mtu 33224 + inet 127.0.0.1 netmask 0xff000000 + inet6 ::1 prefixlen 128 + inet6 fe80::1%lo0 prefixlen 64 scopeid 0x6 +lo1: flags=8008 mtu 33224 +xl0: flags=8843 mtu 1500 + address: 00:01:02:c6:4b:3d + media: Ethernet autoselect (100baseTX full-duplex) + status: active + inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255 + inet6 fe80::201:2ff:fec6:4b3d%xl0 prefixlen 64 scopeid 0x1 +ep0: flags=8863 mtu 1500 + address: 00:20:af:31:99:43 + media: Ethernet 10baseT + inet6 fe80::220:afff:fe31:9943%ep0 prefixlen 64 scopeid 0x2 + inet 24.6.50.88 netmask 0xfffff800 broadcast 255.255.255.255 +pflog0: flags=41 mtu 33224 +pfsync0: flags=0<> mtu 1896 +sl0: flags=c010 mtu 296 +sl1: flags=c010 mtu 296 +ppp0: flags=8010 mtu 1500 +ppp1: flags=8010 mtu 1500 +tun0: flags=10 mtu 3000 +tun1: flags=10 mtu 3000 +enc0: flags=0<> mtu 1536 +bridge0: flags=0<> mtu 1500 +bridge1: flags=0<> mtu 1500 +vlan0: flags=0<> mtu 1500 + address: 00:00:00:00:00:00 +vlan1: flags=0<> mtu 1500 + address: 00:00:00:00:00:00 +gre0: flags=9010 mtu 1450 +gif0: flags=8010 mtu 1280 +gif1: flags=8010 mtu 1280 +gif2: flags=8010 mtu 1280 +gif3: flags=8010 mtu 1280 diff --git a/ifconfig_examples/sunos.txt b/ifconfig_examples/sunos.txt new file mode 100644 index 0000000..39321e4 --- /dev/null +++ b/ifconfig_examples/sunos.txt @@ -0,0 +1,10 @@ +lo0: flags=1000849 mtu 8232 index 1 + inet 127.0.0.1 netmask ff000000 + inet6 ::1/128 +bge0: flags=1000843 mtu 1500 index 2 + inet 10.32.4.138 netmask ffffff00 broadcast 10.32.4.255 + ether 0:3:ba:42:9d:ef + inet6 fe80::a00:20ff:fe72:9724/10 +le1: flags=1000843 mtu 1500 index 3 + inet 172.16.254.99 netmask ffff0000 broadcast 172.16.255.255 + ether 8:0:20:1d:71:eb diff --git a/lib/ifconfig.rb b/lib/ifconfig.rb new file mode 100644 index 0000000..08a9748 --- /dev/null +++ b/lib/ifconfig.rb @@ -0,0 +1,71 @@ +# $Revision: 1.1.1.1 $ +# $Id: ifconfig.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ + +# = Ruby/Ifconfig - ruby interface to the information presented by ifconfig +# +# == Prerequisites +# +# You must have a working ifconfig binary in your path. +# The output format of you particular version of ifconfig must be supported. +# Currently this has only been tested with net-tool 1.6 on Linux +# +# == Example +# require 'ifconfig' +# +# cfg = IfconfigWrapper.new.parse # parses the output of ifconfig +# +# cfg.interfaces() # returns list of interfaces +# +# cfg[eth0].addresses('inet') # returns ipv4 address of eth0 +# +# cfg.addrresses('inet') # returns list of all ipv4 addresses +# +# cfg[eth0].status # returns true if interface is up +# +# cfg.each { block } # run a block on each interface object + + +# +# inspired by Net::Ifconfig::Wrapper perl module +# by Daniel Podolsky, +# +# Ruby version by Daniel Hobe +# Licence:: GPL[http://www.gnu.org/copyleft/gpl.html] +# + +require 'ipaddr' + +class IfconfigWrapper + NAME = 'Ruby/Ifconfig' + include Enumerable + + # + # Can manually specify the platform (should be output of the 'uname' command) + # and the ifconfig input + # + def initialize(platform=nil,input=nil,netstat=nil) + platform = self.get_os unless !platform.nil? + require "ifconfig/"+platform.downcase+"/ifconfig" + @cfg = Ifconfig.new(input,netstat) + end + def parse + return @cfg + end + # Find out what os we are on + # + def get_os + plat = IO.popen('uname'){ |f| f.gets.strip } + case plat + when 'Windows' + return plat + when 'Linux' + return plat + when 'SunOS' + return plat + when 'FreeBSD','OpenBSD','NetBSD','DragonFly','Darwin' + return 'BSD' + else + return 'Linux' + end + end +end diff --git a/lib/ifconfig/bsd/ifconfig.rb b/lib/ifconfig/bsd/ifconfig.rb new file mode 100644 index 0000000..26e7d7d --- /dev/null +++ b/lib/ifconfig/bsd/ifconfig.rb @@ -0,0 +1,72 @@ +# $Id: ifconfig.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# +require 'ifconfig/common/ifconfig' +require 'ifconfig/bsd/network_types' +require 'ifconfig/bsd/interface_types' + +class Ifconfig + # + # ifconfig = user provided ifconifg output + # netstat = same, but for netstat -in + # + @@ifcfg_cmd = "/usr/bin/env ifconfig -a" + @@netstat_cmd = "/usr/bin/env netstat -in" + def initialize(ifconfig=nil,netstat=nil,verbose=nil) + @ifconfig = ifconfig + @ifconfig ||= IO.popen(@@ifcfg_cmd){ |f| f.readlines.join } + + @netstat = netstat + @netstat ||= IO.popen(@@netstat_cmd){ |f| f.readlines.join } + + @verbose = verbose + + @ifaces = {} + split_interfaces(@ifconfig).each do |iface| + iface_name = get_iface_name(iface) + case iface + when /^lo\d\:/im + @ifaces[iface_name] = LoopbackInterface.new(iface_name,iface) + parse_activity(iface_name) + when /\s+media\:\s+Ethernet\s+/im + @ifaces[iface_name] = EthernetAdapter.new(iface_name,iface) + parse_activity(iface_name) + when /\s+supported\smedia\:\s+none\s+autoselect\s+/im + # This clause is only matched on Darwin. This pattern will only be + # matched on ethernet devices (won't match on fw0 or any other + # interface I can see). + @ifaces[iface_name] = EthernetAdapter.new(iface_name,iface) + parse_activity(iface_name) + else + puts "Unknown Adapter Type: #{iface}" if @verbose + end + end + end + + # Parse activity on interface + # + # Not doing it in each interface class so we can pass in + # fake input + # + def parse_activity(iface) + mtu = rxpackets = rxerrors = txpackets = txerrors = 0 + @netstat.split("\n").each { |line| + line.strip! + if line =~ /^#{iface}/ + next if line.split[2] =~ /\/ + puts "matched line for "+iface + toks = line.split + mtu = toks[1] + rxpackets += toks[4].to_i + rxerrors += toks[5].to_i + txpackets += toks[6].to_i + txerrors += toks[7].to_i + @ifaces[iface].mtu = mtu.to_i + @ifaces[iface].rx = { 'packets' => rxpackets, + 'errors' => rxerrors } + @ifaces[iface].tx = { 'packets' => txpackets, + 'errors' => txerrors } + end + } + end + +end diff --git a/lib/ifconfig/bsd/interface_types.rb b/lib/ifconfig/bsd/interface_types.rb new file mode 100644 index 0000000..b21b1bb --- /dev/null +++ b/lib/ifconfig/bsd/interface_types.rb @@ -0,0 +1,69 @@ +# $Id: interface_types.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# +require 'ifconfig/common/interface_types' + +class NetworkAdapter + # becuase on *BSD we get activity from netstat + # we need to have a way to set this: + attr_writer :mtu + + # iterate line by line and dispatch to helper functions + # for lines that match a pattern + # + def parse_ifconfig + @ifconfig.split("\n").each { |line| + case line + when /^\s+#{@protos}/ + add_network(line) + when /flags\=/i + parse_flags(line) + end + } + end + + # parses the "UP LOOPBACK RUNNING MTU:3924 Metric:1" line + # + def parse_flags(line) + flags = line.match(/\<(\S+)\>/i)[1] + @flags = flags.strip.split(',') + @status = true if @flags.include?('UP') + end + + # Parses networks on an interface based on the first token in the line. + # eg: inet or inet6 + # + def add_network(line) + case line + when /^\s+inet\s/ + addr,mask = line.match(/\s+([\d\d?\d?\.]{4,})\s+netmask\s+(\S+)/i)[1..2] + bcast = line.match(/\s+broadcast\s([\d\d?\d?\.]{4,})/i) + bcast = bcast[1] unless bcast.nil? + @networks['inet'] = Ipv4Network.new(addr, mask, bcast) + when /^\s+inet6\s/ + # there can be multiple inet6 entries + begin + addr,scope = line.match(/inet6\s+(\S+)%/i)[1] + rescue NoMethodError + addr,scope = line.match(/inet6\s+(\S+)/i)[1] + end + @networks["inet6:#{addr}"] = Ipv6Network.new(addr) + else + puts "unknown network type: #{line}" + end + end +end + + +class EthernetAdapter + def set_mac + begin + match=@ifconfig.match(/\s+ether\s+([a-f\d]{1,2}(?:\:[a-f\d]{1,2}){5})/im) + return match[1] unless match.nil? + # Openbsd + match = @ifconfig.match(/\s+address\:\s+([a-f\d]{1,2}(?:\:[a-f\d]{1,2}){5})/im) + return match[1] unless match.nil? + rescue NoMethodError + puts "Couldn't Parse MAC Address for: "+@name + end + end +end diff --git a/lib/ifconfig/bsd/network_types.rb b/lib/ifconfig/bsd/network_types.rb new file mode 100644 index 0000000..5f70083 --- /dev/null +++ b/lib/ifconfig/bsd/network_types.rb @@ -0,0 +1,3 @@ +# $Id: network_types.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# +require 'ifconfig/common/network_types' diff --git a/lib/ifconfig/common/ifconfig.rb b/lib/ifconfig/common/ifconfig.rb new file mode 100644 index 0000000..e0c8382 --- /dev/null +++ b/lib/ifconfig/common/ifconfig.rb @@ -0,0 +1,84 @@ +# $Id: ifconfig.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# +class Ifconfig + include Enumerable + + # + # Give hash like access to the interfaces + # + def [](iface) + return @ifaces[iface] + end + + def each( &block ) + return @ifaces.each_value( &block ) + end + + # return list of interface names + # + def interfaces + return @ifaces.keys + end + + # returns array of interface text blocks + # + def split_interfaces(text) + ifaces = [] + text.split("\n").each { |line| + ifaces[ifaces.length] = "" if line =~ /^\S/ + ifaces[ifaces.length-1] += line.rstrip+"\n" + } + return ifaces + end + + # Given an interface block + # returns the name of an interface (eth0, eth0:1 ppp0, etc.) + # + def get_iface_name(text) + name = Regexp.compile(/^(\S+)/).match(text)[1] + # strip trailing :, for bsd, sun + name.sub!(/:$/,'') + return name + end + + def to_s + s="" + self.interfaces.sort.each { |k| + s += @ifaces[k].to_s + s += "\n-------------------------\n" + } + return s + end + + # return list of all addresses on all interfaces reported by ifconfig + # + def addresses(type=nil) + addr = [] + @ifaces.each_value { |iface| + addr += iface.addresses + } + return addr + end + + # returns array of arrays + # [ [address , type ] ] + # + def addrs_with_type + addr = [] + @ifaces.each_value { |iface| + addr += iface.addrs_with_type + } + return addr + end + + def valid_addr?(addr,type='inet') + case type + when /(inet|v4)/ + return addr.ipv4? + when /(inet6|v6)/ + return addr.ipv6? + else + raise "Unknown address type `#{type}' for address `#{addr}'" + end + end +end diff --git a/lib/ifconfig/common/interface_types.rb b/lib/ifconfig/common/interface_types.rb new file mode 100644 index 0000000..0e41e17 --- /dev/null +++ b/lib/ifconfig/common/interface_types.rb @@ -0,0 +1,130 @@ +# $Id: interface_types.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# +class NetworkAdapter + def initialize(name, ifacetxt) + @name = name + @ifconfig = ifacetxt + @status = false + @protos = ['inet','inet6','IPX/Ethernet II', + 'IPX/Ethernet SNAP', + 'IPX/Ethernet 802.2', + 'IPX/Ethernet 802.3', + 'EtherTalk Phase 2'].join("|") + @networks = {} + @flags = [] + @mtu = nil + @metric = nil + @rx = @tx = {} + parse_ifconfig + end + attr_reader :status, :name, :flags, :mtu + attr_accessor :tx, :rx + + # take array and turn each two entries into + # hash key and value, also converts each value to an integer + # + # [1,2,3,4] => { 1 => 2, 3 => 4} + # + # Internal utility function used to populate rx and tx hashes + def array_to_hash_elem(array) + h = {} + if array.length.modulo(2) != 0 + puts "Array mus have even number of elements to turn into a hash" + return nil + end + while array.length > 0 + h[array.shift] = array.shift.to_i + end + return h + end + + # Return all addresses bound to this interface or + # optionally only the specified type of network address + # + def addresses(type=nil) + a = [] + @networks.each_value { |network| + a << (network.addr) if network.nettype == type or type.nil? + } + return a + end + + def ifacetype + return self.class + end + + def up? + return status + end + + # returns array of arrays + # [ [address , type ] ] + # + def addrs_with_type + addrs = [] + @networks.each_value { |network| + addrs.push([network.addr,network.nettype]) + } + return addrs + end + + def addr_types + types = [] + @networks.each_value { |network| + types.push(network.nettype) unless types.include?(network.nettype) + } + return types + end + + def has_addr?(addr) + return self.addresses.include?(addr) + end + + def to_s + s = @name+":"+self.ifacetype.to_s+"\n" + @networks.keys.sort.each { |network| + s += @networks[network].to_s+"\n" + } + if self.rx['bytes'] && self.tx['bytes'] + s += " RX bytes: #{self.rx['bytes']}, TX bytes: #{self.tx['bytes']}\n" + elsif self.rx['packets'] && self.tx['packets'] + s += " RX packets: #{self.rx['packets']}, TX packets: #{self.tx['packets']}\n" + end + + s += " MTU: #{@mtu}\n" + s += " Metric: #{@metric}\n" + s += " Flags: #{@flags.join(',')}\n" + s += " Status: UP" if self.status + return s + end +end + +# each platform defines it's own set_mac +# function to get the mac address +# +class EthernetAdapter < NetworkAdapter + def initialize(name,ifconfigtxt) + super(name,ifconfigtxt) + @mac = set_mac + end + + attr_reader :mac, :interrupt, :rxbytes, :txbytes, :rxpackets, + :txpackets + + def to_s + super + "\n MAC: #{@mac}" + end + +end + +class PPP < NetworkAdapter +end + +class LoopbackInterface < NetworkAdapter +end + +class IPv6_in_IPv4 < NetworkAdapter +end + +class SerialLineIP < NetworkAdapter +end diff --git a/lib/ifconfig/common/network_types.rb b/lib/ifconfig/common/network_types.rb new file mode 100644 index 0000000..7edab12 --- /dev/null +++ b/lib/ifconfig/common/network_types.rb @@ -0,0 +1,49 @@ +# $Id: network_types.rb,v 1.1.1.1 2005/07/02 19:10:58 hobe Exp $ +# + +# base type to hold information about the kinds of networks +# on to each adapter. ipv4,6 ppp etc +class BasicNetworkType + def initialize + @nettype = nil + end + attr_reader :nettype +end + +# +# Ipv4 Network type +# Optional Broadcast and Point to Point Arguments +# +class Ipv4Network < BasicNetworkType + def initialize(addr,mask,bcast=nil,ptp=nil) + super() + @nettype = 'inet' + @addr = IPAddr.new(addr) + @bcast = bcast + @mask = mask + @ptp = ptp + end + attr_reader :addr, :bcast, :mask, :ptp + + def to_s + a = [" #{@nettype} Address: #{@addr}","Mask: #{@mask}"] + a.push "Broadcast: #{@bcast}" unless @bcast.nil? + a.push "P-t-P: #{@ptp}" unless @ptp.nil? + return a.join(', ') + end + +end + +class Ipv6Network < BasicNetworkType + def initialize(addr,scope=nil) + super() + @nettype = 'inet6' + @addr = IPAddr.new(addr) + @scope = scope + end + attr_reader :addr, :scope + + def to_s + " #{@nettype} Address: #{@addr}" + end +end diff --git a/lib/ifconfig/linux/ifconfig.rb b/lib/ifconfig/linux/ifconfig.rb new file mode 100644 index 0000000..7f30459 --- /dev/null +++ b/lib/ifconfig/linux/ifconfig.rb @@ -0,0 +1,41 @@ +# $Id: ifconfig.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/ifconfig' +require 'ifconfig/linux/network_types' +require 'ifconfig/linux/interface_types' + +class Ifconfig + # + # Can manually specify the platform (should be output of the 'uname' command) + # and the ifconfig input + # + def initialize(input=nil,verbose=nil) + if input.nil? + cmd = IO.popen('which ifconfig'){ |f| f.readlines[0] } + exit unless !cmd.nil? + @ifconfig = IO.popen("/sbin/ifconfig -a"){ |f| f.readlines.join } + else + @ifconfig = input + end + @verbose = verbose + @ifaces = {} + split_interfaces(@ifconfig).each do |iface| + iface_name = get_iface_name(iface) + case iface + when /encap\:ethernet/im + @ifaces[iface_name] = EthernetAdapter.new(iface_name,iface) + when /encap\:Local Loopback/im + @ifaces[iface_name] = LoopbackInterface.new(iface_name,iface) + when /encap\:IPv6-in-IPv4/im + @ifaces[iface_name] = IPv6_in_IPv4.new(iface_name,iface) + when /encap\:Point-to-Point Protocol/im + @ifaces[iface_name] = PPP.new(iface_name,iface) + when /encap\:Serial Line IP/im + @ifaces[iface_name] = SerialLineIP.new(iface_name,iface) + else + puts "Unknown Adapter Type on Linux: #{iface}" if @verbose + end + end + end +end diff --git a/lib/ifconfig/linux/interface_types.rb b/lib/ifconfig/linux/interface_types.rb new file mode 100644 index 0000000..ac8e6e7 --- /dev/null +++ b/lib/ifconfig/linux/interface_types.rb @@ -0,0 +1,112 @@ +# $Id: interface_types.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/interface_types' + +class NetworkAdapter + # Parse activity on interface + # + def parse_activity(line) + atr = %w(packets,errors,dropped,overruns) + case line.strip! + + when /^RX packets/ + @rx = array_to_hash_elem( + line.match(/^RX\s+(\w+)\:(\d+)\s+(\w+)\:(\d+)\s+(\w+)\:(\d+)\s+(\w+)\:(\d)/i)[1..8]) + match = line.match(/\s+frame\:(\d+)/i) + @rx['frame'] = match[1] unless match.nil? + + when /^TX packets/ + @tx = array_to_hash_elem( + line.match(/^TX\s+(\w+)\:(\d+)\s+(\w+)\:(\d+)\s+(\w+)\:(\d+)\s+(\w+)\:(\d+)/i)[1..8]) + match = line.match(/\s+carrier\:(\d+)/i) + @tx['carrier'] = match[1] unless match.nil? + + when /^RX bytes/ + match = line.match(/RX\s+(\w+)\:(\d+).*TX\s+(\w+)\:(\d+)/i)[1..4] + @rx.merge!(array_to_hash_elem(match[0..1])) + @tx.merge!(array_to_hash_elem(match[2..3])) + end + end + + # iterate line by line and dispatch to helper functions + # for lines that match a pattern + # + def parse_ifconfig + @ifconfig.split("\n").each { |line| + case line + when /^\s+#{@protos}/ + add_network(line) + when /MTU\:\d+\s+Metric\:/ + parse_flags(line) + when /^\s+RX|TX/ + parse_activity(line) + end + } + end + + # parses the "UP LOOPBACK RUNNING MTU:3924 Metric:1" line + # + def parse_flags(line) + flags = line.strip.split + @metric = flags.pop.split(':')[1].to_i + @mtu = flags.pop.split(':')[1].to_i + @flags = flags + @status = true if @flags.include?('UP') + end + + # Parses networks on an interface based on the first token in the line. + # eg: inet or inet6 + # + def add_network(line) + case line + when /^\s+inet\s/ + addr = line.match(/\s+addr\:([\d\d?\d?\.]{4,})/i)[1] + mask = line.match(/\s+mask\:([\d\d?\d?\.]{4,})/i)[1] + bcast = line.match(/\s+bcast\:([\d\d?\d?\.]{4,})/i) + bcast = bcast[1] unless bcast.nil? + ptp = line.match(/\s+P-t-P\:([\d\d?\d?\.]{4,})/i) + ptp = ptp[1] unless ptp.nil? + @networks['inet'] = Ipv4Network.new(addr, mask, bcast, ptp) + + when /^\s+inet6\s/ + # there can be multiple inet6 entries + addr,scope = line.match(/\s+addr\:\s+(\S+)\s+scope\:\s*(\w+)/i)[1..2] + @networks["inet6:#{addr}"] = Ipv6Network.new(addr,scope) + + when /^\s+#{Regexp.escape('IPX/Ethernet II')}\s/ + addr = line.match(/\s+addr\:\s*(\S+)/)[1] + @networks["IPX/Ethernet II"] = IPX_EthernetII.new(addr) + + when /^\s+#{Regexp.escape('IPX/Ethernet 802.2')}\s/ + addr = line.match(/\s+addr\:\s*(\S+)/)[1] + @networks["IPX/Ethernet 802.2"] = IPX_Ethernet802_2.new(addr) + + when /^\s+#{Regexp.escape('IPX/Ethernet 802.3')}\s/ + addr = line.match(/\s+addr\:\s*(\S+)/)[1] + @networks["IPX/Ethernet 802.3"] = IPX_Ethernet802_3.new(addr) + + when /^\s+#{Regexp.escape('EtherTalk Phase 2')}\s/ + addr = line.match(/\s+addr\:\s*(\S+)/)[1] + @networks["EtherTalk Phase 2"] = EtherTalkPhase2.new(addr) + + when /^\s+#{Regexp.escape('IPX/Ethernet SNAP')}\s/ + addr = line.match(/\s+addr\:\s*(\S+)/)[1] + @networks["IPX/Ethernet SNAP"] = IPX_EthernetSNAP.new(addr) + + else + puts "unknown network type: #{line}" + end + end +end + + +class EthernetAdapter + def set_mac + begin + return @ifconfig.match(/\s+hwaddr\s+([a-f\d]{1,2}(?:\:[a-f\d]{1,2}){5})/im)[1] + rescue NoMethodError + puts "Couldn't Parse MAC Address for: #{@name}: #{$!}" + end + end +end diff --git a/lib/ifconfig/linux/network_types.rb b/lib/ifconfig/linux/network_types.rb new file mode 100644 index 0000000..7e7a1be --- /dev/null +++ b/lib/ifconfig/linux/network_types.rb @@ -0,0 +1,55 @@ +# $Id: network_types.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/network_types' + +# +# Base class for IPX and Appletalk classes +# Shouldn't be used directly +# +class MiscEthernet < BasicNetworkType + def initialize(addr) + super() + @addr = addr + end + attr_reader :addr + def to_s + " #{@nettype} Address: #{@addr}" + end +end + +class IPX_EthernetII < MiscEthernet + def initialize(addr) + super(addr) + @nettype = 'IPX/Ethernet II' + end +end + +class IPX_Ethernet802_2 < MiscEthernet + def initialize(addr) + super(addr) + @nettype = 'IPX/Ethernet 802.2' + end +end + +class IPX_Ethernet802_3 < MiscEthernet + def initialize(addr) + super(addr) + @nettype = 'IPX/Ethernet 802.3' + end +end + +class EtherTalkPhase2 < MiscEthernet + def initialize(addr) + super(addr) + @nettype = 'EtherTalk Phase 2' + end +end + +class IPX_EthernetSNAP < MiscEthernet + def initialize(addr) + super(addr) + @nettype = 'IPX/Ethernet SNAP' + end +end + diff --git a/lib/ifconfig/sunos/ifconfig.rb b/lib/ifconfig/sunos/ifconfig.rb new file mode 100644 index 0000000..b205f52 --- /dev/null +++ b/lib/ifconfig/sunos/ifconfig.rb @@ -0,0 +1,38 @@ +# $Id: ifconfig.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/ifconfig' + +class Ifconfig + # + # Can manually specify the platform (should be output of the 'uname' command) + # and the ifconfig input + # + def initialize(input=nil,verbose=nil) + if input.nil? + cmd = IO.popen('which ifconfig'){ |f| f.readlines[0] } + exit unless !cmd.nil? + @ifconfig = IO.popen("/sbin/ifconfig -a"){ |f| f.readlines.join } + else + @ifconfig = input + end + @verbose = verbose + + require 'ifconfig/sunos/network_types' + require 'ifconfig/sunos/interface_types' + + @ifaces = {} + + split_interfaces(@ifconfig).each do |iface| + iface_name = get_iface_name(iface) + case iface + when /^lo\d\:/im + @ifaces[iface_name] = LoopbackInterface.new(iface_name,iface) + when /\s+ether\s+/im + @ifaces[iface_name] = EthernetAdapter.new(iface_name,iface) + else + puts "Unknown Adapter Type: #{iface}" if @verbose + end + end + end +end diff --git a/lib/ifconfig/sunos/interface_types.rb b/lib/ifconfig/sunos/interface_types.rb new file mode 100644 index 0000000..7644e3d --- /dev/null +++ b/lib/ifconfig/sunos/interface_types.rb @@ -0,0 +1,77 @@ +# $Id: interface_types.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/interface_types' + +# base class for network adapters +class NetworkAdapter + # Parse activity on interface + # + def parse_activity + #imaptest1# netstat -in + #Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue + #lo0 8232 0.0.0.0 0.0.0.4 267824 0 267824 0 0 0 + #bge0 1500 10.0.0.0 10.32.4.138 10935939 0 7741167 0 0 0 + cmd = "netstat -in | grep #{@name}" + line = IO.popen(cmd).gets + return if line.nil? + name,@mtu,dfgw,addr,@rx['packets'],@rx['errors'], + @tx['packets'],@tx['errors'],collisions,queue = line.split + @mtu = @mtu.to_i + end + + # iterate line by line and dispatch to helper functions + # for lines that match a pattern + # + def parse_ifconfig + @ifconfig.split("\n").each { |line| + case line + when /^\s+#{@protos}/ + add_network(line) + when /flags\=/i + parse_flags(line) + end + } + parse_activity + end + + # parses the "UP LOOPBACK RUNNING MTU:3924 Metric:1" line + # + def parse_flags(line) + flags = Regexp.compile(/\<(\S+)\>/i).match(line)[1] + flags = flags.strip.split(',') + @flags = flags + @status = true if @flags.include?('UP') + end + + # Parses networks on an interface based on the first token in the line. + # eg: inet or inet6 + # + def add_network(line) + case line + when /^\s+inet\s/ + addr,mask = Regexp.compile(/\s+([\d\d?\d?\.]{4,})\s+netmask\s+(\S+)/i).match(line)[1..2] + bcast = Regexp.compile(/\s+broadcast\s([\d\d?\d?\.]{4,})/i).match(line) + bcast = bcast[1] unless bcast.nil? + @networks['inet'] = Ipv4Network.new(addr, mask, bcast) + when /^\s+inet6\s/ + # there can be multiple inet6 entries + addr,scope = + Regexp.compile(/inet6\s+(\S+)/i).match(line)[1] + @networks["inet6:#{addr}"] = Ipv6Network.new(addr) + else + puts "unknown network type: #{line}" + end + end +end + + +class EthernetAdapter + def set_mac + begin + @mac = Regexp.compile(/\s+ether\s+([a-f\d]{1,2}(?:\:[a-f\d]{1,2}){5})/im).match(@ifconfig)[1] + rescue NoMethodError + puts "Couldn't Parse MAC Address for: "+@name + end + end +end diff --git a/lib/ifconfig/sunos/network_types.rb b/lib/ifconfig/sunos/network_types.rb new file mode 100644 index 0000000..36e6a99 --- /dev/null +++ b/lib/ifconfig/sunos/network_types.rb @@ -0,0 +1,4 @@ +# $Id: network_types.rb,v 1.1.1.1 2005/07/02 19:10:57 hobe Exp $ +# + +require 'ifconfig/common/network_types' diff --git a/ruby-ifconfig.gemspec b/ruby-ifconfig.gemspec new file mode 100644 index 0000000..9f37773 --- /dev/null +++ b/ruby-ifconfig.gemspec @@ -0,0 +1,67 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{ruby-ifconfig} + s.version = "1.2.1" + s.date = %q{2008-12-09} + s.authors = ["Daniel Hobe", "Alex Peuchert"] + s.email = %q{daniel@nightrunner.com} + s.homepage = %q{http://github.com/aaalex/ruby-ifconfig} + + s.description = %q{Ruby wrapper around the ifconfig command.} + s.summary = %q{This is a Ruby wrapper around the ifconfig command. The goal is to make getting any information that ifconfig provides easy to access.} + + s.has_rdoc = true + s.rdoc_options = ["--main", "README"] + s.extra_rdoc_files = ["INSTALL", "README", "Changelog", "TODO", "COPYING"] + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + + s.require_paths = ["lib"] + s.files = %w[ + lib/ifconfig/sunos/interface_types.rb + lib/ifconfig/sunos/ifconfig.rb + lib/ifconfig/sunos/network_types.rb + lib/ifconfig/bsd/interface_types.rb + lib/ifconfig/bsd/ifconfig.rb + lib/ifconfig/bsd/network_types.rb + lib/ifconfig/linux/interface_types.rb + lib/ifconfig/linux/ifconfig.rb + lib/ifconfig/linux/network_types.rb + lib/ifconfig/common/interface_types.rb + lib/ifconfig/common/ifconfig.rb + lib/ifconfig/common/network_types.rb + lib/ifconfig.rb + Rakefile + ] + + s.test_files = %w[ + test/test_dragonflybsd.rb + test/test_openbsd.rb + test/test_darwin.rb + test/test_bsd.rb + test/test_sunos.rb + test/unit/tc_openbsd.rb + test/unit/tc_dragonflybsd.rb + test/unit/tc_linux.rb + test/unit/tc_freebsd.rb + test/unit/tc_netbsd.rb + test/unit/tc_darwin.rb + test/unit/tc_sunos.rb + test/test_helper.rb + test/test_netbsd.rb + test/test_linux.rb + ifconfig_examples/darwin.txt + ifconfig_examples/dragonflybsd.txt + ifconfig_examples/dragonflybsd_netstat.txt + ifconfig_examples/netbsd.txt + ifconfig_examples/freebsd_netstat.txt + ifconfig_examples/linux.txt + ifconfig_examples/linux_ethernet.txt + ifconfig_examples/freebsd.txt + ifconfig_examples/openbsd.txt + ifconfig_examples/sunos.txt + ] + +end + diff --git a/setup.rb b/setup.rb new file mode 100644 index 0000000..1ad07c0 --- /dev/null +++ b/setup.rb @@ -0,0 +1,1306 @@ +# +# This file is automatically generated. DO NOT MODIFY! +# +# setup.rb +# +# Copyright (c) 2000-2003 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2. +# + +def multipackage_install? + FileTest.directory?(File.dirname($0) + '/packages') +end + +# +# compat.rb +# + +unless Enumerable.method_defined?(:map) + module Enumerable + alias map collect + end +end + +unless Enumerable.method_defined?(:select) + module Enumerable + alias select find_all + end +end + +unless Enumerable.method_defined?(:reject) + module Enumerable + def reject + result = [] + each do |i| + result.push i unless yield(i) + end + result + end + end +end + +unless Enumerable.method_defined?(:inject) + module Enumerable + def inject(result) + each do |i| + result = yield(result, i) + end + result + end + end +end + +unless Enumerable.method_defined?(:any?) + module Enumerable + def any? + each do |i| + return true if yield(i) + end + false + end + end +end + +unless File.respond_to?(:read) + def File.read(fname) + File.open(fname, 'rb') {|f| + return f.read + } + end +end +# +# fileop.rb +# + +module FileOperations + + def mkdir_p(dirname, prefix = nil) + dirname = prefix + dirname if prefix + $stderr.puts "mkdir -p #{dirname}" if verbose? + return if no_harm? + + # does not check '/'... it's too abnormal case + dirs = dirname.split(%r<(?=/)>) + if /\A[a-z]:\z/i =~ dirs[0] + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless File.dir?(path) + end + end + + def rm_f(fname) + $stderr.puts "rm -f #{fname}" if verbose? + return if no_harm? + + if File.exist?(fname) or File.symlink?(fname) + File.chmod 0777, fname + File.unlink fname + end + end + + def rm_rf(dn) + $stderr.puts "rm -rf #{dn}" if verbose? + return if no_harm? + + Dir.chdir dn + Dir.foreach('.') do |fn| + next if fn == '.' + next if fn == '..' + if File.dir?(fn) + verbose_off { + rm_rf fn + } + else + verbose_off { + rm_f fn + } + end + end + Dir.chdir '..' + Dir.rmdir dn + end + + def move_file(src, dest) + File.unlink dest if File.exist?(dest) + begin + File.rename src, dest + rescue + File.open(dest, 'wb') {|f| f.write File.read(src) } + File.chmod File.stat(src).mode, dest + File.unlink src + end + end + + def install(from, dest, mode, prefix = nil) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix + dest if prefix + realdest += '/' + File.basename(from) if File.dir?(realdest) + str = File.read(from) + if diff?(str, realdest) + verbose_off { + rm_f realdest if File.exist?(realdest) + } + File.open(realdest, 'wb') {|f| f.write str } + File.chmod mode, realdest + + File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| f.puts dest } + end + end + + def diff?(orig, targ) + return true unless File.exist?(targ) + orig != File.read(targ) + end + + def command(str) + $stderr.puts str if verbose? + system str or raise RuntimeError, "'system #{str}' failed" + end + + def ruby(str) + command config('ruby-prog') + ' ' + str + end + + def make(task = '') + command config('make-prog') + ' ' + task + end + + def extdir?(dir) + File.exist?(dir + '/MANIFEST') + end + + def all_files_in(dirname) + Dir.open(dirname) {|d| + return d.select {|ent| File.file?("#{dirname}/#{ent}") } + } + end + + REJECT_DIRS = %w( + CVS SCCS RCS CVS.adm + ) + + def all_dirs_in(dirname) + Dir.open(dirname) {|d| + return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS + } + end + +end + + +class File + + def File.dir?(path) + # for corrupted windows stat() + File.directory?((path[-1,1] == '/') ? path : path + '/') + end + +end +# +# config.rb +# + +if idx = ARGV.index(/\A--rbconfig=/) + require ARGV.delete_at(idx).split(/=/, 2)[1] +else + require 'rbconfig' +end + +class ConfigTable + + c = ::Config::CONFIG + + rubypath = c['bindir'] + '/' + c['ruby_install_name'] + + major = c['MAJOR'].to_i + minor = c['MINOR'].to_i + teeny = c['TEENY'].to_i + version = "#{major}.#{minor}" + + # ruby ver. >= 1.4.4? + newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + + subprefix = lambda {|path| + path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix') + } + + if c['rubylibdir'] + # V < 1.6.3 + stdruby = subprefix.call(c['rubylibdir']) + siteruby = subprefix.call(c['sitedir']) + versite = subprefix.call(c['sitelibdir']) + sodir = subprefix.call(c['sitearchdir']) + elsif newpath_p + # 1.4.4 <= V <= 1.6.3 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = subprefix.call(c['sitedir']) + versite = siteruby + '/' + version + sodir = "$site-ruby/#{c['arch']}" + else + # V < 1.4.4 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = "$prefix/lib/ruby/#{version}/site_ruby" + versite = siteruby + sodir = "$site-ruby/#{c['arch']}" + end + + common_descripters = [ + [ 'prefix', [ c['prefix'], + 'path', + 'path prefix of target environment' ] ], + [ 'std-ruby', [ stdruby, + 'path', + 'the directory for standard ruby libraries' ] ], + [ 'site-ruby-common', [ siteruby, + 'path', + 'the directory for version-independent non-standard ruby libraries' ] ], + [ 'site-ruby', [ versite, + 'path', + 'the directory for non-standard ruby libraries' ] ], + [ 'bin-dir', [ '$prefix/bin', + 'path', + 'the directory for commands' ] ], + [ 'rb-dir', [ '$site-ruby', + 'path', + 'the directory for ruby scripts' ] ], + [ 'so-dir', [ sodir, + 'path', + 'the directory for ruby extentions' ] ], + [ 'data-dir', [ '$prefix/share', + 'path', + 'the directory for shared data' ] ], + [ 'ruby-path', [ rubypath, + 'path', + 'path to set to #! line' ] ], + [ 'ruby-prog', [ rubypath, + 'name', + 'the ruby program using for installation' ] ], + [ 'make-prog', [ 'make', + 'name', + 'the make program to compile ruby extentions' ] ], + [ 'without-ext', [ 'no', + 'yes/no', + 'does not compile/install ruby extentions' ] ] + ] + multipackage_descripters = [ + [ 'with', [ '', + 'name,name...', + 'package names that you want to install', + 'ALL' ] ], + [ 'without', [ '', + 'name,name...', + 'package names that you do not want to install', + 'NONE' ] ] + ] + if multipackage_install? + DESCRIPTER = common_descripters + multipackage_descripters + else + DESCRIPTER = common_descripters + end + + SAVE_FILE = 'config.save' + + def ConfigTable.each_name(&block) + keys().each(&block) + end + + def ConfigTable.keys + DESCRIPTER.map {|name, *dummy| name } + end + + def ConfigTable.each_definition(&block) + DESCRIPTER.each(&block) + end + + def ConfigTable.get_entry(name) + name, ent = DESCRIPTER.assoc(name) + ent + end + + def ConfigTable.get_entry!(name) + get_entry(name) or raise ArgumentError, "no such config: #{name}" + end + + def ConfigTable.add_entry(name, vals) + ConfigTable::DESCRIPTER.push [name,vals] + end + + def ConfigTable.remove_entry(name) + get_entry(name) or raise ArgumentError, "no such config: #{name}" + DESCRIPTER.delete_if {|n, arr| n == name } + end + + def ConfigTable.config_key?(name) + get_entry(name) ? true : false + end + + def ConfigTable.bool_config?(name) + ent = get_entry(name) or return false + ent[1] == 'yes/no' + end + + def ConfigTable.value_config?(name) + ent = get_entry(name) or return false + ent[1] != 'yes/no' + end + + def ConfigTable.path_config?(name) + ent = get_entry(name) or return false + ent[1] == 'path' + end + + + class << self + alias newobj new + end + + def ConfigTable.new + c = newobj() + c.initialize_from_table + c + end + + def ConfigTable.load + c = newobj() + c.initialize_from_file + c + end + + def initialize_from_table + @table = {} + DESCRIPTER.each do |k, (default, vname, desc, default2)| + @table[k] = default + end + end + + def initialize_from_file + raise InstallError, "#{File.basename $0} config first"\ + unless File.file?(SAVE_FILE) + @table = {} + File.foreach(SAVE_FILE) do |line| + k, v = line.split(/=/, 2) + @table[k] = v.strip + end + end + + def save + File.open(SAVE_FILE, 'w') {|f| + @table.each do |k, v| + f.printf "%s=%s\n", k, v if v + end + } + end + + def []=(k, v) + raise InstallError, "unknown config option #{k}"\ + unless ConfigTable.config_key?(k) + @table[k] = v + end + + def [](key) + return nil unless @table[key] + @table[key].gsub(%r<\$([^/]+)>) { self[$1] } + end + + def set_raw(key, val) + @table[key] = val + end + + def get_raw(key) + @table[key] + end + +end + + +module MetaConfigAPI + + def eval_file_ifexist(fname) + instance_eval File.read(fname), fname, 1 if File.file?(fname) + end + + def config_names + ConfigTable.keys + end + + def config?(name) + ConfigTable.config_key?(name) + end + + def bool_config?(name) + ConfigTable.bool_config?(name) + end + + def value_config?(name) + ConfigTable.value_config?(name) + end + + def path_config?(name) + ConfigTable.path_config?(name) + end + + def add_config(name, argname, default, desc) + ConfigTable.add_entry name,[default,argname,desc] + end + + def add_path_config(name, default, desc) + add_config name, 'path', default, desc + end + + def add_bool_config(name, default, desc) + add_config name, 'yes/no', default ? 'yes' : 'no', desc + end + + def set_config_default(name, default) + if bool_config?(name) + ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no') + else + ConfigTable.get_entry!(name)[0] = default + end + end + + def remove_config(name) + ent = ConfigTable.get_entry(name) + ConfigTable.remove_entry name + ent + end + +end +# +# base.rb +# + +require 'rbconfig' + + +class InstallError < StandardError; end + + +module HookUtils + + def run_hook(name) + try_run_hook "#{curr_srcdir()}/#{name}" or + try_run_hook "#{curr_srcdir()}/#{name}.rb" + end + + def try_run_hook(fname) + return false unless File.file?(fname) + begin + instance_eval File.read(fname), fname, 1 + rescue + raise InstallError, "hook #{fname} failed:\n" + $!.message + end + true + end + +end + + +module HookScriptAPI + + def get_config(key) + @config[key] + end + + alias config get_config + + def set_config(key, val) + @config[key] = val + end + + # + # srcdir/objdir (works only in the package directory) + # + + #abstract srcdir_root + #abstract objdir_root + #abstract relpath + + def curr_srcdir + "#{srcdir_root()}/#{relpath()}" + end + + def curr_objdir + "#{objdir_root()}/#{relpath()}" + end + + def srcfile(path) + "#{curr_srcdir()}/#{path}" + end + + def srcexist?(path) + File.exist?(srcfile(path)) + end + + def srcdirectory?(path) + File.dir?(srcfile(path)) + end + + def srcfile?(path) + File.file? srcfile(path) + end + + def srcentries(path = '.') + Dir.open("#{curr_srcdir()}/#{path}") {|d| + return d.to_a - %w(. ..) + } + end + + def srcfiles(path = '.') + srcentries(path).select {|fname| + File.file?(File.join(curr_srcdir(), path, fname)) + } + end + + def srcdirectories(path = '.') + srcentries(path).select {|fname| + File.dir?(File.join(curr_srcdir(), path, fname)) + } + end + +end + + +class Installer + + FILETYPES = %w( bin lib ext data ) + + include HookScriptAPI + include HookUtils + include FileOperations + + def initialize(config, opt, srcroot, objroot) + @config = config + @options = opt + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{self.class} #{File.basename(@srcdir)}>" + end + + # + # Hook Script API bases + # + + def srcdir_root + @srcdir + end + + def objdir_root + @objdir + end + + def relpath + @currdir + end + + # + # configs/options + # + + def no_harm? + @options['no-harm'] + end + + def verbose? + @options['verbose'] + end + + def verbose_off + begin + save, @options['verbose'] = @options['verbose'], false + yield + ensure + @options['verbose'] = save + end + end + + # + # TASK config + # + + def exec_config + exec_task_traverse 'config' + end + + def config_dir_bin(rel) + end + + def config_dir_lib(rel) + end + + def config_dir_ext(rel) + extconf if extdir?(curr_srcdir()) + end + + def extconf + opt = @options['config-opt'].join(' ') + command "#{config('ruby-prog')} #{curr_srcdir()}/extconf.rb #{opt}" + end + + def config_dir_data(rel) + end + + # + # TASK setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin(rel) + all_files_in(curr_srcdir()).each do |fname| + adjust_shebang "#{curr_srcdir()}/#{fname}" + end + end + + # modify: #!/usr/bin/ruby + # modify: #! /usr/bin/ruby + # modify: #!ruby + # not modify: #!/usr/bin/env ruby + SHEBANG_RE = /\A\#!\s*\S*ruby\S*/ + + def adjust_shebang(path) + return if no_harm? + + tmpfile = File.basename(path) + '.tmp' + begin + File.open(path, 'rb') {|r| + File.open(tmpfile, 'wb') {|w| + first = r.gets + return unless SHEBANG_RE =~ first + + $stderr.puts "adjusting shebang: #{File.basename path}" if verbose? + w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path')) + w.write r.read + } + } + move_file tmpfile, File.basename(path) + ensure + File.unlink tmpfile if File.exist?(tmpfile) + end + end + + def setup_dir_lib(rel) + end + + def setup_dir_ext(rel) + make if extdir?(curr_srcdir()) + end + + def setup_dir_data(rel) + end + + # + # TASK install + # + + def exec_install + exec_task_traverse 'install' + end + + def install_dir_bin(rel) + install_files collect_filenames_auto(), config('bin-dir') + '/' + rel, 0755 + end + + def install_dir_lib(rel) + install_files ruby_scripts(), config('rb-dir') + '/' + rel, 0644 + end + + def install_dir_ext(rel) + return unless extdir?(curr_srcdir()) + install_files ruby_extentions('.'), + config('so-dir') + '/' + File.dirname(rel), + 0555 + end + + def install_dir_data(rel) + install_files collect_filenames_auto(), config('data-dir') + '/' + rel, 0644 + end + + def install_files(list, dest, mode) + mkdir_p dest, @options['install-prefix'] + list.each do |fname| + install fname, dest, mode, @options['install-prefix'] + end + end + + def ruby_scripts + collect_filenames_auto().select {|n| /\.rb\z/ =~ n } + end + + # picked up many entries from cvs-1.11.1/src/ignore.c + reject_patterns = %w( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + ) + mapping = { + '.' => '\.', + '$' => '\$', + '#' => '\#', + '*' => '.*' + } + REJECT_PATTERNS = Regexp.new('\A(?:' + + reject_patterns.map {|pat| + pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] } + }.join('|') + + ')\z') + + def collect_filenames_auto + mapdir((existfiles() - hookfiles()).reject {|fname| + REJECT_PATTERNS =~ fname + }) + end + + def existfiles + all_files_in(curr_srcdir()) | all_files_in('.') + end + + def hookfiles + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| + %w( config setup install clean ).map {|t| sprintf(fmt, t) } + }.flatten + end + + def mapdir(filelist) + filelist.map {|fname| + if File.exist?(fname) # objdir + fname + else # srcdir + File.join(curr_srcdir(), fname) + end + } + end + + def ruby_extentions(dir) + _ruby_extentions(dir) or + raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first" + end + + DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/ + + def _ruby_extentions(dir) + Dir.open(dir) {|d| + return d.select {|fname| DLEXT =~ fname } + } + end + + # + # TASK clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f 'config.save' + rm_f 'InstalledFiles' + end + + def clean_dir_bin(rel) + end + + def clean_dir_lib(rel) + end + + def clean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'clean' if File.file?('Makefile') + end + + def clean_dir_data(rel) + end + + # + # TASK distclean + # + + def exec_distclean + exec_task_traverse 'distclean' + rm_f 'config.save' + rm_f 'InstalledFiles' + end + + def distclean_dir_bin(rel) + end + + def distclean_dir_lib(rel) + end + + def distclean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'distclean' if File.file?('Makefile') + end + + # + # lib + # + + def exec_task_traverse(task) + run_hook "pre-#{task}" + FILETYPES.each do |type| + if config('without-ext') == 'yes' and type == 'ext' + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, "#{task}_dir_#{type}" + end + run_hook "post-#{task}" + end + + def traverse(task, rel, mid) + dive_into(rel) { + run_hook "pre-#{task}" + __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') + all_dirs_in(curr_srcdir()).each do |d| + traverse task, "#{rel}/#{d}", mid + end + run_hook "post-#{task}" + } + end + + def dive_into(rel) + return unless File.dir?("#{@srcdir}/#{rel}") + + dir = File.basename(rel) + Dir.mkdir dir unless File.dir?(dir) + prevdir = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir prevdir + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + +end +# +# toplevel.rb +# + +class ToplevelInstaller + + Version = '3.2.2' + Copyright = 'Copyright (c) 2000-2003 Minero Aoki' + + TASKS = [ + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles ruby extentions and others' ], + [ 'install', 'installs files' ], + [ 'clean', "does `make clean' for each extention" ], + [ 'distclean',"does `make distclean' for each extention" ] + ] + + def ToplevelInstaller.invoke + instance().invoke + end + + @singleton = nil + + def ToplevelInstaller.instance + @singleton ||= new(File.dirname($0)) + @singleton + end + + include MetaConfigAPI + + def initialize(ardir_root) + @config = nil + @options = { 'verbose' => true } + @ardir = File.expand_path(ardir_root) + end + + def inspect + "#<#{self.class} #{__id__()}>" + end + + def invoke + run_metaconfigs + task = parsearg_global() + @config = load_config(task) + __send__ "parsearg_#{task}" + init_installers + __send__ "exec_#{task}" + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + end + + def load_config(task) + case task + when 'config' + ConfigTable.new + when 'clean', 'distclean' + if File.exist?('config.save') + then ConfigTable.load + else ConfigTable.new + end + else + ConfigTable.load + end + end + + def init_installers + @installer = Installer.new(@config, @options, @ardir, File.expand_path('.')) + end + + # + # Hook Script API bases + # + + def srcdir_root + @ardir + end + + def objdir_root + '.' + end + + def relpath + '.' + end + + # + # Option Parsing + # + + def parsearg_global + valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/ + + while arg = ARGV.shift + case arg + when /\A\w+\z/ + raise InstallError, "invalid task: #{arg}" unless valid_task =~ arg + return arg + + when '-q', '--quiet' + @options['verbose'] = false + + when '--verbose' + @options['verbose'] = true + + when '-h', '--help' + print_usage $stdout + exit 0 + + when '-v', '--version' + puts "#{File.basename($0)} version #{Version}" + exit 0 + + when '--copyright' + puts Copyright + exit 0 + + else + raise InstallError, "unknown global option '#{arg}'" + end + end + + raise InstallError, <" + out.puts " ruby #{File.basename $0} [] []" + + fmt = " %-20s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, '-h,--help', 'print this message' + out.printf fmt, '-v,--version', 'print version and quit' + out.printf fmt, ' --copyright', 'print copyright and quit' + + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf " %-10s %s\n", name, desc + end + + out.puts + out.puts 'Options for config:' + ConfigTable.each_definition do |name, (default, arg, desc, default2)| + out.printf " %-20s %s [%s]\n", + '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg), + desc, + default2 || default + end + out.printf " %-20s %s [%s]\n", + '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's" + + out.puts + out.puts 'Options for install:' + out.printf " %-20s %s [%s]\n", + '--no-harm', 'only display what to do if given', 'off' + out.printf " %-20s %s [%s]\n", + '--prefix', 'install path prefix', '$prefix' + + out.puts + end + + # + # Task Handlers + # + + def exec_config + @installer.exec_config + @config.save # must be final + end + + def exec_setup + @installer.exec_setup + end + + def exec_install + @installer.exec_install + end + + def exec_show + ConfigTable.each_name do |k| + v = @config.get_raw(k) + if not v or v.empty? + v = '(not specified)' + end + printf "%-10s %s\n", k, v + end + end + + def exec_clean + @installer.exec_clean + end + + def exec_distclean + @installer.exec_distclean + end + +end + + +class ToplevelInstallerMulti < ToplevelInstaller + + include HookUtils + include HookScriptAPI + include FileOperations + + def initialize(ardir) + super + @packages = all_dirs_in("#{@ardir}/packages") + raise 'no package exists' if @packages.empty? + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + @packages.each do |name| + eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig" + end + end + + def init_installers + @installers = {} + @packages.each do |pack| + @installers[pack] = Installer.new(@config, @options, + "#{@ardir}/packages/#{pack}", + "packages/#{pack}") + end + + with = extract_selection(config('with')) + without = extract_selection(config('without')) + @selected = @installers.keys.select {|name| + (with.empty? or with.include?(name)) \ + and not without.include?(name) + } + end + + def extract_selection(list) + a = list.split(/,/) + a.each do |name| + raise InstallError, "no such package: #{name}" \ + unless @installers.key?(name) + end + a + end + + def print_usage(f) + super + f.puts 'Inluded packages:' + f.puts ' ' + @packages.sort.join(' ') + f.puts + end + + # + # multi-package metaconfig API + # + + attr_reader :packages + + def declare_packages(list) + raise 'package list is empty' if list.empty? + list.each do |name| + raise "directory packages/#{name} does not exist"\ + unless File.dir?("#{@ardir}/packages/#{name}") + end + @packages = list + end + + # + # Task Handlers + # + + def exec_config + run_hook 'pre-config' + each_selected_installers {|inst| inst.exec_config } + run_hook 'post-config' + @config.save # must be final + end + + def exec_setup + run_hook 'pre-setup' + each_selected_installers {|inst| inst.exec_setup } + run_hook 'post-setup' + end + + def exec_install + run_hook 'pre-install' + each_selected_installers {|inst| inst.exec_install } + run_hook 'post-install' + end + + def exec_clean + rm_f 'config.save' + run_hook 'pre-clean' + each_selected_installers {|inst| inst.exec_clean } + run_hook 'post-clean' + end + + def exec_distclean + rm_f 'config.save' + run_hook 'pre-distclean' + each_selected_installers {|inst| inst.exec_distclean } + run_hook 'post-distclean' + end + + # + # lib + # + + def each_selected_installers + Dir.mkdir 'packages' unless File.dir?('packages') + @selected.each do |pack| + $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose'] + Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") + Dir.chdir "packages/#{pack}" + yield @installers[pack] + Dir.chdir '../..' + end + end + + def verbose? + @options['verbose'] + end + + def no_harm? + @options['no-harm'] + end + +end + +if $0 == __FILE__ + begin + if multipackage_install? + ToplevelInstallerMulti.invoke + else + ToplevelInstaller.invoke + end + rescue + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." + exit 1 + end +end diff --git a/test/test_bsd.rb b/test/test_bsd.rb new file mode 100755 index 0000000..08e29bb --- /dev/null +++ b/test/test_bsd.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +require 'ifconfig' +require 'pp' + +ifcfg = IO.readlines('../ifconfig_examples/freebsd.txt').join +netstat = IO.readlines('../ifconfig_examples/freebsd_netstat.txt').join + +ifconfig = IfconfigWrapper.new('BSD',ifcfg,netstat).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\nrl0 mac address: (ifconfig['rl0'].mac)" +pp ifconfig['rl0'].mac + +puts "\nIpV4 addresses on rl0: (ifconfig['rl0'].addresses('inet'))" +pp ifconfig['rl0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\nList of address types for rl0: (ifconfig['rl0'].addr_types)" +pp ifconfig['rl0'].addr_types + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_darwin.rb b/test/test_darwin.rb new file mode 100755 index 0000000..8887be7 --- /dev/null +++ b/test/test_darwin.rb @@ -0,0 +1,33 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +require 'ifconfig' +require 'pp' + +sample = IO.readlines('../ifconfig_examples/darwin.txt').join +ifconfig = IfconfigWrapper.new('BSD',sample).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\nen0 mac address: (ifconfig['en0'].mac)" +pp ifconfig['en0'].mac + +puts "\nIpV4 addresses on en0: (ifconfig['en0'].addresses('inet'))" +pp ifconfig['en0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\nList of address types for en0: (ifconfig['en0'].addr_types)" +pp ifconfig['en0'].addr_types + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_dragonflybsd.rb b/test/test_dragonflybsd.rb new file mode 100755 index 0000000..ae72253 --- /dev/null +++ b/test/test_dragonflybsd.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +require 'ifconfig' +require 'pp' + +ifcfg = IO.readlines('../ifconfig_examples/dragonflybsd.txt').join +netstat = IO.readlines('../ifconfig_examples/dragonflybsd_netstat.txt').join + +ifconfig = IfconfigWrapper.new('BSD',ifcfg,netstat).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\nrl0 mac address: (ifconfig['rl0'].mac)" +pp ifconfig['rl0'].mac + +puts "\nIpV4 addresses on rl0: (ifconfig['rl0'].addresses('inet'))" +pp ifconfig['rl0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\nList of address types for rl0: (ifconfig['rl0'].addr_types)" +pp ifconfig['rl0'].addr_types + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..28164f1 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,4 @@ +$: << File.dirname(__FILE__)+'/../lib' +require 'ifconfig' +require 'test/unit' +require 'pp' diff --git a/test/test_linux.rb b/test/test_linux.rb new file mode 100755 index 0000000..9e9d371 --- /dev/null +++ b/test/test_linux.rb @@ -0,0 +1,31 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + + +require 'ifconfig' +require 'pp' + +sample = IO.readlines('../ifconfig_examples/linux.txt').join +ifconfig = IfconfigWrapper.new('Linux',sample).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\neth0 mac address: (ifconfig['eth0'].mac)" +pp ifconfig['eth0'].mac + +puts "\nIpV4 addresses on eth0: (ifconfig['eth0'].addresses('inet'))" +pp ifconfig['eth0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_netbsd.rb b/test/test_netbsd.rb new file mode 100755 index 0000000..fed8328 --- /dev/null +++ b/test/test_netbsd.rb @@ -0,0 +1,33 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +require 'ifconfig' +require 'pp' + +sample = IO.readlines('../ifconfig_examples/netbsd.txt').join +ifconfig = IfconfigWrapper.new('BSD',sample).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\ncs0 mac address: (ifconfig['cs0'].mac)" +pp ifconfig['cs0'].mac + +puts "\nIpV4 addresses on cs0: (ifconfig['cs0'].addresses('inet'))" +pp ifconfig['cs0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\nList of address types for cs0: (ifconfig['cs0'].addr_types)" +pp ifconfig['cs0'].addr_types + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_openbsd.rb b/test/test_openbsd.rb new file mode 100755 index 0000000..75e98b2 --- /dev/null +++ b/test/test_openbsd.rb @@ -0,0 +1,33 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +require 'ifconfig' +require 'pp' + +sample = IO.readlines('../ifconfig_examples/openbsd.txt').join +ifconfig = IfconfigWrapper.new('BSD',sample).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\nxl0 mac address: (ifconfig['xl0'].mac)" +pp ifconfig['xl0'].mac + +puts "\nIpV4 addresses on xl0: (ifconfig['xl0'].addresses('inet'))" +pp ifconfig['xl0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\nList of address types for xl0: (ifconfig['xl0'].addr_types)" +pp ifconfig['xl0'].addr_types + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/test_sunos.rb b/test/test_sunos.rb new file mode 100755 index 0000000..114494a --- /dev/null +++ b/test/test_sunos.rb @@ -0,0 +1,35 @@ +#!/usr/bin/ruby -w + +$: << File.dirname(__FILE__) + "/../lib" + +# +#imaptest1# netstat -in +#Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue +#lo0 8232 0.0.0.0 0.0.0.4 267824 0 267824 0 0 0 +#bge0 1500 10.0.0.0 10.32.4.138 10935939 0 7741167 0 0 0 +require 'ifconfig' +require 'pp' + +sample = IO.readlines('../ifconfig_examples/sunos.txt').join +ifconfig = IfconfigWrapper.new('SunOS',sample).parse + +puts "Interfaces: (ifconfig.interfaces)" +pp ifconfig.interfaces + +puts "\nbge0 mac address: (ifconfig['bge0'].mac)" +pp ifconfig['bge0'].mac + +puts "\nIpV4 addresses on bge0: (ifconfig['bge0'].addresses('inet'))" +pp ifconfig['bge0'].addresses('inet') + +puts "\nAll addresses reported by ifconfig: (ifconfig.addresses)" +pp ifconfig.addrs_with_type + +puts "\niconfig.each { block }" +ifconfig.each do |iface| + pp iface.name if iface.up? +end + +puts +s = ifconfig.to_s +puts s diff --git a/test/unit/tc_darwin.rb b/test/unit/tc_darwin.rb new file mode 100644 index 0000000..c5534c9 --- /dev/null +++ b/test/unit/tc_darwin.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_DarwinTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + "/../../ifconfig_examples/darwin.txt").join + @cfg = IfconfigWrapper.new('BSD',sample).parse + end + + def test_interface_list + assert(@cfg.interfaces.sort == ["en0", "lo0"].sort, + "Failed to parse all interfaces") + end + + def test_mac_parse + assert(@cfg['en0'].mac == "00:03:93:0a:16:76", + "Failed to parse MAC address: "+@cfg['en0'].mac) + end + + def test_flags + assert(@cfg['en0'].flags.include?('BROADCAST') && + @cfg['en0'].flags.include?('RUNNING') && + @cfg['en0'].flags.include?('MULTICAST') && + @cfg['en0'].up?, + "FLAG Parsing failed: #{@cfg['en0'].flags}") + end + + def test_addr_types + assert(@cfg['en0'].addr_types.include?('inet') && + @cfg['en0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_attribs + assert(@cfg['en0'].rx['bytes'].class == Fixnum || NilClass && + @cfg['en0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + + end + +end diff --git a/test/unit/tc_dragonflybsd.rb b/test/unit/tc_dragonflybsd.rb new file mode 100644 index 0000000..0177a6d --- /dev/null +++ b/test/unit/tc_dragonflybsd.rb @@ -0,0 +1,39 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_DragonFlyBSDTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + "/../../ifconfig_examples/dragonflybsd.txt").join + @cfg = IfconfigWrapper.new('BSD',sample).parse + end + def test_interface_list + assert(@cfg.interfaces == ["rl0", "lo0"], + "Fauled to parse all interfaces") + end + + def test_mac_parse + assert(@cfg['rl0'].mac == "00:02:44:8f:bb:15", + "Failed to parse MAC address: "+@cfg['rl0'].mac) + end + + def test_flags + assert(@cfg['rl0'].flags.include?('BROADCAST') && + @cfg['rl0'].flags.include?('RUNNING') && + @cfg['rl0'].flags.include?('MULTICAST') && + @cfg['rl0'].up?, + "FLAG Parsing failed: #{@cfg['rl0'].flags}") + end + + def test_addr_types + assert(@cfg['rl0'].addr_types.include?('inet') && + @cfg['rl0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_attribs + assert(@cfg['rl0'].rx['bytes'].class == Fixnum || NilClass && + @cfg['rl0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + + end + +end diff --git a/test/unit/tc_freebsd.rb b/test/unit/tc_freebsd.rb new file mode 100644 index 0000000..9985b67 --- /dev/null +++ b/test/unit/tc_freebsd.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_FreeBSDTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + "/../../ifconfig_examples/freebsd.txt").join + @cfg = IfconfigWrapper.new('BSD',sample).parse + end + + def test_interface_list + assert(@cfg.interfaces == ["rl0", "lo0", "xl0"], + "Failed to parse all interfaces") + end + + def test_mac_parse + assert(@cfg['rl0'].mac == "00:00:21:03:08:e1", + "Failed to parse MAC address: "+@cfg['rl0'].mac) + end + + def test_flags + assert(@cfg['rl0'].flags.include?('BROADCAST') && + @cfg['rl0'].flags.include?('RUNNING') && + @cfg['rl0'].flags.include?('MULTICAST') && + @cfg['rl0'].up?, + "FLAG Parsing failed: #{@cfg['rl0'].flags}") + end + + def test_addr_types + assert(@cfg['rl0'].addr_types.include?('inet') && + @cfg['rl0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_attribs + assert(@cfg['rl0'].rx['bytes'].class == Fixnum || NilClass && + @cfg['rl0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + + end + +end diff --git a/test/unit/tc_linux.rb b/test/unit/tc_linux.rb new file mode 100644 index 0000000..5eabb1a --- /dev/null +++ b/test/unit/tc_linux.rb @@ -0,0 +1,49 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_Linux < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + '/../../ifconfig_examples/linux.txt').join + @cfg = IfconfigWrapper.new('Linux',sample).parse + end + + def test_intefaces + assert(@cfg.interfaces == ["sl0", "lo", "ppp0", "eth0", + "eth0:0", "sit0", "sit1"], + "Not all interfaces parsed") + end + + def test_mtu + assert(@cfg['eth0'].mtu == 1500, "Failed to parse eth0 mtu") + end + + def test_mac_parse + assert(@cfg['eth0'].mac == "00:50:DA:C1:C3:45", + "Failed to parse MAC address: "+@cfg['eth0'].mac) + end + + def test_flags + types = ['BROADCAST', 'RUNNING', 'MULTICAST'] + types.each do |t| + assert(@cfg['eth0'].flags.include?(t), + "FLAG Parsing failed: #{@cfg['eth0'].flags}") + end + assert(@cfg['eth0'].up?, + "FLAG Parsing failed: #{@cfg['eth0'].flags}") + end + + def test_networks + types = ['EtherTalk Phase 2', 'IPX/Ethernet 802.2', 'IPX/Ethernet 802.3', + 'IPX/Ethernet II','IPX/Ethernet SNAP','inet', 'inet6'] + types.each do |t| + assert(@cfg['eth0'].addr_types.include?(t), + "Missing Address Types: #{@cfg['eth0'].addr_types}") + end + end + + def test_attribs + assert(@cfg['eth0'].rx['bytes'] == 1037052545) + assert(@cfg['eth0'].tx['bytes'] == 32859376) + end + +end diff --git a/test/unit/tc_netbsd.rb b/test/unit/tc_netbsd.rb new file mode 100644 index 0000000..f370f42 --- /dev/null +++ b/test/unit/tc_netbsd.rb @@ -0,0 +1,39 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_NetBSDTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + '/../../ifconfig_examples/netbsd.txt').join + @cfg = IfconfigWrapper.new('BSD',sample).parse + end + def test_interface_list + assert(@cfg.interfaces == ["cs0", "lo0"], + "Failed to parse all interfaces") + end + + def test_mac_parse + assert(@cfg['cs0'].mac == "08:00:2b:81:62:ca", + "Failed to parse MAC address: "+@cfg['cs0'].mac) + end + + def test_flags + assert(@cfg['cs0'].flags.include?('BROADCAST') && + @cfg['cs0'].flags.include?('RUNNING') && + @cfg['cs0'].flags.include?('MULTICAST') && + @cfg['cs0'].up?, + "FLAG Parsing failed: #{@cfg['cs0'].flags}") + end + + def test_addr_types + assert(@cfg['cs0'].addr_types.include?('inet') && + @cfg['cs0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_attribs + assert(@cfg['cs0'].rx['bytes'].class == Fixnum || NilClass && + @cfg['cs0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + + end + +end diff --git a/test/unit/tc_openbsd.rb b/test/unit/tc_openbsd.rb new file mode 100644 index 0000000..dbf1ce7 --- /dev/null +++ b/test/unit/tc_openbsd.rb @@ -0,0 +1,39 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_OpenBSDTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + '/../../ifconfig_examples/openbsd.txt').join + @cfg = IfconfigWrapper.new('BSD',sample).parse + end + def test_interface_list + assert(@cfg.interfaces == ["lo0", "lo1", "ep0", "xl0"], + "Failed to parse all interfaces") + end + + def test_mac_parse + assert(@cfg['xl0'].mac == "00:01:02:c6:4b:3d", + "Failed to parse MAC address: "+@cfg['xl0'].mac) + end + + def test_flags + assert(@cfg['xl0'].flags.include?('BROADCAST') && + @cfg['xl0'].flags.include?('RUNNING') && + @cfg['xl0'].flags.include?('MULTICAST') && + @cfg['xl0'].up?, + "FLAG Parsing failed: #{@cfg['xl0'].flags}") + end + + def test_addr_types + assert(@cfg['xl0'].addr_types.include?('inet') && + @cfg['xl0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_attribs + assert(@cfg['xl0'].rx['bytes'].class == Fixnum || NilClass && + @cfg['xl0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + + end + +end diff --git a/test/unit/tc_sunos.rb b/test/unit/tc_sunos.rb new file mode 100644 index 0000000..05fed73 --- /dev/null +++ b/test/unit/tc_sunos.rb @@ -0,0 +1,44 @@ +require File.dirname(__FILE__) + '/../test_helper' + +class TC_SunOSTest < Test::Unit::TestCase + def setup + sample = IO.readlines("#{File.dirname(__FILE__)}"+ + '/../../ifconfig_examples/sunos.txt').join + @@cfg = IfconfigWrapper.new('SunOS',sample).parse + end + def test_interface_list + assert(@@cfg.interfaces == ["le1", "lo0", "bge0"], + "Fauled to parse all interfaces") + end + + def test_mac_parse + assert(@@cfg['bge0'].mac == "0:3:ba:42:9d:ef", + "Failed to parse MAC address: "+@@cfg['bge0'].mac) + end + + def test_flags + assert(@@cfg['bge0'].flags.include?('BROADCAST') && + @@cfg['bge0'].flags.include?('RUNNING') && + @@cfg['bge0'].flags.include?('MULTICAST') && + @@cfg['bge0'].up?, + "FLAG Parsing failed: #{@@cfg['bge0'].flags}") + end + + def test_addr_types + assert(@@cfg['bge0'].addr_types.include?('inet') && + @@cfg['bge0'].addr_types.include?('inet6'), + "Failed to parse all address types") + end + + def test_networks + assert(@@cfg['bge0'].addr_types.include?('inet') && + @@cfg['bge0'].addr_types.include?('inet6'), + "Missing Address Types: #{@@cfg['bge0'].addr_types}") + end + + def test_attribs + assert(@@cfg['bge0'].rx['bytes'].class == Fixnum || NilClass&& + @@cfg['bge0'].tx['bytes'].class == Fixnum || NilClass, "Wrong class") + end + +end