@ -20,10 +20,12 @@
@@ -20,10 +20,12 @@
# include <sys/time.h>
# include <time.h>
# include <math.h>
# include <stdarg.h>
# include <assert.h>
# ifndef WIN32
# include <sys/resource.h>
# endif
# include <get opt.h>
# include <ccan/opt/ opt.h>
# include <jansson.h>
# include <curl/curl.h>
# include "compat.h"
@ -125,7 +127,6 @@ static int opt_queue = 0;
@@ -125,7 +127,6 @@ static int opt_queue = 0;
int opt_vectors ;
int opt_worksize ;
int opt_scantime = 60 ;
static json_t * opt_config ;
static const bool opt_time = true ;
# ifdef WANT_X8664_SSE2
static enum sha256_algos opt_algo = ALGO_SSE2_64 ;
@ -154,142 +155,255 @@ static int accepted, rejected;
@@ -154,142 +155,255 @@ static int accepted, rejected;
int hw_errors ;
static int total_queued ;
struct option_help {
const char * name ;
const char * helptext ;
} ;
static void applog_and_exit ( const char * fmt , . . . )
{
va_list ap ;
static struct option_help options_help [ ] = {
{ " help " ,
" (-h) Display this help text " } ,
va_start ( ap , fmt ) ;
vapplog ( LOG_ERR , fmt , ap ) ;
va_end ( ap ) ;
exit ( 1 ) ;
}
{ " algo XXX " ,
" (-a XXX) Specify sha256 implementation: \n "
" \t c \t \t Linux kernel sha256, implemented in C (default) "
# ifdef WANT_SSE2_4WAY
" \n \t 4way \t \t tcatm's 4-way SSE2 implementation "
# endif
# ifdef WANT_VIA_PADLOCK
" \n \t via \t \t VIA padlock implementation "
# endif
" \n \t cryptopp \t Crypto++ C/C++ implementation "
# ifdef WANT_CRYPTOPP_ASM32
" \n \t cryptopp_asm32 \t Crypto++ 32-bit assembler implementation "
# endif
# ifdef WANT_X8664_SSE2
" \n \t sse2_64 \t \t SSE2 implementation for x86_64 machines "
# endif
} ,
/* FIXME: Use asprintf for better errors. */
static char * set_algo ( const char * arg , enum sha256_algos * algo )
{
enum sha256_algos i ;
{ " config FILE " ,
" (-c FILE) JSON-format configuration file (default: none) \n "
" See example-cfg.json for an example configuration. " } ,
for ( i = 0 ; i < ARRAY_SIZE ( algo_names ) ; i + + ) {
if ( algo_names [ i ] & & ! strcmp ( arg , algo_names [ i ] ) ) {
* algo = i ;
return NULL ;
}
}
return " Unknown algorithm " ;
}
{ " cpu-threads N " ,
" (-t N) Number of miner CPU threads (default: number of processors or 0 if GPU mining) " } ,
static void show_algo ( char buf [ OPT_SHOW_LEN ] , const enum sha256_algos * algo )
{
strncpy ( buf , algo_names [ * algo ] , OPT_SHOW_LEN ) ;
}
{ " debug " ,
" (-D) Enable debug output (default: off) " } ,
static char * set_int_range ( const char * arg , int * i , int min , int max )
{
char * err = opt_set_intval ( arg , i ) ;
if ( err )
return err ;
# ifdef HAVE_OPENCL
{ " gpu-threads N " ,
" (-g N) Number of threads per-GPU (0 - 10, default: 2) " } ,
if ( * i < min | | * i > max )
return " Value out of range " ;
{ " intensity N " ,
" (-I N) Intensity of GPU scanning (0 - 14, default 4) " } ,
# endif
{ " log N " ,
" (-l N) Interval in seconds between log output (default: 5) " } ,
return NULL ;
}
# ifdef HAVE_OPENCL
{ " ndevs " ,
" (-n) Display number of detected GPUs and exit " } ,
# endif
{ " no-longpoll " ,
" Disable X-Long-Polling support (default: enabled) " } ,
static char * set_int_0_to_9999 ( const char * arg , int * i )
{
return set_int_range ( arg , i , 0 , 9999 ) ;
}
{ " pass PASSWORD " ,
" (-p PASSWORD) Password for bitcoin JSON-RPC server "
" (default: " DEF_RPC_PASSWORD " ) " } ,
static char * set_int_0_to_14 ( const char * arg , int * i )
{
return set_int_range ( arg , i , 0 , 14 ) ;
}
{ " protocol-dump " ,
" (-P) Verbose dump of protocol-level activities (default: off) " } ,
static char * set_int_0_to_10 ( const char * arg , int * i )
{
return set_int_range ( arg , i , 0 , 10 ) ;
}
{ " queue N " ,
" (-Q N) Number of extra work items to queue (0 - 10, default 0) " } ,
static char * set_url ( const char * arg , char * * p )
{
opt_set_charp ( arg , p ) ;
if ( strncmp ( arg , " http:// " , 7 ) & &
strncmp ( arg , " https:// " , 8 ) )
return " URL must start with http:// or https:// " ;
{ " quiet " ,
" (-q) Disable per-thread hashmeter output (default: off) " } ,
return NULL ;
}
{ " retries N " ,
" (-r N) Number of times to retry before giving up, if JSON-RPC call fails \n "
" \t (default: -1; use -1 for \" never \" ) " } ,
static char * set_vector ( const char * arg , int * i )
{
char * err = opt_set_intval ( arg , i ) ;
if ( err )
return err ;
{ " retry-pause N " ,
" (-R N) Number of seconds to pause, between retries \n "
" \t (default: 5) " } ,
if ( * i ! = 1 & & * i ! = 2 & & * i ! = 4 )
return " Valid vectors are 1, 2 or 4 " ;
return NULL ;
}
static char * enable_debug ( bool * flag )
{
* flag = true ;
/* Turn out verbose output, too. */
opt_log_output = true ;
return NULL ;
}
{ " scantime N " ,
" (-s N) Upper bound on time spent scanning current work, \n "
" \t in seconds. (default: 60) " } ,
/* These options are available from config file or commandline */
static struct opt_table opt_config_table [ ] = {
OPT_WITH_ARG ( " --algo|-a " ,
set_algo , show_algo , & opt_algo ,
" Specify sha256 implementation: \n "
" \t c \t \t Linux kernel sha256, implemented in C "
# ifdef WANT_SSE2_4WAY
" \n \t 4way \t \t tcatm's 4-way SSE2 implementation "
# endif
# ifdef WANT_VIA_PADLOCK
" \n \t via \t \t VIA padlock implementation "
# endif
" \n \t cryptopp \t Crypto++ C/C++ implementation "
# ifdef WANT_CRYPTOPP_ASM32
" \n \t cryptopp_asm32 \t Crypto++ 32-bit assembler implementation "
# endif
# ifdef WANT_X8664_SSE2
" \n \t sse2_64 \t \t SSE2 implementation for x86_64 machines "
# endif
) ,
OPT_WITH_ARG ( " --cpu-threads|-t " ,
set_int_0_to_9999 , opt_show_intval , & opt_n_threads ,
" Number of miner CPU threads " ) ,
OPT_WITHOUT_ARG ( " --debug|-D " ,
enable_debug , & opt_debug ,
" Enable debug output " ) ,
# ifdef HAVE_OPENCL
OPT_WITH_ARG ( " --gpu-threads|-g " ,
set_int_0_to_10 , opt_show_intval , & opt_g_threads ,
" Number of threads per GPU (0 - 10) " ) ,
OPT_WITH_ARG ( " --intensity|-I " ,
set_int_0_to_14 , opt_show_intval , & scan_intensity ,
" Intensity of GPU scanning (0 - 14) " ) ,
# endif
OPT_WITH_ARG ( " --log|-l " ,
set_int_0_to_9999 , opt_show_intval , & opt_log_interval ,
" Interval in seconds between log output " ) ,
OPT_WITHOUT_ARG ( " --no-longpoll " ,
opt_set_invbool , & want_longpoll ,
" Disable X-Long-Polling support " ) ,
OPT_WITH_ARG ( " --pass|-p " ,
opt_set_charp , NULL , & rpc_pass ,
" Password for bitcoin JSON-RPC server " ) ,
OPT_WITHOUT_ARG ( " --protocol-dump|-P " ,
opt_set_bool , & opt_protocol ,
" Verbose dump of protocol-level activities " ) ,
OPT_WITH_ARG ( " --queue|-Q " ,
set_int_0_to_9999 , opt_show_intval , & opt_queue ,
" Number of extra work items to queue " ) ,
OPT_WITHOUT_ARG ( " --quiet|-q " ,
opt_set_bool , & opt_quiet ,
" Disable per-thread hashmeter output " ) ,
OPT_WITH_ARG ( " --retries|-r " ,
opt_set_intval , opt_show_intval , & opt_retries ,
" Number of times to retry before giving up, if JSON-RPC call fails (-1 means never) " ) ,
OPT_WITH_ARG ( " --retry-pause|-R " ,
set_int_0_to_9999 , opt_show_intval , & opt_fail_pause ,
" Number of seconds to pause, between retries " ) ,
OPT_WITH_ARG ( " --scan-time|-s " ,
set_int_0_to_9999 , opt_show_intval , & opt_scantime ,
" Upper bound on time spent scanning current work, in seconds " ) ,
# ifdef HAVE_SYSLOG_H
{ " syslog " ,
" Use system log for output messages (default: standard error) " } ,
OPT_WITHOUT_ARG ( " --syslog " ,
opt_set_bool , & use_syslog ,
" Use system log for output messages (default: standard error) " ) ,
# endif
OPT_WITH_ARG ( " --url|-o " ,
set_url , opt_show_charp , & rpc_url ,
" URL for bitcoin JSON-RPC server " ) ,
OPT_WITH_ARG ( " --user|-u " ,
opt_set_charp , NULL , & rpc_user ,
" Username for bitcoin JSON-RPC server " ) ,
# ifdef HAVE_OPENCL
OPT_WITH_ARG ( " --vectors|-v " ,
set_vector , NULL , & opt_vectors ,
" Override detected optimal vector width (1, 2 or 4) " ) ,
# endif
OPT_WITHOUT_ARG ( " --verbose " ,
opt_set_bool , & opt_log_output ,
" Log verbose output to stderr as well as status output " ) ,
# ifdef HAVE_OPENCL
OPT_WITH_ARG ( " --worksize|-w " ,
set_int_0_to_9999 , opt_show_intval , & opt_worksize ,
" Override detected optimal worksize " ) ,
# endif
OPT_WITH_ARG ( " --userpass|-O " ,
opt_set_charp , NULL , & rpc_userpass ,
" Username:Password pair for bitcoin JSON-RPC server " ) ,
OPT_ENDTABLE
} ;
{ " url URL " ,
" (-o URL) URL for bitcoin JSON-RPC server "
" (default: " DEF_RPC_URL " ) " } ,
static char * parse_config ( json_t * config )
{
static char err_buf [ 200 ] ;
json_t * val ;
struct opt_table * opt ;
for ( opt = opt_config_table ; opt - > type ! = OPT_END ; opt + + ) {
char * p , * name ;
/* We don't handle subtables. */
assert ( ! ( opt - > type & OPT_SUBTABLE ) ) ;
/* Pull apart the option name(s). */
name = strdup ( opt - > names ) ;
for ( p = strtok ( name , " | " ) ; p ; p = strtok ( NULL , " | " ) ) {
char * err ;
/* Ignore short options. */
if ( p [ 1 ] ! = ' - ' )
continue ;
val = json_object_get ( config , p + 2 ) ;
if ( ! val )
continue ;
if ( ( opt - > type & OPT_HASARG ) & & json_is_string ( val ) ) {
err = opt - > cb_arg ( json_string_value ( val ) ,
opt - > u . arg ) ;
} else if ( ( opt - > type & OPT_NOARG ) & & json_is_true ( val ) ) {
err = opt - > cb ( opt - > u . arg ) ;
} else {
err = " Invalid value " ;
}
if ( err ) {
sprintf ( err_buf , " Parsing JSON option %s: %s " ,
p , err ) ;
return err_buf ;
}
}
free ( name ) ;
}
return NULL ;
}
{ " userpass USERNAME:PASSWORD " ,
" (-O USERNAME:PASSWORD) Username:Password pair for bitcoin JSON-RPC server "
" (default: " DEF_RPC_USERPASS " ) " } ,
static char * load_config ( const char * arg , void * unused )
{
json_error_t err ;
json_t * config ;
{ " user USERNAME " ,
" (-u USERNAME) Username for bitcoin JSON-RPC server "
" (default: " DEF_RPC_USERNAME " ) " } ,
config = json_load_file ( arg , & err ) ;
if ( ! json_is_object ( config ) )
return " JSON decode of file failed " ;
{ " verbose " ,
" (-V) Log verbose output to stderr as well as status output (default: off) " } ,
/* Parse the config now, so we can override it. That can keep pointers
* so don ' t free config object . */
return parse_config ( config ) ;
}
/* These options are available from commandline only */
static struct opt_table opt_cmdline_table [ ] = {
OPT_WITH_ARG ( " --config|-c " ,
load_config , NULL , NULL ,
" Load a JSON-format configuration file \n "
" See example-cfg.json for an example configuration. " ) ,
OPT_WITHOUT_ARG ( " --help|-h " ,
opt_usage_and_exit ,
# ifdef HAVE_OPENCL
{ " vectors N " ,
" (-v N) Override detected optimal vector width (default: detected, 1,2 or 4) " } ,
{ " worksize N " ,
" (-w N) Override detected optimal worksize (default: detected) " } ,
# endif
} ;
static struct option options [ ] = {
{ " algo " , 1 , NULL , ' a ' } ,
{ " config " , 1 , NULL , ' c ' } ,
{ " cpu-threads " , 1 , NULL , ' t ' } ,
{ " gpu-threads " , 1 , NULL , ' g ' } ,
{ " debug " , 0 , NULL , ' D ' } ,
{ " help " , 0 , NULL , ' h ' } ,
{ " intensity " , 1 , NULL , ' I ' } ,
{ " log " , 1 , NULL , ' l ' } ,
{ " ndevs " , 0 , NULL , ' n ' } ,
{ " no-longpoll " , 0 , NULL , 1003 } ,
{ " pass " , 1 , NULL , ' p ' } ,
{ " protocol-dump " , 0 , NULL , ' P ' } ,
{ " queue " , 1 , NULL , ' Q ' } ,
{ " quiet " , 0 , NULL , ' q ' } ,
{ " retries " , 1 , NULL , ' r ' } ,
{ " retry-pause " , 1 , NULL , ' R ' } ,
{ " scantime " , 1 , NULL , ' s ' } ,
# ifdef HAVE_SYSLOG_H
{ " syslog " , 0 , NULL , 1004 } ,
" \n Built with CPU and GPU mining support. \n \n " ,
# else
" \n Built with CPU mining support only. \n \n " ,
# endif
{ " url " , 1 , NULL , ' o ' } ,
{ " user " , 1 , NULL , ' u ' } ,
{ " verbose " , 0 , NULL , ' V ' } ,
{ " vectors " , 1 , NULL , ' v ' } ,
{ " worksize " , 1 , NULL , ' w ' } ,
{ " userpass " , 1 , NULL , ' O ' } ,
{ 0 , 0 , 0 , 0 }
" Print this message " ) ,
OPT_ENDTABLE
} ;
static bool jobj_binary ( const json_t * obj , const char * key ,
@ -1313,221 +1427,6 @@ static void *wakeup_thread(void *userdata)
@@ -1313,221 +1427,6 @@ static void *wakeup_thread(void *userdata)
return NULL ;
}
static void show_usage ( void )
{
int i ;
printf ( " cgminer version %s \n " , VERSION ) ;
# ifdef HAVE_OPENCL
printf ( " Built with CPU and GPU mining support. \n \n " ) ;
# else
printf ( " Built with CPU mining support only. \n \n " ) ;
# endif
printf ( " Usage: \t cgminer [options] \n \n Supported options: \n " ) ;
for ( i = 0 ; i < ARRAY_SIZE ( options_help ) ; i + + ) {
struct option_help * h ;
h = & options_help [ i ] ;
printf ( " --%s \n %s \n \n " , h - > name , h - > helptext ) ;
}
exit ( 1 ) ;
}
static void parse_arg ( int key , char * arg )
{
int v , i ;
switch ( key ) {
case ' a ' :
for ( i = 0 ; i < ARRAY_SIZE ( algo_names ) ; i + + ) {
if ( algo_names [ i ] & &
! strcmp ( arg , algo_names [ i ] ) ) {
opt_algo = i ;
break ;
}
}
if ( i = = ARRAY_SIZE ( algo_names ) )
show_usage ( ) ;
break ;
case ' c ' : {
json_error_t err ;
if ( opt_config )
json_decref ( opt_config ) ;
opt_config = json_load_file ( arg , & err ) ;
if ( ! json_is_object ( opt_config ) ) {
applog ( LOG_ERR , " JSON decode of %s failed " , arg ) ;
show_usage ( ) ;
}
break ;
}
case ' g ' :
v = atoi ( arg ) ;
if ( v < 0 | | v > 10 )
show_usage ( ) ;
opt_g_threads = v ;
break ;
case ' D ' :
opt_debug = true ;
opt_log_output = true ;
break ;
case ' I ' :
v = atoi ( arg ) ;
if ( v < 0 | | v > 14 ) /* sanity check */
show_usage ( ) ;
scan_intensity = v ;
break ;
case ' l ' :
v = atoi ( arg ) ;
if ( v < 0 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_log_interval = v ;
break ;
case ' n ' :
opt_log_output = true ;
opt_ndevs = true ;
break ;
case ' p ' :
free ( rpc_pass ) ;
rpc_pass = strdup ( arg ) ;
break ;
case ' P ' :
opt_protocol = true ;
break ;
case ' Q ' :
v = atoi ( arg ) ;
if ( v < 0 | | v > 10 )
show_usage ( ) ;
opt_queue = v ;
break ;
case ' q ' :
opt_quiet = true ;
break ;
case ' r ' :
v = atoi ( arg ) ;
if ( v < - 1 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_retries = v ;
break ;
case ' R ' :
v = atoi ( arg ) ;
if ( v < 1 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_fail_pause = v ;
break ;
case ' s ' :
v = atoi ( arg ) ;
if ( v < 1 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_scantime = v ;
break ;
case ' t ' :
v = atoi ( arg ) ;
if ( v < 0 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_n_threads = v ;
break ;
case ' u ' :
free ( rpc_user ) ;
rpc_user = strdup ( arg ) ;
break ;
case ' V ' :
opt_log_output = true ;
break ;
case ' v ' :
v = atoi ( arg ) ;
if ( v ! = 1 & & v ! = 2 & & v ! = 4 )
show_usage ( ) ;
opt_vectors = v ;
break ;
case ' w ' :
v = atoi ( arg ) ;
if ( v < 1 | | v > 9999 ) /* sanity check */
show_usage ( ) ;
opt_worksize = v ;
break ;
case ' o ' : /* --url */
if ( strncmp ( arg , " http:// " , 7 ) & &
strncmp ( arg , " https:// " , 8 ) )
show_usage ( ) ;
free ( rpc_url ) ;
rpc_url = strdup ( arg ) ;
break ;
case ' O ' : /* --userpass */
if ( ! strchr ( arg , ' : ' ) )
show_usage ( ) ;
free ( rpc_userpass ) ;
rpc_userpass = strdup ( arg ) ;
break ;
case 1003 :
want_longpoll = false ;
break ;
case 1004 :
use_syslog = true ;
break ;
case ' ? ' :
default :
show_usage ( ) ;
}
}
static void parse_config ( void )
{
int i ;
json_t * val ;
if ( ! json_is_object ( opt_config ) )
return ;
for ( i = 0 ; i < ARRAY_SIZE ( options ) ; i + + ) {
if ( ! options [ i ] . name )
break ;
if ( ! strcmp ( options [ i ] . name , " config " ) )
continue ;
val = json_object_get ( opt_config , options [ i ] . name ) ;
if ( ! val )
continue ;
if ( options [ i ] . has_arg & & json_is_string ( val ) ) {
char * s = strdup ( json_string_value ( val ) ) ;
if ( ! s )
break ;
parse_arg ( options [ i ] . val , s ) ;
free ( s ) ;
} else if ( ! options [ i ] . has_arg & & json_is_true ( val ) )
parse_arg ( options [ i ] . val , " " ) ;
else
applog ( LOG_ERR , " JSON option %s invalid " ,
options [ i ] . name ) ;
}
}
static void parse_cmdline ( int argc , char * argv [ ] )
{
int key ;
while ( 1 ) {
key = getopt_long ( argc , argv , " a:c:Dg:I:l:no:O:p:PQ:qr:R:s:t:u:Vv:w:h? " , options , NULL ) ;
if ( key < 0 )
break ;
parse_arg ( key , optarg ) ;
}
parse_config ( ) ;
}
int main ( int argc , char * argv [ ] )
{
struct thr_info * thr ;
@ -1553,7 +1452,16 @@ int main (int argc, char *argv[])
@@ -1553,7 +1452,16 @@ int main (int argc, char *argv[])
rpc_url = strdup ( DEF_RPC_URL ) ;
/* parse command line */
parse_cmdline ( argc , argv ) ;
opt_register_table ( opt_config_table ,
" Options for both config file and command line " ) ;
opt_register_table ( opt_cmdline_table ,
" Options for command line only " ) ;
opt_parse ( & argc , argv , applog_and_exit ) ;
if ( argc ! = 1 ) {
applog ( LOG_ERR , " Unexpected extra commandline arguments " ) ;
return 1 ;
}
# ifdef HAVE_OPENCL
if ( opt_ndevs ) {