wanpipe/util/bwm-ng/src/options.c

491 lines
15 KiB
C

/******************************************************************************
* bwm-ng handle cmdline and config file options *
* *
* Copyright (C) 2004-2007 Volker Gropp (bwmng@gropp.org) *
* *
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
* *
*****************************************************************************/
#define EXTERN
#include "global_vars.h"
#include "options.h"
#ifdef CONFIG_FILE
/******************************************************************************
* This is a replacement for strsep which is not portable (missing on Solaris).
*/
static char* getToken(char** str, const char* delims)
{
char* token;
if (*str==NULL) {
/* No more tokens */
return NULL;
}
token=*str;
while (**str!='\0') {
if (strchr(delims,**str)!=NULL) {
**str='\0';
(*str)++;
return token;
}
(*str)++;
}
/* There is no other token */
*str=NULL;
return token;
}
/******************************************************************************/
#endif
inline int str2output_unit(char *optarg) {
if (optarg) {
if (!strcasecmp(optarg,"bytes")) return BYTES_OUT;
if (!strcasecmp(optarg,"bits")) return BITS_OUT;
if (!strcasecmp(optarg,"packets")) return PACKETS_OUT;
if (!strcasecmp(optarg,"errors")) return ERRORS_OUT;
}
return BYTES_OUT;
}
#if EXTENDED_STATS
inline int str2output_type(char *optarg) {
if (optarg) {
if (!strcasecmp(optarg,"rate")) return RATE_OUT;
if (!strcasecmp(optarg,"max")) return MAX_OUT;
if (!strcasecmp(optarg,"sum")) return SUM_OUT;
if (!strcasecmp(optarg,"avg")) return AVG_OUT;
}
return RATE_OUT;
}
#endif
inline int str2out_method(char *optarg) {
if (optarg) {
if (!strcasecmp(optarg,"plain")) return PLAIN_OUT;
#ifdef HAVE_CURSES
else
if (!strcasecmp(optarg,"curses")) return CURSES_OUT;
else
if (!strcasecmp(optarg,"curses2")) return CURSES2_OUT;
#endif
#ifdef CSV
else
if (!strcasecmp(optarg,"csv")) return CSV_OUT;
#endif
#ifdef HTML
else
if (!strcasecmp(optarg,"html")) return HTML_OUT;
#endif
}
return -1;
}
inline int str2in_method(char *optarg) {
if (optarg) {
#ifdef PROC_NET_DEV
if (!strcasecmp(optarg,"proc")) return PROC_IN;
#endif
#ifdef NETSTAT
if (!strcasecmp(optarg,"netstat")) return NETSTAT_IN;
#endif
#ifdef LIBSTATGRAB
if (!strcasecmp(optarg,"libstat") || !strcasecmp(optarg,"statgrab") || !strcasecmp(optarg,"libstatgrab")) return LIBSTAT_IN;
if (!strcasecmp(optarg,"libstatdisk")) return LIBSTATDISK_IN;
#endif
#ifdef GETIFADDRS
if (!strcasecmp(optarg,"getifaddrs")) return GETIFADDRS_IN;
#endif
#if DEVSTAT_IN
if (!strcasecmp(optarg,"devstat")) return DEVSTAT_IN;
#endif
#ifdef SYSCTL
if (!strcasecmp(optarg,"sysctl")) return SYSCTL_IN;
#endif
#if SYSCTLDISK_IN
if (!strcasecmp(optarg,"sysctldisk")) return SYSCTLDISK_IN;
#endif
#ifdef PROC_DISKSTATS
if (!strcasecmp(optarg,"disk")) return DISKLINUX_IN;
#endif
#ifdef WIN32
if (!strcasecmp(optarg,"win32")) return WIN32_IN;
#endif
#ifdef HAVE_LIBKSTAT
if (!strcasecmp(optarg,"kstat")) return KSTAT_IN;
if (!strcasecmp(optarg,"kstatdisk")) return KSTATDISK_IN;
#endif
#if IOSERVICE_IN
if (!strcasecmp(optarg,"ioservice")) return IOSERVICE_IN;
#endif
}
return -1;
}
#ifdef CONFIG_FILE
char *trim_whitespace(char *str) {
char *dud = str;
int i;
/* beginning whitespace first */
while( (int)*dud && isspace((int)*dud) )
++dud;
/* now trailing whitespace */
i = strlen(dud) - 1;
while( i>=0 && isspace((int)dud[i]) )
--i;
dud[i+1] = 0;
return dud;
}
int read_config(char *config_file) {
FILE *fp;
char *buffer;
char *token, *value;
if (config_file==NULL) return -1;
if( (fp = fopen( config_file, "r" ) ) == NULL ) {
return -1;
}
buffer = (char*)malloc( sizeof(char) * 4096 );
dynamic=1;
while( fgets( buffer, 4096, fp ) ) {
value = trim_whitespace( buffer );
token = getToken( &value, "=" );
if( token == NULL ) /* ignore this line if there isn't a token/value pair */
continue;
token = trim_whitespace( token );
if( strcasecmp( token, "TIMEOUT" ) == 0 ) {
if (value && atol(value)>0) { delay=atol(value); }
#ifdef PROC_NET_DEV
} else if( strcasecmp( token, "PROCFILE" ) == 0 ) {
if (value && (strlen(value)<PATH_MAX)) strcpy(PROC_FILE,value);
#endif
#ifdef PROC_DISKSTATS
} else if( strcasecmp( token, "DISKSTATSFILE" ) == 0 ) {
if (value && (strlen(value)<PATH_MAX)) strcpy(PROC_DISKSTATS_FILE,value);
} else if( strcasecmp( token, "PARTITIONSFILE" ) == 0 ) {
if (value && (strlen(value)<PATH_MAX)) strcpy(PROC_PARTITIONS_FILE,value);
#endif
#if ALLOW_NETSTATPATH
#ifdef NETSTAT
} else if( strcasecmp( token, "NETSTAT" ) == 0 ) {
if (value && (strlen(value)<PATH_MAX)) strcpy(NETSTAT_FILE,value);
#endif
#endif
} else if( strcasecmp( token, "INPUT" ) == 0 ) {
if (value) input_method=str2in_method(value);
} else if( strcasecmp( token, "ANSIOUT" ) == 0 ) {
if (value) ansi_output=value[0]=='0' ? 1 : 0;
} else if( strcasecmp( token, "DYNAMIC" ) == 0 ) {
if (value) dynamic=value[0]=='0' ? 1 : 0;
} else if( strcasecmp( token, "UNIT" ) == 0 ) {
if (value) output_unit=str2output_unit(value);
#if EXTENDED_STATS
} else if( strcasecmp( token, "TYPE" ) == 0 ) {
if (value) output_type=str2output_type(value);
} else if( strcasecmp( token, "AVGLENGTH" ) == 0 ) {
if (value) avg_length=atoi(value)*1000;
#endif
} else if( strcasecmp( token, "ALLIF" ) == 0 ) {
if (value) show_all_if=value[0];
} else if( strcasecmp( token, "INTERFACES" ) == 0 ) {
if (value) iface_list=(char *)strdup(value);
} else if( strcasecmp( token, "OUTPUT" ) == 0 ) {
if (value) output_method=str2out_method(value);
#ifdef CSV
} else if( strcasecmp( token, "CSVCHAR" ) == 0 ) {
if (value) csv_char=value[0];
#endif
#if CSV || HTML
} else if( strcasecmp( token, "OUTFILE" ) == 0 ) {
if (value) {
if (out_file) fclose(out_file);
out_file=fopen(value,"a");
if (!out_file) deinit(1, "failed to open outfile\n");
if (out_file_path) free(out_file_path);
out_file_path=(char *)strdup(value);
}
#endif
} else if( strcasecmp( token, "COUNT" ) == 0 ) {
if (value) output_count=atol(value);
} else if( strcasecmp( token, "DAEMON" ) == 0 ) {
if (value) daemonize=value[0]=='0' ? 0 : 1;
} else if( strcasecmp( token, "SUMHIDDEN" ) == 0 ) {
if (value) sumhidden=value[0]=='0' ? 0 : 1;
#if IOSERVICE_IN
} else if( strcasecmp( token, "LONGDISKNAMES" ) == 0) {
if (value) long_darwin_disk_names=value[0]=='0' ? 0 : 1;
#endif
#ifdef HTML
} else if( strcasecmp( token, "HTMLREFRESH" ) == 0 ) {
if (value && atol(value)>0) { html_refresh=atol(value); }
} else if( strcasecmp( token, "HTMLHEADER" ) == 0 ) {
if (value) html_header=value[0]=='0' ? 0 : 1;
#endif
}
}
free(buffer);
fclose(fp);
return 0;
}
#endif
void get_cmdln_options(int argc, char *argv[]) {
int o;
#if CONFIG_FILE && HAVE_GETPWUID
static struct passwd *pwd_entry;
char *str;
#endif
#ifdef LONG_OPTIONS
int option_index = 0;
dynamic=1;
output_unit=BITS_OUT;
static struct option long_options[] = {
{"timeout", 1, 0, 't'},
#ifdef PROC_NET_DEV
{"procfile",1,0,'f'},
#endif
#ifdef PROC_DISKSTATS
{"diskstatsfile",1,0,1000},
{"partitionsfile",1,0,1001},
#endif
#if NETSTAT && ALLOW_NETSTATPATH
{"netstat",1,0,'n'},
#endif
#if IOSERVICE_IN
{"longdisknames",0,0,1002},
#endif
{"input",1,0,'i'},
{"dynamic",1,0,'d'},
{"help", 0, 0, 'h'},
{"version",0,0,'V'},
{"allif",1,0,'a'},
{"unit",1,0,'u'},
{"ansiout",0,0,'N'},
#if EXTENDED_STATS
{"type",1,0,'T'},
{"avglength",1,0,'A'},
#endif
{"interfaces",1,0,'I'},
{"sumhidden",1,0,'S'},
{"output",1,0,'o'},
#ifdef CSV
{"csvchar",1,0,'C'},
{"csvfile",1,0,'F'},
#endif
{"count",1,0,'c'},
{"daemon",1,0,'D'},
#ifdef HTML
{"htmlrefresh",1,0,'R'},
{"htmlheader",1,0,'H'},
#endif
{0,0,0,0}
};
#endif
#ifdef CONFIG_FILE
/* loop till first non option argument */
opterr=0;
while (1) {
#ifdef LONG_OPTIONS
o=getopt_long (argc,argv,SHORT_OPTIONS,long_options, &option_index);
#else
o=getopt (argc,argv,SHORT_OPTIONS);
#endif
if (o==-1) break;
}
opterr=1;
if (optind < argc) {
read_config(argv[optind]);
} else {
read_config("/etc/bwm-ng.conf");
#ifdef HAVE_GETPWUID
pwd_entry=getpwuid(getuid());
if (pwd_entry!=NULL) {
str=(char*)malloc(strlen(pwd_entry->pw_dir)+14);
snprintf(str,strlen(pwd_entry->pw_dir)+14,"%s/.bwm-ng.conf",pwd_entry->pw_dir);
read_config(str);
free(str);
}
#endif
}
/* reset getopt again */
optind=1;
#endif
/* get command line arguments, kinda ugly, wanna rewrite it? */
while (1) {
#ifdef LONG_OPTIONS
o=getopt_long (argc,argv,SHORT_OPTIONS,long_options, &option_index);
#else
o=getopt (argc,argv,SHORT_OPTIONS);
#endif
if (o==-1) break;
switch (o) {
case '?': printf("unknown option: %s\n",argv[optind-1]);
exit(EXIT_FAILURE);
break;
/* ugly workaround to handle optional arguments for all platforms */
case ':': if (!strcmp(argv[optind-1],"-a") || !strcasecmp(argv[optind-1],"--allif"))
show_all_if=1;
else if (!strcmp(argv[optind-1],"-d") || !strcasecmp(argv[optind-1],"--dynamic"))
dynamic=1;
else if (!strcmp(argv[optind-1],"-D") || !strcasecmp(argv[optind-1],"--daemon"))
daemonize=1;
#ifdef HTML
else if (!strcmp(argv[optind-1],"-H") || !strcasecmp(argv[optind-1],"--htmlheader"))
html_header=1;
#endif
else if (!strcmp(argv[optind-1],"-S") || !strcasecmp(argv[optind-1],"--sumhidden"))
sumhidden=1;
else {
printf("%s requires an argument!\n",argv[optind-1]);
exit(EXIT_FAILURE);
}
break;
#ifdef PROC_DISKSTATS
case 1000:
if (strlen(optarg)<PATH_MAX)
strcpy(PROC_DISKSTATS_FILE,optarg);
break;
case 1001:
if (strlen(optarg)<PATH_MAX)
strcpy(PROC_PARTITIONS_FILE,optarg);
break;
#endif
#if IOSERVICE_IN
case 1002:
long_darwin_disk_names=!long_darwin_disk_names;
break;
#endif
case 'D':
if (optarg) daemonize=atoi(optarg);
break;
#ifdef HTML
case 'R':
if ((optarg) && atol(optarg)>0) { html_refresh=atol(optarg); }
break;
case 'H':
if (optarg) html_header=atoi(optarg);
break;
#endif
case 'c':
if (optarg) output_count=atol(optarg);
break;
#if CSV || HTML
case 'F':
if (optarg) {
if (out_file) fclose(out_file);
out_file=fopen(optarg,"a");
if (!out_file) deinit(1, "failed to open outfile\n");
if (out_file_path) free(out_file_path);
out_file_path=(char *)strdup(optarg);
}
break;
#endif
#ifdef CSV
case 'C':
if (optarg) csv_char=optarg[0];
break;
#endif
case 'h':
cmdln_printhelp();
break;
#ifdef PROC_NET_DEV
case 'f':
if (optarg && (strlen(optarg)<PATH_MAX)) strcpy(PROC_FILE,optarg);
break;
#endif
case 'i':
if (optarg) {
input_method=str2in_method(optarg);
}
break;
case 'I':
if (optarg) iface_list=(char *)strdup(optarg);
break;
case 'S':
if (optarg) sumhidden=atoi(optarg);
break;
case 'o':
if (optarg) {
output_method=str2out_method(optarg);
}
break;
case 'N':
ansi_output=!ansi_output;
case 'a':
if (optarg) show_all_if=atoi(optarg);
break;
case 't':
if ((optarg) && atol(optarg)>0) { delay=atol(optarg); }
break;
#if EXTENDED_STATS
case 'T':
output_type=str2output_type(optarg);
break;
case 'A':
if (optarg) avg_length=atoi(optarg)*1000;
break;
#endif
case 'd':
if (optarg) dynamic=atoi(optarg);
break;
case 'u':
output_unit=str2output_unit(optarg);
break;
#if NETSTAT && ALLOW_NETSTATPATH
case 'n':
if (optarg && (strlen(optarg)<PATH_MAX)) strcpy(NETSTAT_FILE,optarg);
break;
#endif
case 'V':
print_version;
exit(EXIT_SUCCESS);
break;
}
}
if (iface_list==NULL && show_all_if==1) show_all_if=2;
#if EXTENDED_STATS
/* default init of avg_length */
if (avg_length==0) {
if (delay<AVG_LENGTH/2)
avg_length=AVG_LENGTH;
else
avg_length=(delay*2)+1;
} else /* avg_length was set via cmdline or config file, better check it */
if (delay*2>=avg_length) deinit(1, "avglength needs to be a least twice the value of timeout\n");
#endif
if ((output_unit==ERRORS_OUT && !net_input_method(input_method)) ||
(output_unit==PACKETS_OUT && input_method==LIBSTATDISK_IN))
output_unit=BITS_OUT;
return;
}