/****************************************************************************** * bwm-ng * * * * for more info read README. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * * *****************************************************************************/ #include "global_vars.h" #include "bwm-ng.h" /* handle interrupt signal */ void sigint(int sig) FUNCATTR_NORETURN; static inline void init(void); /* clear stuff and exit */ #ifdef __STDC__ void deinit(int code, const char *error_msg, ...) { #else void deinit(int code, ...) { #endif va_list ap; #if EXTENDED_STATS int local_if_count; struct double_list *list_p; #endif #ifdef HAVE_CURSES if (mywin!=NULL && (output_method==CURSES_OUT || output_method==CURSES2_OUT)) { /* first close curses, so we dont leave mess behind */ #if HAVE_CURS_SET curs_set(1); #endif endwin(); } #endif #ifdef IOCTL /* close socket if we opened it for ioctl */ if (skfd >= 0) { close(skfd); } #endif /* we should clean if_state, the data array */ if (if_stats!=NULL) { #if EXTENDED_STATS /* clean avg list for each iface */ for (local_if_count=0;local_if_countnext; free(list_p); } } #endif free(if_stats); } /* free the opt iface_list, ifaces to show or hide */ if (iface_list!=NULL) free(iface_list); #if CSV || HTML /* close the out_file */ if (out_file!=NULL) fclose(out_file); if (out_file_path!=NULL) free(out_file_path); #endif #ifdef __STDC__ /* output errormsg if given */ if (error_msg!=NULL) { va_start(ap, error_msg); vprintf(error_msg,ap); } #else va_start(ap); vprintf(ap); #endif /* we are done, say goodbye */ exit(code); } /* sigint handler */ void sigint(int sig) { /* we got a sigint, call deinit and exit */ deinit(0, NULL); } static inline void init(void) { if_count=0; delay=500; #if EXTENDED_STATS avg_length=0; #endif output_unit=BYTES_OUT; output_type=RATE_OUT; show_all_if=0; #ifdef HAVE_CURSES output_method=CURSES_OUT; mywin=NULL; max_rt=32; scale=0; show_only_if=0; #else output_method=PLAIN_OUT; #endif iface_list=NULL; #ifdef CSV csv_char=';'; #endif #if CSV || HTML out_file=NULL; out_file_path=NULL; #endif output_count=-1; daemonize=0; sumhidden=0; /* gcc doesnt support #elifdef so we have to use this ugly piece */ #ifdef PROC_NET_DEV input_method=PROC_IN; #elif defined(GETIFADDRS) input_method=GETIFADDRS_IN; #elif defined(LIBSTATGRAB) input_method=LIBSTAT_IN; #elif defined(SYSCTL) input_method=SYSCTL_IN; #elif defined(HAVE_LIBKSTAT) input_method=KSTAT_IN; #elif defined(NETSTAT) input_method=NETSTAT_IN; #elif defined(WIN32) input_method=WIN32_IN; #elif defined(HAVE_PROC_DISKSTATS) input_method=DISKLINUX_IN; #else #error "NO INPUT DEFINED!" input_method=0; #endif ansi_output=1; #ifdef HTML html_refresh=5; html_header=0; #endif #ifdef IOCTL skfd=-1; #endif if_stats=NULL; #ifdef PROC_NET_DEV strncpy(PROC_FILE,PROC_NET_DEV,PATH_MAX); #endif #ifdef PROC_DISKSTATS strncpy(PROC_DISKSTATS_FILE,PROC_DISKSTATS,PATH_MAX); #endif #ifdef PROC_PARTITIONS strncpy(PROC_PARTITIONS_FILE,PROC_PARTITIONS,PATH_MAX); #endif #if IOSERVICE_IN long_darwin_disk_names = 0; #endif time_t t = time(NULL); strftime(start_time, sizeof(start_time), "%c", localtime(&t)); } /* do the main thing */ int main (int argc, char *argv[]) { unsigned char idle_chars_p=0; char ch; init(); /* handle all cmd line and configfile options */ get_cmdln_options(argc,argv); /* check them */ if (output_method<0) deinit(1,"invalid output selected\n"); if (input_method<0) deinit(1,"invalid input selected\n"); #ifdef LIBSTATGRAB if (sg_init(0) != 0) { deinit(1,"libstatgrab failed to initialise\n"); } #endif /* init total stats to zero */ memset(&if_stats_total,0,(size_t)sizeof(t_iface_stats)); #ifdef HAVE_CURSES if (output_method==CURSES_OUT || output_method==CURSES2_OUT) { /* init curses */ if (init_curses()) signal(SIGWINCH,sigwinch); } #endif /* end of init curses, now set a sigint handler to deinit the screen on ctrl-break */ signal(SIGINT,sigint); signal(SIGTERM,sigint); #ifdef CSV /* get stats without verbose if cvs */ if (output_method==CSV_OUT && output_count>-1) { get_iface_stats(0); #ifdef HAVE_USLEEP if (usleep(delay*1000) != 0) { if (errno == EINVAL) { errno = 0; /* there seems to be systems where 1million usecs is max */ usleep(999999); } } #else Sleep(delay); #endif } #endif #ifdef HAVE_FORK if (daemonize) { int nbyt = 0; /* lets fork into background */ if ((nbyt = fork()) == -1) { deinit(1,"could not fork into background: %s\n",strerror(errno)); } if (nbyt != 0) { /* nbyt is the new child pid here */ deinit(1,"forking into background\n"); } setsid(); } #endif if (output_count==0) output_count=-1; if (output_method==PLAIN_OUT && output_count==1) output_method=PLAIN_OUT_ONCE; if (output_method==PLAIN_OUT) printf("\033[2J"); /* clear screen for plain out */ while (1) { /* do the main loop */ #ifdef HTML /* open the output file */ if (output_method==HTML_OUT && out_file_path) { if (out_file) fclose(out_file); out_file=fopen(out_file_path,"w"); } #endif /* check if we will output anything */ ch=!(output_method==PLAIN_OUT_ONCE #ifdef HTML || (output_method==HTML_OUT && !daemonize) #endif ); /* print the header (info) if verbose */ if (ch) idle_chars_p=print_header(idle_chars_p); /* do the actual work, get and print stats */ get_iface_stats(ch); #if HTML /* close html tags */ if (output_method==HTML_OUT && html_header && daemonize) fprintf((out_file==NULL ? stdout : out_file),"\n\n\n"); /* close the output file, so we dont sit on it and block it */ if (out_file && output_method==HTML_OUT && daemonize) { fclose(out_file); out_file=NULL; } #endif /* handle the number of max outputs if set */ if (( #ifdef CSV output_method==CSV_OUT || #endif output_method==PLAIN_OUT) && output_count>0) { output_count--; /* go to exit if we are done, will break the while(1) */ if (output_count==0) break; } /* either refresh the output and handle gui input */ #ifdef HAVE_CURSES if (output_method==CURSES_OUT || output_method==CURSES2_OUT) { refresh(); handle_gui_input(getch()); } else #endif /* or just wait delay ms */ #ifdef HAVE_USLEEP if (usleep(delay*1000)==EINVAL) { usleep(999999); delay=999; } #else Sleep(delay); #endif /* quit if we should only output once */ if (output_method==PLAIN_OUT_ONCE #ifdef HTML || (output_method==HTML_OUT && !daemonize) #endif ) break; /* dont loop when we have plain output */ } #ifdef HTML /* do we need to output for html? */ if (output_method==HTML_OUT && !daemonize) { print_header(0); get_iface_stats(1); if (html_header) fprintf(out_file==NULL ? stdout : out_file,"\n\n\n"); } #endif /* do we need to output for plain? */ if (output_method==PLAIN_OUT_ONCE) { print_header(0); get_iface_stats(1); } deinit(0,NULL); return 0; /* only to avoid gcc warning */ }