1 /******************************************************************************
2  *  bwm-ng                                                                    *
3  *                                                                            *
4  *  Copyright (C) 2004-2006 Volker Gropp (bwmng@gropp.org)                    *
5  *                                                                            *
6  *  for more info read README.                                                *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
21  *                                                                            *
22  *****************************************************************************/
23 
24 #include "global_vars.h"
25 #include "bwm-ng.h"
26 
27 /* clear stuff and exit */
28 #ifdef __STDC__
29 void deinit(int code, char *error_msg, ...) FUNCATTR_NORETURN;
deinit(int code,char * error_msg,...)30 void deinit(int code, char *error_msg, ...) {
31 #else
32 void deinit(int code, ...) FUNCATTR_NORETURN;
33 void deinit(int code, ...) {
34 #endif
35     va_list    ap;
36 #if EXTENDED_STATS
37     int local_if_count;
38     struct double_list *list_p;
39 #endif
40 #ifdef HAVE_CURSES
41 	if (mywin!=NULL && (output_method==CURSES_OUT || output_method==CURSES2_OUT)) {
42 		/* first close curses, so we dont leave mess behind */
43 #if HAVE_CURS_SET
44         curs_set(1);
45 #endif
46 		  endwin();
47 	}
48 #endif
49 #ifdef IOCTL
50 	/* close socket if we opened it for ioctl */
51 	if (skfd >= 0) {
52 		close(skfd);
53 	}
54 #endif
55 	/* we should clean if_state, the data array */
56 	if (if_stats!=NULL) {
57 #if EXTENDED_STATS
58         /* clean avg list for each iface */
59         for (local_if_count=0;local_if_count<if_count;local_if_count++) {
60             /* free the name */
61             free(if_stats[local_if_count].if_name);
62             while (if_stats[local_if_count].avg.first!=NULL) {
63                 list_p=if_stats[local_if_count].avg.first;
64                 if_stats[local_if_count].avg.first=if_stats[local_if_count].avg.first->next;
65                 free(list_p);
66             }
67         }
68 #endif
69         free(if_stats);
70     }
71 	/* free the opt iface_list, ifaces to show or hide */
72 	if (iface_list!=NULL) free(iface_list);
73 #if CSV || HTML
74 	/* close the out_file */
75 	if (out_file!=NULL) fclose(out_file);
76     if (out_file_path!=NULL) free(out_file_path);
77 #endif
78 #ifdef __STDC__
79     /* output errormsg if given */
80     if (error_msg!=NULL) {
81         va_start(ap, error_msg);
82 		vprintf(error_msg,ap);
83     }
84 #else
85     va_start(ap);
86     vprintf(ap);
87 #endif
88 	/* we are done, say goodbye */
89     exit(code);
90 }
91 
92 
93 /* handle interrupt signal */
94 void sigint(int sig) FUNCATTR_NORETURN;
95 
96 /* sigint handler */
97 void sigint(int sig) {
98 	/* we got a sigint, call deinit and exit */
99 	deinit(0, NULL);
100 }
101 
102 inline void init() {
103 	if_count=0;
104 	delay=500;
105 #if EXTENDED_STATS
106 	avg_length=0;
107 #endif
108 	output_unit=BYTES_OUT;
109 	output_type=RATE_OUT;
110 	show_all_if=0;
111 #ifdef HAVE_CURSES
112 	output_method=CURSES_OUT;
113 	mywin=NULL;
114 	max_rt=32;
115 	scale=0;
116 	show_only_if=0;
117 #else
118 	output_method=PLAIN_OUT;
119 #endif
120 	iface_list=NULL;
121 #ifdef CSV
122 	csv_char=';';
123 #endif
124 
125 #if CSV || HTML
126 	out_file=NULL;
127 	out_file_path=NULL;
128 #endif
129 
130 	output_count=-1;
131 	daemonize=0;
132 	sumhidden=0;
133 /* gcc doesnt support #elifdef so we have to use this ugly piece */
134 #ifdef PROC_NET_DEV
135 	input_method=PROC_IN;
136 #elif defined(GETIFADDRS)
137 	input_method=GETIFADDRS_IN;
138 #elif defined(LIBSTATGRAB)
139 	input_method=LIBSTAT_IN;
140 #elif defined(SYSCTL)
141 	input_method=SYSCTL_IN;
142 #elif defined(HAVE_LIBKSTAT)
143 	input_method=KSTAT_IN;
144 #elif defined(NETSTAT)
145 	input_method=NETSTAT_IN;
146 #elif defined(WIN32)
147 	input_method=WIN32_IN;
148 #elif defined(HAVE_PROC_DISKSTATS)
149 	input_method=DISKLINUX_IN;
150 #else
151 #error "NO INPUT DEFINED!"
152 	input_method=0;
153 #endif
154 
155 	ansi_output=1;
156 
157 #ifdef HTML
158 	html_refresh=5;
159 	html_header=0;
160 #endif
161 #ifdef IOCTL
162 	skfd=-1;
163 #endif
164 	if_stats=NULL;
165 #ifdef PROC_NET_DEV
166    strncpy(PROC_FILE,PROC_NET_DEV,PATH_MAX);
167 #endif
168 
169 #ifdef PROC_DISKSTATS
170    strncpy(PROC_DISKSTATS_FILE,PROC_DISKSTATS,PATH_MAX);
171 #endif
172 #ifdef PROC_PARTITIONS
173    strncpy(PROC_PARTITIONS_FILE,PROC_PARTITIONS,PATH_MAX);
174 #endif
175 
176 #if IOSERVICE_IN
177 	long_darwin_disk_names = 0;
178 #endif
179 
180 }
181 
182 /* do the main thing */
183 int main (int argc, char *argv[]) {
184 	unsigned char idle_chars_p=0;
185 	char ch;
186 
187 	init();
188 
189     /* handle all cmd line and configfile options */
190 	get_cmdln_options(argc,argv);
191     /* check them */
192     if (output_method<0)
193         deinit(1,"invalid output selected\n");
194     if (input_method<0)
195         deinit(1,"invalid input selected\n");
196 
197 #ifdef LIBSTATGRAB
198 	if (sg_init(0) != 0) {
199 		deinit(1,"libstatgrab failed to initialise\n");
200 	}
201 #endif
202 
203     /* init total stats to zero */
204 	memset(&if_stats_total,0,(size_t)sizeof(t_iface_stats));
205 #ifdef HAVE_CURSES
206 	if (output_method==CURSES_OUT || output_method==CURSES2_OUT) {
207 		/* init curses */
208         if (init_curses())
209             signal(SIGWINCH,sigwinch);
210 	}
211 #endif
212 	/* end of init curses, now set a sigint handler to deinit the screen on ctrl-break */
213 	signal(SIGINT,sigint);
214 	signal(SIGTERM,sigint);
215 #ifdef CSV
216     /* get stats without verbose if cvs */
217 	if (output_method==CSV_OUT && output_count>-1) {
218 		get_iface_stats(0);
219 #ifdef HAVE_USLEEP
220 		if (EINVAL==usleep(delay*1000))
221 			/* there seems to be systems where 1million usecs is max */
222 			usleep(999999);
223 #else
224 		Sleep(delay);
225 #endif
226 	}
227 #endif
228 #ifdef HAVE_FORK
229 	if (daemonize) {
230 	  	int nbyt = 0;
231 	  	/* lets fork into background */
232 		if ((nbyt = fork()) == -1) {
233 			deinit(1,"could not fork into background: %s\n",strerror(errno));
234 		}
235 		if (nbyt != 0) { /* nbyt is the new child pid here */
236 			deinit(1,"forking into background\n");
237 		}
238 		setsid();
239 	}
240 #endif
241 	if (output_count==0) output_count=-1;
242 	if (output_method==PLAIN_OUT && output_count==1) output_method=PLAIN_OUT_ONCE;
243 	if (output_method==PLAIN_OUT) printf("\033[2J"); /* clear screen for plain out */
244     while (1) { /* do the main loop */
245 #ifdef HTML
246         /* open the output file */
247         if (output_method==HTML_OUT && out_file_path) {
248             if (out_file) fclose(out_file);
249             out_file=fopen(out_file_path,"w");
250         }
251 #endif
252         /* check if we will output anything */
253         ch=!(output_method==PLAIN_OUT_ONCE
254 #ifdef HTML
255                     || (output_method==HTML_OUT && !daemonize)
256 #endif
257             );
258 
259         /* print the header (info) if verbose */
260 		if (ch) idle_chars_p=print_header(idle_chars_p);
261         /* do the actual work, get and print stats */
262 		get_iface_stats(ch);
263 
264 #if HTML
265         /* close html tags */
266         if (output_method==HTML_OUT && html_header && daemonize)
267             fprintf((out_file==NULL ? stdout : out_file),"</table>\n</body>\n</html>\n");
268         /* close the output file, so we dont sit on it and block it */
269         if (out_file && output_method==HTML_OUT && daemonize) { fclose(out_file); out_file=NULL; }
270 #endif
271         /* handle the number of max outputs if set */
272 		if ((
273 #ifdef CSV
274 			    output_method==CSV_OUT ||
275 #endif
276 				output_method==PLAIN_OUT) && output_count>0) {
277 			output_count--;
278             /* go to exit if we are done, will break the while(1) */
279 			if (output_count==0) break;
280 		}
281         /* either refresh the output and handle gui input */
282 #ifdef HAVE_CURSES
283 		if (output_method==CURSES_OUT || output_method==CURSES2_OUT) {
284 			refresh();
285 			handle_gui_input(getch());
286 		} else
287 #endif
288         /* or just wait delay ms */
289 #ifdef HAVE_USLEEP
290 			if (usleep(delay*1000)==EINVAL) {
291 				usleep(999999);
292 				delay=999;
293 			}
294 #else
295 		Sleep(delay);
296 #endif
297 
298         /* quit if we should only output once */
299 		if (output_method==PLAIN_OUT_ONCE
300 #ifdef HTML
301 				|| (output_method==HTML_OUT && !daemonize)
302 #endif
303 				) break; /* dont loop when we have plain output */
304     }
305 #ifdef HTML
306 	/* do we need to output for html? */
307 	if (output_method==HTML_OUT && !daemonize) {
308 		print_header(0);
309 		get_iface_stats(1);
310         if (html_header) fprintf(out_file==NULL ? stdout : out_file,"</table>\n</body>\n</html>\n");
311 	}
312 #endif
313 	/* do we need to output for plain? */
314 	if (output_method==PLAIN_OUT_ONCE) {
315 		print_header(0);
316 		get_iface_stats(1);
317 	}
318 	deinit(0,NULL);
319 	return 0; /* only to avoid gcc warning */
320 }
321