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