├── .cvsignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── COPYRIGHT ├── ChangeLog ├── FAQ ├── KEYS ├── README.md ├── THANKS ├── THEMES.txt ├── TODO ├── config.h.in ├── error.c ├── error.h ├── meson.build ├── os.h ├── slurm.1 ├── slurm.c ├── slurm.h ├── slurm.spec ├── slurm_termcast.svg ├── src ├── freebsd.c ├── freebsd.h ├── hpux.c ├── hpux.h ├── if_media.c ├── if_media.h ├── linux.c ├── linux.h ├── macos.c ├── macos.h ├── netbsd.c ├── netbsd.h ├── openbsd.c ├── openbsd.h ├── solaris.c ├── solaris.h ├── unsupported.c └── unsupported.h ├── theme.c ├── theme.h └── themes ├── black.theme ├── blue.theme ├── cyan.theme └── foo.theme /.cvsignore: -------------------------------------------------------------------------------- 1 | slurm 2 | slurm.core 3 | slurm.o 4 | .slurm.c.swp 5 | slurm.gmon 6 | config.h 7 | config.log 8 | config.status 9 | autom4te.cache 10 | .deps 11 | stamp-h1 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | arch: 2 | - amd64 3 | - ppc64le 4 | language: c 5 | compiler: 6 | - gcc 7 | - clang 8 | script: mkdir _build && cd _build && cmake ../ && make 9 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Hendrik Scholz 2 | Matthias Schmitz 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2 | ========= 3 | 4 | slurm is copyright (c) 2002 by Hendrik Scholz and the slurm 5 | authors licensed through the GNU General Public License. 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2022-04-29 Matthias Schmitz 2 | * tag version 0.4.4 3 | * Use meson to build 4 | * Add interface detection for Linux: 5 | slurm defaults now to the only non-loopback and up interface. 6 | If more than one interface up it quits with a warning. 7 | * Increase the maximum length of an interface name to match the length 8 | of newer Linux kernels. 9 | * Make slurm work again on FreeBSD, OpenBSD and MacOS 10 | 11 | 2015-08-16 Matthias Schmitz 12 | * tag version 0.4.3 13 | * switch to cmake as build system 14 | 15 | 2014-10-14 Matthias Schmitz 16 | * tag version 0.4.2 17 | * Always use "defined" when testing for a preprocessor macro 18 | 19 | 2011-09-05 Matthias Schmitz 20 | * tag version 0.4.0 21 | * Remove gnu build system, use scons instead 22 | * Add support for GNU/kFreeBSD 23 | * Probably break support for any other os than Linux and kFreeBSD ( 24 | will fixed soon ) 25 | 26 | 27 | - tag SLURM-0_3_3 28 | 29 | 2004-10-12 Hendrik Scholz 30 | 31 | * Makefile: 32 | * config.guess: 33 | * config.sub: 34 | 35 | - update config.* to allow configure run on DragonFly BSD (i386 only) 36 | 37 | 38 | 2004-09-28 Hendrik Scholz 39 | 40 | * Makefile: 41 | * configure: 42 | * configure.in: 43 | 44 | bump to VERSION 0.3.3 45 | 46 | 2004-09-28 Hendrik Scholz 47 | 48 | * README: minor OS updates 49 | * os.h: allow compilation on Sun Forte CC systems again 50 | * slurm.c: (main): 51 | * theme.c: (theme_readfile): remove NOTICE error 52 | * themes/black.theme: new theme 53 | 54 | 2004-09-27 Hendrik Scholz 55 | 56 | * src/if_media.c: (get_if_speed): 57 | 58 | - use better CPP magic to detect OS features 59 | - allow compilation on a few OpenBSD systems again 60 | 61 | 2004-05-27 Hendrik Scholz 62 | 63 | * .cvsignore: 64 | * os.h: 65 | * src/if_media.c: (get_if_speed): 66 | 67 | - add validinterface() check on Mac OS X 68 | 69 | 2004-02-13 Hendrik Scholz 70 | 71 | * Makefile: 72 | * Makefile.in: 73 | * aclocal.m4: 74 | * config.h.in: 75 | * configure: 76 | * configure.in: 77 | * slurm.c: (usage): 78 | * slurm.h: 79 | 80 | - remove version name from OS for 'darwin' aka Mac OS X 81 | - s/VERSION/PACKAGE_VERSION/ 82 | 83 | 2004-02-13 Hendrik Scholz 84 | 85 | * AUTHORS: 86 | * COPYING: 87 | * Changelog: 88 | * INSTALL: 89 | * Makefile: 90 | * Makefile.am: 91 | * Makefile.in: 92 | * THEMES: 93 | * THEMES.txt: 94 | * aclocal.m4: 95 | * config.guess: 96 | * config.h.in: 97 | * config.sub: 98 | * configure: 99 | * configure.in: 100 | * depcomp: 101 | * install-sh: 102 | * missing: 103 | * mkinstalldirs: 104 | 105 | - major config subsystem replacement 106 | - mv THEMES THEMES.txt (welcome to Mac OS X :)) 107 | 108 | 2004-02-05 Hendrik Scholz 109 | 110 | * src/if_media.c: (get_if_speed): 111 | 112 | - add support for pre 4.5-RELEASE FreeBSD (tested on 4.2-REL :)) 113 | 114 | 2004-02-05 Hendrik Scholz 115 | 116 | * FAQ: added Linux media Q/A 117 | * README: s/raisdorf/wormulon/ 118 | * slurm.1: s/raisdorf/wormulon/, added -L option 119 | * slurm.c: (slurm_shutdown): s/raisdorf/wormulon/ 120 | * slurm.spec: s/raisdorf/wormulon/ 121 | * theme.c: (theme_readfile): added -D__Debian__ to search for 122 | themes in /usr/share rather than /usr/local/share 123 | 124 | 2004-02-05 Hendrik Scholz 125 | 126 | * Makefile: 127 | * Makefile.in: add -DWITH_LED per default 128 | * slurm.c: (update_stat_large), (update_stat_split), 129 | (update_stat_combined), (usage), (draw_face), (main): 130 | * slurm.h: 131 | 132 | - add -L switch to enable LED 133 | 134 | 2003-10-07 Hendrik Scholz 135 | 136 | * Makefile: 137 | * Makefile.in: 138 | * theme.c: (theme_readfile): 139 | 140 | - reduce overhead in upcoming NetBSD port upgrade 141 | 142 | 2003-09-18 Hendrik Scholz 143 | 144 | * TODO: upd 145 | * slurm.spec: initial specfile based on 0.2.3 146 | 147 | Thu Sep 11 14:08:07 CEST 2003 148 | 149 | - clean up Solaris code 150 | - 0.3.1 RELEASE 151 | 152 | Wed Sep 10 21:18:32 CEST 2003 153 | 154 | - print usage information if no interface was given at startup 155 | 156 | Wed Sep 10 21:03:59 CEST 2003 157 | 158 | - add Mac OS X support (thanks Jan-Eric Kolbe for providing access!) 159 | - 0.3.1-pre2 160 | 161 | Mon Sep 8 23:22:00 CEST 2003 162 | 163 | - calculate traffic right when using -d option 164 | 165 | Sat Sep 6 06:01:27 EDT 2003 166 | 167 | - disable LED (set -DWITH_LED to enable them) 168 | - moved left part of statistics left to allow traffic > 10.000kBytes/s 169 | - make slurm Gbit-safe (tests with >100MByte/s will be done soon :)) 170 | - make -Wall happy on Linux 171 | 172 | Fri Aug 22 06:20:36 EDT 2003 173 | 174 | - fix 32bit signed vs. unsigned bug 175 | - improve Linux /proc/net/dev parsing 176 | 177 | Sat Aug 16 16:06:32 CEST 2003 178 | 179 | - 0.3.0 release 180 | - again modify sleep stuff to recognize input while sleeping 181 | 182 | Wed Aug 13 00:16:57 CEST 2003 183 | 184 | - unify sleep method 185 | 186 | Wed Aug 13 00:03:21 CEST 2003 187 | 188 | - add 'make prof' target for profiling and update .cvsignore 189 | 190 | Thu Aug 7 04:21:01 CEST 2003 191 | 192 | - use sleep() instead of usleep() for sleep durations longer 193 | than one second on Linux to prevent wasting cpu cycles 194 | - update FAQ, README and add THEMES file 195 | 196 | Wed Jul 9 18:44:24 CEST 2003 197 | 198 | - add FAQ 199 | - add -Wall to compile flags 200 | 201 | Wed Jul 9 18:39:26 CEST 2003 202 | 203 | - add signalhandler for various signal so killing slurm doesn't 204 | leave a scrambled terminal behind 205 | - add -t option to usage() 206 | 207 | Sun May 25 16:44:49 CEST 2003 208 | 209 | - remove -H option and make it default 210 | - add initial theme engine (only tested on FreeBSD! until now) 211 | 212 | Sun May 4 13:55:46 CEST 2003 213 | 214 | - catch up on FreeBSDs include/net/if_media.h since the typos 215 | have been fixed. 216 | 217 | Sun Apr 27 18:12:49 CEST 2003 218 | 219 | - change data_type structure so we won't get into trouble displaying 220 | up to 999999.999GB 221 | 222 | Sat Apr 19 20:09:29 CEST 2003 223 | 224 | - add THE missing 'E' 225 | 226 | Tue Apr 8 22:58:45 CEST 2003 227 | 228 | - Solaris interface speed detection code added to src/if_media.c 229 | 230 | Wed Apr 2 00:00:34 CEST 2003 231 | 232 | - add Solaris support to auto* stuff so slurm can be build on Solaris 233 | with just ./configure && make 234 | 235 | Wed Mar 26 23:43:54 CET 2003 236 | 237 | - add -z command line option and 'z' key to virtually reset all counters 238 | 239 | Thu Mar 20 23:23:46 CET 2003 240 | 241 | - fix padding problems with speeds changing dimensions 242 | 243 | Mon Feb 24 19:55:56 CET 2003 244 | 245 | - NetBSD support w/ curses only 246 | 247 | Sun Feb 23 18:26:40 CET 2003 248 | 249 | - auto* updates 250 | - add checkinterface() for Linux 251 | - unify checkinterface() in src/.h 252 | - manpage update 253 | 254 | Thu Feb 20 21:06:22 CET 2003 255 | 256 | - use autoconf for Makefile generation 257 | 258 | Wed Feb 19 17:12:37 CET 2003 259 | 260 | - -d delay option (also suggested bt Joe Laffey) 261 | 262 | Tue Feb 18 23:27:55 CET 2003 263 | 264 | - slurm now has transparent graphics (for Eterm, aterm, ...) 265 | 266 | Tue Feb 18 20:06:22 CET 2003 267 | 268 | - add -H flag to display hostname in title as suggested by Joe Laffey 269 | 270 | Mon Feb 17 22:14:58 CET 2003 271 | 272 | - full MicroBSD support using OpenBSD functions 273 | 274 | Thu Feb 13 10:57:15 CET 2003 275 | 276 | - swap rx and tx in large view 277 | 278 | Fri Feb 7 20:58:12 CET 2003 279 | 280 | - slurm 0.2.0 281 | - minor string length fix in split mode 282 | 283 | Wed Feb 5 19:50:51 CET 2003 284 | 285 | - some really minor changes made it into the tree, the most important 286 | of them is a small fix the the Linux networking code to fix 287 | the 32bit counter overflow issue 288 | 289 | Jan 10 18:57:20 CET 2003 290 | 291 | - add more accurate FreeBSD version description to src/if_media.c 292 | so older FreeBSD releases don't break due to missing defines 293 | 294 | Tue Dec 31 23:24:53 CET 2002 295 | 296 | - slurm 0.0.10 297 | 298 | Tue Dec 31 20:52:30 MET 2002 299 | 300 | - added Solaris curses support. The network code was already working so 301 | now slurm can be used on Solaris. Further tests will follow. See 302 | TODO for status. 303 | 304 | Tue Dec 31 01:38:43 CET 2002 305 | 306 | - utilize a small char array as temporary storage for all changing strings 307 | we print so we can prevent leaving garbage on the screen 308 | 309 | Tue Dec 31 00:52:54 CET 2002 310 | 311 | - revert src/linux.c to 0.0.8 as my untested 0.0.9 version did not work 312 | as expected. Thanks to Felix von Leitner for mentioning this. 313 | 314 | Sat Dec 28 13:41:06 CET 2002 315 | 316 | - add another NetBSD Gbit Ethernet type 317 | 318 | Wed Dec 25 21:00:40 CET 2002 319 | 320 | - remove check if interface if up from src/if_media.c as it is causing 321 | more and more problems. 322 | - speed up interface detection code for NetBSD and OpenBSD while I'm at it 323 | 324 | Wed Dec 25 12:11:19 CET 2002 325 | 326 | - prevent calculation of negative rx/tx speed in case of a 327 | 32bit counter overflow 328 | 329 | Wed Dec 25 10:57:03 CET 2002 330 | 331 | - added FreeBSD -stable Wireless speed definitions to src/if_media.c 332 | 333 | Mon Dec 23 14:00:00 CET 2002 334 | 335 | - slurm 0.0.9 released 336 | 337 | Mon Dec 23 13:19:05 CET 2002 338 | 339 | - speedup src/linux.c by fseeking() to the third line before starting 340 | to parse each line until we get the needed information 341 | 342 | Mon Dec 23 12:53:55 CET 2002 343 | 344 | - (re)add -s cli option 345 | 346 | Sat Dec 21 15:29:12 CET 2002 347 | 348 | - added Solaris support in the meanwhile. Network stuff works 349 | but curses causes segmentation faults. 350 | 351 | Sat Dec 7 17:00:39 CET 2002 352 | 353 | - slurm 0.0.8 354 | 355 | Sat Dec 7 16:51:11 CET 2002 356 | 357 | - update_() functions now save more data than needed for seamless 358 | display mode switching 359 | 360 | Fri Dec 6 00:44:21 CET 2002 361 | 362 | - OpenBSD 2.9 (others?) compile fix 363 | - OpenBSD BNC media detection fix (ugly workaround but OpenBSD 364 | doesn't seem to set the correct status bits) 365 | 366 | Wed Dec 4 14:44:20 CET 2002 367 | 368 | - improve the HPUX support 369 | 370 | Wed Dec 4 00:10:20 CET 2002 371 | 372 | - added Linux sanity checks and more documentation 373 | - remove annoying compiler warnings on Linux for src/if_media.c 374 | 375 | Tue Dec 3 23:59:16 CET 2002 376 | 377 | - added initial HPUX support (thanks Oliver Lehmann) 378 | - tagged as SLURM-0_0_8PRE3 379 | 380 | Tue Nov 19 00:17:40 CET 2002 381 | 382 | - added KEYS file, please read it as there are helpful keys :) 383 | I guess it's time for a manpage now 384 | 385 | Mon Nov 18 23:48:54 CET 2002 386 | 387 | - added a new "large split window" mode 388 | 389 | Fri Nov 15 18:11:07 CET 2002 390 | 391 | - add checkinterface() for NetBSD and OpenBSD 392 | 393 | Wed Nov 13 13:45:53 CET 2002 394 | 395 | - NetBSD port 396 | 397 | Wed Nov 13 07:35:04 CET 2002 398 | 399 | - fix 32bit counter overruns 400 | 401 | Wed Nov 13 07:25:21 CET 2002 (done last night :)) 402 | 403 | - added OpenBSD support 404 | - fixed some ugla off-by-one errors which lead to crashes on OpenBSD 405 | and broken graphs in some cases. 406 | 407 | Mon Nov 11 19:48:11 CET 2002 408 | 409 | - code cleanup 410 | 411 | Mon Nov 11 19:24:05 CET 2002 412 | 413 | - FreeBSD -current fix 414 | - Bandwidth detection now prints correct strings 415 | 416 | Mon Nov 11 00:00:34 CET 2002 417 | 418 | - fix build problems on FreeBSD -current 419 | 420 | Sun Nov 10 20:18:57 CET 2002 421 | 422 | - merged split and combined view 423 | - command line option -c switched back to the classic view 424 | - operating system dependend functions moved to src/ 425 | 426 | Sun Nov 10 18:51:46 CET 2002 427 | 428 | - finally added a working splitted view for RX and TX 429 | - interface speed detection moved to src/if_media.[ch] 430 | 431 | Sat Nov 2 00:52:18 CET 2002 432 | 433 | - finished getopt() interface and checks for FreeBSD 434 | 435 | Fri Nov 1 23:50:33 CET 2002 436 | 437 | - added compilier flags to produce more errors :) 438 | - major graph upgrade so the graph scales up/down to give a better 439 | overview 440 | 441 | Tue Oct 29 23:46:08 CET 2002 442 | 443 | - added basic Linux support 444 | 445 | Sun Oct 27 20:21:12 CET 2002 446 | 447 | - solved 32bit counter issues by adding an overflow counter 448 | - fixed curses problems 449 | 450 | Sat Oct 26 18:58:20 CEST 2002 451 | 452 | - cannot read speed on tun devices. returns 115200 for my pppoe link 453 | - curses problems 454 | - received/sent bytes are only 32bit 455 | -------------------------------------------------------------------------------- /FAQ: -------------------------------------------------------------------------------- 1 | This is just kinda Q & A thing. 2 | _______________________________________________________________________________ 3 | 4 | Q: Why does slurm have themes? 5 | A: Because it can. 6 | 7 | Q: WTF is 'slurm'? / How did it all start? 8 | A: The idea came up while installing Linux systems during a small 9 | Linux installation party. Using pppstatus to monitor the ADSL 10 | uplink I did not find any equivalent app for *BSD. Lacking a similar 11 | application I removed the Linux dependent ppp code from pppstatus 12 | and added FreeBSD sysctl() code for data aquisation at ~3AM the 13 | same night. 14 | Ripping off the connection time accounting and email checks I ended 15 | up with something useful. Adding it to my CVS repository it needed 16 | a name, so the first thing that came into my mind was 'slurm' since 17 | I just saw the latest Futurama episode featuring 'Slurm Mc Kenzie' 18 | and the 'Slurm Factory', hence the name slurm. 19 | P.S. wormulon which is based on slurm is the name of the homeplanet 20 | of Slurm McKenzie. 21 | 22 | Q: Why are you not showing link information like 100MBits on Linux? 23 | A: Linux does not have a common way to save media type an link information. 24 | Gathering those information with tools like mii-tool or ethtool involve 25 | reading data directly from the ethernet cards EEPROM and success 26 | depends the card. Have a look at the ethtool source code if you want 27 | to know how nasty the whole thing might get. Integrating this slurm 28 | would need suid root privileges on Linux which is normally a bad idea. 29 | 30 | _______________________________________________________________________________ 31 | -------------------------------------------------------------------------------- /KEYS: -------------------------------------------------------------------------------- 1 | 2 | As of 0.0.7 the user can change the display mode without quitting slurm. 3 | Just press "m" to cycle between modes or 4 | 5 | - "c" for the old combined/classic mode 6 | - "s" for the split window mode with stats 7 | - "l" for the large window mode w/o stats 8 | 9 | - "z" to reset most counters 10 | - "r" to redraw the screen 11 | - "q" to quit slurm 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slurm - yet another network load monitor 2 | 3 | slurm started as a FreeBSD port of the Linux ppp link monitor called pppstatus 4 | by Gabriel Montenegro. Hendrik Scholz ripped off the ppp dependent parts and the 5 | email checks to turn it into a generic network load monitor for *BSD, Linux, 6 | HP-UX and Solaris. 7 | 8 | 9 | 10 | ## Features: 11 | - "realtime" traffic statistics 12 | - three graph modes: combined RX and TX and two split views 13 | - can monitor any network device 14 | - curses ascii graphics 15 | - ascii theme support 16 | 17 | ## slurm was tested on: 18 | - Debian GNU/Linux 10/11 (buster/bullseye) 19 | - CentOS 7/8 20 | - FreeBSD 12 21 | - OpenBSD 6.9 22 | - MacOS 12 (Monterey) 23 | 24 | ## Compiling: 25 | - Install meson and libncurses6-dev e.g.: 26 | 27 | on Debian (if you don't want to use the Debian package of slurm) 28 | 29 | sudo apt install build-essential meson libncurses6-dev 30 | 31 | or on CentOS / RedHat 32 | 33 | # Add EPEL on CentOS 7 34 | sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 35 | 36 | # Enable PowerTools repo in CentOS 8 37 | sudo dnf config-manager --set-enabled powertools 38 | 39 | sudo yum groupinstall 'Development Tools' 40 | sudo yum install meson ncurses-devel 41 | 42 | or on FreeBSD 12 43 | 44 | pkg install meson pkgconf ncurses 45 | 46 | or on Alpine Linux 47 | 48 | apk add gcc musl-dev pkgconf meson ncurses-dev linux-headers 49 | 50 | or on OpenBSD 6.9 51 | 52 | pkg_add meson 53 | 54 | - Setup a build directory 55 | 56 | meson setup _build 57 | 58 | - Run meson to build 59 | 60 | cd _build/ 61 | meson compile 62 | 63 | - Install the program 64 | 65 | sudo meson install 66 | 67 | - Try it! 68 | 69 | slurm -i eth0 # or whatever your interface is 70 | 71 | Please report bugs and feature requests in the github bugtracker: 72 | website: https://github.com/mattthias/slurm 73 | 74 | License: 75 | As pppstatus is licensed under the GPL, slurm is too. 76 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Thanks: 2 | 3 | - Gabriel for a nice ppp status monitor 4 | - Oliver Lehmann for initial HPUX support and testing/suggestions 5 | - Joe Laffey for comments/ideas/code 6 | - everyone else for ideas 7 | -------------------------------------------------------------------------------- /THEMES.txt: -------------------------------------------------------------------------------- 1 | _______________________________________________________________________________ 2 | T H E M E S 3 | 4 | Themes basicly allow the user to change the look of slurm. 5 | In case you don't like the default color set you can create a new 6 | one and instruct slurm to use it: 7 | 8 | $ slurm -i foo0 -t mytheme 9 | 10 | In this case 'mytheme' is the name of the theme that should be installed 11 | in either in the current working directory, ~/.slurm or 12 | /usr/local/share/slurm. 13 | 14 | F I L E L A Y O U T 15 | 16 | For a quick start just copy an existing theme and modify it. 17 | The main part (comments are allowed) is a simple key & value thing 18 | you should be familiar with. 19 | 20 | In case there are any questions please contact me. 21 | I'd like to add some themes to the main distribution but won't add 22 | all since the codebase should stay small. 23 | _______________________________________________________________________________ 24 | $Id: THEMES.txt,v 1.1 2004/02/13 05:13:52 hscholz Exp $ 25 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | known issues: 2 | 3 | - when resizing the terminal while running slurm in screen it might be 4 | possible that the static parts of the window are not redrawn so we 5 | should care about signals. 6 | 7 | - Solaris curses problems (Sat Dec 21 15:30:45 CET 2002) 8 | 9 | the solaris network stuff is ok but curses causes crashes 10 | UPDATE: fixed as of 2002-12-31. 11 | 12 | - BNC media detection (Fri Dec 6 00:50:18 CET 2002) 13 | 14 | While testing slurm on OpenBSD (thanks Auge for the account) I discovered 15 | a problem regarding the ifmedireq flags. OpenBSD does not set 16 | IFM_ACTIVE or IFM_AVALID for BNC interfaces. 17 | 18 | - high load on Linux 2.5 (Thu Dec 5 23:30:43 CET 2002) 19 | 20 | slurm caused 99% load on a Linux 2.5.40 box while transfering data 21 | on a saturated 100Mbit link. 22 | UPDATE: This hasn't been reproduced until now so it's low priority 23 | until someone reports it again. 24 | UPDATE: perhaps a usleep() problem might leads to wasting cpu cycles. 25 | 26 | - NetBSD interface speed detecion code (Thu Dec 5 23:30:43 CET 2002) 27 | 28 | As of today the interface speed detection code seems to not work 29 | correctly on NetBSD/stable. 30 | UPDATE: This seems to only concern my sq interface on my Indy. 31 | 32 | This matrix shows what works and what not. Feel free to contribute code. 33 | 34 | OS | get_stat | if_media | check_interface || overall 35 | ---------+----------+----------+-----------------++---------- 36 | FreeBSD | done | done | done || works 37 | OpenBSD | done | done | done || works 38 | NetBSD | done | done | done || works 39 | Solaris | done | done | done || works 40 | Linux | done | N/A | done || works 41 | HP-UX | done | | || works 42 | MicroBSD | done | done | done || works 43 | MacOS X | done | done | done || works 44 | 45 | $Id: TODO,v 1.15 2003/09/18 09:59:01 hscholz Exp $ 46 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #define PACKAGE_VERSION "@version@" 2 | #define VERSION "@version@" 3 | #define INSTALL_PREFIX "@install_prefix@" 4 | -------------------------------------------------------------------------------- /error.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * error.c - generic error handling function 4 | * 5 | ***************************************************************************** 6 | * $Id: error.c,v 1.1 2003/05/25 14:45:23 hscholz Exp $ 7 | ****************************************************************************/ 8 | 9 | #ifndef _ERROR_C 10 | #define _ERROR_C 11 | 12 | #include "error.h" 13 | 14 | /***************************************************************************** 15 | * 16 | * error() 17 | * 18 | * print error message and exit if asked for 19 | * 20 | ****************************************************************************/ 21 | 22 | void error(int level, char *msg, ...) 23 | { 24 | va_list arguments; 25 | int debug = 1; 26 | va_start(arguments, msg); 27 | 28 | switch (level) { 29 | case ERR_DEBUG: 30 | if (debug != 0) 31 | fprintf(stderr, "DEBUG: "); 32 | break; 33 | case ERR_NOTICE: 34 | fprintf(stderr, "NOTICE: "); 35 | break; 36 | case ERR_WARNING: 37 | fprintf(stderr, "WARNING: "); 38 | break; 39 | case ERR_ERROR: 40 | fprintf(stderr, "ERROR: "); 41 | break; 42 | case ERR_FATAL: 43 | fprintf(stderr, "FATAL: "); 44 | break; 45 | } 46 | /* print the remaining arguments */ 47 | vfprintf(stderr, msg, arguments); 48 | va_end(arguments); 49 | fprintf(stderr, "\n"); 50 | if (level == ERR_FATAL) 51 | exit(1); 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /error.h: -------------------------------------------------------------------------------- 1 | /* $Id: error.h,v 1.1 2003/05/25 14:45:23 hscholz Exp $ */ 2 | #ifndef _ERROR_H 3 | #define _ERROR_H 4 | 5 | /* error type definition 6 | * 7 | * lower Byte identifies the error 8 | * upper Byte is reserved for future use 9 | * (i.e. & 0x01ff to enable syslog logging) 10 | */ 11 | 12 | #define ERR_DEBUG 0x0001 13 | #define ERR_NOTICE 0x0003 14 | #define ERR_WARNING 0x0004 15 | #define ERR_ERROR 0x0005 16 | #define ERR_FATAL 0x0006 17 | #define ERRBUF BUFSIZ 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('slurm', 'c') 2 | 3 | conf_data = configuration_data() 4 | conf_data.set('version', '0.4.5-dev') 5 | conf_data.set('install_prefix', get_option('prefix')) 6 | 7 | configure_file(input : 'config.h.in', 8 | output : 'config.h', 9 | configuration : conf_data) 10 | 11 | # We want ncurses but meson wraps ncurses and curses into the curses dependency 12 | # https://mesonbuild.com/Dependencies.html#curses 13 | # dependency "ncurses" doesn't work on OpenBSD so we use "curses" on all OS 14 | curses_dep = dependency('curses', version: '>=5') 15 | 16 | add_global_arguments('-D_HAVE_NCURSES', language: 'c') 17 | 18 | # build and install slurm binary 19 | executable('slurm', 'slurm.c', dependencies: curses_dep, install:true ) 20 | 21 | # install manpage and theme files 22 | install_man('slurm.1') 23 | install_subdir('themes', 24 | install_dir: get_option('datadir') / 'slurm', 25 | strip_directory: true) 26 | -------------------------------------------------------------------------------- /os.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * os.h - OS dependent headers 4 | * 5 | ***************************************************************************** 6 | * $Id: os.h,v 1.7 2004/10/12 19:55:58 hscholz Exp $ 7 | ***************************************************************************** 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22 | * USA. 23 | * 24 | *****************************************************************************/ 25 | 26 | #ifndef _OS_H_ 27 | #define _OS_H_ 28 | 29 | /* set variables for extra features */ 30 | #if defined (__sun__) || defined (__sun) 31 | # ifndef __Solaris__ 32 | # define __Solaris__ 1 33 | # endif 34 | #endif 35 | 36 | #if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \ 37 | || defined (__MicroBSD__) || defined (__APPLE__) || defined (__DragonFly__) 38 | #define _HAVE_BSD 39 | #define _HAVE_CHECKINTERFACE 40 | #elif defined (__HPUX__) 41 | #define _HAVE_CHECKINTERFACE 42 | #elif defined (__Solaris__) 43 | #define _HAVE_CHECKINTERFACE 44 | #elif defined (__linux__) 45 | #define _HAVE_CHECKINTERFACE 46 | #endif 47 | 48 | #ifdef __HPUX__ /* H P U X */ 49 | #define _XOPEN_SOURCE_EXTENDED 50 | #define NO_CURSES_E 1 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #elif defined (__FreeBSD__) /* F R E E B S D */ 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | #include 82 | #include 83 | #include 84 | #include 85 | #include 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | #include 96 | #include 97 | #ifndef __DragonFly__ 98 | #include 99 | #endif 100 | #elif defined (__NetBSD__) /* N E T B S D */ 101 | #include 102 | #include 103 | #include 104 | #include 105 | #include 106 | #include 107 | #include 108 | #include 109 | #include 110 | #include 111 | #include 112 | #include 113 | #include 114 | #include 115 | #include 116 | #include 117 | #include 118 | #include 119 | #include 120 | #include 121 | #include 122 | #include 123 | #include 124 | #include 125 | #include 126 | #include 127 | #elif defined (__OpenBSD__) || defined (__MicroBSD__) /* O P E N B S D */ 128 | #include 129 | #include 130 | #include 131 | #include 132 | #include 133 | #include 134 | #include 135 | #include 136 | #include 137 | #include 138 | #include 139 | #include 140 | #include 141 | #include 142 | #include 143 | #include 144 | #include 145 | #include 146 | #include 147 | #include 148 | #include 149 | #include 150 | #include 151 | #include 152 | #include 153 | #elif defined (__APPLE__) /* Mac OS X */ 154 | #include 155 | #include 156 | #include 157 | #include 158 | #include 159 | #include 160 | #include 161 | #include 162 | #include 163 | #include 164 | #include 165 | #include 166 | #include 167 | #include 168 | #include 169 | #include 170 | #include 171 | #include 172 | #include 173 | #include 174 | #include 175 | #include 176 | #include 177 | #include 178 | #include 179 | #elif defined (__linux__) /* L I N U X */ 180 | #include 181 | #include 182 | #include 183 | #include 184 | #include 185 | #include 186 | #include 187 | #include 188 | #include 189 | #include 190 | #include 191 | #include 192 | #include 193 | #include 194 | #include 195 | #include 196 | #include 197 | #include 198 | #include 199 | #include 200 | #include 201 | #elif defined (__Solaris__) /* S O L A R I S */ 202 | #include 203 | #define NO_CURSES_E 1 204 | #define _WIDEC_H 205 | #include 206 | #include 207 | #include 208 | #include 209 | #include 210 | #include 211 | #include 212 | #include 213 | #include 214 | #include 215 | #include 216 | #include 217 | #include 218 | #include 219 | #include 220 | #include 221 | #include 222 | #include 223 | #include 224 | #include 225 | #include 226 | #include 227 | #include 228 | #include 229 | #include 230 | #include 231 | #include 232 | #elif defined (__FreeBSD_kernel__) /* G N U / k F r e e B S D */ 233 | #include 234 | #include 235 | #include 236 | #include 237 | #include 238 | #include 239 | #include 240 | #include 241 | #include 242 | #include 243 | #include 244 | #include 245 | #include 246 | #include 247 | #include 248 | #include 249 | #include 250 | #include 251 | #include 252 | #include 253 | #include 254 | #include 255 | #else 256 | #error "Your OS is not supported! Please report to hscholz@raisdorf.net" 257 | #endif /* OS selection */ 258 | 259 | #endif 260 | -------------------------------------------------------------------------------- /slurm.1: -------------------------------------------------------------------------------- 1 | .Dd February 4, 2024 2 | .Dt slurm 1 3 | .\" $Id: slurm.1,v 1.4 2004/02/06 02:33:54 hscholz Exp $ 4 | .\" 5 | .Sh NAME 6 | slurm \- yet another network load monitor 7 | .Sh SYNOPSIS 8 | .Nm slurm 9 | .Op Fl hHz 10 | .Op Fl csl 11 | .Op Fl d Ar delay 12 | .Op Fl i Ar interface 13 | .Op Fl t Ar theme 14 | .Sh DESCRIPTION 15 | slurm is a generic network load monitor which shows device statistics 16 | together with a nice ascii graph. Three different types of graphs are 17 | supported. 18 | .Sh OPTIONS 19 | .Bl -tag -width Ds 20 | .It Fl h 21 | Print usage information and quit. 22 | .It Fl H 23 | add hostname to title 24 | .It Fl c 25 | start slurm with classic/combined graph 26 | .It Fl s 27 | start slurm in split graph mode 28 | .It Fl l 29 | start slurm in large split graph mode 30 | .It Fl z 31 | virtually zero traffic counters instead of showing values stored in kernel 32 | .It Fl d Ar delay 33 | delay between screen updates in seconds (must be between 1 and 300) 34 | .It Fl i Ar interface 35 | select interface to monitor (required) 36 | .It Fl t Ar theme 37 | select theme, searches ~/.slurm and ${PREFIX}/share/slurm 38 | .El 39 | .Sh KEYS 40 | slurm supports several different keys for interaction: 41 | .Bl -tag -width Ds 42 | .It Ar c 43 | switch to classic mode 44 | .It Ar s 45 | switch to split graph mode 46 | .It Ar l 47 | switch to large graph mode 48 | .It Ar L 49 | enable TX/RX led 50 | .It Ar m 51 | switch between classic, split and large view 52 | .It Ar z 53 | zero counters 54 | .It Ar r 55 | redraw screen 56 | .It Ar q 57 | quit slurm 58 | .El 59 | .Sh BUGS 60 | Several features of slurm are not supported on certain platforms, i.e. 61 | Interface speed detection is only supported on *BSD. Please check 62 | the source code documentation to see if your bug is really a bug. 63 | Please report bugs at https://github.com/mattthias/slurm/issues 64 | .Sh AUTHOR 65 | Hendrik Scholz 66 | .br 67 | Matthias Schmitz 68 | .br 69 | https://github.com/mattthias/slurm 70 | -------------------------------------------------------------------------------- /slurm.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * slurm - yet another network load monitor 4 | * 5 | * slurm started as a FreeBSD port of the Linux ppp link monitor called 6 | * pppstatus by Gabriel Montenegro. 7 | * I ripped of the ppp dependend parts and the email checks to turn in into 8 | * a generic network load monitor running on all common Unices. 9 | * 10 | * author: Hendrik Scholz, Matthias Schmitz 11 | * website: https://www.github.com/mattthias/slurm 12 | * 13 | * As pppstatus is licensed under the GPL, slurm is too. See the following 14 | * paragraphs for information about pppstatus and the license. 15 | * 16 | ***************************************************************************** 17 | * $Id: slurm.c,v 1.86 2004/10/12 19:44:36 hscholz Exp $ 18 | ***************************************************************************** 19 | * 20 | * This program is free software; you can redistribute it and/or modify 21 | * it under the terms of the GNU General Public License as published by 22 | * the Free Software Foundation; either version 2 of the License, or 23 | * (at your option) any later version. 24 | * 25 | * This program is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | * GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License 31 | * along with this program; if not, write to the Free Software 32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 33 | * USA. 34 | * 35 | *****************************************************************************/ 36 | 37 | #include "os.h" 38 | 39 | #include "config.h" 40 | #include "slurm.h" 41 | #include "src/if_media.h" 42 | #include "src/if_media.c" 43 | 44 | #include "error.h" 45 | #include "error.c" 46 | #include "theme.h" 47 | #include "theme.c" 48 | 49 | #ifdef __HPUX__ 50 | #include "src/hpux.h" 51 | #include "src/hpux.c" 52 | #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__) 53 | #include "src/freebsd.h" 54 | #include "src/freebsd.c" 55 | #elif defined (__linux__) 56 | #include "src/linux.h" 57 | #include "src/linux.c" 58 | #elif defined (__OpenBSD__) || defined (__MicroBSD__) 59 | #include "src/openbsd.h" 60 | #include "src/openbsd.c" 61 | #elif defined (__NetBSD__) 62 | #include "src/netbsd.h" 63 | #include "src/netbsd.c" 64 | #elif defined (__Solaris__) 65 | #include "src/solaris.h" 66 | #include "src/solaris.c" 67 | #elif defined (__APPLE__) 68 | #include "src/macos.h" 69 | #include "src/macos.c" 70 | #elif defined (__DragonFly__) 71 | #include "src/freebsd.h" 72 | #include "src/freebsd.c" 73 | #else 74 | #warning "Your OS is not supported. Including dummy code!" 75 | #include "src/unsupported.h" 76 | #include "src/unsupported.c" 77 | #endif 78 | 79 | /****************************************************************************** 80 | * 81 | * center() 82 | * 83 | * center a given string on a given line 84 | * this is pppstatus code :) 85 | * 86 | *****************************************************************************/ 87 | 88 | void center(short int line, char *strg, ...) 89 | { 90 | short int where; 91 | char *final; 92 | va_list trans; 93 | 94 | final = malloc(80); 95 | va_start(trans, strg); 96 | (void) vsnprintf(final, 80, strg, trans); 97 | va_end(trans); 98 | where = (int) (40 - (strlen(final) / 2)); 99 | if (line != 0 && line != 24) { 100 | move(line, 20); 101 | hline(32, 50); 102 | } 103 | mvprintw(line, where, "%s", final); 104 | free(final); 105 | } 106 | 107 | /****************************************************************************** 108 | * 109 | * get_time() 110 | * 111 | * uptime stats struct with current time 112 | * 113 | *****************************************************************************/ 114 | 115 | void get_time(void) 116 | { 117 | long x; 118 | stats.current_time = time(NULL); 119 | x = stats.current_time - stats.connect_time; 120 | stats.online_sec = x % 60; 121 | stats.online_min = (x / 60) % 60; 122 | stats.online_hour = (x / 3600) % 24; 123 | stats.online_days = (x / (3600 * 24)) % 365; 124 | } 125 | 126 | /****************************************************************************** 127 | * 128 | * update_info() 129 | * 130 | * update the statistics and pay attention to buffer overruns while we are 131 | * here. As we allow decreasing values we have to pay attention to 132 | * no leave garbage on the screen. 133 | * 134 | *****************************************************************************/ 135 | 136 | void update_info(int displaymode) 137 | { 138 | char draw[DRAWLEN + 1]; 139 | attrset(COLOR_PAIR(PAIR_VAR) | 140 | ((unsigned long) (t.var_attrib == 141 | COL_BOLD) ? A_BOLD : A_NORMAL)); 142 | if (displaymode != MODE_LARGE) { 143 | snprintf(draw, DRAWLEN - 1, "%lu", 144 | stats.rx_packets - stats.rx_packets_off); 145 | strncat(draw, " ", DRAWLEN - strlen(draw)); 146 | mvprintw(20, 24, "%s", draw); 147 | 148 | snprintf(draw, DRAWLEN - 1, "%lu", 149 | stats.tx_packets - stats.tx_packets_off); 150 | strncat(draw, " ", DRAWLEN - strlen(draw)); 151 | mvprintw(20, 65, "%s", draw); 152 | 153 | snprintf(draw, DRAWLEN - 1, "%lu", 154 | stats.rx_errors - stats.rx_errors_off); 155 | strncat(draw, " ", DRAWLEN - strlen(draw)); 156 | mvprintw(22, 24, "%s", draw); 157 | 158 | snprintf(draw, DRAWLEN - 1, "%lu", 159 | stats.tx_errors - stats.tx_errors_off); 160 | strncat(draw, " ", DRAWLEN - strlen(draw)); 161 | mvprintw(22, 65, "%s", draw); 162 | 163 | switch (data_type) { 164 | case TYPE_MEGA: 165 | snprintf(draw, DRAWLEN - 1, "%.3f MB", (stats.rx_bytes + 166 | (stats.rx_over * 167 | SNMPMAXBYTES) - 168 | stats.rx_bytes_off) / 169 | 1048570); 170 | strncat(draw, " ", DRAWLEN - strlen(draw)); 171 | mvprintw(21, 24, "%s", draw); 172 | 173 | snprintf(draw, DRAWLEN - 1, "%.3f MB", (stats.tx_bytes + 174 | (stats.tx_over * 175 | SNMPMAXBYTES) - 176 | stats.tx_bytes_off) / 177 | 1048570); 178 | strncat(draw, " ", DRAWLEN - strlen(draw)); 179 | mvprintw(21, 65, "%s", draw); 180 | break; 181 | case TYPE_GIGA: 182 | snprintf(draw, DRAWLEN - 1, "%.3f GB", (stats.rx_bytes + 183 | (stats.rx_over * 184 | SNMPMAXBYTES) - 185 | stats.rx_bytes_off) 186 | / 1073735680); 187 | strncat(draw, " ", DRAWLEN - strlen(draw)); 188 | mvprintw(21, 24, "%s", draw); 189 | 190 | snprintf(draw, DRAWLEN - 1, "%.3f GB", (stats.tx_bytes + 191 | (stats.tx_over * 192 | SNMPMAXBYTES) - 193 | stats.tx_bytes_off) 194 | / 1073735680); 195 | strncat(draw, " ", DRAWLEN - strlen(draw)); 196 | mvprintw(21, 65, "%s", draw); 197 | break; 198 | } 199 | } 200 | } 201 | 202 | #ifdef WITH_LED 203 | /****************************************************************************** 204 | * 205 | * led_on() / led_off() 206 | * 207 | * blinkenlights(tm) 208 | * 209 | *****************************************************************************/ 210 | 211 | void led_on(unsigned int who) 212 | { 213 | int CHAR = 215; 214 | 215 | if (who == LED_RX) { 216 | attrset(COLOR_PAIR(PAIR_RX) | 217 | ((unsigned long) (t.rx_attrib == 218 | COL_BOLD) ? A_BOLD : A_NORMAL)); 219 | move(14, 37); 220 | hline(CHAR, 2); 221 | } else if (who == LED_TX) { 222 | attrset(COLOR_PAIR(PAIR_TX) | 223 | ((unsigned long) (t.tx_attrib == 224 | COL_BOLD) ? A_BOLD : A_NORMAL)); 225 | move(14, 41); 226 | hline(CHAR, 2); 227 | } 228 | } 229 | 230 | void led_off(unsigned int who) 231 | { 232 | if (who == LED_RX) { 233 | attrset(COLOR_PAIR(PAIR_VAR) | 234 | ((unsigned long) (t.var_attrib == 235 | COL_BOLD) ? A_BOLD : A_NORMAL)); 236 | mvprintw(14, 37, "RX"); 237 | } else if (who == LED_TX) { 238 | attrset(COLOR_PAIR(PAIR_VAR) | 239 | ((unsigned long) (t.var_attrib == 240 | COL_BOLD) ? A_BOLD : A_NORMAL)); 241 | mvprintw(14, 41, "TX"); 242 | } 243 | } 244 | #endif 245 | 246 | /****************************************************************************** 247 | * 248 | * update_stat_large() 249 | * 250 | * update the data array holding the needed information and redraw the graph 251 | * this mode shows two large graphs, one for each direction 252 | * 253 | *****************************************************************************/ 254 | 255 | int update_stat_large(void) 256 | { 257 | float rxspeed; 258 | float txspeed; 259 | int i = 0, x, y; 260 | int rx_scalechanged = 0; /* traffic scale changed? */ 261 | int tx_scalechanged = 0; 262 | 263 | float tmp_maxspeed = 0; /* needed for max speed calc in graph */ 264 | int tmp_maxspeedpos = 1; /* same here */ 265 | 266 | char draw[DRAWLEN + 1]; /* what we draw on the screen */ 267 | 268 | /* in case of REINIT we want to keep the rx and tx values as we can 269 | * recalculate the graph for the new mode based on them. 270 | * recalculation is done automatically as ??_maxspeed equals 0 after 271 | * initilization. 272 | */ 273 | 274 | if (db_status == DB_STATUS_REINIT || db_status == DB_STATUS_STARTUP) { 275 | rx_maxspeed = 0; 276 | rx_overallmax = 0; 277 | tx_maxspeed = 0; 278 | tx_overallmax = 0; 279 | /* fill the graph array with zeros */ 280 | for (x = 0; x < GRAPH_WIDTH; x++) { 281 | for (y = 0; y < GRAPH_HEIGHT; y++) { 282 | rx_graph[x][y] = 0; 283 | tx_graph[x][y] = 0; 284 | } 285 | } 286 | 287 | if (db_status == DB_STATUS_STARTUP) { 288 | stats.rx_bytes_comp = stats.rx_bytes; 289 | stats.tx_bytes_comp = stats.tx_bytes; 290 | for (x = 0; x < GRAPH_WIDTH; x++) { 291 | rx_speedarray[x] = 0; 292 | tx_speedarray[x] = 0; 293 | } 294 | db_status = DB_STATUS_RUNNING; 295 | 296 | return 1; 297 | } 298 | db_status = DB_STATUS_RUNNING; 299 | } 300 | 301 | /* 302 | * current speed in bits/s 303 | * 304 | * in case of the expected u_long overflow in stats.?x_bytes 305 | * we will calculate a negative number as {sum|tx|rx}speed. 306 | * to prevent this we have to check if the _comp value is larger 307 | * than the current value. If true, we set _comp to 0 308 | */ 309 | 310 | if (stats.rx_bytes_comp > stats.rx_bytes) 311 | stats.rx_bytes_comp = 0; 312 | if (stats.tx_bytes_comp > stats.tx_bytes) 313 | stats.tx_bytes_comp = 0; 314 | 315 | rxspeed = (stats.rx_bytes - stats.rx_bytes_comp) / refreshdelay; 316 | txspeed = (stats.tx_bytes - stats.tx_bytes_comp) / refreshdelay; 317 | 318 | /* print current speed */ 319 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", (float) rxspeed / 1024); 320 | strncat(draw, " ", DRAWLEN - strlen(draw)); 321 | mvprintw(21, 24, "%s", draw); 322 | 323 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", (float) txspeed / 1024); 324 | strncat(draw, " ", DRAWLEN - strlen(draw)); 325 | mvprintw(21, 65, "%s", draw); 326 | 327 | stats.rx_bytes_comp = stats.rx_bytes; 328 | stats.tx_bytes_comp = stats.tx_bytes; 329 | 330 | /* set new max speed for graph if reached */ 331 | if (rxspeed > rx_maxspeed) { 332 | rx_maxspeed = rxspeed; 333 | rx_maxspeedpos = 0; 334 | rx_scalechanged++; 335 | if (rxspeed > rx_overallmax) 336 | rx_overallmax = rxspeed; 337 | } 338 | 339 | /* set new max speed for graph if reached */ 340 | if (txspeed > tx_maxspeed) { 341 | tx_maxspeed = txspeed; 342 | tx_maxspeedpos = 0; 343 | tx_scalechanged++; 344 | if (txspeed > tx_overallmax) 345 | tx_overallmax = txspeed; 346 | } 347 | 348 | /* 349 | * update the Graph Top Speed field 350 | * as it might be shorter than before just be sure to not leave 351 | * trailing garbage by printing spaces 352 | */ 353 | 354 | if (rx_scalechanged) { 355 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", 356 | (float) rx_maxspeed / 1024); 357 | strncat(draw, " ", DRAWLEN - strlen(draw)); 358 | mvprintw(22, 24, "%s", draw); 359 | } 360 | if (tx_scalechanged) { 361 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", 362 | (float) tx_maxspeed / 1024); 363 | strncat(draw, " ", DRAWLEN - strlen(draw)); 364 | mvprintw(22, 65, "%s", draw); 365 | } 366 | 367 | 368 | /* increment position of max speed as we move the graph */ 369 | rx_maxspeedpos++; 370 | tx_maxspeedpos++; 371 | 372 | /* check if max speed has to be lowered for the graph as the max speed 373 | * was reached too long ago 374 | */ 375 | 376 | tmp_maxspeed = 0; 377 | tmp_maxspeedpos = 1; 378 | if (rx_maxspeedpos >= GRAPH_WIDTH) { 379 | /* max speed calculation has to be redone */ 380 | for (i = 0; i < GRAPH_WIDTH; i++) { 381 | if (rx_speedarray[i] > tmp_maxspeed) { 382 | tmp_maxspeed = rx_speedarray[1]; 383 | tmp_maxspeedpos = i; 384 | } 385 | } 386 | /* set new values */ 387 | rx_maxspeed = tmp_maxspeed; 388 | rx_maxspeedpos = tmp_maxspeedpos; 389 | } 390 | 391 | tmp_maxspeed = 0; 392 | tmp_maxspeedpos = 1; 393 | if (tx_maxspeedpos >= GRAPH_WIDTH) { 394 | /* max speed calculation has to be redone */ 395 | for (i = 0; i < GRAPH_WIDTH; i++) { 396 | if (tx_speedarray[i] > tmp_maxspeed) { 397 | tmp_maxspeed = tx_speedarray[1]; 398 | tmp_maxspeedpos = i; 399 | } 400 | } 401 | /* set new values */ 402 | tx_maxspeed = tmp_maxspeed; 403 | tx_maxspeedpos = tmp_maxspeedpos; 404 | } 405 | 406 | /* prepare the graph array 407 | * 408 | * shift the graph to the left and then add the last entry 409 | * in addition move the traffic stats left 410 | */ 411 | 412 | /* move */ 413 | for (x = GRAPH_WIDTH - 1; x >= 0; x--) { 414 | rx_speedarray[x] = rx_speedarray[x - 1]; 415 | tx_speedarray[x] = tx_speedarray[x - 1]; 416 | for (y = 0; y < GRAPHLARGE_HEIGHT; y++) { 417 | rx_graph[x][y] = rx_graph[x - 1][y]; 418 | tx_graph[x][y] = tx_graph[x - 1][y]; 419 | } 420 | } 421 | 422 | /* add the last column */ 423 | if (rx_maxspeed > 0) 424 | i = (int) ((rxspeed / rx_maxspeed) * GRAPHLARGE_HEIGHT); 425 | for (y = 0; y <= GRAPHLARGE_HEIGHT; y++) { 426 | if (i > y) 427 | rx_graph[0][y] = 1; 428 | else 429 | rx_graph[0][y] = 0; 430 | } 431 | if (0 != (int) rxspeed) 432 | rx_graph[0][1] = 1; 433 | rx_speedarray[0] = rxspeed; 434 | 435 | if (tx_maxspeed > 0) 436 | i = (int) ((txspeed / tx_maxspeed) * GRAPHLARGE_HEIGHT); 437 | for (y = 0; y <= GRAPHLARGE_HEIGHT; y++) { 438 | if (i > y) 439 | tx_graph[0][y] = 1; 440 | else 441 | tx_graph[0][y] = 0; 442 | } 443 | if (0 != (int) txspeed) 444 | tx_graph[0][1] = 1; 445 | tx_speedarray[0] = txspeed; 446 | 447 | /* 448 | * rescale graph 449 | * 450 | * in case the maxspeed for the shown graph changed we need to 451 | * recalculate the whole graph 452 | * 453 | */ 454 | 455 | if (rx_scalechanged) { 456 | /* for each line rewrite the graph */ 457 | for (x = GRAPH_WIDTH - 1; x >= 0; x--) { 458 | i = (int) ((rx_speedarray[x] / rx_maxspeed) * 459 | GRAPHLARGE_HEIGHT); 460 | for (y = 0; y <= GRAPHLARGE_HEIGHT; y++) { 461 | if (i > y) 462 | rx_graph[x][y] = 1; 463 | else 464 | rx_graph[x][y] = 0; 465 | } 466 | if (rx_speedarray[x] != 0) 467 | rx_graph[x][1] = 1; 468 | } 469 | } 470 | if (tx_scalechanged) { 471 | /* for each line rewrite the graph */ 472 | for (x = GRAPH_WIDTH - 1; x >= 0; x--) { 473 | i = (int) ((tx_speedarray[x] / tx_maxspeed) * 474 | GRAPHLARGE_HEIGHT); 475 | for (y = 0; y <= GRAPHLARGE_HEIGHT; y++) { 476 | if (i > y) 477 | tx_graph[x][y] = 1; 478 | else 479 | tx_graph[x][y] = 0; 480 | } 481 | if (tx_speedarray[x] != 0) 482 | tx_graph[x][1] = 1; 483 | } 484 | } 485 | 486 | 487 | /* 488 | * finally draw the two graphs line by line 489 | * 490 | * the rx graphs grows to the bottom 491 | */ 492 | 493 | for (y = GRAPHLARGE_HEIGHT - 1; y > 0; y--) { 494 | for (x = 0; x <= GRAPH_WIDTH; x++) { 495 | /* RX graph */ 496 | if (rx_graph[x][y] == 1) { 497 | attrset(COLOR_PAIR(PAIR_RX) | 498 | ((unsigned long) (t.rx_attrib == 499 | COL_BOLD) ? A_BOLD : A_NORMAL)); 500 | mvprintw(11 - y, x + 1, SYMBOL_TRAFFIC); 501 | } else 502 | mvprintw(11 - y, x + 1, SYMBOL_NOTRAFFIC); 503 | /* TX graph */ 504 | if (tx_graph[x][y] == 1) { 505 | attrset(COLOR_PAIR(PAIR_TX) | 506 | ((unsigned long) (t.tx_attrib == 507 | COL_BOLD) ? A_BOLD : A_NORMAL)); 508 | mvprintw(10 + y, x + 1, SYMBOL_TRAFFIC); 509 | } else 510 | mvprintw(10 + y, x + 1, SYMBOL_NOTRAFFIC); 511 | } 512 | } 513 | return 0; 514 | } 515 | 516 | /****************************************************************************** 517 | * 518 | * update_stat_split() 519 | * 520 | * updates the array holding information about the graph and redraw 521 | * the graph. 522 | * 523 | *****************************************************************************/ 524 | 525 | int update_stat_split(void) 526 | { 527 | float rxspeed; 528 | float txspeed; 529 | int i = 0, x, y; 530 | int rx_scalechanged = 0; /* traffic scale changed? */ 531 | int tx_scalechanged = 0; 532 | 533 | float tmp_maxspeed = 0; /* needed for max speed calc in graph */ 534 | int tmp_maxspeedpos = 1; /* same here */ 535 | 536 | char draw[DRAWLEN + 1]; /* what we draw on the screen */ 537 | 538 | /* in case of REINIT we want to keep the rx and tx values as we can 539 | * recalculate the graph for the new mode based on them. 540 | * recalculation is done automatically as ??_maxspeed equals 0 after 541 | * initilization. 542 | */ 543 | 544 | if (db_status != DB_STATUS_RUNNING) { 545 | rx_maxspeed = 0; 546 | rx_overallmax = 0; 547 | tx_maxspeed = 0; 548 | tx_overallmax = 0; 549 | /* fill the graph array with zeros */ 550 | for (x = 0; x < GRAPH_WIDTH; x++) { 551 | for (y = 0; y < GRAPH_HEIGHT; y++) { 552 | rx_graph[x][y] = 0; 553 | tx_graph[x][y] = 0; 554 | } 555 | } 556 | 557 | if (db_status == DB_STATUS_STARTUP) { 558 | stats.rx_bytes_comp = stats.rx_bytes; 559 | stats.tx_bytes_comp = stats.tx_bytes; 560 | for (x = 0; x < GRAPH_WIDTH; x++) { 561 | rx_speedarray[x] = 0; 562 | tx_speedarray[x] = 0; 563 | } 564 | db_status = DB_STATUS_RUNNING; 565 | 566 | return 1; 567 | } 568 | db_status = DB_STATUS_RUNNING; 569 | } 570 | 571 | /* 572 | * current speed in bits/s 573 | * 574 | * in case of the expected u_long overflow in stats.?x_bytes 575 | * we will calculate a negative number as {sum|tx|rx}speed. 576 | * to prevent this we have to check if the _comp value is larger 577 | * than the current value. If true, we set _comp to to 2^32 - _comp 578 | */ 579 | 580 | if (stats.rx_bytes_comp > stats.rx_bytes) 581 | stats.rx_bytes_comp = SNMPMAXBYTES - stats.rx_bytes_comp; 582 | if (stats.tx_bytes_comp > stats.tx_bytes) 583 | stats.tx_bytes_comp = SNMPMAXBYTES - stats.tx_bytes_comp; 584 | 585 | 586 | rxspeed = (stats.rx_bytes - stats.rx_bytes_comp) / refreshdelay; 587 | txspeed = (stats.tx_bytes - stats.tx_bytes_comp) / refreshdelay; 588 | 589 | /* print current speed 590 | * instead of directly printing the string we first clear the draw string 591 | * and then fill in the speed. This way we prevent garbage from being 592 | * left on the screen. 593 | */ 594 | 595 | attrset(COLOR_PAIR(PAIR_VAR) | 596 | ((unsigned long) (t.var_attrib == 597 | COL_BOLD) ? A_BOLD : A_NORMAL)); 598 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s ", rxspeed / 1024); 599 | strncat(draw, " ", DRAWLEN - strlen(draw)); 600 | mvprintw(17, 24, "%s", draw); 601 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s ", txspeed / 1024); 602 | strncat(draw, " ", DRAWLEN - strlen(draw)); 603 | mvprintw(17, 65, "%s", draw); 604 | 605 | stats.rx_bytes_comp = stats.rx_bytes; 606 | stats.tx_bytes_comp = stats.tx_bytes; 607 | 608 | /* set new max speed for graph if reached */ 609 | if (rxspeed > rx_maxspeed) { 610 | rx_maxspeed = rxspeed; 611 | rx_maxspeedpos = 0; 612 | rx_scalechanged++; 613 | if (rxspeed > rx_overallmax) { 614 | rx_overallmax = rxspeed; 615 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", 616 | (float) rxspeed / 1024); 617 | strncat(draw, " ", DRAWLEN - strlen(draw)); 618 | mvprintw(19, 24, "%s", draw); 619 | } 620 | } 621 | 622 | /* set new max speed for graph if reached */ 623 | if (txspeed > tx_maxspeed) { 624 | tx_maxspeed = txspeed; 625 | tx_maxspeedpos = 0; 626 | tx_scalechanged++; 627 | if (txspeed > tx_overallmax) { 628 | tx_overallmax = txspeed; 629 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", 630 | (float) txspeed / 1024); 631 | strncat(draw, " ", DRAWLEN - strlen(draw)); 632 | mvprintw(19, 65, "%s", draw); 633 | } 634 | } 635 | 636 | /* 637 | * update the Graph Top Speed field 638 | * as it might be shorter than before just be sure to not leave 639 | * trailing garbage by printing spaces 640 | */ 641 | 642 | if (rx_scalechanged) { 643 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", rx_maxspeed / 1024); 644 | strncat(draw, " ", DRAWLEN - strlen(draw)); 645 | mvprintw(18, 24, "%s", draw); 646 | } 647 | if (tx_scalechanged) { 648 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", tx_maxspeed / 1024); 649 | strncat(draw, " ", DRAWLEN - strlen(draw)); 650 | mvprintw(18, 65, "%s", draw); 651 | } 652 | 653 | 654 | /* increment position of max speed as we move the graph */ 655 | rx_maxspeedpos++; 656 | tx_maxspeedpos++; 657 | 658 | /* check if max speed has to be lowered for the graph as the max speed 659 | * was reached too long ago 660 | */ 661 | 662 | tmp_maxspeed = 0; 663 | tmp_maxspeedpos = 1; 664 | if (rx_maxspeedpos >= GRAPHSPLIT_WIDTH) { 665 | /* max speed calculation has to be redone */ 666 | for (i = 0; i < GRAPHSPLIT_WIDTH; i++) { 667 | if (rx_speedarray[i] > tmp_maxspeed) { 668 | tmp_maxspeed = rx_speedarray[1]; 669 | tmp_maxspeedpos = i; 670 | } 671 | } 672 | /* set new values */ 673 | rx_maxspeed = tmp_maxspeed; 674 | rx_maxspeedpos = tmp_maxspeedpos; 675 | } 676 | 677 | tmp_maxspeed = 0; 678 | tmp_maxspeedpos = 1; 679 | if (tx_maxspeedpos >= GRAPHSPLIT_WIDTH) { 680 | /* max speed calculation has to be redone */ 681 | for (i = 0; i < GRAPHSPLIT_WIDTH; i++) { 682 | if (tx_speedarray[i] > tmp_maxspeed) { 683 | tmp_maxspeed = tx_speedarray[1]; 684 | tmp_maxspeedpos = i; 685 | } 686 | } 687 | /* set new values */ 688 | tx_maxspeed = tmp_maxspeed; 689 | tx_maxspeedpos = tmp_maxspeedpos; 690 | } 691 | 692 | /* prepare the graph array 693 | * 694 | * shift the graph to the left and then add the last entry 695 | * in addition move the traffic stats left 696 | */ 697 | 698 | /* move */ 699 | for (x = GRAPHSPLIT_WIDTH - 1; x >= 0; x--) { 700 | rx_speedarray[x] = rx_speedarray[x - 1]; 701 | tx_speedarray[x] = tx_speedarray[x - 1]; 702 | for (y = 0; y < GRAPHSPLIT_HEIGHT; y++) { 703 | rx_graph[x][y] = rx_graph[x - 1][y]; 704 | tx_graph[x][y] = tx_graph[x - 1][y]; 705 | } 706 | } 707 | 708 | /* add the last column */ 709 | if (rx_maxspeed > 0) 710 | i = (int) ((rxspeed / rx_maxspeed) * GRAPHSPLIT_HEIGHT); 711 | for (y = 0; y <= GRAPHSPLIT_HEIGHT; y++) { 712 | if (i > y) 713 | rx_graph[0][y] = 1; 714 | else 715 | rx_graph[0][y] = 0; 716 | } 717 | if (0 != (int) rxspeed) 718 | rx_graph[0][1] = 1; 719 | rx_speedarray[0] = rxspeed; 720 | 721 | if (tx_maxspeed > 0) 722 | i = (int) ((txspeed / tx_maxspeed) * GRAPHSPLIT_HEIGHT); 723 | for (y = 0; y <= GRAPHSPLIT_HEIGHT; y++) { 724 | if (i > y) 725 | tx_graph[0][y] = 1; 726 | else 727 | tx_graph[0][y] = 0; 728 | } 729 | if (0 != (int) txspeed) 730 | tx_graph[0][1] = 1; 731 | tx_speedarray[0] = txspeed; 732 | 733 | /* 734 | * rescale graph 735 | * 736 | * in case the maxspeed for the shown graph changed we need to 737 | * recalculate the whole graph 738 | * 739 | */ 740 | 741 | if (rx_scalechanged) { 742 | /* for each line rewrite the graph */ 743 | for (x = GRAPHSPLIT_WIDTH - 1; x >= 0; x--) { 744 | i = (int) ((rx_speedarray[x] / rx_maxspeed) * 745 | GRAPHSPLIT_HEIGHT); 746 | for (y = 0; y <= GRAPHSPLIT_HEIGHT; y++) { 747 | if (i > y) 748 | rx_graph[x][y] = 1; 749 | else 750 | rx_graph[x][y] = 0; 751 | } 752 | if (rx_speedarray[x] != 0) 753 | rx_graph[x][1] = 1; 754 | } 755 | } 756 | if (tx_scalechanged) { 757 | /* for each line rewrite the graph */ 758 | for (x = GRAPHSPLIT_WIDTH - 1; x >= 0; x--) { 759 | i = (int) ((tx_speedarray[x] / tx_maxspeed) * 760 | GRAPHSPLIT_HEIGHT); 761 | for (y = 0; y <= GRAPHSPLIT_HEIGHT; y++) { 762 | if (i > y) 763 | tx_graph[x][y] = 1; 764 | else 765 | tx_graph[x][y] = 0; 766 | } 767 | if (tx_speedarray[x] != 0) 768 | tx_graph[x][1] = 1; 769 | } 770 | } 771 | 772 | 773 | /* 774 | * finally draw the two graphs line by line 775 | * 776 | * the rx graphs grows to the bottom 777 | */ 778 | 779 | for (y = GRAPHSPLIT_HEIGHT - 1; y > 0; y--) { 780 | for (x = 0; x <= GRAPHSPLIT_WIDTH; x++) { 781 | /* RX graph */ 782 | if (rx_graph[x][y] == 1) { 783 | attrset(COLOR_PAIR(PAIR_RX) | 784 | ((unsigned long) (t.rx_attrib == 785 | COL_BOLD) ? A_BOLD : A_NORMAL)); 786 | mvprintw(7 - y, x + 1, SYMBOL_TRAFFIC); 787 | } else 788 | mvprintw(7 - y, x + 1, SYMBOL_NOTRAFFIC); 789 | /* TX graph */ 790 | if (tx_graph[x][y] == 1) { 791 | attrset(COLOR_PAIR(PAIR_TX) | 792 | ((unsigned long) (t.tx_attrib == 793 | COL_BOLD) ? A_BOLD : A_NORMAL)); 794 | mvprintw(6 + y, x + 1, SYMBOL_TRAFFIC); 795 | } else 796 | mvprintw(6 + y, x + 1, SYMBOL_NOTRAFFIC); 797 | } 798 | } 799 | return 0; 800 | } 801 | 802 | /****************************************************************************** 803 | * 804 | * update_stat_combined() 805 | * 806 | * this is the classic view for the graph known from 0.0.3 807 | * 808 | *****************************************************************************/ 809 | int update_stat_combined(void) 810 | { 811 | float sumspeed; 812 | float rxspeed; 813 | float txspeed; 814 | int i = 0, x, y; 815 | int rx_scalechanged = 0; /* traffic scale changed? */ 816 | 817 | float tmp_maxspeed = 0; /* needed for max speed calc in graph */ 818 | int tmp_maxspeedpos = 1; /* same here */ 819 | 820 | char draw[DRAWLEN + 1]; /* what we draw on the screen */ 821 | 822 | /* in case of REINIT we want to keep the rx and tx values as we can 823 | * recalculate the graph for the new mode based on them. 824 | */ 825 | 826 | if (db_status == DB_STATUS_REINIT || db_status == DB_STATUS_STARTUP) { 827 | 828 | tx_maxspeed = 0; 829 | tx_overallmax = 0; 830 | rx_maxspeed = 0; 831 | rx_overallmax = 0; 832 | comb_maxspeed = 0; 833 | comb_overallmax = 0; 834 | /* fill the graph array with zeros */ 835 | for (x = 0; x < GRAPH_WIDTH; x++) { 836 | for (y = 0; y < GRAPH_HEIGHT; y++) { 837 | rx_graph[x][y] = 0; 838 | tx_graph[x][y] = 0; 839 | } 840 | } 841 | 842 | /* force graph recalculation */ 843 | rx_scalechanged++; 844 | 845 | if (db_status == DB_STATUS_STARTUP) { 846 | stats.rx_bytes_comp = stats.rx_bytes; 847 | stats.tx_bytes_comp = stats.tx_bytes; 848 | for (x = 0; x < GRAPH_WIDTH; x++) { 849 | rx_speedarray[x] = 0; 850 | tx_speedarray[x] = 0; 851 | } 852 | db_status = DB_STATUS_RUNNING; 853 | return 1; 854 | } 855 | db_status = DB_STATUS_RUNNING; 856 | } 857 | 858 | /* 859 | * current speed in bits/s 860 | * 861 | * in case of the expected u_long overflow in stats.?x_bytes 862 | * we will calculate a negative number as {sum|tx|rx}speed. 863 | * to prevent this we have to check if the _comp value is larger 864 | * than the current value. If true, we set _comp to 0 865 | */ 866 | 867 | if (stats.rx_bytes_comp > stats.rx_bytes) 868 | stats.rx_bytes_comp = 0; 869 | if (stats.tx_bytes_comp > stats.tx_bytes) 870 | stats.tx_bytes_comp = 0; 871 | 872 | sumspeed = ((stats.rx_bytes - stats.rx_bytes_comp) + 873 | (stats.tx_bytes - stats.tx_bytes_comp)) / refreshdelay; 874 | 875 | rxspeed = (stats.rx_bytes - stats.rx_bytes_comp) / refreshdelay; 876 | txspeed = (stats.tx_bytes - stats.tx_bytes_comp) / refreshdelay; 877 | 878 | /* print current speed */ 879 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", sumspeed / 1024); 880 | strncat(draw, " ", DRAWLEN - strlen(draw)); 881 | mvprintw(18, 24, "%s", draw); 882 | 883 | stats.rx_bytes_comp = stats.rx_bytes; 884 | stats.tx_bytes_comp = stats.tx_bytes; 885 | 886 | /* set new max speed for graph if reached */ 887 | if (sumspeed > comb_maxspeed) { 888 | comb_maxspeed = sumspeed; 889 | rx_maxspeedpos = 0; 890 | rx_scalechanged++; 891 | if (sumspeed > comb_overallmax) { 892 | comb_overallmax = sumspeed; 893 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", 894 | (float) sumspeed / 1024); 895 | strncat(draw, " ", DRAWLEN - strlen(draw)); 896 | mvprintw(19, 65, "%s", draw); 897 | } 898 | } 899 | 900 | /* 901 | * update the Graph Top Speed field 902 | * as it might be shorter than before just be sure to not leave 903 | * trailing garbage by printing spaces 904 | */ 905 | 906 | if (rx_scalechanged) { 907 | snprintf(draw, DRAWLEN - 1, "%.2f KB/s", comb_maxspeed / 1024); 908 | strncat(draw, " ", DRAWLEN - strlen(draw)); 909 | mvprintw(19, 24, "%s", draw); 910 | } 911 | 912 | /* increment position of max speed as we move the graph */ 913 | rx_maxspeedpos++; 914 | 915 | /* check if max speed has to be lowered for the graph as the max speed 916 | * was reached too long ago 917 | */ 918 | 919 | tmp_maxspeed = 0; 920 | tmp_maxspeedpos = 1; 921 | if (rx_maxspeedpos >= GRAPHCOMBINED_WIDTH) { 922 | /* max speed calculation has to be redone */ 923 | for (i = 0; i < GRAPHCOMBINED_WIDTH; i++) { 924 | if (rx_speedarray[i] > tmp_maxspeed) { 925 | tmp_maxspeed = rx_speedarray[1]; 926 | tmp_maxspeedpos = i; 927 | } 928 | } 929 | /* set new values */ 930 | comb_maxspeed = tmp_maxspeed; 931 | rx_maxspeedpos = tmp_maxspeedpos; 932 | } 933 | 934 | /* prepare the graph array 935 | * 936 | * shift the graph to the left and then add the last entry 937 | * in addition move the traffic stats left 938 | * 939 | * there seems to be some redundancy in here regarding the rx/tx values 940 | * but we need it for seamless mode switching 941 | * 942 | */ 943 | 944 | /* move */ 945 | for (x = GRAPHCOMBINED_WIDTH - 1; x >= 0; x--) { 946 | rx_speedarray[x] = rx_speedarray[x - 1]; 947 | tx_speedarray[x] = tx_speedarray[x - 1]; 948 | for (y = 0; y < GRAPHCOMBINED_HEIGHT; y++) { 949 | rx_graph[x][y] = rx_graph[x - 1][y]; 950 | tx_graph[x][y] = tx_graph[x - 1][y]; 951 | } 952 | } 953 | 954 | /* add the last column */ 955 | if (comb_maxspeed > 0) 956 | i = (int) ((sumspeed / comb_maxspeed) * GRAPHCOMBINED_HEIGHT); 957 | for (y = 0; y <= GRAPHCOMBINED_HEIGHT; y++) { 958 | if (i > y) 959 | rx_graph[0][y] = 1; 960 | else 961 | rx_graph[0][y] = 0; 962 | } 963 | if (0 != (int) sumspeed) 964 | rx_graph[0][1] = 1; 965 | 966 | rx_speedarray[0] = rxspeed; 967 | tx_speedarray[0] = txspeed; 968 | 969 | /* 970 | * rescale graph 971 | * 972 | * in case the maxspeed for the shown graph changed we need to 973 | * recalculate the whole graph 974 | * 975 | */ 976 | 977 | if (rx_scalechanged) { 978 | /* for each line rewrite the graph */ 979 | for (x = GRAPHCOMBINED_WIDTH - 1; x >= 0; x--) { 980 | i = (int) ((rx_speedarray[x] / comb_maxspeed) * 981 | GRAPHSPLIT_HEIGHT); 982 | for (y = 0; y <= GRAPHCOMBINED_HEIGHT; y++) { 983 | if (i > y) 984 | rx_graph[x][y] = 1; 985 | else 986 | rx_graph[x][y] = 0; 987 | } 988 | if (rx_speedarray[x] != 0) 989 | rx_graph[x][1] = 1; 990 | } 991 | } 992 | 993 | /* 994 | * finally draw the two graphs line by line 995 | * 996 | * the rx graphs grows to the bottom 997 | */ 998 | 999 | for (y = GRAPHCOMBINED_HEIGHT - 1; y > 0; y--) { 1000 | for (x = 0; x <= GRAPHCOMBINED_WIDTH; x++) { 1001 | /* RX graph */ 1002 | if (rx_graph[x][y] == 1) { 1003 | attrset(COLOR_PAIR(PAIR_RX) | 1004 | ((unsigned long) (t.rx_attrib == 1005 | COL_BOLD) ? A_BOLD : A_NORMAL)); 1006 | mvprintw(13 - y, x + 1, SYMBOL_TRAFFIC); 1007 | } else 1008 | mvprintw(13 - y, x + 1, SYMBOL_NOTRAFFIC); 1009 | } 1010 | } 1011 | return 0; 1012 | } 1013 | 1014 | /****************************************************************************** 1015 | * 1016 | * usage() 1017 | * 1018 | * print usage and die 1019 | * 1020 | *****************************************************************************/ 1021 | 1022 | void usage(int code, char **argv) 1023 | { 1024 | fprintf(stderr, "slurm %s - https://github.com/mattthias/slurm\n\n" 1025 | "usage: %s [-hHz] [-csl] [-d delay] [-t theme] -i interface\n\n", 1026 | PACKAGE_VERSION, argv[0]); 1027 | fprintf(stderr, " -h print help\n" 1028 | " -z zero counters at startup\n" 1029 | " -d delay delay between refreshs in seconds" 1030 | " (%d < delay < %d)\n" 1031 | " -c old classic/combined view\n" 1032 | " -s split window mode with stats\n" 1033 | " -l large split window mode\n" 1034 | " -L enable TX/RX 'leds'\n" 1035 | " -i interface select network interface\n" 1036 | " -t theme select a theme\n\n", 1037 | REFRESH_MIN, REFRESH_MAX); 1038 | _exit(code); 1039 | } 1040 | 1041 | /****************************************************************************** 1042 | * 1043 | * draw_face() 1044 | * 1045 | * draw the static parts of the screen 1046 | * 1047 | *****************************************************************************/ 1048 | 1049 | void draw_face(int displaymode, char *hostname) 1050 | { 1051 | int x, y; 1052 | 1053 | attrset(COLOR_PAIR(PAIR_TEXT) | 1054 | ((unsigned long) (t.text_attrib == 1055 | COL_BOLD) ? A_BOLD : A_NORMAL)); 1056 | for (x = 0; x <= 24; x++) { 1057 | for (y = 0; y <= 80; y++) { 1058 | mvprintw(x, y, " "); 1059 | } 1060 | } 1061 | refresh(); 1062 | if (displaymode != MODE_LARGE) { 1063 | mvprintw(20, 6, "Received Packets:"); 1064 | mvprintw(22, 3, "Errors on Receiving:"); 1065 | mvprintw(20, 44, "Transmitted Packets:"); 1066 | switch (data_type) { 1067 | case TYPE_MEGA: 1068 | mvprintw(21, 7, "MBytes Received:"); 1069 | mvprintw(21, 45, "MBytes Transmitted:"); 1070 | break; 1071 | case TYPE_GIGA: 1072 | mvprintw(21, 7, "GBytes Received:"); 1073 | mvprintw(21, 45, "GBytes Transmitted:"); 1074 | break; 1075 | } 1076 | } 1077 | 1078 | if (displaymode == MODE_SPLIT) { 1079 | mvprintw(22, 41, "Errors on Transmission:"); 1080 | #ifdef WITH_LED 1081 | if (ledenabled) { 1082 | mvprintw(14, 37, "RX"); 1083 | mvprintw(14, 41, "TX"); 1084 | } 1085 | #endif 1086 | mvprintw(17, 6, "Current RX Speed:"); 1087 | mvprintw(19, 2, "Overall Top RX Speed:"); 1088 | mvprintw(18, 4, "Graph Top RX Speed:"); 1089 | mvprintw(17, 47, "Current TX Speed:"); 1090 | mvprintw(19, 43, "Overall Top TX Speed:"); 1091 | mvprintw(18, 45, "Graph Top TX Speed:"); 1092 | mvprintw(15, 6, "Active Interface:"); 1093 | mvprintw(15, 48, "Interface Speed:"); 1094 | } else if (displaymode == MODE_COMBINED) { 1095 | mvprintw(22, 41, "Errors on Transmission:"); 1096 | #ifdef WITH_LED 1097 | if (ledenabled) { 1098 | mvprintw(14, 37, "RX"); 1099 | mvprintw(14, 41, "TX"); 1100 | } 1101 | #endif 1102 | 1103 | mvprintw(18, 9, "Current Speed:"); 1104 | mvprintw(19, 46, "Overall Top Speed:"); 1105 | mvprintw(19, 7, "Graph Top Speed:"); 1106 | mvprintw(16, 6, "Active Interface:"); 1107 | mvprintw(16, 48, "Interface Speed:"); 1108 | } else { 1109 | /* large split mode */ 1110 | mvprintw(21, 6, "Current RX Speed:"); 1111 | mvprintw(21, 47, "Current TX Speed:"); 1112 | mvprintw(22, 4, "Graph Top RX Speed:"); 1113 | mvprintw(22, 45, "Graph Top TX Speed:"); 1114 | 1115 | } 1116 | attrset(COLOR_PAIR(PAIR_TITLE) | 1117 | ((unsigned long) (t.title_attrib == 1118 | COL_BOLD) ? A_BOLD : A_NORMAL)); 1119 | if (hostname[0] != '\0') 1120 | center(00, "-= slurm %s on %s =-", VERSION, hostname); 1121 | else 1122 | center(00, "-= slurm %s =-", VERSION); 1123 | attrset(COLOR_PAIR(PAIR_VAR) | 1124 | ((unsigned long) (t.var_attrib == 1125 | COL_BOLD) ? A_BOLD : A_NORMAL)); 1126 | if (displaymode == MODE_SPLIT) { 1127 | mvprintw(15, 24, "%s", ifdata.if_name); 1128 | mvprintw(15, 65, "%s", (char *) ifdata.if_speedstring); 1129 | } else if (displaymode == MODE_COMBINED) { 1130 | mvprintw(16, 24, "%s", ifdata.if_name); 1131 | mvprintw(16, 65, "%s", (char *) ifdata.if_speedstring); 1132 | } 1133 | refresh(); 1134 | } 1135 | 1136 | /***************************************************************************** 1137 | * 1138 | * main() 1139 | * 1140 | * this is where the nightmare starts 1141 | * 1142 | ****************************************************************************/ 1143 | 1144 | int main(int argc, char *argv[]) 1145 | { 1146 | short int key_pressed; 1147 | long old[2]; 1148 | int sec_value = 0; 1149 | int validinterface = 0; 1150 | int displaymode = MODE_SPLIT; 1151 | int modechange = 0; 1152 | unsigned short int first = 1; 1153 | unsigned short int disconnected = 0; 1154 | char hostname[MAXHOSTNAMELEN + 1]; 1155 | extern long refreshdelay; 1156 | extern int ledenabled; 1157 | float tmpdelay; 1158 | int op; 1159 | int z_option = FALSE; 1160 | char *themep = NULL; 1161 | hostname[0] = '\0'; 1162 | 1163 | /* HP-UX related as of now but could become standard */ 1164 | ifdata.if_valid = 0; 1165 | ifdata.if_id = 0; 1166 | ifdata.if_amount = 0; 1167 | 1168 | ledenabled = 0; 1169 | 1170 | /* determine hostname */ 1171 | if (gethostname(hostname, MAXHOSTNAMELEN) != 0) 1172 | hostname[0] = '\0'; 1173 | 1174 | /* handle command line options */ 1175 | while ((op = getopt(argc, argv, "Lhzd:clsi:t:")) != EOF) { 1176 | switch (op) { 1177 | case 'i': 1178 | /* interface */ 1179 | snprintf((char *) ifdata.if_name, 1180 | (size_t) sizeof(ifdata.if_name), "%s", optarg); 1181 | /* check if interface really exists */ 1182 | #ifdef _HAVE_CHECKINTERFACE 1183 | validinterface = checkinterface(); 1184 | #else 1185 | /* just trust the user for now */ 1186 | validinterface++; 1187 | #endif 1188 | break; 1189 | case 'h': 1190 | /* print help and exit peacefully */ 1191 | usage(0, argv); 1192 | break; 1193 | case 'z': 1194 | /* virtually reset all counters by adding an offset */ 1195 | z_option = TRUE; 1196 | break; 1197 | case 'd': 1198 | /* delay between updates */ 1199 | tmpdelay = atof(optarg); 1200 | if ((tmpdelay < REFRESH_MIN) || (tmpdelay > REFRESH_MAX)) { 1201 | fprintf(stderr, 1202 | "delay has to be between %d and %d seconds!\n", 1203 | REFRESH_MIN, REFRESH_MAX); 1204 | return 1; 1205 | } else 1206 | refreshdelay = tmpdelay; 1207 | break; 1208 | case 'c': 1209 | /* use old classic/combined view */ 1210 | displaymode = MODE_COMBINED; 1211 | break; 1212 | case 'l': 1213 | /* use large split window mode */ 1214 | displaymode = MODE_LARGE; 1215 | break; 1216 | case 'L': 1217 | /* enable TX/RX led */ 1218 | ledenabled = 1; 1219 | break; 1220 | case 's': 1221 | /* use default split window mode */ 1222 | displaymode = MODE_SPLIT; 1223 | break; 1224 | case 't': 1225 | /* theme */ 1226 | themep = optarg; 1227 | break; 1228 | default: 1229 | usage(1, argv); 1230 | break; 1231 | } 1232 | } 1233 | 1234 | if (strlen(ifdata.if_name) == 0) { 1235 | #ifdef __linux__ 1236 | /* If no interface was given as option make an educated guess for a default interface */ 1237 | int rv = get_default_interface(&ifdata); 1238 | if (rv == 0) { 1239 | validinterface = checkinterface(); 1240 | } else { 1241 | fprintf(stderr, 1242 | "\nNo network interface given on command line and auto-detect failed.\n" 1243 | "Please specify a network interface using \"-i \".\n\n"); 1244 | usage(1, argv); 1245 | 1246 | } 1247 | #else 1248 | usage(1, argv); 1249 | #endif 1250 | } 1251 | 1252 | if (!validinterface) { 1253 | fprintf(stderr, "specified device does not exist or cannot " 1254 | "be monitored!\n\nIf you think this is an error please report " 1255 | "it to https://github.com/mattthias/slurm/issues . Thanks!\n"); 1256 | exit(1); 1257 | } 1258 | 1259 | /* Initialize some info variables */ 1260 | stats.tx_packets = 0; 1261 | stats.tx_bytes = 0; 1262 | stats.tx_errors = 0; 1263 | stats.rx_packets = 0; 1264 | stats.rx_bytes = 0; 1265 | stats.rx_errors = 0; 1266 | stats.tx_bytes_comp = 0; 1267 | stats.tx_bytes_comp = 0; 1268 | /* overruns */ 1269 | stats.rx_over = 0; 1270 | stats.tx_over = 0; 1271 | 1272 | /* 1273 | * run get_stat() once so watchif gets set and we get offsets in case 1274 | * -z cli option was given. 1275 | */ 1276 | get_stat(); 1277 | if (z_option == TRUE) 1278 | zero_stats(); 1279 | else { 1280 | /* set all counters to zero */ 1281 | stats.rx_packets_off = stats.rx_errors_off = 0; 1282 | stats.rx_over_off = stats.tx_packets_off = 0; 1283 | stats.tx_errors_off = stats.tx_over_off = 0; 1284 | stats.rx_bytes_off = stats.tx_bytes_off = 0; 1285 | stats.rx_bytes_comp_off = stats.tx_bytes_comp_off = 0; 1286 | } 1287 | 1288 | /* determine interface speed 1289 | * not all systems have this nice feature we display "unknown" 1290 | * if the speed could not determined due to errors or lack of 1291 | * this feature on the host operating system 1292 | */ 1293 | #if defined(_HAVE_BSD) || defined(__HPUX__) || defined(__Solaris__) || defined(__APPLE__) || defined(__linux__) 1294 | ifdata.if_speed = get_if_speed(ifdata.if_name); 1295 | 1296 | /* if ERR_IFACE_NO_SPEED we could not determine the interface speed 1297 | * if ERR_IFACE_DOWN the interface was down 1298 | * as we cannot monitor an interface which is down we exit quit 1299 | */ 1300 | if (ifdata.if_speed == ERR_IFACE_DOWN) { 1301 | fprintf(stderr, "interface '%s' is down\n", 1302 | (char *) ifdata.if_name); 1303 | return 1; 1304 | } 1305 | 1306 | /* ifdata.if_speed is in kbit/s */ 1307 | if (ifdata.if_speed >= 1000) 1308 | snprintf((char *) ifdata.if_speedstring, 1309 | sizeof(ifdata.if_speedstring), "%d Mbit/s", 1310 | (int) ifdata.if_speed / 1000); 1311 | else if ((ifdata.if_speed == 0) 1312 | || (ifdata.if_speed == ERR_IFACE_NO_SPEED)) 1313 | snprintf((char *) ifdata.if_speedstring, 1314 | sizeof(ifdata.if_speedstring), "unknown"); 1315 | else 1316 | snprintf((char *) ifdata.if_speedstring, 1317 | sizeof(ifdata.if_speedstring), "%d kbit/s", 1318 | (int) ifdata.if_speed / 100); 1319 | #else 1320 | snprintf((char *) ifdata.if_speedstring, 1321 | sizeof(ifdata.if_speedstring), "unknown"); 1322 | #endif 1323 | 1324 | #if MEDIADEBUG 1325 | return 0; 1326 | #endif 1327 | 1328 | #ifndef NO_CURSES_E 1329 | printf("\e(U"); 1330 | #endif 1331 | 1332 | 1333 | if (themep == NULL) 1334 | theme_setdefault(&t); 1335 | else 1336 | theme_readfile(&t, themep); 1337 | 1338 | if (t.complete != E_ALL) 1339 | error(ERR_FATAL, "broken theme"); 1340 | 1341 | initscr(); 1342 | intrflush(stdscr, FALSE); 1343 | start_color(); 1344 | curs_set(0); /* Toggle the cursor off */ 1345 | nonl(); 1346 | noecho(); 1347 | cbreak(); 1348 | nodelay(stdscr, TRUE); 1349 | 1350 | #ifdef _HAVE_NCURSES 1351 | if (use_default_colors() == OK) /* need ncurses for transparency */ 1352 | t.background = -1; 1353 | #endif 1354 | 1355 | init_pair(PAIR_TEXT, t.text, t.background); 1356 | init_pair(PAIR_RX, t.rx, t.background); 1357 | init_pair(PAIR_TX, t.tx, t.background); 1358 | init_pair(PAIR_VAR, t.var, t.background); 1359 | init_pair(PAIR_TITLE, t.title, t.background); 1360 | attrset(COLOR_PAIR(PAIR_TEXT) | 1361 | ((unsigned long) (t.text_attrib == 1362 | COL_BOLD) ? A_BOLD : A_NORMAL)); 1363 | 1364 | /* curses is set up so make sure to shut it down correctly when 1365 | * receiving termination signals by calling slurm_shutdown() 1366 | */ 1367 | 1368 | signal(SIGHUP, slurm_shutdown); 1369 | signal(SIGINT, slurm_shutdown); 1370 | signal(SIGQUIT, slurm_shutdown); 1371 | signal(SIGKILL, slurm_shutdown); 1372 | signal(SIGTERM, slurm_shutdown); 1373 | 1374 | draw_face(displaymode, hostname); 1375 | update_info(displaymode); 1376 | old[0] = old[1] = time(NULL) - 3; 1377 | 1378 | for (;;) { 1379 | get_stat(); 1380 | #ifdef WITH_LED 1381 | if (ledenabled) { 1382 | if (displaymode != MODE_LARGE) { 1383 | /* In case of a new RX Packet... the RX Led Turn on 1384 | * Else... Turn off */ 1385 | if (stats.rx_packets != stats.rx_packets_led) 1386 | led_on(LED_RX); 1387 | else 1388 | led_off(LED_RX); 1389 | /* In case of a new TX Packet... the TX Led Turn on 1390 | * Else... Turn off */ 1391 | if (stats.tx_packets != stats.tx_packets_led) 1392 | led_on(LED_TX); 1393 | else 1394 | led_off(LED_TX); 1395 | } 1396 | } /* end ledenabled */ 1397 | #endif 1398 | 1399 | stats.rx_packets_led = stats.rx_packets; 1400 | stats.tx_packets_led = stats.tx_packets; 1401 | 1402 | get_time(); 1403 | /* check if we have to switch to Gbytes mode */ 1404 | if (data_type != TYPE_GIGA && 1405 | ((stats.tx_bytes > 1073735680) || 1406 | (stats.rx_bytes > 1073735680))) { 1407 | data_type = TYPE_GIGA; 1408 | draw_face(displaymode, hostname); 1409 | } 1410 | 1411 | update_info(displaymode); 1412 | 1413 | if ((!sec_value && first) || disconnected) { 1414 | sec_value = stats.online_sec; 1415 | update_stat(displaymode); 1416 | first = 0; 1417 | disconnected = 0; 1418 | } 1419 | 1420 | 1421 | if (stats.online_sec != sec_value) { 1422 | update_stat(displaymode); 1423 | sec_value = stats.online_sec; 1424 | } 1425 | 1426 | /* move cursor to upper left corner */ 1427 | move(0, 0); 1428 | 1429 | tmpdelay = refreshdelay * 10; 1430 | do { 1431 | usleep(100 * 1000); /* 10th of a second */ 1432 | tmpdelay--; 1433 | key_pressed = getch(); 1434 | if (key_pressed != ERR) 1435 | break; 1436 | } while (tmpdelay > 0); 1437 | 1438 | if (key_pressed != ERR && tolower(key_pressed) == 'q') 1439 | break; 1440 | else if (key_pressed != ERR && tolower(key_pressed) == 'c') { 1441 | displaymode = MODE_COMBINED; 1442 | modechange++; 1443 | } else if (key_pressed != ERR && tolower(key_pressed) == 'l') { 1444 | displaymode = MODE_LARGE; 1445 | modechange++; 1446 | } else if (key_pressed != ERR && tolower(key_pressed) == 's') { 1447 | displaymode = MODE_SPLIT; 1448 | modechange++; 1449 | } else if (key_pressed != ERR && tolower(key_pressed) == 'm') { 1450 | if (displaymode == MODE_COMBINED) 1451 | displaymode = MODE_SPLIT; 1452 | else if (displaymode == MODE_SPLIT) 1453 | displaymode = MODE_LARGE; 1454 | else 1455 | displaymode = MODE_COMBINED; 1456 | 1457 | modechange++; 1458 | } else if (key_pressed != ERR && tolower(key_pressed) == 'r') { 1459 | draw_face(displaymode, hostname); 1460 | update_stat(displaymode); 1461 | } else if (key_pressed != ERR && tolower(key_pressed) == 'z') { 1462 | zero_stats(); 1463 | update_stat(displaymode); 1464 | } 1465 | 1466 | /* if the display mode change we need to redraw the face and 1467 | * reinitialize the graph arrays 1468 | * draw_face() clears the screen 1469 | */ 1470 | 1471 | if (modechange) { 1472 | db_status = DB_STATUS_REINIT; 1473 | modechange = 0; 1474 | draw_face(displaymode, hostname); 1475 | } 1476 | } 1477 | slurm_shutdown(1); /* needs a bogus parameter :) */ 1478 | return 0; 1479 | } 1480 | 1481 | /****************************************************************************** 1482 | * 1483 | * update_stat() 1484 | * 1485 | * graph update dispatcher, just calls the right function 1486 | * 1487 | *****************************************************************************/ 1488 | int update_stat(int displaymode) 1489 | { 1490 | switch (displaymode) { 1491 | case MODE_COMBINED: 1492 | return update_stat_combined(); 1493 | break; 1494 | case MODE_SPLIT: 1495 | return update_stat_split(); 1496 | break; 1497 | case MODE_LARGE: 1498 | return update_stat_large(); 1499 | break; 1500 | default: 1501 | return 1; 1502 | } 1503 | } 1504 | 1505 | /****************************************************************************** 1506 | * 1507 | * zero_stats() 1508 | * 1509 | * redefine the offsets for all counters so we can virtually reset 1510 | * the counters on the display 1511 | * 1512 | *****************************************************************************/ 1513 | 1514 | void zero_stats(void) 1515 | { 1516 | stats.rx_packets_off = stats.rx_packets; 1517 | stats.rx_errors_off = stats.rx_errors; 1518 | stats.rx_over_off = stats.rx_over; 1519 | stats.tx_packets_off = stats.tx_packets; 1520 | stats.tx_errors_off = stats.tx_errors; 1521 | stats.tx_over_off = stats.tx_over; 1522 | stats.rx_bytes_off = stats.rx_bytes; 1523 | stats.tx_bytes_off = stats.tx_bytes; 1524 | stats.rx_bytes_comp_off = stats.rx_bytes_comp; 1525 | stats.tx_bytes_comp_off = stats.tx_bytes_comp; 1526 | } 1527 | 1528 | /****************************************************************************** 1529 | * 1530 | * slurm_shutdown() 1531 | * 1532 | * shutdown curses so we get a clean terminal. 1533 | * 1534 | *****************************************************************************/ 1535 | 1536 | void slurm_shutdown(int sig) 1537 | { 1538 | endwin(); 1539 | system("clear"); 1540 | curs_set(1); 1541 | fprintf(stdout, "slurm %s - " 1542 | "http://www.github.com/mattthias/slurm/\n", VERSION); 1543 | 1544 | /* close dev if running Linux */ 1545 | #ifdef __linux__ 1546 | fclose(proc_net_dev); 1547 | #endif 1548 | exit(0); 1549 | } 1550 | -------------------------------------------------------------------------------- /slurm.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * slurm config file, heavily based on the pppstatus version 4 | * see README file or slurm.c for more information 5 | * 6 | * $Id: slurm.h,v 1.42 2004/02/13 05:41:30 hscholz Exp $ 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 21 | * USA. 22 | * 23 | ***************************************************************************/ 24 | 25 | #define LED_RX 1 26 | #define LED_TX 2 27 | 28 | #ifndef TRUE 29 | #define TRUE 1 30 | #endif 31 | #ifndef FALSE 32 | #define FALSE 0 33 | #endif 34 | 35 | #define SYMBOL_TRAFFIC "x" 36 | #define SYMBOL_NOTRAFFIC " " 37 | 38 | #ifdef __linux__ 39 | #define PATH_NET_DEV "/proc/net/dev" 40 | #endif 41 | 42 | #define MODE_COMBINED 1 43 | #define MODE_SPLIT 2 44 | #define MODE_LARGE 3 45 | 46 | /* slap HPUX with a large trout 47 | * HPUX 10.xx cannot handle 2^32 int constants, so we have to "tweak" it 48 | */ 49 | 50 | #ifdef __HPUX__ 51 | #define SNMPMAXBYTES (4294967295 + 1) 52 | #else 53 | #define SNMPMAXBYTES (4294967296ULL) 54 | #endif 55 | 56 | #undef MAXHOSTNAMELEN 57 | #define MAXHOSTNAMELEN 64 58 | 59 | #define DRAWLEN 16 60 | 61 | /* 10th of a second */ 62 | #define REFRESH_DEFAULT 1 63 | #define REFRESH_MIN 1 64 | #define REFRESH_MAX 300 65 | 66 | #ifndef BUFSIZ 67 | #define BUFSIZ 1024 68 | #warning "setting buf size to 1024" 69 | #endif 70 | 71 | typedef struct statvline { 72 | int hline[76]; /* This will be the horzontal lines */ 73 | } statvline[10]; /* ... and this will be vertical lines */ 74 | statvline graph; 75 | 76 | /* This structure stays the INFO variables */ 77 | typedef struct DataStats { 78 | unsigned long rx_packets; 79 | unsigned long rx_errors; 80 | int rx_over; 81 | unsigned long tx_packets; 82 | unsigned long tx_errors; 83 | int tx_over; 84 | double rx_bytes; 85 | double tx_bytes; 86 | double rx_bytes_comp; 87 | double tx_bytes_comp; 88 | double rx_packets_led; 89 | double tx_packets_led; 90 | unsigned long connect_time; 91 | unsigned long current_time; 92 | float top_speed; 93 | int online_days; 94 | int online_hour; 95 | int online_min; 96 | int online_sec; 97 | unsigned long rx_packets_off; 98 | unsigned long rx_errors_off; 99 | int rx_over_off; 100 | unsigned long tx_packets_off; 101 | unsigned long tx_errors_off; 102 | int tx_over_off; 103 | double rx_bytes_off; 104 | double tx_bytes_off; 105 | double rx_bytes_comp_off; 106 | double tx_bytes_comp_off; 107 | } DataStats; 108 | DataStats stats; 109 | 110 | typedef struct IfData{ 111 | char if_name[16]; /* The device name given as start parameter*/ 112 | int if_speed; /* The Interface speed */ 113 | char if_speedstring[12]; /* the measuring unit like Mbit, kbit */ 114 | int if_id; /* The ID which the interface inside the OS has */ 115 | int if_amount; /* The amount of all interfaces available */ 116 | int if_valid; /* 1 = selected interface exists 117 | * 0 = interfaces does not exists */ 118 | } IfData; 119 | 120 | IfData ifdata; 121 | 122 | /* Prototypes */ 123 | void center(short int line, char *strg, ...); 124 | void chcolor(int x, int y); 125 | int update_stat_combined(void); 126 | int update_stat_split(void); 127 | int update_stat_large(void); 128 | int update_stat(int); 129 | void update_info(int); 130 | void led_on(unsigned int who); 131 | void led_off(unsigned int who); 132 | int is_online(void); 133 | int get_stat(void); 134 | void clear_info(void); 135 | void ip_address(int display); 136 | void get_time (void); 137 | void do_exit (int, char *, short int); 138 | void usage (int, char **); 139 | void draw_face (int, char *); 140 | void zero_stats (void); 141 | void slurm_shutdown (int); 142 | 143 | /* Variables Declarations */ 144 | #define TYPE_MEGA 0 145 | #define TYPE_GIGA 1 146 | int data_type = TYPE_MEGA; 147 | long refreshdelay = REFRESH_DEFAULT; 148 | 149 | /* internal database status */ 150 | /* possible modes are: */ 151 | #define DB_STATUS_STARTUP 1 152 | #define DB_STATUS_RUNNING 2 153 | #define DB_STATUS_REINIT 3 154 | int db_status = DB_STATUS_STARTUP; 155 | 156 | #ifdef __linux 157 | static FILE *proc_net_dev; 158 | #endif 159 | /* End of Variables Declarations */ 160 | 161 | /* max speed in graph */ 162 | #define GRAPHSINGLE_WIDTH 77 163 | #define GRAPHSINGLE_HEIGHT 10 164 | 165 | /* define graph height for split screen graphs */ 166 | #define GRAPHSPLIT_HEIGHT 6 167 | #define GRAPHSPLIT_WIDTH 77 168 | 169 | #define GRAPHCOMBINED_WIDTH 77 170 | #define GRAPHCOMBINED_HEIGHT 12 171 | 172 | /* new max height */ 173 | #define GRAPH_HEIGHT 12 174 | #define GRAPH_WIDTH 77 175 | 176 | /* large split mode graph height */ 177 | #define GRAPHLARGE_HEIGHT 11 178 | 179 | /* rx is higher than need as we use it for the combined view */ 180 | int rx_graph[GRAPHSPLIT_WIDTH][GRAPHCOMBINED_HEIGHT]; 181 | float rx_speedarray[GRAPHSPLIT_WIDTH]; 182 | static float rx_maxspeed; 183 | static int rx_maxspeedpos; 184 | int rx_overallmax; 185 | 186 | int tx_graph[GRAPHSPLIT_WIDTH][GRAPHCOMBINED_HEIGHT]; 187 | float tx_speedarray[GRAPHSPLIT_WIDTH]; 188 | static float tx_maxspeed; 189 | static int tx_maxspeedpos; 190 | int tx_overallmax; 191 | 192 | /* combined view */ 193 | static float comb_maxspeed; 194 | int comb_overallmax; 195 | int solcount; 196 | 197 | int ledenabled; /* TX/RX led enabled */ 198 | -------------------------------------------------------------------------------- /slurm.spec: -------------------------------------------------------------------------------- 1 | %define name slurm 2 | %define version 0.2.3 3 | %define release 1 4 | 5 | Summary: A realtime network traffic statistic tool 6 | Name: %{name} 7 | Version: %{version} 8 | Release: %{release} 9 | Source0: %{name}-%{version}.tar.gz 10 | License: GPL 11 | Group: Applications/Multimedia 12 | BuildRoot: %{_tmppath}/%{name}-buildroot 13 | Requires: ncurses 14 | BuildRequires: ncurses-devel 15 | Packager: Ralf Ertzinger 16 | URL: http://www.wormulon.net/projects/slurm 17 | 18 | %description 19 | slurm started as a pppstatus port to FreeBSD. Features: 20 | 21 | * realtime traffic statistics divided into incoming and outgoing 22 | * optional combined view 23 | * can monitor any kind of network interface (testers welcome!) 24 | * shows detailed statistics about the interface. 25 | * contact me if you need anything else. 26 | 27 | %prep 28 | %setup 29 | 30 | %build 31 | %configure 32 | %{__make} 33 | 34 | %install 35 | [ $RPM_BUILD_ROOT != "/" ] && rm -rf $RPM_BUILD_ROOT 36 | %{__mkdir} -p $RPM_BUILD_ROOT 37 | 38 | %{__install} -d %{buildroot}/%{_bindir} 39 | %{__install} -d %{buildroot}/%{_mandir}/man1 40 | %{__install} slurm %{buildroot}/%{_bindir} 41 | %{__install} slurm.1 %{buildroot}/%{_mandir}/man1 42 | 43 | %clean 44 | [ $RPM_BUILD_ROOT != "/" ] && rm -rf $RPM_BUILD_ROOT 45 | 46 | %files 47 | %defattr(-,root,root) 48 | %doc Changelog README KEYS TODO THANKS COPYRIGHT 49 | %{_bindir}/slurm 50 | %{_mandir}/man1/slurm.1.gz 51 | 52 | %changelog 53 | * Thu May 15 2003 Ralf Ertzinger 54 | - Initial RPM build 55 | 56 | # end of file 57 | -------------------------------------------------------------------------------- /src/freebsd.c: -------------------------------------------------------------------------------- 1 | /* $Id: freebsd.c,v 1.8 2003/02/23 17:26:02 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists and is up. 8 | * return TRUE if it does and FALSE if not 9 | * 10 | ****************************************************************************/ 11 | 12 | int checkinterface(void) 13 | { 14 | int validinterface = FALSE; 15 | 16 | int i, num_iface; 17 | size_t len; 18 | int name[6]; 19 | struct ifmibdata ifmd; 20 | 21 | len = sizeof(num_iface); 22 | sysctlbyname("net.link.generic.system.ifcount", &num_iface, &len, NULL, 23 | 0); 24 | for (i = 1; i <= num_iface; i++) { 25 | name[0] = CTL_NET; 26 | name[1] = PF_LINK; 27 | name[2] = NETLINK_GENERIC; 28 | name[3] = IFMIB_IFDATA; 29 | name[4] = i; 30 | name[5] = IFDATA_GENERAL; 31 | 32 | len = sizeof(ifmd); 33 | sysctl(name, 6, &ifmd, &len, NULL, 0); 34 | if (strcmp(ifmd.ifmd_name, (char *) ifdata.if_name) == 0) { 35 | /* 36 | * now we have an interface and just have to see if it's up 37 | * in case we just want to debug media types we disable 38 | * IFF_UP flags 39 | */ 40 | #ifndef MEDIADEBUG 41 | if (ifmd.ifmd_flags & IFF_UP) 42 | #endif 43 | validinterface = TRUE; 44 | break; /* in any case we can stop searching here */ 45 | } 46 | } 47 | return validinterface; 48 | } 49 | 50 | /****************************************************************************** 51 | * 52 | * get_stat() 53 | * 54 | * use sysctl() to read the statistics and fill statistics struct 55 | * 56 | ****************************************************************************/ 57 | 58 | int get_stat(void) 59 | { 60 | /* 61 | * use sysctl() to get the right interface number if !dev_opened 62 | * then read the data directly from the ifmd_data struct 63 | */ 64 | 65 | static int watchif = -1; 66 | int i, num_iface; 67 | size_t len; 68 | int name[6]; 69 | struct ifmibdata ifmd; 70 | static int dev_opened = 0; 71 | unsigned long rx_o, tx_o; 72 | 73 | if (!dev_opened) { 74 | len = sizeof(num_iface); 75 | sysctlbyname("net.link.generic.system.ifcount", &num_iface, &len, 76 | NULL, 0); 77 | for (i = 1; i <= num_iface; i++) { 78 | name[0] = CTL_NET; 79 | name[1] = PF_LINK; 80 | name[2] = NETLINK_GENERIC; 81 | name[3] = IFMIB_IFDATA; 82 | name[4] = i; 83 | name[5] = IFDATA_GENERAL; 84 | 85 | len = sizeof(ifmd); 86 | sysctl(name, 6, &ifmd, &len, NULL, 0); 87 | if (strcmp(ifmd.ifmd_name, (char *) ifdata.if_name) == 0) { 88 | /* got the right interface */ 89 | watchif = i; 90 | dev_opened++; 91 | } 92 | } 93 | } 94 | /* in any case read the struct and record statistics */ 95 | name[0] = CTL_NET; 96 | name[1] = PF_LINK; 97 | name[2] = NETLINK_GENERIC; 98 | name[3] = IFMIB_IFDATA; 99 | name[4] = watchif; 100 | name[5] = IFDATA_GENERAL; 101 | 102 | len = sizeof(ifmd); 103 | sysctl(name, 6, &ifmd, &len, NULL, 0); 104 | 105 | rx_o = stats.rx_bytes; 106 | tx_o = stats.tx_bytes; 107 | 108 | stats.tx_packets = ifmd.ifmd_data.ifi_opackets; 109 | stats.rx_packets = ifmd.ifmd_data.ifi_ipackets; 110 | stats.rx_bytes = ifmd.ifmd_data.ifi_ibytes; 111 | stats.tx_bytes = ifmd.ifmd_data.ifi_obytes; 112 | stats.rx_errors = ifmd.ifmd_data.ifi_ierrors; 113 | stats.tx_errors = ifmd.ifmd_data.ifi_oerrors; 114 | 115 | if (rx_o > stats.rx_bytes) 116 | stats.rx_over++; 117 | if (tx_o > stats.tx_bytes) 118 | stats.tx_over++; 119 | 120 | return (0); 121 | } 122 | -------------------------------------------------------------------------------- /src/freebsd.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | int checkinterface(void); 3 | -------------------------------------------------------------------------------- /src/hpux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define WAIT_PCKS_COUNTER 15 3 | 4 | /* $Id: hpux.c,v 1.7 2003/02/23 17:26:02 hscholz Exp $ */ 5 | 6 | /***************************************************************************** 7 | * 8 | * _countinterfaces() 9 | * 10 | * count all network interfaces in the system. This function is intended to 11 | * use it only in hpux.c 12 | * 13 | ****************************************************************************/ 14 | 15 | int _countinterfaces(void) 16 | { 17 | int val, num_iface = -1, sd; 18 | if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 19 | return (-1); 20 | 21 | if (ioctl(sd, SIOCGIFNUM, &val) != -1) 22 | num_iface = val; 23 | close(sd); 24 | 25 | return num_iface; 26 | } 27 | 28 | /***************************************************************************** 29 | * 30 | * _getifdata() 31 | * 32 | * get the Interface-ID, the Interface-Speed, and over all, check if the 33 | * given interface really exists. This function is intended to use it only in 34 | * hpux.c 35 | * 36 | ****************************************************************************/ 37 | 38 | void _getifdata() 39 | { 40 | int buffer, fd, val, ret = -1; 41 | unsigned int len, i; 42 | char tmpinterfacestring[sizeof(ifdata.if_name) + 1], *strstrmatch; 43 | struct nmparms params; 44 | mib_ifEntry *if_buf; 45 | 46 | 47 | /* 48 | * The interface description is more then the pure devicename. 49 | * Let's do some formating to allow a propper pattern matching 50 | */ 51 | strcpy(tmpinterfacestring, ifdata.if_name); 52 | strcat(tmpinterfacestring, " "); 53 | 54 | for (i = 0; i <= ifdata.if_amount; i++) { 55 | if ((fd = open_mib("/dev/lan", O_RDWR, i, 0)) >= 0) { 56 | if ((if_buf = 57 | (mib_ifEntry *) malloc(sizeof(mib_ifEntry))) != 0) { 58 | params.objid = ID_ifEntry; 59 | params.buffer = if_buf; 60 | len = sizeof(mib_ifEntry); 61 | params.len = &len; 62 | if_buf->ifIndex = i + 1; 63 | if ((ret = get_mib_info(fd, ¶ms)) == 0) { 64 | /* 65 | * The interface given by the user must start at the 66 | * beginning of if_buf->ifDescr. If that's the case, 67 | * strstrmatch is equal to if_buf->ifDescr. If not, 68 | * strstrmatch might be a subset of if_buf->ifDescr, 69 | * or NULL 70 | */ 71 | strstrmatch = 72 | strstr(if_buf->ifDescr, 73 | (char *) tmpinterfacestring); 74 | if (strstrmatch 75 | && (strcmp(strstrmatch, if_buf->ifDescr) == 0)) { 76 | ifdata.if_valid = 1; 77 | ifdata.if_id = i + 1; 78 | break; 79 | } 80 | } 81 | } 82 | } 83 | free(if_buf); 84 | close_mib(fd); 85 | } 86 | return; 87 | } 88 | 89 | /***************************************************************************** 90 | * 91 | * checkinterface() 92 | * 93 | * check if a given interface exists, return 1 if it does and 0 if not (This 94 | * function is a wrapper function for _countinterfaces && _getifdata.) 95 | * 96 | ****************************************************************************/ 97 | int checkinterface(void) 98 | { 99 | /* == 0 no network interfaces, -1 sth. went wrong */ 100 | if ((ifdata.if_amount = _countinterfaces()) > 0) 101 | _getifdata(); 102 | return ifdata.if_valid; 103 | } 104 | 105 | /****************************************************************************** 106 | * 107 | * get_stat() 108 | * 109 | * stub function for all unsupported operating systems 110 | * 111 | *****************************************************************************/ 112 | 113 | int get_stat(void) 114 | { 115 | int i, fd, ret = -1; 116 | static int wait_pcks_counter = WAIT_PCKS_COUNTER + 1; 117 | unsigned int len; 118 | unsigned long rx_o, tx_o; 119 | struct nmparms params, params2; 120 | mib_ifEntry *if_buf; 121 | 122 | static nmapi_logstat *if_ptr = (nmapi_logstat *) 0; 123 | if (ifdata.if_valid == 1 124 | && (fd = open_mib("/dev/lan", O_RDWR, 0, 0)) >= 0) { 125 | if ((if_buf = (mib_ifEntry *) malloc(sizeof(mib_ifEntry))) != 0) { 126 | if_buf->ifIndex = ifdata.if_id; 127 | params.objid = ID_ifEntry; 128 | params.buffer = if_buf; 129 | len = (unsigned int) sizeof(mib_ifEntry); 130 | params.len = &len; 131 | if ((ret = get_mib_info(fd, ¶ms)) == 0) { 132 | rx_o = stats.rx_bytes; 133 | tx_o = stats.tx_bytes; 134 | 135 | stats.tx_bytes = if_buf->ifOutOctets; 136 | stats.rx_bytes = if_buf->ifInOctets; 137 | stats.tx_errors = if_buf->ifOutErrors; 138 | stats.rx_errors = if_buf->ifInErrors; 139 | 140 | if (rx_o > stats.rx_bytes) 141 | stats.rx_over++; 142 | if (tx_o > stats.tx_bytes) 143 | stats.tx_over++; 144 | } 145 | } 146 | free(if_buf); 147 | 148 | /* 149 | * Getting the tx/rx packets every run often hurts to much performance 150 | * With WAIT_PCKS_COUNTER=15 i save on my system 43% cpu usage.instead of 151 | * WAIT_PCKS_COUNTER=0 152 | */ 153 | if (wait_pcks_counter > WAIT_PCKS_COUNTER) { 154 | if ((if_ptr = 155 | (nmapi_logstat *) malloc(sizeof(nmapi_logstat) * 156 | ifdata.if_amount)) != 0) { 157 | len = 158 | (unsigned int) ifdata.if_amount * 159 | sizeof(nmapi_logstat); 160 | if ((ret = get_logical_stat(if_ptr, &len)) == 0) { 161 | for (i = 0; i <= ifdata.if_amount; i++) { 162 | if (if_ptr[i].ifindex == ifdata.if_id) { 163 | stats.tx_packets = if_ptr[i].out_packets; 164 | stats.rx_packets = if_ptr[i].in_packets; 165 | } 166 | } 167 | } 168 | } 169 | free(if_ptr); 170 | wait_pcks_counter = 0; 171 | } else { 172 | wait_pcks_counter++; 173 | } 174 | } 175 | close_mib(fd); 176 | 177 | return (0); 178 | } 179 | -------------------------------------------------------------------------------- /src/hpux.h: -------------------------------------------------------------------------------- 1 | #ifndef _HPUX_H_ 2 | #define _HPUX_H_ 3 | extern int checkinterface(void); 4 | extern int get_stat(void); 5 | #endif 6 | -------------------------------------------------------------------------------- /src/if_media.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * src/if_media.h - part of slurm 4 | * 5 | * this file handles basic network information functions for all 6 | * operating systems. 7 | * 8 | ***************************************************************************** 9 | * $Id: if_media.c,v 1.35 2004/09/27 13:08:59 hscholz Exp $ 10 | *****************************************************************************/ 11 | 12 | #if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) || defined (__MicroBSD__) || defined (__APPLE__) 13 | #define MEDIA_H_SUPPORTED 14 | #endif 15 | 16 | #if defined (__OpenBSD__) || defined (__NetBSD__) || defined (__MicroBSD__) || defined (__APPLE__) 17 | #define NON_FreeBSD 1 18 | #define WIRELESS 1 19 | #else 20 | #if defined(__FreeBSD__) 21 | #if (__FreeBSD_version >= 450000) 22 | #define WIRELESS 1 23 | #endif 24 | #else 25 | #define WIRELESS 0 26 | #endif 27 | #endif 28 | 29 | #if defined(__linux__) 30 | #include 31 | #include 32 | #endif 33 | 34 | 35 | /****************************************************************************** 36 | * 37 | * get_if_speed() 38 | * 39 | * determine current interface speed, needs interface name as argument 40 | * return the interface speed as an integer. unit: kbit/s 41 | * in case of error return ERR_IFACE_NO_SPEED 42 | * 43 | * tested/supported operating systems: 44 | * 45 | * - FreeBSD 46 | * - OpenBSD 47 | * - NetBSD 48 | * - MicroBSD (99% OpenBSD) 49 | * 50 | *****************************************************************************/ 51 | 52 | #ifdef MEDIA_H_SUPPORTED 53 | int get_if_speed(char *ifstring) 54 | { 55 | int speed = ERR_IFACE_NO_SPEED; 56 | int s; /* socket */ 57 | struct ifmediareq ifmr; 58 | 59 | #if defined (__OpenBSD__) 60 | uint64_t *media_list; 61 | #else 62 | int *media_list; 63 | #endif 64 | 65 | int type, physical; 66 | 67 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 68 | fprintf(stderr, "cannot create socket!\n"); 69 | return ERR_IFACE_NO_SPEED; 70 | } 71 | 72 | memset(&ifmr, 0, sizeof(ifmr)); 73 | strncpy(ifmr.ifm_name, (char *) ifstring, sizeof(ifmr.ifm_name)); 74 | 75 | if (ioctl(s, SIOCGIFMEDIA, (caddr_t) & ifmr) < 0) { 76 | fprintf(stderr, 77 | "interface does not support SIOCGIFMEDIA ioctl()\n"); 78 | return ERR_IFACE_NO_SPEED; 79 | } 80 | 81 | if (ifmr.ifm_count == 0) { 82 | fprintf(stderr, "%s: no media types?\n", (char *) ifstring); 83 | return ERR_IFACE_NO_SPEED; 84 | } 85 | 86 | #if defined (__OpenBSD__) 87 | media_list = (uint64_t *) malloc(ifmr.ifm_count * sizeof(uint64_t)); 88 | #else 89 | media_list = (int *) malloc(ifmr.ifm_count * sizeof(int)); 90 | #endif 91 | 92 | if (media_list == NULL) 93 | fprintf(stderr, "malloc() error in if_media.c\n"); 94 | ifmr.ifm_ulist = media_list; 95 | 96 | if (ioctl(s, SIOCGIFMEDIA, (caddr_t) & ifmr) < 0) { 97 | fprintf(stderr, "ioctl(SIOCGIFMEDIA) failed\n"); 98 | return -1; 99 | } 100 | 101 | /* 102 | * define type and physical 103 | * 104 | * bits: 105 | * 0-4 Media variant 106 | * 5-7 Media type 107 | * 108 | */ 109 | 110 | #ifdef IFM_TYPE 111 | type = IFM_TYPE(ifmr.ifm_active); 112 | #else 113 | type = ifmr.ifm_active & 0xf0; 114 | #endif 115 | #ifdef IFM_TYPE 116 | physical = IFM_SUBTYPE(ifmr.ifm_active); 117 | #else 118 | physical = ifmr.ifm_active & 0x0f; 119 | #endif 120 | 121 | #ifdef MEDIADEBUG 122 | printf(" all: %6d\n", ifmr.ifm_current); 123 | printf(" active: %6d\n", ifmr.ifm_active); 124 | printf(" status: %6d\n", ifmr.ifm_status); 125 | printf(" type: %6d\n", type); 126 | printf(" phys: %6d\n", physical); 127 | printf("if active: %6d\n", ifmr.ifm_active & IFM_ACTIVE); 128 | 129 | #ifdef __APPLE__ 130 | printf(" count: %6d\n", ifmr.ifm_count); 131 | #endif /* Apple debugging */ 132 | #endif 133 | 134 | /* switch type */ 135 | switch (type) { 136 | /* Ethernet */ 137 | case IFM_ETHER: 138 | switch (physical) { 139 | #ifdef __FreeBSD__ 140 | #if __FreeBSD__ <= 4 141 | case IFM_1000_FX: 142 | case IFM_1000_TX: 143 | #endif 144 | #endif 145 | case IFM_1000_SX: 146 | case IFM_1000_LX: 147 | case IFM_1000_CX: 148 | #ifdef IFM_1000_T 149 | case IFM_1000_T: 150 | #endif 151 | speed = 1000 * 1000; 152 | break; 153 | case IFM_100_TX: 154 | case IFM_100_FX: 155 | case IFM_100_T4: 156 | case IFM_100_VG: 157 | case IFM_100_T2: 158 | speed = 100 * 1000; 159 | break; 160 | case IFM_10_T: 161 | case IFM_10_2: 162 | case IFM_10_5: 163 | case IFM_10_FL: 164 | case IFM_10_STP: 165 | speed = 10 * 1000; 166 | break; 167 | #if defined(__OpenBSD__) || defined (__MicroBSD__) || defined (__NetBSD__) || defined (__APPLE__) 168 | case IFM_HPNA_1: 169 | #else 170 | #if __FreeBSD__ <= 4 171 | case IFM_homePNA: 172 | #endif 173 | #endif 174 | speed = 1 * 1000; 175 | break; 176 | default: 177 | speed = ERR_IFACE_NO_SPEED; 178 | break; 179 | } /* end switch physical */ 180 | break; 181 | #if WIRELESS 182 | /* IEEE 802.11 wireless interfaces */ 183 | case IFM_IEEE80211: 184 | switch (physical) { 185 | case IFM_IEEE80211_FH1: 186 | case IFM_IEEE80211_DS1: 187 | speed = 1 * 1000; 188 | break; 189 | case IFM_IEEE80211_FH2: 190 | case IFM_IEEE80211_DS2: 191 | speed = 2 * 1000; 192 | break; 193 | case IFM_IEEE80211_DS5: 194 | speed = (int) 5.5 *1000; 195 | break; 196 | case IFM_IEEE80211_DS11: 197 | speed = 11 * 1000; 198 | break; 199 | #if WIRELESS && defined(__FreeBSD__) && (__FreeBSD_version >= 460102) 200 | case IFM_IEEE80211_DS22: 201 | speed = 22 * 1000; 202 | break; 203 | #endif 204 | #if WIRELESS && \ 205 | (defined(__FreeBSD__) && (__FreeBSD_version >= 500111)) || \ 206 | (defined(__NetBSD__) && (__NetBSD_Version_ > 106020000)) || \ 207 | defined(__OpenBSD__) 208 | case IFM_IEEE80211_OFDM6: 209 | speed = 6 * 1000; 210 | break; 211 | case IFM_IEEE80211_OFDM9: 212 | speed = 9 * 1000; 213 | break; 214 | case IFM_IEEE80211_OFDM12: 215 | speed = 12 * 1000; 216 | break; 217 | case IFM_IEEE80211_OFDM18: 218 | speed = 18 * 1000; 219 | break; 220 | case IFM_IEEE80211_OFDM24: 221 | speed = 24 * 1000; 222 | break; 223 | case IFM_IEEE80211_OFDM36: 224 | speed = 36 * 1000; 225 | break; 226 | case IFM_IEEE80211_OFDM48: 227 | speed = 48 * 1000; 228 | break; 229 | case IFM_IEEE80211_OFDM54: 230 | speed = 54 * 1000; 231 | break; 232 | case IFM_IEEE80211_OFDM72: 233 | speed = 72 * 1000; 234 | break; 235 | #endif 236 | default: 237 | speed = ERR_IFACE_NO_SPEED; 238 | break; 239 | } 240 | break; 241 | #endif 242 | default: 243 | speed = ERR_IFACE_NO_SPEED; 244 | } /* end switch type */ 245 | 246 | #ifdef MEDIADEBUG 247 | printf(" speed: %6d\n", speed); 248 | #endif 249 | return speed; 250 | } 251 | #elif defined (__HPUX__) 252 | int get_if_speed(char *ifstring) 253 | { 254 | int speed = ERR_IFACE_NO_SPEED, buffer, fd, val, ret = -1; 255 | unsigned int len, i; 256 | struct nmparms params; 257 | mib_ifEntry *if_buf; 258 | 259 | for (i = 0; i <= ifdata.if_amount; i++) { 260 | if ((fd = open_mib("/dev/lan", O_RDWR, i, 0)) >= 0) { 261 | if ((if_buf = 262 | (mib_ifEntry *) malloc(sizeof(mib_ifEntry))) != 0) { 263 | params.objid = ID_ifEntry; 264 | params.buffer = if_buf; 265 | len = sizeof(mib_ifEntry); 266 | params.len = &len; 267 | if_buf->ifIndex = i + 1; 268 | if ((ret = get_mib_info(fd, ¶ms)) == 0) { 269 | if (i + 1 == ifdata.if_id) 270 | if (if_buf->ifOper == 1) 271 | speed = if_buf->ifSpeed / 1000; 272 | else 273 | speed ERR_IFACE_DOWN; 274 | } 275 | } 276 | } 277 | free(if_buf); 278 | close_mib(fd); 279 | } 280 | return speed; 281 | } 282 | #elif defined (__Solaris__) 283 | /****************************************************************************** 284 | * 285 | * Solaris interface speed detection 286 | * 287 | *****************************************************************************/ 288 | int get_if_speed(char *ifstring) 289 | { 290 | int speed = ERR_IFACE_NO_SPEED; 291 | kstat_t *ksp; 292 | kstat_named_t *knp; 293 | kstat_ctl_t *kc; 294 | 295 | if ((kc = kstat_open()) == NULL) 296 | return ERR_IFACE_NO_SPEED; 297 | 298 | ksp = kstat_lookup(kc, NULL, -1, ifstring); 299 | if (ksp && kstat_read(kc, ksp, NULL) >= 0) { 300 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "ifspeed"); 301 | if (knp) 302 | speed = (int) knp->value.ui64 / 1000; 303 | } 304 | kstat_close(kc); 305 | 306 | return speed; 307 | } 308 | #elif defined(__linux__) 309 | int get_if_speed(char *ifstring) 310 | { 311 | int sock; 312 | struct ifreq ifr; 313 | struct ethtool_cmd edata; 314 | int rc; 315 | 316 | sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); 317 | if (sock < 0) { 318 | fprintf(stderr, "cannot create socket to guess interface speed"); 319 | return -1; 320 | } 321 | 322 | strncpy(ifr.ifr_name, ifstring, sizeof(ifr.ifr_name)); 323 | ifr.ifr_data = (void *)&edata; 324 | 325 | edata.cmd = ETHTOOL_GSET; 326 | 327 | rc = ioctl(sock, SIOCETHTOOL, &ifr); 328 | if (rc < 0) { 329 | fprintf(stderr, "failed to guess interface speed"); 330 | return -1; 331 | } 332 | switch (ethtool_cmd_speed(&edata)) { 333 | case SPEED_10: return 10*1000; 334 | case SPEED_100: return 100*1000; 335 | case SPEED_1000: return 1000*1000; 336 | case SPEED_2500: return 2500*1000; 337 | case SPEED_10000: return 10000*1000; 338 | default: return edata.speed*1000; 339 | } 340 | } 341 | #else 342 | int get_if_speed(char *ifstring) 343 | { 344 | ifstring++; /* ugly hack to prevent compiler warning on Linux */ 345 | return ERR_IFACE_NO_SPEED; 346 | } 347 | #endif 348 | -------------------------------------------------------------------------------- /src/if_media.h: -------------------------------------------------------------------------------- 1 | /* interface speed detection errors */ 2 | #define ERR_IFACE_NO_SPEED -1 3 | #define ERR_IFACE_DOWN -2 4 | 5 | int get_if_speed(char *); 6 | -------------------------------------------------------------------------------- /src/linux.c: -------------------------------------------------------------------------------- 1 | /* $Id: linux.c,v 1.12 2003/09/06 10:44:50 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists and is up. 8 | * return TRUE if found, FALSE if not 9 | * 10 | ****************************************************************************/ 11 | 12 | int checkinterface(void) 13 | { 14 | int interfacefound = FALSE; 15 | unsigned int i; 16 | struct if_nameindex *ifs; 17 | 18 | if ((ifs = if_nameindex()) == NULL) 19 | return FALSE; 20 | 21 | for (i = 0; ifs[i].if_index; i++) { 22 | if (strcmp(ifs[i].if_name, ifdata.if_name) == 0) { 23 | interfacefound = TRUE; 24 | break; 25 | } 26 | } 27 | 28 | return interfacefound; 29 | } 30 | 31 | /****************************************************************************** 32 | * 33 | * get_stat() 34 | * 35 | * read the network statistics from /proc/net/dev (PATH_NET_DEV) 36 | * if the file is not open open it. fseek() to the beginning and parse 37 | * each line until we've found the right interface 38 | * 39 | * returns 0 if successful, 1 in case of error 40 | * 41 | *****************************************************************************/ 42 | 43 | int get_stat(void) 44 | { 45 | char buffer[BUFSIZ]; 46 | char *ptr; 47 | char *devname; 48 | unsigned long dump; 49 | int interfacefound; 50 | unsigned long rx_o, tx_o; 51 | 52 | if (proc_net_dev == NULL) { 53 | if ((proc_net_dev = fopen(PATH_NET_DEV, "r")) == NULL) { 54 | fprintf(stderr, "cannot open %s!\nnot running Linux?\n", 55 | PATH_NET_DEV); 56 | exit(1); 57 | } 58 | } 59 | 60 | /* backup old rx/tx values */ 61 | rx_o = stats.rx_bytes; 62 | tx_o = stats.tx_bytes; 63 | 64 | /* do not parse the first two lines as they only contain static garbage */ 65 | fseek(proc_net_dev, 0, SEEK_SET); 66 | fgets(buffer, BUFSIZ - 1, proc_net_dev); 67 | fgets(buffer, BUFSIZ - 1, proc_net_dev); 68 | 69 | interfacefound = 0; 70 | while (fgets(buffer, BUFSIZ - 1, proc_net_dev) != NULL) { 71 | /* find the device name and substitute ':' with '\0' */ 72 | ptr = buffer; 73 | while (*ptr == ' ') 74 | ptr++; 75 | devname = ptr; 76 | while (*ptr != ':') 77 | ptr++; 78 | *ptr = '\0'; 79 | ptr++; 80 | if (!strcmp(devname, (char *) ifdata.if_name)) { 81 | /* read stats and fill struct */ 82 | sscanf(ptr, 83 | "%lg %lu %lu %lu %lu %lu %lu %lu %lg %lu %lu %lu %lu %lu %lu %lu", 84 | &stats.rx_bytes, &stats.rx_packets, &stats.rx_errors, 85 | &dump, &dump, &dump, &dump, &dump, &stats.tx_bytes, 86 | &stats.tx_packets, &stats.tx_errors, &dump, &dump, 87 | &dump, &dump, &dump); 88 | interfacefound = 1; 89 | continue; /* break, as we won't get any new information */ 90 | } 91 | } 92 | if (interfacefound) { 93 | if (rx_o > stats.rx_bytes) 94 | stats.rx_over++; 95 | if (tx_o > stats.tx_bytes) 96 | stats.tx_over++; 97 | } 98 | return (interfacefound == 1) ? 0 : 1; 99 | } 100 | 101 | 102 | /***************************************************************************** 103 | * 104 | * get_default_interface() 105 | * 106 | * If only one non local interface is up use that as default 107 | * 108 | ****************************************************************************/ 109 | int get_default_interface(IfData * ifdata) 110 | { 111 | 112 | 113 | struct if_nameindex *ifs; 114 | ifs = if_nameindex(); 115 | 116 | struct ifreq ifr; 117 | unsigned int i; 118 | unsigned int index; 119 | unsigned int iface_up = 0; 120 | int ret; 121 | 122 | /* Create a socket to ioctl on */ 123 | int sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 124 | 125 | /* get an array of if_nameindex structs (one for each iface) */ 126 | ifs = if_nameindex(); 127 | 128 | /* iterate over the array and .. */ 129 | for (i = 0; ifs[i].if_index; i++) { 130 | 131 | /* ..write the name of the iface we want to check into the ifr struct and .. */ 132 | strncpy(ifr.ifr_name, ifs[i].if_name, IFNAMSIZ); 133 | 134 | /* .. perform an ioctl SIOCGIFFLAGS to get the iface flags */ 135 | ret = ioctl(sk, SIOCGIFFLAGS, &ifr); 136 | if (ret < 0) 137 | return ret; 138 | 139 | if (ifr.ifr_flags & IFF_LOOPBACK) { /* skip local loopback */ 140 | continue; 141 | } else if (ifr.ifr_flags & IFF_UP) { /* check if the iface is up (IFF_UP is set) */ 142 | iface_up++; 143 | index = i; /* save the index to get the iface name later */ 144 | } 145 | } 146 | 147 | if (iface_up == 1) { 148 | strncpy(ifdata->if_name, ifs[index].if_name, 149 | sizeof(ifdata->if_name)); 150 | ret = 0; 151 | } else { 152 | ret = -1; 153 | } 154 | 155 | return ret; 156 | } 157 | -------------------------------------------------------------------------------- /src/linux.h: -------------------------------------------------------------------------------- 1 | int checkinterface(void); 2 | int get_stat(void); 3 | -------------------------------------------------------------------------------- /src/macos.c: -------------------------------------------------------------------------------- 1 | /* $Id: macos.c,v 1.1 2003/09/10 19:07:32 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists, return TRUE if it does and FALSE if not 8 | * 9 | ****************************************************************************/ 10 | int checkinterface() 11 | { 12 | int validinterface = FALSE; 13 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 14 | static char *buf; 15 | static int alloc; 16 | char *lim, *next; 17 | struct if_msghdr *ifm, *nextifm; 18 | struct sockaddr_dl *sdl; 19 | size_t needed; 20 | char s[32]; 21 | 22 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 23 | return FALSE; 24 | if (alloc < (signed long) needed) { 25 | if (buf != NULL) 26 | free(buf); 27 | buf = malloc(needed); 28 | if (buf == NULL) 29 | return FALSE; 30 | alloc = needed; 31 | } 32 | 33 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 34 | return FALSE; 35 | lim = buf + needed; 36 | next = buf; 37 | while ((next < lim) && (validinterface == 0)) { 38 | ifm = (struct if_msghdr *) next; 39 | if (ifm->ifm_type != RTM_IFINFO) 40 | return FALSE; 41 | next += ifm->ifm_msglen; 42 | 43 | while (next < lim) { 44 | nextifm = (struct if_msghdr *) next; 45 | if (nextifm->ifm_type != RTM_NEWADDR) 46 | break; 47 | next += nextifm->ifm_msglen; 48 | } 49 | 50 | if (ifm->ifm_flags & IFF_UP) { 51 | sdl = (struct sockaddr_dl *) (ifm + 1); 52 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 53 | s[sdl->sdl_nlen] = '\0'; 54 | /* search for the right network interface */ 55 | if (sdl->sdl_family != AF_LINK) 56 | continue; 57 | if (strcmp(s, ifdata.if_name) != 0) 58 | continue; 59 | else { 60 | validinterface = TRUE; 61 | break; /* stop searching */ 62 | } 63 | } 64 | } 65 | return validinterface; 66 | } 67 | 68 | /****************************************************************************** 69 | * 70 | * get_stat() 71 | * 72 | * this code is based on gkrellm code (thanks guys!) 73 | * 74 | ****************************************************************************/ 75 | 76 | int get_stat(void) 77 | { 78 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 79 | static char *buf; 80 | static int alloc; 81 | char *lim, *next; 82 | struct if_msghdr *ifm, *nextifm; 83 | struct sockaddr_dl *sdl; 84 | char s[32]; 85 | size_t needed; 86 | unsigned long rx_o, tx_o; 87 | 88 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 89 | return 1; 90 | if (alloc < (signed long) needed) { 91 | if (buf != NULL) 92 | free(buf); 93 | buf = malloc(needed); 94 | if (buf == NULL) 95 | return 1; 96 | alloc = needed; 97 | } 98 | 99 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 100 | return 1; 101 | lim = buf + needed; 102 | next = buf; 103 | while (next < lim) { 104 | ifm = (struct if_msghdr *) next; 105 | if (ifm->ifm_type != RTM_IFINFO) 106 | return 1; 107 | next += ifm->ifm_msglen; 108 | 109 | while (next < lim) { 110 | nextifm = (struct if_msghdr *) next; 111 | if (nextifm->ifm_type != RTM_NEWADDR) 112 | break; 113 | next += nextifm->ifm_msglen; 114 | } 115 | 116 | if (ifm->ifm_flags & IFF_UP) { 117 | sdl = (struct sockaddr_dl *) (ifm + 1); 118 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 119 | s[sdl->sdl_nlen] = '\0'; 120 | 121 | /* search for the right network interface */ 122 | if (strcmp(s, ifdata.if_name) != 0) 123 | continue; 124 | 125 | rx_o = stats.rx_bytes; 126 | tx_o = stats.tx_bytes; 127 | /* write stats */ 128 | stats.tx_packets = ifm->ifm_data.ifi_opackets; 129 | stats.rx_packets = ifm->ifm_data.ifi_ipackets; 130 | stats.rx_bytes = ifm->ifm_data.ifi_ibytes; 131 | stats.tx_bytes = ifm->ifm_data.ifi_obytes; 132 | stats.rx_errors = ifm->ifm_data.ifi_ierrors; 133 | stats.tx_errors = ifm->ifm_data.ifi_oerrors; 134 | 135 | if (rx_o > stats.rx_bytes) 136 | stats.rx_over++; 137 | if (tx_o > stats.tx_bytes) 138 | stats.tx_over++; 139 | } 140 | } 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /src/macos.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | int checkinterface(void); 3 | -------------------------------------------------------------------------------- /src/netbsd.c: -------------------------------------------------------------------------------- 1 | /* $Id: netbsd.c,v 1.5 2003/02/23 17:26:02 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists, return TRUE if it does and FALSE if not 8 | * 9 | ****************************************************************************/ 10 | int checkinterface() 11 | { 12 | int validinterface = FALSE; 13 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 14 | static char *buf; 15 | static int alloc; 16 | char *lim, *next; 17 | struct if_msghdr *ifm, *nextifm; 18 | struct sockaddr_dl *sdl; 19 | size_t needed; 20 | char s[32]; 21 | 22 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 23 | return FALSE; 24 | if (alloc < (signed long) needed) { 25 | if (buf != NULL) 26 | free(buf); 27 | buf = malloc(needed); 28 | if (buf == NULL) 29 | return FALSE; 30 | alloc = needed; 31 | } 32 | 33 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 34 | return FALSE; 35 | lim = buf + needed; 36 | next = buf; 37 | while ((next < lim) && (validinterface == 0)) { 38 | ifm = (struct if_msghdr *) next; 39 | if (ifm->ifm_type != RTM_IFINFO) 40 | return FALSE; 41 | next += ifm->ifm_msglen; 42 | 43 | while (next < lim) { 44 | nextifm = (struct if_msghdr *) next; 45 | if (nextifm->ifm_type != RTM_NEWADDR) 46 | break; 47 | next += nextifm->ifm_msglen; 48 | } 49 | 50 | if (ifm->ifm_flags & IFF_UP) { 51 | sdl = (struct sockaddr_dl *) (ifm + 1); 52 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 53 | s[sdl->sdl_nlen] = '\0'; 54 | /* search for the right network interface */ 55 | if (sdl->sdl_family != AF_LINK) 56 | continue; 57 | if (strcmp(s, ifdata.if_name) != 0) 58 | continue; 59 | else { 60 | validinterface = TRUE; 61 | break; /* stop searching */ 62 | } 63 | } 64 | } 65 | return validinterface; 66 | } 67 | 68 | /****************************************************************************** 69 | * 70 | * get_stat() 71 | * 72 | * this code is based on gkrellm code (thanks guys!) 73 | * 74 | ****************************************************************************/ 75 | 76 | int get_stat(void) 77 | { 78 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 79 | static char *buf; 80 | static int alloc; 81 | char *lim, *next; 82 | struct if_msghdr *ifm, *nextifm; 83 | struct sockaddr_dl *sdl; 84 | char s[32]; 85 | size_t needed; 86 | unsigned long rx_o, tx_o; 87 | 88 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 89 | return 1; 90 | if (alloc < (signed long) needed) { 91 | if (buf != NULL) 92 | free(buf); 93 | buf = malloc(needed); 94 | if (buf == NULL) 95 | return 1; 96 | alloc = needed; 97 | } 98 | 99 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 100 | return 1; 101 | lim = buf + needed; 102 | next = buf; 103 | while (next < lim) { 104 | ifm = (struct if_msghdr *) next; 105 | if (ifm->ifm_type != RTM_IFINFO) 106 | return 1; 107 | next += ifm->ifm_msglen; 108 | 109 | while (next < lim) { 110 | nextifm = (struct if_msghdr *) next; 111 | if (nextifm->ifm_type != RTM_NEWADDR) 112 | break; 113 | next += nextifm->ifm_msglen; 114 | } 115 | 116 | if (ifm->ifm_flags & IFF_UP) { 117 | sdl = (struct sockaddr_dl *) (ifm + 1); 118 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 119 | s[sdl->sdl_nlen] = '\0'; 120 | 121 | /* search for the right network interface */ 122 | if (strcmp(s, ifdata.if_name) != 0) 123 | continue; 124 | 125 | rx_o = stats.rx_bytes; 126 | tx_o = stats.tx_bytes; 127 | /* write stats */ 128 | stats.tx_packets = ifm->ifm_data.ifi_opackets; 129 | stats.rx_packets = ifm->ifm_data.ifi_ipackets; 130 | stats.rx_bytes = ifm->ifm_data.ifi_ibytes; 131 | stats.tx_bytes = ifm->ifm_data.ifi_obytes; 132 | stats.rx_errors = ifm->ifm_data.ifi_ierrors; 133 | stats.tx_errors = ifm->ifm_data.ifi_oerrors; 134 | 135 | if (rx_o > stats.rx_bytes) 136 | stats.rx_over++; 137 | if (tx_o > stats.tx_bytes) 138 | stats.tx_over++; 139 | } 140 | } 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /src/netbsd.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | int checkinterface(void); 3 | -------------------------------------------------------------------------------- /src/openbsd.c: -------------------------------------------------------------------------------- 1 | /* $Id: openbsd.c,v 1.7 2003/02/23 17:26:02 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists, return TRUE if it does and FALSE if not 8 | * 9 | ****************************************************************************/ 10 | int checkinterface() 11 | { 12 | int validinterface = FALSE; 13 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 14 | static char *buf; 15 | static int alloc; 16 | char *lim, *next; 17 | struct if_msghdr *ifm, *nextifm; 18 | struct sockaddr_dl *sdl; 19 | size_t needed; 20 | char s[32]; 21 | 22 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 23 | return FALSE; 24 | if (alloc < (signed long) needed) { 25 | if (buf != NULL) 26 | free(buf); 27 | buf = malloc(needed); 28 | if (buf == NULL) 29 | return FALSE; 30 | alloc = needed; 31 | } 32 | 33 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 34 | return FALSE; 35 | 36 | lim = buf + needed; 37 | next = buf; 38 | while ((next < lim) && (validinterface == 0)) { 39 | ifm = (struct if_msghdr *) next; 40 | if (ifm->ifm_type != RTM_IFINFO) 41 | return FALSE; 42 | next += ifm->ifm_msglen; 43 | 44 | while (next < lim) { 45 | nextifm = (struct if_msghdr *) next; 46 | if (nextifm->ifm_type != RTM_NEWADDR) 47 | break; 48 | next += nextifm->ifm_msglen; 49 | } 50 | 51 | if (ifm->ifm_flags & IFF_UP) { 52 | sdl = (struct sockaddr_dl *) (ifm + 1); 53 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 54 | s[sdl->sdl_nlen] = '\0'; 55 | /* search for the right network interface */ 56 | if (sdl->sdl_family != AF_LINK) 57 | continue; 58 | if (strcmp(s, ifdata.if_name) != 0) 59 | continue; 60 | else { 61 | validinterface = TRUE; 62 | break; /* stop searching */ 63 | } 64 | } 65 | } 66 | return validinterface; 67 | } 68 | 69 | /***************************************************************************** 70 | * 71 | * get_stat() 72 | * 73 | * this code is based on gkrellm code (thanks guys!) 74 | * 75 | ****************************************************************************/ 76 | 77 | int get_stat(void) 78 | { 79 | static int mib_name[] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 }; 80 | static char *buf; 81 | static int alloc; 82 | char *lim, *next; 83 | struct if_msghdr *ifm, *nextifm; 84 | struct sockaddr_dl *sdl; 85 | char s[32]; 86 | size_t needed; 87 | unsigned long rx_o, tx_o; 88 | 89 | if (sysctl(mib_name, 6, NULL, &needed, NULL, 0) < 0) 90 | return 1; 91 | if (alloc < (signed long) needed) { 92 | if (buf != NULL) 93 | free(buf); 94 | buf = malloc(needed); 95 | if (buf == NULL) 96 | return 1; 97 | alloc = needed; 98 | } 99 | 100 | if (sysctl(mib_name, 6, buf, &needed, NULL, 0) < 0) 101 | return 1; 102 | lim = buf + needed; 103 | next = buf; 104 | while (next < lim) { 105 | ifm = (struct if_msghdr *) next; 106 | if (ifm->ifm_type != RTM_IFINFO) 107 | return 1; 108 | next += ifm->ifm_msglen; 109 | 110 | while (next < lim) { 111 | nextifm = (struct if_msghdr *) next; 112 | if (nextifm->ifm_type != RTM_NEWADDR) 113 | break; 114 | next += nextifm->ifm_msglen; 115 | } 116 | 117 | if (ifm->ifm_flags & IFF_UP) { 118 | sdl = (struct sockaddr_dl *) (ifm + 1); 119 | /* search for the right network interface */ 120 | if (sdl->sdl_family != AF_LINK) 121 | continue; 122 | if (strncmp(sdl->sdl_data, ifdata.if_name, sdl->sdl_nlen) != 0) 123 | continue; 124 | strncpy(s, sdl->sdl_data, sdl->sdl_nlen); 125 | s[sdl->sdl_nlen] = '\0'; 126 | 127 | rx_o = stats.rx_bytes; 128 | tx_o = stats.tx_bytes; 129 | /* write stats */ 130 | stats.tx_packets = ifm->ifm_data.ifi_opackets; 131 | stats.rx_packets = ifm->ifm_data.ifi_ipackets; 132 | stats.rx_bytes = ifm->ifm_data.ifi_ibytes; 133 | stats.tx_bytes = ifm->ifm_data.ifi_obytes; 134 | stats.rx_errors = ifm->ifm_data.ifi_ierrors; 135 | stats.tx_errors = ifm->ifm_data.ifi_oerrors; 136 | 137 | if (rx_o > stats.rx_bytes) 138 | stats.rx_over++; 139 | if (tx_o > stats.tx_bytes) 140 | stats.tx_over++; 141 | } 142 | } 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /src/openbsd.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | int checkinterface(void); 3 | -------------------------------------------------------------------------------- /src/solaris.c: -------------------------------------------------------------------------------- 1 | /* $Id: solaris.c,v 1.6 2003/09/11 12:08:17 hscholz Exp $ */ 2 | 3 | /***************************************************************************** 4 | * 5 | * checkinterface() 6 | * 7 | * check if a given interface exists, return TRUE if it does and FALSE if not 8 | * 9 | ****************************************************************************/ 10 | 11 | int checkinterface() 12 | { 13 | int validinterface = FALSE; 14 | int sockfd, i, numifs, numifreqs; 15 | size_t bufsize; 16 | char *buf; 17 | struct ifreq ifr, *ifrp; 18 | struct ifconf ifc; 19 | 20 | if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 21 | perror("socket"); 22 | return FALSE; 23 | } 24 | if (ioctl(sockfd, SIOCGIFNUM, (char *) &numifs) < 0) { 25 | perror("SIOCGIFNUM"); 26 | close(sockfd); 27 | return FALSE; 28 | } 29 | bufsize = ((size_t) numifs) * sizeof(struct ifreq); 30 | buf = (char *) malloc(bufsize); 31 | if (!buf) { 32 | perror("malloc"); 33 | close(sockfd); 34 | return FALSE; 35 | } 36 | 37 | ifc.ifc_len = bufsize; 38 | ifc.ifc_buf = buf; 39 | 40 | if (ioctl(sockfd, SIOCGIFCONF, (char *) &ifc) < 0) { 41 | perror("SIOCGIFCONF"); 42 | close(sockfd); 43 | free(buf); 44 | return FALSE; 45 | } 46 | 47 | ifrp = ifc.ifc_req; 48 | numifreqs = ifc.ifc_len / sizeof(struct ifreq); 49 | 50 | for (i = 0; i < numifreqs; i++, ifrp++) { 51 | memset((char *) &ifr, 0, sizeof(ifr)); 52 | strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); 53 | /* do not check for loopback device as it cannot be monitored */ 54 | if (!strncmp(ifr.ifr_name, "lo", 2)) 55 | continue; 56 | if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 57 | perror("SIOCGIFFLAGS"); 58 | continue; 59 | } 60 | if (!strcmp(ifdata.if_name, ifr.ifr_name) 61 | && (ifr.ifr_flags & IFF_UP)) { 62 | validinterface = TRUE; 63 | break; 64 | } 65 | } 66 | free(buf); 67 | close(sockfd); 68 | 69 | return validinterface; 70 | } 71 | 72 | /***************************************************************************** 73 | * 74 | * get_stat() 75 | * 76 | * use the Solaris kstat_*() interface to gather statistics 77 | * We have to open/close *kc each time :( 78 | * 79 | ****************************************************************************/ 80 | 81 | int get_stat(void) 82 | { 83 | kstat_t *ksp; 84 | kstat_named_t *knp; 85 | kstat_ctl_t *kc; 86 | unsigned long rx_o, tx_o; 87 | 88 | if ((kc = kstat_open()) == NULL) { 89 | perror("kstat_open()"); 90 | return 1; 91 | } 92 | 93 | rx_o = stats.rx_bytes; 94 | tx_o = stats.tx_bytes; 95 | 96 | ksp = kstat_lookup(kc, NULL, -1, ifdata.if_name); 97 | if (ksp && kstat_read(kc, ksp, NULL) >= 0) { 98 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "opackets"); 99 | if (knp) 100 | stats.tx_packets = knp->value.ui32; 101 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "ipackets"); 102 | if (knp) 103 | stats.rx_packets = knp->value.ui32; 104 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "obytes"); 105 | if (knp) 106 | stats.tx_bytes = knp->value.ui32; 107 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "rbytes"); 108 | if (knp) 109 | stats.rx_bytes = knp->value.ui32; 110 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "oerrors"); 111 | if (knp) 112 | stats.tx_errors = knp->value.ui32; 113 | knp = (kstat_named_t *) kstat_data_lookup(ksp, "ierrors"); 114 | if (knp) 115 | stats.rx_errors = knp->value.ui32; 116 | } 117 | 118 | kstat_close(kc); 119 | 120 | /* check for overflows */ 121 | if (rx_o > stats.rx_bytes) 122 | stats.rx_over++; 123 | if (tx_o > stats.tx_bytes) 124 | stats.tx_over++; 125 | 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /src/solaris.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | int checkinterface(void); 3 | -------------------------------------------------------------------------------- /src/unsupported.c: -------------------------------------------------------------------------------- 1 | /* $Id: unsupported.c,v 1.2 2003/02/23 17:26:02 hscholz Exp $ */ 2 | 3 | /****************************************************************************** 4 | * 5 | * get_stat() 6 | * 7 | * stub function for all unsupported operating systems 8 | * 9 | *****************************************************************************/ 10 | 11 | int get_stat(void) 12 | { 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/unsupported.h: -------------------------------------------------------------------------------- 1 | int get_stat(void); 2 | -------------------------------------------------------------------------------- /theme.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * theme.c - slurm theme engine 4 | * 5 | ****************************************************************************** 6 | * $Id: theme.c,v 1.5 2004/09/28 14:23:02 hscholz Exp $ 7 | *****************************************************************************/ 8 | 9 | #ifndef _THEME_C 10 | #define _THEME_C 11 | 12 | /****************************************************************************** 13 | * 14 | * theme_setdefault() 15 | * 16 | * set default theme 17 | * 18 | *****************************************************************************/ 19 | 20 | void theme_setdefault(theme * t) 21 | { 22 | if (t == NULL) 23 | error(ERR_FATAL, "theme_setdefault() received NULL pointer"); 24 | 25 | t->background = COLOR_TRANSPARENT; 26 | t->rx = COLOR_GREEN; 27 | t->tx = COLOR_RED; 28 | t->text = COLOR_WHITE; 29 | t->var = COLOR_WHITE; 30 | t->title = COLOR_WHITE; 31 | t->rx_attrib = COL_BOLD; 32 | t->tx_attrib = COL_BOLD; 33 | t->text_attrib = COL_NORMAL; 34 | t->var_attrib = COL_BOLD; 35 | t->title_attrib = COL_BOLD; 36 | t->complete = E_ALL; 37 | } 38 | 39 | /****************************************************************************** 40 | * 41 | * theme_readfile() 42 | * 43 | * read color definitions from the given file and store in theme struct 44 | * 45 | *****************************************************************************/ 46 | 47 | int theme_readfile(theme * t, char *name) 48 | { 49 | FILE *f; 50 | char buf[BUFSIZ + 1]; 51 | char filename[BUFSIZ + 1]; 52 | char *search_paths[3]; 53 | char *p, *val, *key; 54 | int iter; 55 | char pref[sizeof(INSTALL_PREFIX)+15]; 56 | 57 | strcpy(pref, INSTALL_PREFIX); 58 | 59 | t->complete = E_NULL; 60 | 61 | /* search for the theme: 62 | * - in the local directory 63 | * - in ~/.slurm 64 | * - in /usr/local/share/slurm 65 | * (make this /usr/share/slurm for Debian systems by specifing 66 | * -D__Debian__) 67 | */ 68 | search_paths[0] = "."; /* local directory */ 69 | search_paths[1] = strcat(getenv("HOME"), "/.slurm"); /* $HOME/.slurm/ */ 70 | search_paths[2] = strcat(pref, "/share/slurm"); /* search in $PREFIX/share/slurm/ */ 71 | 72 | for (iter = 0; iter <= 2; iter++) { 73 | bzero(&filename, BUFSIZ); 74 | snprintf(filename, BUFSIZ, "%s/%s.theme", search_paths[iter], 75 | name); 76 | 77 | if ((f = fopen(filename, "r")) != NULL) { 78 | /* found the theme; leave the loop */ 79 | break; 80 | } 81 | } 82 | 83 | /* lets see if we found the theme */ 84 | if ((f = fopen(filename, "r")) == NULL) { 85 | error(ERR_FATAL, "cannot find theme '%s'", name); 86 | } 87 | 88 | 89 | while (fgets(buf, BUFSIZ, f) != NULL) { 90 | if (!strncmp(buf, "#", 1)) 91 | continue; /* comment */ 92 | p = buf; 93 | while (isspace((int) *p) && (*p + 1 != '\0')) 94 | p++; 95 | key = p; 96 | while (isalpha((int) *p) && (*p + 1 != '\0')) 97 | p++; 98 | if (isspace((int) *p)) { 99 | *p++ = '\0'; 100 | while (isspace((int) *p) && (*p + 1 != '\0')) 101 | p++; 102 | if (*p != '=') 103 | continue; 104 | p++; 105 | while (isspace((int) *p) && (*p + 1 != '\0')) 106 | p++; 107 | } else if (*p == '=') { 108 | *p++ = '\0'; 109 | while (isspace((int) *p) && (*p + 1 != '\0')) 110 | p++; 111 | } else 112 | continue; 113 | val = p; 114 | while (isalpha((int) *p) && (*p + 1 != '\0')) 115 | p++; 116 | *p++ = '\0'; 117 | 118 | switch (theme_mapkey(key)) { 119 | case E_BACKGROUND: 120 | t->background = theme_mapcolor(val); 121 | t->complete |= E_BACKGROUND; 122 | break; 123 | case E_RX: 124 | t->rx = theme_mapcolor(val); 125 | t->complete |= E_RX; 126 | break; 127 | case E_TX: 128 | t->tx = theme_mapcolor(val); 129 | t->complete |= E_TX; 130 | break; 131 | case E_TEXT: 132 | t->text = theme_mapcolor(val); 133 | t->complete |= E_TEXT; 134 | break; 135 | case E_TITLE: 136 | t->title = theme_mapcolor(val); 137 | t->complete |= E_TITLE; 138 | break; 139 | case E_TEXTVAR: 140 | t->var = theme_mapcolor(val); 141 | t->complete |= E_TEXTVAR; 142 | break; 143 | case E_RXATTR: 144 | t->rx_attrib = theme_mapattrib(val); 145 | t->complete |= E_RXATTR; 146 | break; 147 | case E_TXATTR: 148 | t->tx_attrib = theme_mapattrib(val); 149 | t->complete |= E_TXATTR; 150 | break; 151 | case E_TEXTATTR: 152 | t->text_attrib = theme_mapattrib(val); 153 | t->complete |= E_TEXTATTR; 154 | break; 155 | case E_TEXTVARATTR: 156 | t->var_attrib = theme_mapattrib(val); 157 | t->complete |= E_TEXTVARATTR; 158 | break; 159 | case E_TITLEATTR: 160 | t->title_attrib = theme_mapattrib(val); 161 | t->complete |= E_TITLEATTR; 162 | break; 163 | default: 164 | error(ERR_WARNING, "unknown key '%s' in theme '%s'", 165 | key, filename); 166 | } 167 | } 168 | fclose(f); 169 | return (t->complete == E_ALL) ? 1 : 0; 170 | } 171 | 172 | /****************************************************************************** 173 | * 174 | * theme_mapattrib() 175 | * 176 | * map entity attribute to coresponding curses attribute 177 | * 178 | *****************************************************************************/ 179 | 180 | int theme_mapattrib(char *str) 181 | { 182 | int val = COL_BOLD; 183 | char buf[32]; 184 | int i; 185 | 186 | if (strlen(str) > 31) 187 | return val; 188 | bzero(&buf, 31); 189 | for (i = 0; i < strlen(str); i++) 190 | buf[i] = toupper((int) str[i]); 191 | buf[i + 1] = '\0'; 192 | 193 | if (!strcmp(buf, "BOLD")) 194 | val = COL_BOLD; 195 | else if (!strcmp(buf, "NORMAL")) 196 | val = COL_NORMAL; 197 | else if (!strcmp(buf, "DIM")) 198 | val = COL_DIM; 199 | 200 | return val; 201 | } 202 | 203 | /****************************************************************************** 204 | * 205 | * theme_mapcolor() 206 | * 207 | * map color name to coresponding curses color name 208 | * 209 | *****************************************************************************/ 210 | 211 | int theme_mapcolor(char *str) 212 | { 213 | int val = COLOR_GREEN; 214 | char buf[32]; 215 | int i; 216 | 217 | if (strlen(str) > 31) 218 | return val; 219 | bzero(&buf, 31); 220 | for (i = 0; i < strlen(str); i++) 221 | buf[i] = toupper((int) str[i]); 222 | buf[i + 1] = '\0'; 223 | 224 | if (!strcmp(buf, "BLACK")) 225 | val = COLOR_BLACK; 226 | else if (!strcmp(buf, "RED")) 227 | val = COLOR_RED; 228 | else if (!strcmp(buf, "GREEN")) 229 | val = COLOR_GREEN; 230 | else if (!strcmp(buf, "YELLOW")) 231 | val = COLOR_YELLOW; 232 | else if (!strcmp(buf, "BLUE")) 233 | val = COLOR_BLUE; 234 | else if (!strcmp(buf, "MAGENTA")) 235 | val = COLOR_MAGENTA; 236 | else if (!strcmp(buf, "CYAN")) 237 | val = COLOR_CYAN; 238 | else if (!strcmp(buf, "WHITE")) 239 | val = COLOR_WHITE; 240 | else if (!strcmp(buf, "TRANSPARENT")) 241 | val = COLOR_TRANSPARENT; 242 | 243 | return val; 244 | } 245 | 246 | /****************************************************************************** 247 | * 248 | * theme_mapkey() 249 | * 250 | * map entity name to internal name 251 | * 252 | *****************************************************************************/ 253 | 254 | int theme_mapkey(char *str) 255 | { 256 | int e = 0; 257 | char buf[32]; 258 | int i; 259 | 260 | if (strlen(str) > 31) 261 | return e; 262 | bzero(&buf, 31); 263 | for (i = 0; i < strlen(str); i++) 264 | buf[i] = toupper((int) str[i]); 265 | buf[i + 1] = '\0'; 266 | 267 | if (!strcmp(buf, "BACKGROUND")) 268 | e = E_BACKGROUND; 269 | else if (!strcmp(buf, "RX")) 270 | e = E_RX; 271 | else if (!strcmp(buf, "TX")) 272 | e = E_TX; 273 | else if (!strcmp(buf, "TEXT")) 274 | e = E_TEXT; 275 | else if (!strcmp(buf, "TITLE")) 276 | e = E_TITLE; 277 | else if (!strcmp(buf, "TEXTVAR")) 278 | e = E_TEXTVAR; 279 | else if (!strcmp(buf, "RXATTR")) 280 | e = E_RXATTR; 281 | else if (!strcmp(buf, "TXATTR")) 282 | e = E_TXATTR; 283 | else if (!strcmp(buf, "TEXTATTR")) 284 | e = E_TEXTATTR; 285 | else if (!strcmp(buf, "TEXTVARATTR")) 286 | e = E_TEXTVARATTR; 287 | else if (!strcmp(buf, "TITLEATTR")) 288 | e = E_TITLEATTR; 289 | return e; 290 | } 291 | #endif 292 | -------------------------------------------------------------------------------- /theme.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * theme.h - slurm theme engine definitions 4 | * 5 | ****************************************************************************** 6 | * $Id: theme.h,v 1.2 2003/07/09 16:45:37 hscholz Exp $ 7 | *****************************************************************************/ 8 | 9 | #ifndef _THEME_H 10 | #define _THEME_H 11 | 12 | /* prototypes */ 13 | int theme_mapcolor(char *); 14 | int theme_mapattrib(char *); 15 | int theme_mapkey(char *); 16 | 17 | typedef struct { 18 | int complete; 19 | int background; 20 | int rx; 21 | int rx_attrib; 22 | int tx; 23 | int tx_attrib; 24 | int text; 25 | int text_attrib; 26 | int var; 27 | int var_attrib; 28 | int title; 29 | int title_attrib; 30 | } theme; 31 | theme t; 32 | 33 | /* possible entities */ 34 | #define E_BACKGROUND 0x0101 35 | #define E_RX 0x0102 36 | #define E_TX 0x0104 37 | #define E_TEXT 0x0108 38 | #define E_TEXTVAR 0x0110 39 | #define E_TITLE 0x0120 40 | #define E_RXATTR 0x0201 41 | #define E_TXATTR 0x0202 42 | #define E_TEXTATTR 0x0204 43 | #define E_TEXTVARATTR 0x0208 44 | #define E_TITLEATTR 0x0210 45 | 46 | #define E_ALL (E_BACKGROUND | E_RX | E_TX | E_TEXT | E_TEXTVAR | \ 47 | E_RXATTR | E_TXATTR | E_TEXTATTR | E_TEXTVARATTR | \ 48 | E_TITLE | E_TITLEATTR) 49 | #define E_NULL 0 50 | 51 | /* color definitions */ 52 | #ifndef COLOR_BLACK 53 | #define COLOR_BLACK 0 54 | #define COLOR_RED 1 55 | #define COLOR_GREEN 2 56 | #define COLOR_YELLOW 3 57 | #define COLOR_BLUE 4 58 | #define COLOR_MAGENTA 5 59 | #define COLOR_CYAN 6 60 | #define COLOR_WHITE 7 61 | #endif 62 | #define COLOR_TRANSPARENT -1 63 | 64 | #define COL_NORMAL 0 65 | #define COL_BOLD 1 66 | #define COL_DIM 2 67 | 68 | /* internal color pairs */ 69 | #define PAIR_TEXT 1 70 | #define PAIR_RX 2 71 | #define PAIR_TX 3 72 | #define PAIR_VAR 4 73 | #define PAIR_TITLE 5 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /themes/black.theme: -------------------------------------------------------------------------------- 1 | # 2 | # black.theme 3 | # 4 | # $Id: black.theme,v 1.1 2004/09/28 13:44:35 hscholz Exp $ 5 | # 6 | 7 | BACKGROUND=TRANSPARENT 8 | RX=GREEN 9 | TX=RED 10 | TEXT=BLACK 11 | TEXTVAR=BLACK 12 | TEXTATTR=NORMAL 13 | RXATTR=NORMAL 14 | TXATTR=BOLD 15 | TEXTVARATTR=BOLD 16 | TITLE=BLACK 17 | TITLEATTR=BOLD 18 | -------------------------------------------------------------------------------- /themes/blue.theme: -------------------------------------------------------------------------------- 1 | # 2 | # blue.theme 3 | # 4 | # $Id: blue.theme,v 1.1 2003/05/25 14:45:23 hscholz Exp $ 5 | # 6 | 7 | BACKGROUND=TRANSPARENT 8 | RX=BLUE 9 | RXATTR=NORMAL 10 | TX=BLUE 11 | TXATTR=BOLD 12 | TEXT=BLUE 13 | TEXTVAR=BLUE 14 | TEXTATTR=NORMAL 15 | TEXTVARATTR=BOLD 16 | TITLE=BLUE 17 | TITLEATTR=BOLD 18 | -------------------------------------------------------------------------------- /themes/cyan.theme: -------------------------------------------------------------------------------- 1 | # 2 | # cyan.theme 3 | # 4 | # $Id: cyan.theme,v 1.1 2003/07/09 16:45:38 hscholz Exp $ 5 | # 6 | 7 | BACKGROUND=TRANSPARENT 8 | RX=CYAN 9 | RXATTR=normal 10 | TX=CYAN 11 | TXATTR=BOLD 12 | TEXT=BLUE 13 | TEXTVAR=CYAN 14 | TEXTATTR=NORMAL 15 | TEXTVARATTR=normal 16 | TITLE=WHITE 17 | TITLEATTR=BOLD 18 | -------------------------------------------------------------------------------- /themes/foo.theme: -------------------------------------------------------------------------------- 1 | # 2 | # bright.theme 3 | # 4 | # $Id: foo.theme,v 1.1 2003/05/25 14:45:23 hscholz Exp $ 5 | # 6 | 7 | BACKGROUND=TRANSPARENT 8 | RX=GREEN 9 | TX=RED 10 | TEXT=WHITE 11 | TEXTVAR=CYAN 12 | TEXTATTR=NORMAL 13 | RXATTR=NORMAL 14 | TXATTR=BOLD 15 | TEXTVARATTR=BOLD 16 | TITLE=WHITE 17 | TITLEATTR=BOLD 18 | --------------------------------------------------------------------------------