mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-21 21:04:32 -04:00
- added argstream to handle commandline arguments
- switched tests to use the common value of argstream in libretroshare, rather than the one in tests/common - reworked command line arguments in rsinit and retroshare-nogui. - improved passwd hash explanations - improved command-line help. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6559 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
9ffb625f9a
commit
aba5033604
13 changed files with 1031 additions and 1094 deletions
|
@ -92,7 +92,7 @@ std::string pgp_pwd_callback(void * /*hook*/, const char *uid_hint, const char *
|
||||||
fprintf(stderr, "pgp_pwd_callback() called.\n");
|
fprintf(stderr, "pgp_pwd_callback() called.\n");
|
||||||
#endif
|
#endif
|
||||||
std::string password;
|
std::string password;
|
||||||
rsicontrol->getNotify().askForPassword(uid_hint, prev_was_bad, password) ;
|
rsicontrol->getNotify().askForPassword(std::string("Please enter your PGP password for key ")+uid_hint+" :", prev_was_bad, password) ;
|
||||||
|
|
||||||
return password ;
|
return password ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "util/rswin.h"
|
#include "util/rswin.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "util/argstream.h"
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "util/rsrandom.h"
|
#include "util/rsrandom.h"
|
||||||
|
@ -122,12 +123,11 @@ class RsInitConfig
|
||||||
static bool forceExtPort;
|
static bool forceExtPort;
|
||||||
static bool forceLocalAddr;
|
static bool forceLocalAddr;
|
||||||
static unsigned short port;
|
static unsigned short port;
|
||||||
static char inet[256];
|
static std::string inet ;
|
||||||
|
|
||||||
/* Logging */
|
/* Logging */
|
||||||
static bool haveLogFile;
|
static bool haveLogFile;
|
||||||
static bool outStderr;
|
static bool outStderr;
|
||||||
static bool haveDebugLevel;
|
|
||||||
static int debugLevel;
|
static int debugLevel;
|
||||||
static std::string logfname;
|
static std::string logfname;
|
||||||
|
|
||||||
|
@ -183,12 +183,11 @@ bool RsInitConfig::isWindowsXP = false;
|
||||||
bool RsInitConfig::forceExtPort;
|
bool RsInitConfig::forceExtPort;
|
||||||
bool RsInitConfig::forceLocalAddr;
|
bool RsInitConfig::forceLocalAddr;
|
||||||
unsigned short RsInitConfig::port;
|
unsigned short RsInitConfig::port;
|
||||||
char RsInitConfig::inet[256];
|
std::string RsInitConfig::inet;
|
||||||
|
|
||||||
/* Logging */
|
/* Logging */
|
||||||
bool RsInitConfig::haveLogFile;
|
bool RsInitConfig::haveLogFile;
|
||||||
bool RsInitConfig::outStderr;
|
bool RsInitConfig::outStderr;
|
||||||
bool RsInitConfig::haveDebugLevel;
|
|
||||||
int RsInitConfig::debugLevel;
|
int RsInitConfig::debugLevel;
|
||||||
std::string RsInitConfig::logfname;
|
std::string RsInitConfig::logfname;
|
||||||
|
|
||||||
|
@ -220,12 +219,11 @@ void RsInit::InitRsConfig()
|
||||||
RsInitConfig::outStderr = false;
|
RsInitConfig::outStderr = false;
|
||||||
RsInitConfig::forceExtPort = false;
|
RsInitConfig::forceExtPort = false;
|
||||||
|
|
||||||
strcpy(RsInitConfig::inet, "127.0.0.1");
|
RsInitConfig::inet = std::string("127.0.0.1");
|
||||||
|
|
||||||
RsInitConfig::autoLogin = false; // .
|
RsInitConfig::autoLogin = false; // .
|
||||||
RsInitConfig::startMinimised = false;
|
RsInitConfig::startMinimised = false;
|
||||||
RsInitConfig::passwd = "";
|
RsInitConfig::passwd = "";
|
||||||
RsInitConfig::haveDebugLevel = false;
|
|
||||||
RsInitConfig::debugLevel = PQL_WARNING;
|
RsInitConfig::debugLevel = PQL_WARNING;
|
||||||
RsInitConfig::udpListenerOnly = false;
|
RsInitConfig::udpListenerOnly = false;
|
||||||
|
|
||||||
|
@ -330,19 +328,12 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||||
{
|
{
|
||||||
|
|
||||||
/* THIS IS A HACK TO ALLOW WINDOWS TO ACCEPT COMMANDLINE ARGUMENTS */
|
/* THIS IS A HACK TO ALLOW WINDOWS TO ACCEPT COMMANDLINE ARGUMENTS */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
int i;
|
int i;
|
||||||
#ifdef USE_CMD_ARGS
|
#ifdef USE_CMD_ARGS
|
||||||
char** argv = argvIgnored;
|
char** argv = argvIgnored;
|
||||||
argc = argcIgnored;
|
argc = argcIgnored;
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
const int MAX_ARGS = 32;
|
const int MAX_ARGS = 32;
|
||||||
int j;
|
int j;
|
||||||
char *argv[MAX_ARGS];
|
char *argv[MAX_ARGS];
|
||||||
|
@ -368,24 +359,16 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argc = i;
|
argc = i;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for( i=0; i<argc; i++)
|
for( i=0; i<argc; i++)
|
||||||
{
|
|
||||||
printf("%d: %s\n", i, argv[i]);
|
printf("%d: %s\n", i, argv[i]);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* for static PThreads under windows... we need to init the library...
|
/* for static PThreads under windows... we need to init the library...
|
||||||
*/
|
*/
|
||||||
#ifdef PTW32_STATIC_LIB
|
#ifdef PTW32_STATIC_LIB
|
||||||
pthread_win32_process_attach_np();
|
pthread_win32_process_attach_np();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
|
|
||||||
|
@ -394,6 +377,41 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||||
/* getopt info: every availiable option is listed here. if it is followed by a ':' it
|
/* getopt info: every availiable option is listed here. if it is followed by a ':' it
|
||||||
needs an argument. If it is followed by a '::' the argument is optional.
|
needs an argument. If it is followed by a '::' the argument is optional.
|
||||||
*/
|
*/
|
||||||
|
//RsInitConfig::logfname = "" ;
|
||||||
|
//RsInitConfig::inet = "" ;
|
||||||
|
|
||||||
|
argstream as(argc,argv) ;
|
||||||
|
|
||||||
|
as >> option('a',"auto-login" ,RsInitConfig::autoLogin ,"AutoLogin (Windows Only) + StartMinimised")
|
||||||
|
>> option('m',"minimized" ,RsInitConfig::startMinimised ,"Start minimized." )
|
||||||
|
>> option('s',"stderr" ,RsInitConfig::outStderr ,"output to stderr instead of log file." )
|
||||||
|
>> option('u',"udp" ,RsInitConfig::udpListenerOnly,"Only listen to UDP." )
|
||||||
|
>> option('e',"external-port" ,RsInitConfig::forceExtPort ,"Use a forwarded external port." )
|
||||||
|
|
||||||
|
>> parameter('l',"log-file" ,RsInitConfig::logfname ,"logfile" ,"Set Log filename." ,false)
|
||||||
|
>> parameter('d',"debug-level" ,RsInitConfig::debugLevel ,"level" ,"Set debug level." ,false)
|
||||||
|
>> parameter('w',"password" ,RsInitConfig::passwd ,"password" ,"Set Login Password." ,false)
|
||||||
|
>> parameter('i',"ip-address" ,RsInitConfig::inet ,"nnn.nnn.nnn.nnn", "Set IP address to use." ,false)
|
||||||
|
>> parameter('p',"port" ,RsInitConfig::port ,"port", "Set listenning port to use." ,false)
|
||||||
|
>> parameter('c',"base-dir" ,RsInitConfig::basedir ,"directory", "Set base directory." ,false)
|
||||||
|
>> parameter('U',"user-id" ,prefUserString ,"ID", "[User Name/GPG id/SSL id] Sets Account to Use, Useful when Autologin is enabled",false)
|
||||||
|
>> parameter('r',"link" ,RsInitConfig::RetroShareLink ,"retroshare://...", "Use a given Retroshare Link" ,false)
|
||||||
|
#ifdef LOCALNET_TESTING
|
||||||
|
>> parameter('R',"restrict-port" ,portRestrictions ,"port1-port2","Apply port restriction" ,false)
|
||||||
|
#endif
|
||||||
|
>> help() ;
|
||||||
|
|
||||||
|
as.defaultErrorHandling(true) ;
|
||||||
|
|
||||||
|
if(RsInitConfig::autoLogin) RsInitConfig::startMinimised = true ;
|
||||||
|
if(RsInitConfig::outStderr) RsInitConfig::haveLogFile = false ;
|
||||||
|
if(!RsInitConfig::logfname.empty()) RsInitConfig::haveLogFile = true;
|
||||||
|
if(!RsInitConfig::inet.empty()) RsInitConfig::forceLocalAddr = true;
|
||||||
|
#ifdef LOCALNET_TESTING
|
||||||
|
if(!portRestrictions.empty()) doPortRestrictions = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SUSPENDED_CODE
|
||||||
#ifdef LOCALNET_TESTING
|
#ifdef LOCALNET_TESTING
|
||||||
while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:U:r:R:")) != -1)
|
while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:U:r:R:")) != -1)
|
||||||
#else
|
#else
|
||||||
|
@ -402,85 +420,6 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'a':
|
|
||||||
RsInitConfig::autoLogin = true;
|
|
||||||
RsInitConfig::startMinimised = true;
|
|
||||||
std::cerr << "AutoLogin Allowed / Start Minimised On";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
RsInitConfig::startMinimised = true;
|
|
||||||
std::cerr << "Start Minimised On";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
RsInitConfig::logfname = optarg;
|
|
||||||
std::cerr << "LogFile (" << RsInitConfig::logfname;
|
|
||||||
std::cerr << ") Selected" << std::endl;
|
|
||||||
RsInitConfig::haveLogFile = true;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
RsInitConfig::passwd = optarg;
|
|
||||||
std::cerr << "Password Specified(********" ; //<< RsInitConfig::passwd;
|
|
||||||
std::cerr << ") Selected" << std::endl;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
strncpy(RsInitConfig::inet, optarg, 256);
|
|
||||||
std::cerr << "New Inet Addr(" << RsInitConfig::inet;
|
|
||||||
std::cerr << ") Selected" << std::endl;
|
|
||||||
RsInitConfig::forceLocalAddr = true;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
RsInitConfig::port = atoi(optarg);
|
|
||||||
std::cerr << "New Listening Port(" << RsInitConfig::port;
|
|
||||||
std::cerr << ") Selected" << std::endl;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
RsInitConfig::basedir = optarg;
|
|
||||||
std::cerr << "New Base Config Dir(";
|
|
||||||
std::cerr << RsInitConfig::basedir;
|
|
||||||
std::cerr << ") Selected" << std::endl;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
RsInitConfig::outStderr = true;
|
|
||||||
RsInitConfig::haveLogFile = false;
|
|
||||||
std::cerr << "Output to Stderr";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
RsInitConfig::haveDebugLevel = true;
|
|
||||||
RsInitConfig::debugLevel = atoi(optarg);
|
|
||||||
std::cerr << "Opt for new Debug Level";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
RsInitConfig::udpListenerOnly = true;
|
|
||||||
std::cerr << "Opt for only udpListener";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
RsInitConfig::forceExtPort = true;
|
|
||||||
std::cerr << "Opt for External Port Mode";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'U':
|
|
||||||
prefUserString = optarg;
|
|
||||||
std::cerr << "Opt for User Id ";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
RsInitConfig::RetroShareLink = optarg;
|
|
||||||
std::cerr << "Opt for RetroShare link";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
#ifdef LOCALNET_TESTING
|
|
||||||
case 'R':
|
|
||||||
portRestrictions = optarg;
|
|
||||||
doPortRestrictions = true;
|
|
||||||
std::cerr << "Opt for Port Restrictions";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 'h':
|
case 'h':
|
||||||
std::cerr << "Help: " << std::endl;
|
std::cerr << "Help: " << std::endl;
|
||||||
std::cerr << "The commandline options are for retroshare-nogui, a headless server in a shell, or systems without QT." << std::endl << std::endl;
|
std::cerr << "The commandline options are for retroshare-nogui, a headless server in a shell, or systems without QT." << std::endl << std::endl;
|
||||||
|
@ -510,32 +449,31 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// set the default Debug Level...
|
|
||||||
if (RsInitConfig::haveDebugLevel)
|
|
||||||
{
|
|
||||||
if ((RsInitConfig::debugLevel > 0) &&
|
|
||||||
(RsInitConfig::debugLevel <= PQL_DEBUG_ALL))
|
|
||||||
{
|
|
||||||
std::cerr << "Setting Debug Level to: ";
|
|
||||||
std::cerr << RsInitConfig::debugLevel;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
setOutputLevel(RsInitConfig::debugLevel);
|
setOutputLevel(RsInitConfig::debugLevel);
|
||||||
}
|
|
||||||
else
|
// // set the default Debug Level...
|
||||||
{
|
// if (RsInitConfig::haveDebugLevel)
|
||||||
std::cerr << "Ignoring Invalid Debug Level: ";
|
// {
|
||||||
std::cerr << RsInitConfig::debugLevel;
|
// if ((RsInitConfig::debugLevel > 0) &&
|
||||||
std::cerr << std::endl;
|
// (RsInitConfig::debugLevel <= PQL_DEBUG_ALL))
|
||||||
}
|
// {
|
||||||
}
|
// std::cerr << "Setting Debug Level to: ";
|
||||||
|
// std::cerr << RsInitConfig::debugLevel;
|
||||||
|
// std::cerr << std::endl;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// std::cerr << "Ignoring Invalid Debug Level: ";
|
||||||
|
// std::cerr << RsInitConfig::debugLevel;
|
||||||
|
// std::cerr << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// set the debug file.
|
// set the debug file.
|
||||||
if (RsInitConfig::haveLogFile)
|
if (RsInitConfig::haveLogFile)
|
||||||
{
|
|
||||||
setDebugFile(RsInitConfig::logfname.c_str());
|
setDebugFile(RsInitConfig::logfname.c_str());
|
||||||
}
|
|
||||||
|
|
||||||
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
||||||
#ifndef WINDOWS_SYS
|
#ifndef WINDOWS_SYS
|
||||||
|
@ -2599,7 +2537,7 @@ int RsServer::StartupRetroShare()
|
||||||
laddr.sin_port = htons(RsInitConfig::port);
|
laddr.sin_port = htons(RsInitConfig::port);
|
||||||
|
|
||||||
// universal
|
// universal
|
||||||
laddr.sin_addr.s_addr = inet_addr(RsInitConfig::inet);
|
laddr.sin_addr.s_addr = inet_addr(RsInitConfig::inet.c_str());
|
||||||
|
|
||||||
mPeerMgr->setLocalAddress(ownId, laddr);
|
mPeerMgr->setLocalAddress(ownId, laddr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,814 +0,0 @@
|
||||||
/* Copyright (C) 2004 Xavier Décoret <Xavier.Decoret@imag.fr>
|
|
||||||
*
|
|
||||||
* argsteam 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.
|
|
||||||
*
|
|
||||||
* Foobar 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 Foobar; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARGSTREAM_H
|
|
||||||
#define ARGSTREAM_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string>
|
|
||||||
#include <list>
|
|
||||||
#include <deque>
|
|
||||||
#include <map>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class argstream;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class ValueHolder;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
argstream& operator>> (argstream&, const ValueHolder<T>&);
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Interface of ValueHolder<T>
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
template<class T>
|
|
||||||
class ValueHolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ValueHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
T& b,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory);
|
|
||||||
ValueHolder(const char* l,
|
|
||||||
T& b,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory);
|
|
||||||
ValueHolder(char s,
|
|
||||||
T& b,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory);
|
|
||||||
friend argstream& operator>><>(argstream& s,const ValueHolder<T>& v);
|
|
||||||
std::string name() const;
|
|
||||||
std::string description() const;
|
|
||||||
private:
|
|
||||||
std::string shortName_;
|
|
||||||
std::string longName_;
|
|
||||||
T* value_;
|
|
||||||
T initialValue_;
|
|
||||||
std::string description_;
|
|
||||||
bool mandatory_;
|
|
||||||
};
|
|
||||||
template <class T>
|
|
||||||
inline ValueHolder<T>
|
|
||||||
parameter(char s,
|
|
||||||
const char* l,
|
|
||||||
T& b,
|
|
||||||
const char* desc="",
|
|
||||||
bool mandatory = true)
|
|
||||||
{
|
|
||||||
return ValueHolder<T>(s,l,b,desc,mandatory);
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
inline ValueHolder<T>
|
|
||||||
parameter(char s,
|
|
||||||
T& b,
|
|
||||||
const char* desc="",
|
|
||||||
bool mandatory = true)
|
|
||||||
{
|
|
||||||
return ValueHolder<T>(s,b,desc,mandatory);
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
inline ValueHolder<T>
|
|
||||||
parameter(const char* l,
|
|
||||||
T& b,
|
|
||||||
const char* desc="",
|
|
||||||
bool mandatory = true)
|
|
||||||
{
|
|
||||||
return ValueHolder<T>(l,b,desc,mandatory);
|
|
||||||
}
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Interface of OptionHolder
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
class OptionHolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline OptionHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc);
|
|
||||||
inline OptionHolder(const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc);
|
|
||||||
inline OptionHolder(char s,
|
|
||||||
bool& b,
|
|
||||||
const char* desc);
|
|
||||||
friend argstream& operator>>(argstream& s,const OptionHolder& v);
|
|
||||||
inline std::string name() const;
|
|
||||||
inline std::string description() const;
|
|
||||||
protected:
|
|
||||||
inline OptionHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
const char* desc);
|
|
||||||
friend OptionHolder help(char s='h',
|
|
||||||
const char* l="help",
|
|
||||||
const char* desc="Display this help");
|
|
||||||
private:
|
|
||||||
std::string shortName_;
|
|
||||||
std::string longName_;
|
|
||||||
bool* value_;
|
|
||||||
std::string description_;
|
|
||||||
};
|
|
||||||
inline OptionHolder
|
|
||||||
option(char s,
|
|
||||||
const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc="")
|
|
||||||
{
|
|
||||||
return OptionHolder(s,l,b,desc);
|
|
||||||
}
|
|
||||||
inline OptionHolder
|
|
||||||
option(char s,
|
|
||||||
bool& b,
|
|
||||||
const char* desc="")
|
|
||||||
{
|
|
||||||
return OptionHolder(s,b,desc);
|
|
||||||
}
|
|
||||||
inline OptionHolder
|
|
||||||
option(const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc="")
|
|
||||||
{
|
|
||||||
return OptionHolder(l,b,desc);
|
|
||||||
}
|
|
||||||
inline OptionHolder
|
|
||||||
help(char s,
|
|
||||||
const char* l,
|
|
||||||
const char* desc)
|
|
||||||
{
|
|
||||||
return OptionHolder(s,l,desc);
|
|
||||||
}
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Interface of ValuesHolder
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
template<class T,class O>
|
|
||||||
class ValuesHolder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ValuesHolder(const O& o,
|
|
||||||
const char* desc,
|
|
||||||
int len);
|
|
||||||
template<class A,class B> friend argstream& operator>>(argstream& s,const ValuesHolder<A,B>& v);
|
|
||||||
std::string name() const;
|
|
||||||
std::string description() const;
|
|
||||||
typedef T value_type;
|
|
||||||
private:
|
|
||||||
mutable O value_;
|
|
||||||
std::string description_;
|
|
||||||
int len_;
|
|
||||||
char letter_;
|
|
||||||
};
|
|
||||||
template<class T,class O>
|
|
||||||
inline ValuesHolder<T,O>
|
|
||||||
values(const O& o,
|
|
||||||
const char* desc="",
|
|
||||||
int len=-1)
|
|
||||||
{
|
|
||||||
return ValuesHolder<T,O>(o,desc,len);
|
|
||||||
}
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Interface of ValueParser
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
template <class T>
|
|
||||||
class ValueParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline T operator()(const std::string& s) const
|
|
||||||
{
|
|
||||||
std::istringstream is(s);
|
|
||||||
T t;
|
|
||||||
is>>t;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// We need to specialize for string otherwise parsing of a value that
|
|
||||||
// contains space (for example a string with space passed in quotes on the
|
|
||||||
// command line) would parse only the first element of the value!!!
|
|
||||||
template <>
|
|
||||||
class ValueParser<std::string>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline std::string operator()(const std::string& s) const
|
|
||||||
{
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
// Interface of argstream
|
|
||||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
class argstream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline argstream(int argc,char** argv);
|
|
||||||
inline argstream(const char* c);
|
|
||||||
template<class T>
|
|
||||||
friend argstream& operator>>(argstream& s,const ValueHolder<T>& v);
|
|
||||||
friend inline argstream& operator>>(argstream& s,const OptionHolder& v);
|
|
||||||
template<class T,class O>
|
|
||||||
friend argstream& operator>>(argstream& s,const ValuesHolder<T,O>& v);
|
|
||||||
|
|
||||||
inline bool helpRequested() const;
|
|
||||||
inline bool isOk() const;
|
|
||||||
inline std::string errorLog() const;
|
|
||||||
inline std::string usage() const;
|
|
||||||
inline void defaultErrorHandling(bool ignoreUnused=false) const;
|
|
||||||
static inline char uniqueLetter();
|
|
||||||
protected:
|
|
||||||
void parse(int argc,char** argv);
|
|
||||||
private:
|
|
||||||
typedef std::list<std::string>::iterator value_iterator;
|
|
||||||
typedef std::pair<std::string,std::string> help_entry;
|
|
||||||
std::string progName_;
|
|
||||||
std::map<std::string,value_iterator> options_;
|
|
||||||
std::list<std::string> values_;
|
|
||||||
bool minusActive_;
|
|
||||||
bool isOk_;
|
|
||||||
std::deque<help_entry> argHelps_;
|
|
||||||
std::string cmdLine_;
|
|
||||||
std::deque<std::string> errors_;
|
|
||||||
bool helpRequested_;
|
|
||||||
};
|
|
||||||
//************************************************************
|
|
||||||
// Implementation of ValueHolder<T>
|
|
||||||
//************************************************************
|
|
||||||
template<class T>
|
|
||||||
ValueHolder<T>::ValueHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
T& v,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory)
|
|
||||||
: shortName_(1,s),
|
|
||||||
longName_(l),
|
|
||||||
value_(&v),
|
|
||||||
initialValue_(v),
|
|
||||||
description_(desc),
|
|
||||||
mandatory_(mandatory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
ValueHolder<T>::ValueHolder(const char* l,
|
|
||||||
T& v,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory)
|
|
||||||
: longName_(l),
|
|
||||||
value_(&v),
|
|
||||||
initialValue_(v),
|
|
||||||
description_(desc),
|
|
||||||
mandatory_(mandatory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
ValueHolder<T>::ValueHolder(char s,
|
|
||||||
T& v,
|
|
||||||
const char* desc,
|
|
||||||
bool mandatory)
|
|
||||||
: shortName_(1,s),
|
|
||||||
value_(&v),
|
|
||||||
initialValue_(v),
|
|
||||||
description_(desc),
|
|
||||||
mandatory_(mandatory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
std::string
|
|
||||||
ValueHolder<T>::name() const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
if (!shortName_.empty()) os<<'-'<<shortName_;
|
|
||||||
if (!longName_.empty()) {
|
|
||||||
if (!shortName_.empty()) os<<'/';
|
|
||||||
os<<"--"<<longName_;
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
std::string
|
|
||||||
ValueHolder<T>::description() const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<description_;
|
|
||||||
if (mandatory_)
|
|
||||||
{
|
|
||||||
os<<"(mandatory)";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
os<<"(default="<<initialValue_<<")";
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
//************************************************************
|
|
||||||
// Implementation of OptionHolder
|
|
||||||
//************************************************************
|
|
||||||
inline OptionHolder::OptionHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc)
|
|
||||||
: shortName_(1,s),
|
|
||||||
longName_(l),
|
|
||||||
value_(&b),
|
|
||||||
description_(desc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
inline OptionHolder::OptionHolder(const char* l,
|
|
||||||
bool& b,
|
|
||||||
const char* desc)
|
|
||||||
: longName_(l),
|
|
||||||
value_(&b),
|
|
||||||
description_(desc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
inline OptionHolder::OptionHolder(char s,
|
|
||||||
bool& b,
|
|
||||||
const char* desc)
|
|
||||||
: shortName_(1,s),
|
|
||||||
value_(&b),
|
|
||||||
description_(desc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
inline OptionHolder::OptionHolder(char s,
|
|
||||||
const char* l,
|
|
||||||
const char* desc)
|
|
||||||
: shortName_(1,s),
|
|
||||||
longName_(l),
|
|
||||||
value_(NULL),
|
|
||||||
description_(desc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
inline std::string
|
|
||||||
OptionHolder::name() const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
if (!shortName_.empty()) os<<'-'<<shortName_;
|
|
||||||
if (!longName_.empty())
|
|
||||||
{
|
|
||||||
if (!shortName_.empty()) os<<'/';
|
|
||||||
os<<"--"<<longName_;
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
inline std::string
|
|
||||||
OptionHolder::description() const
|
|
||||||
{
|
|
||||||
return description_;
|
|
||||||
}
|
|
||||||
//************************************************************
|
|
||||||
// Implementation of ValuesHolder<T,O>
|
|
||||||
//************************************************************
|
|
||||||
template<class T,class O>
|
|
||||||
ValuesHolder<T,O>::ValuesHolder(const O& o,
|
|
||||||
const char* desc,
|
|
||||||
int len)
|
|
||||||
: value_(o),
|
|
||||||
description_(desc),
|
|
||||||
len_(len)
|
|
||||||
{
|
|
||||||
letter_ = argstream::uniqueLetter();
|
|
||||||
}
|
|
||||||
template <class T,class O>
|
|
||||||
std::string
|
|
||||||
ValuesHolder<T,O>::name() const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<letter_<<"i";
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
template <class T,class O>
|
|
||||||
std::string
|
|
||||||
ValuesHolder<T,O>::description() const
|
|
||||||
{
|
|
||||||
return description_;
|
|
||||||
}
|
|
||||||
//************************************************************
|
|
||||||
// Implementation of argstream
|
|
||||||
//************************************************************
|
|
||||||
inline
|
|
||||||
argstream::argstream(int argc,char** argv)
|
|
||||||
: progName_(argv[0]),
|
|
||||||
minusActive_(true),
|
|
||||||
isOk_(true)
|
|
||||||
{
|
|
||||||
parse(argc,argv);
|
|
||||||
}
|
|
||||||
inline
|
|
||||||
argstream::argstream(const char* c)
|
|
||||||
: progName_(""),
|
|
||||||
minusActive_(true),
|
|
||||||
isOk_(true)
|
|
||||||
{
|
|
||||||
std::string s(c);
|
|
||||||
// Build argc, argv from s. We must add a dummy first element for
|
|
||||||
// progName because parse() expects it!!
|
|
||||||
std::deque<std::string> args;
|
|
||||||
args.push_back("");
|
|
||||||
std::istringstream is(s);
|
|
||||||
while (is.good())
|
|
||||||
{
|
|
||||||
std::string t;
|
|
||||||
is>>t;
|
|
||||||
args.push_back(t);
|
|
||||||
}
|
|
||||||
char* pargs[args.size()];
|
|
||||||
char** p = pargs;
|
|
||||||
for (std::deque<std::string>::const_iterator
|
|
||||||
iter = args.begin();
|
|
||||||
iter != args.end();++iter)
|
|
||||||
{
|
|
||||||
*p++ = const_cast<char*>(iter->c_str());
|
|
||||||
}
|
|
||||||
parse(args.size(),pargs);
|
|
||||||
}
|
|
||||||
inline void
|
|
||||||
argstream::parse(int argc,char** argv)
|
|
||||||
{
|
|
||||||
// Run thru all arguments.
|
|
||||||
// * it has -- in front : it is a long name option, if remainder is empty,
|
|
||||||
// it is an error
|
|
||||||
// * it has - in front : it is a sequence of short name options, if
|
|
||||||
// remainder is empty, deactivates option (- will
|
|
||||||
// now be considered a char).
|
|
||||||
// * if any other char, or if option was deactivated
|
|
||||||
// : it is a value. Values are split in parameters
|
|
||||||
// (immediately follow an option) and pure values.
|
|
||||||
// Each time a value is parsed, if the previously parsed argument was an
|
|
||||||
// option, then the option is linked to the value in case of it is a
|
|
||||||
// option with parameter. The subtle point is that when several options
|
|
||||||
// are given with short names (ex: -abc equivalent to -a -b -c), the last
|
|
||||||
// parsed option is -c).
|
|
||||||
// Since we use map for option, any successive call overides the previous
|
|
||||||
// one: foo -a -b -a hello is equivalent to foo -b -a hello
|
|
||||||
// For values it is not true since we might have several times the same
|
|
||||||
// value.
|
|
||||||
value_iterator* lastOption = NULL;
|
|
||||||
for (char** a = argv,**astop=a+argc;++a!=astop;)
|
|
||||||
{
|
|
||||||
std::string s(*a);
|
|
||||||
if (minusActive_ && s[0] == '-')
|
|
||||||
{
|
|
||||||
if (s.size() > 1 && s[1] == '-')
|
|
||||||
{
|
|
||||||
if (s.size() == 2)
|
|
||||||
{
|
|
||||||
minusActive_ = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
lastOption = &(options_[s.substr(2)] = values_.end());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (s.size() > 1)
|
|
||||||
{
|
|
||||||
// Parse all chars, if it is a minus we have an error
|
|
||||||
for (std::string::const_iterator cter = s.begin();
|
|
||||||
++cter != s.end();)
|
|
||||||
{
|
|
||||||
if (*cter == '-')
|
|
||||||
{
|
|
||||||
isOk_ = false;
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"- in the middle of a switch "<<a;
|
|
||||||
errors_.push_back(os.str());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastOption = &(options_[std::string(1,*cter)] = values_.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isOk_ = false;
|
|
||||||
errors_.push_back("Invalid argument -");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
values_.push_back(s);
|
|
||||||
if (lastOption != NULL)
|
|
||||||
{
|
|
||||||
*lastOption = --values_.end();
|
|
||||||
}
|
|
||||||
lastOption = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef ARGSTREAM_DEBUG
|
|
||||||
for (std::map<std::string,value_iterator>::const_iterator
|
|
||||||
iter = options_.begin();iter != options_.end();++iter)
|
|
||||||
{
|
|
||||||
std::cout<<"DEBUG: option "<<iter->first;
|
|
||||||
if (iter->second != values_.end())
|
|
||||||
{
|
|
||||||
std::cout<<" -> "<<*(iter->second);
|
|
||||||
}
|
|
||||||
std::cout<<std::endl;
|
|
||||||
}
|
|
||||||
for (std::list<std::string>::const_iterator
|
|
||||||
iter = values_.begin();iter != values_.end();++iter)
|
|
||||||
{
|
|
||||||
std::cout<<"DEBUG: value "<<*iter<<std::endl;
|
|
||||||
}
|
|
||||||
#endif // ARGSTREAM_DEBUG
|
|
||||||
}
|
|
||||||
inline bool
|
|
||||||
argstream::isOk() const
|
|
||||||
{
|
|
||||||
return isOk_;
|
|
||||||
}
|
|
||||||
inline bool
|
|
||||||
argstream::helpRequested() const
|
|
||||||
{
|
|
||||||
return helpRequested_;
|
|
||||||
}
|
|
||||||
inline std::string
|
|
||||||
argstream::usage() const
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"usage: "<<progName_<<cmdLine_<<'\n';
|
|
||||||
unsigned int lmax = 0;
|
|
||||||
for (std::deque<help_entry>::const_iterator
|
|
||||||
iter = argHelps_.begin();iter != argHelps_.end();++iter)
|
|
||||||
{
|
|
||||||
if (lmax<iter->first.size()) lmax = iter->first.size();
|
|
||||||
}
|
|
||||||
for (std::deque<help_entry>::const_iterator
|
|
||||||
iter = argHelps_.begin();iter != argHelps_.end();++iter)
|
|
||||||
{
|
|
||||||
os<<'\t'<<iter->first<<std::string(lmax-iter->first.size(),' ')
|
|
||||||
<<" : "<<iter->second<<'\n';
|
|
||||||
}
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
inline std::string
|
|
||||||
argstream::errorLog() const
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
for(std::deque<std::string>::const_iterator iter = errors_.begin();
|
|
||||||
iter != errors_.end();++iter)
|
|
||||||
{
|
|
||||||
s += *iter;
|
|
||||||
s += '\n';
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
inline char
|
|
||||||
argstream::uniqueLetter()
|
|
||||||
{
|
|
||||||
static unsigned int c = 'a';
|
|
||||||
return c++;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
argstream&
|
|
||||||
operator>>(argstream& s,const ValueHolder<T>& v)
|
|
||||||
{
|
|
||||||
// Search in the options if there is any such option defined either with a
|
|
||||||
// short name or a long name. If both are found, only the last one is
|
|
||||||
// used.
|
|
||||||
#ifdef ARGSTREAM_DEBUG
|
|
||||||
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
|
|
||||||
#endif
|
|
||||||
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
|
||||||
if (v.mandatory_)
|
|
||||||
{
|
|
||||||
if (!v.shortName_.empty())
|
|
||||||
{
|
|
||||||
s.cmdLine_ += " -";
|
|
||||||
s.cmdLine_ += v.shortName_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.cmdLine_ += " --";
|
|
||||||
s.cmdLine_ += v.longName_;
|
|
||||||
}
|
|
||||||
s.cmdLine_ += " value";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!v.shortName_.empty())
|
|
||||||
{
|
|
||||||
s.cmdLine_ += " [-";
|
|
||||||
s.cmdLine_ += v.shortName_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.cmdLine_ += " [--";
|
|
||||||
s.cmdLine_ += v.longName_;
|
|
||||||
}
|
|
||||||
s.cmdLine_ += " value]";
|
|
||||||
|
|
||||||
}
|
|
||||||
std::map<std::string,argstream::value_iterator>::iterator iter =
|
|
||||||
s.options_.find(v.shortName_);
|
|
||||||
if (iter == s.options_.end())
|
|
||||||
{
|
|
||||||
iter = s.options_.find(v.longName_);
|
|
||||||
}
|
|
||||||
if (iter != s.options_.end())
|
|
||||||
{
|
|
||||||
// If we find counterpart for value holder on command line, either it
|
|
||||||
// has an associated value in which case we assign it, or it has not, in
|
|
||||||
// which case we have an error.
|
|
||||||
if (iter->second != s.values_.end())
|
|
||||||
{
|
|
||||||
#ifdef ARGSTREAM_DEBUG
|
|
||||||
std::cout<<"DEBUG: found value "<<*(iter->second)<<std::endl;
|
|
||||||
#endif
|
|
||||||
ValueParser<T> p;
|
|
||||||
*(v.value_) = p(*(iter->second));
|
|
||||||
// The option and its associated value are removed, the subtle thing
|
|
||||||
// is that someother options might have this associated value too,
|
|
||||||
// which we must invalidate.
|
|
||||||
s.values_.erase(iter->second);
|
|
||||||
for (std::map<std::string,argstream::value_iterator>::iterator
|
|
||||||
jter = s.options_.begin();jter != s.options_.end();++jter)
|
|
||||||
{
|
|
||||||
if (jter->second == iter->second)
|
|
||||||
{
|
|
||||||
jter->second = s.values_.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.options_.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.isOk_ = false;
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"No value following switch "<<iter->first
|
|
||||||
<<" on command line";
|
|
||||||
s.errors_.push_back(os.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (v.mandatory_)
|
|
||||||
{
|
|
||||||
s.isOk_ = false;
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"Mandatory parameter ";
|
|
||||||
if (!v.shortName_.empty()) os<<'-'<<v.shortName_;
|
|
||||||
if (!v.longName_.empty())
|
|
||||||
{
|
|
||||||
if (!v.shortName_.empty()) os<<'/';
|
|
||||||
os<<"--"<<v.longName_;
|
|
||||||
}
|
|
||||||
os<<" missing";
|
|
||||||
s.errors_.push_back(os.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
inline argstream&
|
|
||||||
operator>>(argstream& s,const OptionHolder& v)
|
|
||||||
{
|
|
||||||
// Search in the options if there is any such option defined either with a
|
|
||||||
// short name or a long name. If both are found, only the last one is
|
|
||||||
// used.
|
|
||||||
#ifdef ARGSTREAM_DEBUG
|
|
||||||
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
|
|
||||||
#endif
|
|
||||||
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
|
||||||
{
|
|
||||||
std::string c;
|
|
||||||
if (!v.shortName_.empty())
|
|
||||||
{
|
|
||||||
c += " [-";
|
|
||||||
c += v.shortName_;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c += " [--";
|
|
||||||
c += v.longName_;
|
|
||||||
}
|
|
||||||
c += "]";
|
|
||||||
s.cmdLine_ = c+s.cmdLine_;
|
|
||||||
}
|
|
||||||
std::map<std::string,argstream::value_iterator>::iterator iter =
|
|
||||||
s.options_.find(v.shortName_);
|
|
||||||
if (iter == s.options_.end())
|
|
||||||
{
|
|
||||||
iter = s.options_.find(v.longName_);
|
|
||||||
}
|
|
||||||
if (iter != s.options_.end())
|
|
||||||
{
|
|
||||||
// If we find counterpart for value holder on command line then the
|
|
||||||
// option is true and if an associated value was found, it is ignored
|
|
||||||
if (v.value_ != NULL)
|
|
||||||
{
|
|
||||||
*(v.value_) = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.helpRequested_ = true;
|
|
||||||
}
|
|
||||||
// The option only is removed
|
|
||||||
s.options_.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (v.value_ != NULL)
|
|
||||||
{
|
|
||||||
*(v.value_) = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.helpRequested_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
template<class T,class O>
|
|
||||||
argstream&
|
|
||||||
operator>>(argstream& s,const ValuesHolder<T,O>& v)
|
|
||||||
{
|
|
||||||
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<' '<<v.letter_<<'1';
|
|
||||||
switch (v.len_)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
os<<"...";
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
os<<"..."<<v.letter_<<v.len_;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
s.cmdLine_ += os.str();
|
|
||||||
}
|
|
||||||
std::list<std::string>::iterator first = s.values_.begin();
|
|
||||||
// We add to the iterator as much values as we can, limited to the length
|
|
||||||
// specified (if different of -1)
|
|
||||||
int n = v.len_ != -1?v.len_:s.values_.size();
|
|
||||||
while (first != s.values_.end() && n-->0)
|
|
||||||
{
|
|
||||||
// Read the value from the string *first
|
|
||||||
ValueParser<T> p;
|
|
||||||
*(v.value_++) = p(*first );
|
|
||||||
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
|
||||||
// The value we just removed was maybe "remembered" by an option so we
|
|
||||||
// remove it now.
|
|
||||||
for (std::map<std::string,argstream::value_iterator>::iterator
|
|
||||||
jter = s.options_.begin();jter != s.options_.end();++jter)
|
|
||||||
{
|
|
||||||
if (jter->second == first)
|
|
||||||
{
|
|
||||||
jter->second = s.values_.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
// Check if we have enough values
|
|
||||||
if (n != 0)
|
|
||||||
{
|
|
||||||
s.isOk_ = false;
|
|
||||||
std::ostringstream os;
|
|
||||||
os<<"Expecting "<<v.len_<<" values";
|
|
||||||
s.errors_.push_back(os.str());
|
|
||||||
}
|
|
||||||
// Erase the values parsed
|
|
||||||
s.values_.erase(s.values_.begin(),first);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
inline void
|
|
||||||
argstream::defaultErrorHandling(bool ignoreUnused) const
|
|
||||||
{
|
|
||||||
if (helpRequested_)
|
|
||||||
{
|
|
||||||
std::cout<<usage();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (!isOk_)
|
|
||||||
{
|
|
||||||
std::cerr<<errorLog();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (!ignoreUnused &&
|
|
||||||
(!values_.empty() || !options_.empty()))
|
|
||||||
{
|
|
||||||
std::cerr<<"Unused arguments"<<std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif // ARGSTREAM_H
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "util/utest.h"
|
#include "util/utest.h"
|
||||||
#include <common/testutils.h>
|
#include <common/testutils.h>
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
|
|
||||||
INITTEST() ;
|
INITTEST() ;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <util/utest.h>
|
#include <util/utest.h>
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
//#include <pqi/cleanupxpgp.h>
|
//#include <pqi/cleanupxpgp.h>
|
||||||
#include <retroshare/rspeers.h>
|
#include <retroshare/rspeers.h>
|
||||||
#include <pgp/rscertificate.h>
|
#include <pgp/rscertificate.h>
|
||||||
|
|
|
@ -11,7 +11,7 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <util/utest.h>
|
#include <util/utest.h>
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
|
|
||||||
INITTEST() ;
|
INITTEST() ;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <pgp/pgphandler.h>
|
#include <pgp/pgphandler.h>
|
||||||
#include <util/utest.h>
|
#include <util/utest.h>
|
||||||
#include <util/rsdir.h>
|
#include <util/rsdir.h>
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
|
|
||||||
INITTEST() ;
|
INITTEST() ;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include "util/rsaes.h"
|
#include "util/rsaes.h"
|
||||||
#include "util/utest.h"
|
#include "util/utest.h"
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "util/utest.h"
|
#include "util/utest.h"
|
||||||
#include <common/argstream.h>
|
#include <util/argstream.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
839
libretroshare/src/util/argstream.h
Normal file
839
libretroshare/src/util/argstream.h
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
/* Copyright (C) 2004 Xavier Décoret <Xavier.Decoret@imag.fr>
|
||||||
|
*
|
||||||
|
* argsteam 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.
|
||||||
|
*
|
||||||
|
* Foobar 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 Foobar; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARGSTREAM_H
|
||||||
|
#define ARGSTREAM_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class argstream;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class ValueHolder;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
argstream& operator>> (argstream&, const ValueHolder<T>&);
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// Interface of ValueHolder<T>
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
template<class T>
|
||||||
|
class ValueHolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ValueHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
T& b,
|
||||||
|
const char *valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory);
|
||||||
|
ValueHolder(const char* l,
|
||||||
|
T& b,
|
||||||
|
const char *valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory);
|
||||||
|
ValueHolder(char s,
|
||||||
|
T& b,
|
||||||
|
const char *valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory);
|
||||||
|
friend argstream& operator>><>(argstream& s,const ValueHolder<T>& v);
|
||||||
|
std::string name() const;
|
||||||
|
std::string description() const;
|
||||||
|
private:
|
||||||
|
std::string shortName_;
|
||||||
|
std::string longName_;
|
||||||
|
std::string valueName_;
|
||||||
|
T* value_;
|
||||||
|
T initialValue_;
|
||||||
|
std::string description_;
|
||||||
|
bool mandatory_;
|
||||||
|
};
|
||||||
|
template <class T>
|
||||||
|
inline ValueHolder<T>
|
||||||
|
parameter(char s,
|
||||||
|
const char* l,
|
||||||
|
T& b,
|
||||||
|
const char* desc="",
|
||||||
|
bool mandatory = true)
|
||||||
|
{
|
||||||
|
return ValueHolder<T>(s,l,b,"value",desc,mandatory);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline ValueHolder<T>
|
||||||
|
parameter(char s,
|
||||||
|
const char* l,
|
||||||
|
T& b,
|
||||||
|
const char* valueName="value",
|
||||||
|
const char* desc="",
|
||||||
|
bool mandatory = true)
|
||||||
|
{
|
||||||
|
return ValueHolder<T>(s,l,b,valueName,desc,mandatory);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline ValueHolder<T>
|
||||||
|
parameter(char s,
|
||||||
|
T& b,
|
||||||
|
const char* valueName="value",
|
||||||
|
const char* desc="",
|
||||||
|
bool mandatory = true)
|
||||||
|
{
|
||||||
|
return ValueHolder<T>(s,b,valueName,desc,mandatory);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
inline ValueHolder<T>
|
||||||
|
parameter(const char* l,
|
||||||
|
T& b,
|
||||||
|
const char* valueName="value",
|
||||||
|
const char* desc="",
|
||||||
|
bool mandatory = true)
|
||||||
|
{
|
||||||
|
return ValueHolder<T>(l,b,desc,mandatory);
|
||||||
|
}
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// Interface of OptionHolder
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
class OptionHolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline OptionHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc);
|
||||||
|
inline OptionHolder(const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc);
|
||||||
|
inline OptionHolder(char s,
|
||||||
|
bool& b,
|
||||||
|
const char* desc);
|
||||||
|
friend argstream& operator>>(argstream& s,const OptionHolder& v);
|
||||||
|
inline std::string name() const;
|
||||||
|
inline std::string description() const;
|
||||||
|
protected:
|
||||||
|
inline OptionHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
const char* desc);
|
||||||
|
friend OptionHolder help(char s='h',
|
||||||
|
const char* l="help",
|
||||||
|
const char* desc="Display this help");
|
||||||
|
private:
|
||||||
|
std::string shortName_;
|
||||||
|
std::string longName_;
|
||||||
|
bool* value_;
|
||||||
|
std::string description_;
|
||||||
|
};
|
||||||
|
inline OptionHolder
|
||||||
|
option(char s,
|
||||||
|
const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc="")
|
||||||
|
{
|
||||||
|
return OptionHolder(s,l,b,desc);
|
||||||
|
}
|
||||||
|
inline OptionHolder
|
||||||
|
option(char s,
|
||||||
|
bool& b,
|
||||||
|
const char* desc="")
|
||||||
|
{
|
||||||
|
return OptionHolder(s,b,desc);
|
||||||
|
}
|
||||||
|
inline OptionHolder
|
||||||
|
option(const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc="")
|
||||||
|
{
|
||||||
|
return OptionHolder(l,b,desc);
|
||||||
|
}
|
||||||
|
inline OptionHolder
|
||||||
|
help(char s,
|
||||||
|
const char* l,
|
||||||
|
const char* desc)
|
||||||
|
{
|
||||||
|
return OptionHolder(s,l,desc);
|
||||||
|
}
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// Interface of ValuesHolder
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
template<class T,class O>
|
||||||
|
class ValuesHolder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ValuesHolder(const O& o,
|
||||||
|
const char* desc,
|
||||||
|
int len);
|
||||||
|
template<class A,class B> friend argstream& operator>>(argstream& s,const ValuesHolder<A,B>& v);
|
||||||
|
std::string name() const;
|
||||||
|
std::string description() const;
|
||||||
|
typedef T value_type;
|
||||||
|
private:
|
||||||
|
mutable O value_;
|
||||||
|
std::string description_;
|
||||||
|
int len_;
|
||||||
|
char letter_;
|
||||||
|
};
|
||||||
|
template<class T,class O>
|
||||||
|
inline ValuesHolder<T,O>
|
||||||
|
values(const O& o,
|
||||||
|
const char* desc="",
|
||||||
|
int len=-1)
|
||||||
|
{
|
||||||
|
return ValuesHolder<T,O>(o,desc,len);
|
||||||
|
}
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// Interface of ValueParser
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
template <class T>
|
||||||
|
class ValueParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline T operator()(const std::string& s) const
|
||||||
|
{
|
||||||
|
std::istringstream is(s);
|
||||||
|
T t;
|
||||||
|
is>>t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We need to specialize for string otherwise parsing of a value that
|
||||||
|
// contains space (for example a string with space passed in quotes on the
|
||||||
|
// command line) would parse only the first element of the value!!!
|
||||||
|
template <>
|
||||||
|
class ValueParser<std::string>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline std::string operator()(const std::string& s) const
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
// Interface of argstream
|
||||||
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
class argstream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline argstream(int argc,char** argv);
|
||||||
|
inline argstream(const char* c);
|
||||||
|
template<class T>
|
||||||
|
friend argstream& operator>>(argstream& s,const ValueHolder<T>& v);
|
||||||
|
friend inline argstream& operator>>(argstream& s,const OptionHolder& v);
|
||||||
|
template<class T,class O>
|
||||||
|
friend argstream& operator>>(argstream& s,const ValuesHolder<T,O>& v);
|
||||||
|
|
||||||
|
inline bool helpRequested() const;
|
||||||
|
inline bool isOk() const;
|
||||||
|
inline std::string errorLog() const;
|
||||||
|
inline std::string usage() const;
|
||||||
|
inline bool defaultErrorHandling(bool ignoreUnused=false) const;
|
||||||
|
static inline char uniqueLetter();
|
||||||
|
protected:
|
||||||
|
void parse(int argc,char** argv);
|
||||||
|
private:
|
||||||
|
typedef std::list<std::string>::iterator value_iterator;
|
||||||
|
typedef std::pair<std::string,std::string> help_entry;
|
||||||
|
std::string progName_;
|
||||||
|
std::map<std::string,value_iterator> options_;
|
||||||
|
std::list<std::string> values_;
|
||||||
|
bool minusActive_;
|
||||||
|
bool isOk_;
|
||||||
|
std::deque<help_entry> argHelps_;
|
||||||
|
std::string cmdLine_;
|
||||||
|
std::deque<std::string> errors_;
|
||||||
|
bool helpRequested_;
|
||||||
|
};
|
||||||
|
//************************************************************
|
||||||
|
// Implementation of ValueHolder<T>
|
||||||
|
//************************************************************
|
||||||
|
template<class T>
|
||||||
|
ValueHolder<T>::ValueHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
T& v,
|
||||||
|
const char* valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory)
|
||||||
|
: shortName_(1,s),
|
||||||
|
longName_(l),
|
||||||
|
valueName_(valueName),
|
||||||
|
value_(&v),
|
||||||
|
initialValue_(v),
|
||||||
|
description_(desc),
|
||||||
|
mandatory_(mandatory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
ValueHolder<T>::ValueHolder(const char* l,
|
||||||
|
T& v,
|
||||||
|
const char* valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory)
|
||||||
|
: longName_(l),
|
||||||
|
value_(&v),
|
||||||
|
valueName_(valueName),
|
||||||
|
initialValue_(v),
|
||||||
|
description_(desc),
|
||||||
|
mandatory_(mandatory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
ValueHolder<T>::ValueHolder(char s,
|
||||||
|
T& v,
|
||||||
|
const char* valueName,
|
||||||
|
const char* desc,
|
||||||
|
bool mandatory)
|
||||||
|
: shortName_(1,s),
|
||||||
|
value_(&v),
|
||||||
|
initialValue_(v),
|
||||||
|
valueName_(valueName),
|
||||||
|
description_(desc),
|
||||||
|
mandatory_(mandatory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
std::string
|
||||||
|
ValueHolder<T>::name() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
if (!shortName_.empty()) os<<'-'<<shortName_;
|
||||||
|
if (!longName_.empty()) {
|
||||||
|
if (!shortName_.empty()) os<<'/';
|
||||||
|
os<<"--"<<longName_;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
std::string
|
||||||
|
ValueHolder<T>::description() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<description_;
|
||||||
|
if (mandatory_)
|
||||||
|
{
|
||||||
|
os<<"(mandatory)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os<<"(default="<<initialValue_<<")";
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
//************************************************************
|
||||||
|
// Implementation of OptionHolder
|
||||||
|
//************************************************************
|
||||||
|
inline OptionHolder::OptionHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc)
|
||||||
|
: shortName_(1,s),
|
||||||
|
longName_(l),
|
||||||
|
value_(&b),
|
||||||
|
description_(desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
inline OptionHolder::OptionHolder(const char* l,
|
||||||
|
bool& b,
|
||||||
|
const char* desc)
|
||||||
|
: longName_(l),
|
||||||
|
value_(&b),
|
||||||
|
description_(desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
inline OptionHolder::OptionHolder(char s,
|
||||||
|
bool& b,
|
||||||
|
const char* desc)
|
||||||
|
: shortName_(1,s),
|
||||||
|
value_(&b),
|
||||||
|
description_(desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
inline OptionHolder::OptionHolder(char s,
|
||||||
|
const char* l,
|
||||||
|
const char* desc)
|
||||||
|
: shortName_(1,s),
|
||||||
|
longName_(l),
|
||||||
|
value_(NULL),
|
||||||
|
description_(desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
inline std::string
|
||||||
|
OptionHolder::name() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
if (!shortName_.empty()) os<<'-'<<shortName_;
|
||||||
|
if (!longName_.empty())
|
||||||
|
{
|
||||||
|
if (!shortName_.empty()) os<<'/';
|
||||||
|
os<<"--"<<longName_;
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
inline std::string
|
||||||
|
OptionHolder::description() const
|
||||||
|
{
|
||||||
|
return description_;
|
||||||
|
}
|
||||||
|
//************************************************************
|
||||||
|
// Implementation of ValuesHolder<T,O>
|
||||||
|
//************************************************************
|
||||||
|
template<class T,class O>
|
||||||
|
ValuesHolder<T,O>::ValuesHolder(const O& o,
|
||||||
|
const char* desc,
|
||||||
|
int len)
|
||||||
|
: value_(o),
|
||||||
|
description_(desc),
|
||||||
|
len_(len)
|
||||||
|
{
|
||||||
|
letter_ = argstream::uniqueLetter();
|
||||||
|
}
|
||||||
|
template <class T,class O>
|
||||||
|
std::string
|
||||||
|
ValuesHolder<T,O>::name() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<letter_<<"i";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
template <class T,class O>
|
||||||
|
std::string
|
||||||
|
ValuesHolder<T,O>::description() const
|
||||||
|
{
|
||||||
|
return description_;
|
||||||
|
}
|
||||||
|
//************************************************************
|
||||||
|
// Implementation of argstream
|
||||||
|
//************************************************************
|
||||||
|
inline
|
||||||
|
argstream::argstream(int argc,char** argv)
|
||||||
|
: progName_(argv[0]),
|
||||||
|
minusActive_(true),
|
||||||
|
isOk_(true),
|
||||||
|
helpRequested_(false)
|
||||||
|
{
|
||||||
|
parse(argc,argv);
|
||||||
|
}
|
||||||
|
inline
|
||||||
|
argstream::argstream(const char* c)
|
||||||
|
: progName_(""),
|
||||||
|
minusActive_(true),
|
||||||
|
isOk_(true)
|
||||||
|
{
|
||||||
|
std::string s(c);
|
||||||
|
// Build argc, argv from s. We must add a dummy first element for
|
||||||
|
// progName because parse() expects it!!
|
||||||
|
std::deque<std::string> args;
|
||||||
|
args.push_back("");
|
||||||
|
std::istringstream is(s);
|
||||||
|
while (is.good())
|
||||||
|
{
|
||||||
|
std::string t;
|
||||||
|
is>>t;
|
||||||
|
args.push_back(t);
|
||||||
|
}
|
||||||
|
char* pargs[args.size()];
|
||||||
|
char** p = pargs;
|
||||||
|
for (std::deque<std::string>::const_iterator
|
||||||
|
iter = args.begin();
|
||||||
|
iter != args.end();++iter)
|
||||||
|
{
|
||||||
|
*p++ = const_cast<char*>(iter->c_str());
|
||||||
|
}
|
||||||
|
parse(args.size(),pargs);
|
||||||
|
}
|
||||||
|
inline void
|
||||||
|
argstream::parse(int argc,char** argv)
|
||||||
|
{
|
||||||
|
// Run thru all arguments.
|
||||||
|
// * it has -- in front : it is a long name option, if remainder is empty,
|
||||||
|
// it is an error
|
||||||
|
// * it has - in front : it is a sequence of short name options, if
|
||||||
|
// remainder is empty, deactivates option (- will
|
||||||
|
// now be considered a char).
|
||||||
|
// * if any other char, or if option was deactivated
|
||||||
|
// : it is a value. Values are split in parameters
|
||||||
|
// (immediately follow an option) and pure values.
|
||||||
|
// Each time a value is parsed, if the previously parsed argument was an
|
||||||
|
// option, then the option is linked to the value in case of it is a
|
||||||
|
// option with parameter. The subtle point is that when several options
|
||||||
|
// are given with short names (ex: -abc equivalent to -a -b -c), the last
|
||||||
|
// parsed option is -c).
|
||||||
|
// Since we use map for option, any successive call overides the previous
|
||||||
|
// one: foo -a -b -a hello is equivalent to foo -b -a hello
|
||||||
|
// For values it is not true since we might have several times the same
|
||||||
|
// value.
|
||||||
|
value_iterator* lastOption = NULL;
|
||||||
|
for (char** a = argv,**astop=a+argc;++a!=astop;)
|
||||||
|
{
|
||||||
|
std::string s(*a);
|
||||||
|
if (minusActive_ && s[0] == '-')
|
||||||
|
{
|
||||||
|
if (s.size() > 1 && s[1] == '-')
|
||||||
|
{
|
||||||
|
if (s.size() == 2)
|
||||||
|
{
|
||||||
|
minusActive_ = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lastOption = &(options_[s.substr(2)] = values_.end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (s.size() > 1)
|
||||||
|
{
|
||||||
|
// Parse all chars, if it is a minus we have an error
|
||||||
|
for (std::string::const_iterator cter = s.begin();
|
||||||
|
++cter != s.end();)
|
||||||
|
{
|
||||||
|
if (*cter == '-')
|
||||||
|
{
|
||||||
|
isOk_ = false;
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"- in the middle of a switch "<<a;
|
||||||
|
errors_.push_back(os.str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastOption = &(options_[std::string(1,*cter)] = values_.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isOk_ = false;
|
||||||
|
errors_.push_back("Invalid argument -");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
values_.push_back(s);
|
||||||
|
if (lastOption != NULL)
|
||||||
|
{
|
||||||
|
*lastOption = --values_.end();
|
||||||
|
}
|
||||||
|
lastOption = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef ARGSTREAM_DEBUG
|
||||||
|
for (std::map<std::string,value_iterator>::const_iterator
|
||||||
|
iter = options_.begin();iter != options_.end();++iter)
|
||||||
|
{
|
||||||
|
std::cout<<"DEBUG: option "<<iter->first;
|
||||||
|
if (iter->second != values_.end())
|
||||||
|
{
|
||||||
|
std::cout<<" -> "<<*(iter->second);
|
||||||
|
}
|
||||||
|
std::cout<<std::endl;
|
||||||
|
}
|
||||||
|
for (std::list<std::string>::const_iterator
|
||||||
|
iter = values_.begin();iter != values_.end();++iter)
|
||||||
|
{
|
||||||
|
std::cout<<"DEBUG: value "<<*iter<<std::endl;
|
||||||
|
}
|
||||||
|
#endif // ARGSTREAM_DEBUG
|
||||||
|
}
|
||||||
|
inline bool
|
||||||
|
argstream::isOk() const
|
||||||
|
{
|
||||||
|
return isOk_;
|
||||||
|
}
|
||||||
|
inline bool
|
||||||
|
argstream::helpRequested() const
|
||||||
|
{
|
||||||
|
return helpRequested_;
|
||||||
|
}
|
||||||
|
inline std::string
|
||||||
|
argstream::usage() const
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"usage: "<<progName_<<cmdLine_<<'\n';
|
||||||
|
unsigned int lmax = 0;
|
||||||
|
for (std::deque<help_entry>::const_iterator
|
||||||
|
iter = argHelps_.begin();iter != argHelps_.end();++iter)
|
||||||
|
{
|
||||||
|
if (lmax<iter->first.size()) lmax = iter->first.size();
|
||||||
|
}
|
||||||
|
for (std::deque<help_entry>::const_iterator
|
||||||
|
iter = argHelps_.begin();iter != argHelps_.end();++iter)
|
||||||
|
{
|
||||||
|
os<<'\t'<<iter->first<<std::string(lmax-iter->first.size(),' ')
|
||||||
|
<<" : "<<iter->second<<'\n';
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
inline std::string
|
||||||
|
argstream::errorLog() const
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
for(std::deque<std::string>::const_iterator iter = errors_.begin();
|
||||||
|
iter != errors_.end();++iter)
|
||||||
|
{
|
||||||
|
s += *iter;
|
||||||
|
s += '\n';
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline char
|
||||||
|
argstream::uniqueLetter()
|
||||||
|
{
|
||||||
|
static unsigned int c = 'a';
|
||||||
|
return c++;
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
argstream&
|
||||||
|
operator>>(argstream& s,const ValueHolder<T>& v)
|
||||||
|
{
|
||||||
|
// Search in the options if there is any such option defined either with a
|
||||||
|
// short name or a long name. If both are found, only the last one is
|
||||||
|
// used.
|
||||||
|
#ifdef ARGSTREAM_DEBUG
|
||||||
|
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
|
||||||
|
#endif
|
||||||
|
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
||||||
|
if (v.mandatory_)
|
||||||
|
{
|
||||||
|
if (!v.shortName_.empty())
|
||||||
|
{
|
||||||
|
s.cmdLine_ += " -";
|
||||||
|
s.cmdLine_ += v.shortName_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.cmdLine_ += " --";
|
||||||
|
s.cmdLine_ += v.longName_;
|
||||||
|
}
|
||||||
|
s.cmdLine_ += " " + v.valueName_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!v.shortName_.empty())
|
||||||
|
{
|
||||||
|
s.cmdLine_ += " [-";
|
||||||
|
s.cmdLine_ += v.shortName_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.cmdLine_ += " [--";
|
||||||
|
s.cmdLine_ += v.longName_;
|
||||||
|
}
|
||||||
|
s.cmdLine_ += " " + v.valueName_ +"]";
|
||||||
|
|
||||||
|
}
|
||||||
|
std::map<std::string,argstream::value_iterator>::iterator iter =
|
||||||
|
s.options_.find(v.shortName_);
|
||||||
|
if (iter == s.options_.end())
|
||||||
|
{
|
||||||
|
iter = s.options_.find(v.longName_);
|
||||||
|
}
|
||||||
|
if (iter != s.options_.end())
|
||||||
|
{
|
||||||
|
// If we find counterpart for value holder on command line, either it
|
||||||
|
// has an associated value in which case we assign it, or it has not, in
|
||||||
|
// which case we have an error.
|
||||||
|
if (iter->second != s.values_.end())
|
||||||
|
{
|
||||||
|
#ifdef ARGSTREAM_DEBUG
|
||||||
|
std::cout<<"DEBUG: found value "<<*(iter->second)<<std::endl;
|
||||||
|
#endif
|
||||||
|
ValueParser<T> p;
|
||||||
|
*(v.value_) = p(*(iter->second));
|
||||||
|
// The option and its associated value are removed, the subtle thing
|
||||||
|
// is that someother options might have this associated value too,
|
||||||
|
// which we must invalidate.
|
||||||
|
s.values_.erase(iter->second);
|
||||||
|
for (std::map<std::string,argstream::value_iterator>::iterator
|
||||||
|
jter = s.options_.begin();jter != s.options_.end();++jter)
|
||||||
|
{
|
||||||
|
if (jter->second == iter->second)
|
||||||
|
{
|
||||||
|
jter->second = s.values_.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.options_.erase(iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.isOk_ = false;
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"No value following switch "<<iter->first
|
||||||
|
<<" on command line";
|
||||||
|
s.errors_.push_back(os.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v.mandatory_)
|
||||||
|
{
|
||||||
|
s.isOk_ = false;
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"Mandatory parameter ";
|
||||||
|
if (!v.shortName_.empty()) os<<'-'<<v.shortName_;
|
||||||
|
if (!v.longName_.empty())
|
||||||
|
{
|
||||||
|
if (!v.shortName_.empty()) os<<'/';
|
||||||
|
os<<"--"<<v.longName_;
|
||||||
|
}
|
||||||
|
os<<" missing";
|
||||||
|
s.errors_.push_back(os.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline argstream&
|
||||||
|
operator>>(argstream& s,const OptionHolder& v)
|
||||||
|
{
|
||||||
|
// Search in the options if there is any such option defined either with a
|
||||||
|
// short name or a long name. If both are found, only the last one is
|
||||||
|
// used.
|
||||||
|
#ifdef ARGSTREAM_DEBUG
|
||||||
|
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
|
||||||
|
#endif
|
||||||
|
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
||||||
|
{
|
||||||
|
std::string c;
|
||||||
|
if (!v.shortName_.empty())
|
||||||
|
{
|
||||||
|
c += " [-";
|
||||||
|
c += v.shortName_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c += " [--";
|
||||||
|
c += v.longName_;
|
||||||
|
}
|
||||||
|
c += "]";
|
||||||
|
s.cmdLine_ = c+s.cmdLine_;
|
||||||
|
}
|
||||||
|
std::map<std::string,argstream::value_iterator>::iterator iter =
|
||||||
|
s.options_.find(v.shortName_);
|
||||||
|
if (iter == s.options_.end())
|
||||||
|
{
|
||||||
|
iter = s.options_.find(v.longName_);
|
||||||
|
}
|
||||||
|
if (iter != s.options_.end())
|
||||||
|
{
|
||||||
|
// If we find counterpart for value holder on command line then the
|
||||||
|
// option is true and if an associated value was found, it is ignored
|
||||||
|
if (v.value_ != NULL)
|
||||||
|
{
|
||||||
|
*(v.value_) = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.helpRequested_ = true;
|
||||||
|
}
|
||||||
|
// The option only is removed
|
||||||
|
s.options_.erase(iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v.value_ != NULL)
|
||||||
|
{
|
||||||
|
*(v.value_) = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.helpRequested_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
template<class T,class O>
|
||||||
|
argstream&
|
||||||
|
operator>>(argstream& s,const ValuesHolder<T,O>& v)
|
||||||
|
{
|
||||||
|
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<' '<<v.letter_<<'1';
|
||||||
|
switch (v.len_)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
os<<"...";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
os<<"..."<<v.letter_<<v.len_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s.cmdLine_ += os.str();
|
||||||
|
}
|
||||||
|
std::list<std::string>::iterator first = s.values_.begin();
|
||||||
|
// We add to the iterator as much values as we can, limited to the length
|
||||||
|
// specified (if different of -1)
|
||||||
|
int n = v.len_ != -1?v.len_:s.values_.size();
|
||||||
|
while (first != s.values_.end() && n-->0)
|
||||||
|
{
|
||||||
|
// Read the value from the string *first
|
||||||
|
ValueParser<T> p;
|
||||||
|
*(v.value_++) = p(*first );
|
||||||
|
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
|
||||||
|
// The value we just removed was maybe "remembered" by an option so we
|
||||||
|
// remove it now.
|
||||||
|
for (std::map<std::string,argstream::value_iterator>::iterator
|
||||||
|
jter = s.options_.begin();jter != s.options_.end();++jter)
|
||||||
|
{
|
||||||
|
if (jter->second == first)
|
||||||
|
{
|
||||||
|
jter->second = s.values_.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
// Check if we have enough values
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
s.isOk_ = false;
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"Expecting "<<v.len_<<" values";
|
||||||
|
s.errors_.push_back(os.str());
|
||||||
|
}
|
||||||
|
// Erase the values parsed
|
||||||
|
s.values_.erase(s.values_.begin(),first);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
inline bool
|
||||||
|
argstream::defaultErrorHandling(bool ignoreUnused) const
|
||||||
|
{
|
||||||
|
if (helpRequested_)
|
||||||
|
{
|
||||||
|
std::cout<<usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!isOk_)
|
||||||
|
{
|
||||||
|
std::cerr<<errorLog();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!ignoreUnused &&
|
||||||
|
(!values_.empty() || !options_.empty()))
|
||||||
|
{
|
||||||
|
std::cerr<<"Unused arguments"<<std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // ARGSTREAM_H
|
||||||
|
|
|
@ -101,9 +101,9 @@ bool NotifyTxt::askForPluginConfirmation(const std::string& plugin_file_name, co
|
||||||
return a == 'y' ;
|
return a == 'y' ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password)
|
bool NotifyTxt::askForPassword(const std::string& question, bool prev_is_bad, std::string& password)
|
||||||
{
|
{
|
||||||
char *passwd = getpass(("Please enter GPG password for key "+key_details+": ").c_str()) ;
|
char *passwd = getpass(question.c_str()) ;
|
||||||
password = passwd;
|
password = passwd;
|
||||||
|
|
||||||
return !password.empty();
|
return !password.empty();
|
||||||
|
|
|
@ -42,7 +42,7 @@ class NotifyTxt: public NotifyBase
|
||||||
virtual void notifyListChange(int list, int type);
|
virtual void notifyListChange(int list, int type);
|
||||||
virtual void notifyErrorMsg(int list, int sev, std::string msg);
|
virtual void notifyErrorMsg(int list, int sev, std::string msg);
|
||||||
virtual void notifyChat();
|
virtual void notifyChat();
|
||||||
virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password);
|
virtual bool askForPassword(const std::string& question, bool prev_is_bad, std::string& password);
|
||||||
virtual bool askForPluginConfirmation(const std::string& plugin_file, const std::string& plugin_hash);
|
virtual bool askForPluginConfirmation(const std::string& plugin_file, const std::string& plugin_hash);
|
||||||
|
|
||||||
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files);
|
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "notifytxt.h"
|
#include "notifytxt.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <util/argstream.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#ifdef WINDOWS_SYS
|
#ifdef WINDOWS_SYS
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
@ -53,6 +54,10 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef RS_SSH_SERVER
|
||||||
|
void generatePasswordHash() ;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Basic instructions for running libretroshare as background thread.
|
/* Basic instructions for running libretroshare as background thread.
|
||||||
* ******************************************************************* *
|
* ******************************************************************* *
|
||||||
* This allows your program to communicate with authenticated peers.
|
* This allows your program to communicate with authenticated peers.
|
||||||
|
@ -102,7 +107,6 @@ int main(int argc, char **argv)
|
||||||
bool enableRpc = false;
|
bool enableRpc = false;
|
||||||
bool enableSsh = false;
|
bool enableSsh = false;
|
||||||
bool enableSshHtml = false;
|
bool enableSshHtml = false;
|
||||||
bool enableSshPwd = false;
|
|
||||||
bool enableTerminal = false;
|
bool enableTerminal = false;
|
||||||
bool enableSshRsa = false;
|
bool enableSshRsa = false;
|
||||||
bool genPwdHash = false;
|
bool genPwdHash = false;
|
||||||
|
@ -112,167 +116,75 @@ int main(int argc, char **argv)
|
||||||
std::string sshPortStr = "0";
|
std::string sshPortStr = "0";
|
||||||
|
|
||||||
uint16_t extPort = 0;
|
uint16_t extPort = 0;
|
||||||
|
uint16_t sshPort = 7022;
|
||||||
bool extPortSet = false;
|
bool extPortSet = false;
|
||||||
|
bool displayRPCInfo = false ;
|
||||||
|
|
||||||
while((c = getopt(argc, argv,"ChTL:P:K:GS:E:")) != -1)
|
argstream as(argc,argv) ;
|
||||||
{
|
|
||||||
switch(c)
|
as >> option('X',"enable-ssh" ,enableSsh ,"Enable SSH" )
|
||||||
{
|
>> option('T',"enable-terminal",enableTerminal ,"Enable terminal interface." )
|
||||||
case 'C':
|
>> option('C',"enable-rpc" ,enableRpc ,"Enable RPC protocol. To be used with e.g. -X (SSH).")
|
||||||
enableRpc = true;
|
>> option('G',"gen-password" ,genPwdHash ,"Generate password hash (to supply to option -P)")
|
||||||
strictCheck = false;
|
#if 0
|
||||||
break;
|
>> option('H',"enable-ssh-html",enableSshHtml ,"Enable SSH html." )
|
||||||
case 'S':
|
|
||||||
enableSsh = true;
|
|
||||||
sshPortStr = optarg; // no longer optional.
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
extPort = atoi(optarg);
|
|
||||||
extPortSet = true;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
case 'H':
|
|
||||||
enableSshHtml = true;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
enableTerminal = true;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
sshUser = optarg;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
enableSshPwd = true;
|
|
||||||
sshPwdHash = optarg;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
#if 0 // NOT FINISHED YET.
|
|
||||||
case 'K':
|
|
||||||
enableSshRsa = true;
|
|
||||||
sshRsaFile = optarg;
|
|
||||||
strictCheck = false;
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case 'G':
|
>> parameter('S',"ssh-port" ,sshPort ,"port" ,"SSH port to contact the interface.",false)
|
||||||
genPwdHash = true;
|
>> parameter('E',"ext-port" ,extPort ,"port" ,"Specify Alternative External Port (provided to Clients)",false)
|
||||||
break;
|
>> parameter('L',"ssh-user" ,sshUser ,"name" ,"Ssh login user",false)
|
||||||
case 'h':
|
>> parameter('P',"ssh-p-hash" ,sshPwdHash ,"hash" ,"Ssh login password hash (Generated by retroshare-nogui -G)",false)
|
||||||
/* nogui help */
|
>> parameter('K',"ssh-key-file" ,sshRsaFile ,"RSA key file", "RSA key file for SSH login (not yet implemented).",false )// NOT FINISHED YET.
|
||||||
std::cerr << argv[0] << std::endl;
|
|
||||||
std::cerr << "Specific Help Options: " << std::endl;
|
|
||||||
std::cerr << "\t-G Generate a Password Hash for SSH Server" << std::endl;
|
|
||||||
std::cerr << "\t-T Enable Terminal Interface" << std::endl;
|
|
||||||
std::cerr << "\t-S <port> Enable SSH Server on specified port" << std::endl;
|
|
||||||
std::cerr << "\t-E <port> Specify Alternative External Port (provided to Clients)" << std::endl;
|
|
||||||
std::cerr << "\t-L <user> Specify SSH login user (default:user)" << std::endl;
|
|
||||||
std::cerr << "\t-P <pwdhash> Enable SSH login via Password" << std::endl;
|
|
||||||
std::cerr << "\t-C Enable RPC Protocol (requires -S too)" << std::endl;
|
|
||||||
//std::cerr << "\t-K [rsapubkeyfile] Enable SSH login via RSA key" << std::endl;
|
|
||||||
//std::cerr << "\t NB: Two Factor Auth, specify both -P & -K" << std::endl;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
std::cerr << "\t To setup rs-nogui as a SSH Server is a three step process: " << std::endl;
|
|
||||||
std::cerr << "\t 1) \"ssh-keygen -t rsa -f rs_ssh_host_rsa_key\" " << std::endl;
|
|
||||||
std::cerr << "\t 2) \"./retroshare-nogui -G\" " << std::endl;
|
|
||||||
std::cerr << "\t 3) \"./retroshare-nogui -S [port] -L <user> -P <passwordhash>\" " << std::endl;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
std::cerr << "Further Options ";
|
|
||||||
/* libretroshare will call exit(1) after printing its options */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
>> help() ;
|
||||||
/* let others through - for libretroshare */
|
|
||||||
break;
|
// Normally argstream would handle this by itself, if we called
|
||||||
|
// as.defaultErrorHandling() ;
|
||||||
|
//
|
||||||
|
// but we have other parameter handling functions after, so we don't want to quit if help is requested.
|
||||||
|
//
|
||||||
|
if (as.helpRequested())
|
||||||
|
{
|
||||||
|
std::cerr << "\nSpecific Help Options:" << std::endl;
|
||||||
|
std::cerr << as.usage() << std::endl;
|
||||||
|
std::cerr << "\t To setup rs-nogui as a SSH Server is a three step process: " << std::endl;
|
||||||
|
std::cerr << "\t 1) Generate a RSA keypair in the current directory: \"ssh-keygen -t rsa -f rs_ssh_host_rsa_key\" " << std::endl;
|
||||||
|
std::cerr << "\t 2) Generate a password hash for the RPC login: \"./retroshare-nogui -G\" " << std::endl;
|
||||||
|
std::cerr << "\t 3) Launch the RS with remote control enabled: \"./retroshare-nogui -X/-T [-C] -S [port] -L <user> -P <passwordhash>\" " << std::endl;
|
||||||
|
|
||||||
|
std::cerr << "\nAdditional options: \n" << std::endl;
|
||||||
}
|
}
|
||||||
|
if (!as.isOk())
|
||||||
|
{
|
||||||
|
std::cerr << as.errorLog();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
// reset optind for Retroshare commandline arguments.
|
|
||||||
optind = 1;
|
|
||||||
|
|
||||||
if (genPwdHash)
|
if (genPwdHash)
|
||||||
{
|
{
|
||||||
std::string saltBin;
|
generatePasswordHash() ;
|
||||||
std::string pwdHashRadix64;
|
return 0 ;
|
||||||
std::string sshPwdForHash = "";
|
|
||||||
|
|
||||||
std::cout << "Type in your Password:" << std::flush;
|
|
||||||
char pwd[1024];
|
|
||||||
if (!fgets(pwd, 1024, stdin))
|
|
||||||
{
|
|
||||||
std::cerr << "Error Reading Password";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip newline.
|
|
||||||
for(int i = 0; (i < 1024) && (pwd[i] != '\n') && (pwd[i] != '\0'); i++)
|
|
||||||
{
|
|
||||||
sshPwdForHash += pwd[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cerr << "Chosen Password : " << sshPwdForHash;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
GenerateSalt(saltBin);
|
|
||||||
if (!GeneratePasswordHash(saltBin, sshPwdForHash, pwdHashRadix64))
|
|
||||||
{
|
|
||||||
std::cerr << "Error Generating Password Hash, password probably too short";
|
|
||||||
std::cerr << pwdHashRadix64;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Generated Password Hash for rs-nogui: ";
|
|
||||||
std::cout << pwdHashRadix64;
|
|
||||||
std::cout << std::endl;
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
/* checking match */
|
|
||||||
if (CheckPasswordHash(pwdHashRadix64, sshPwdForHash))
|
|
||||||
{
|
|
||||||
std::cerr << "Passed Check Okay!";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "ERROR: Failed CheckPassword!";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::cerr << "Usage:";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
std::cerr << " - for SSH access: ./retroshare-nogui -S [port] -L <username> -P " << pwdHashRadix64;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
std::cerr << " - for RPC access: ./retroshare-nogui -C -S [port] -L <username> -P " << pwdHashRadix64;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* enforce conditions */
|
/* enforce conditions */
|
||||||
if (((enableSshRsa) || (enableSshPwd)) && (!enableSsh))
|
if ((!sshRsaFile.empty() || !sshPwdHash.empty()) && (!enableSsh))
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: SSH Server (-S) must be enabled to specify SSH Pwd (-P) or SSH RSA (-K)";
|
std::cerr << "ERROR: SSH Server (-X) must be enabled to specify SSH Pwd (-P) or SSH RSA (-K)";
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
exit(1);
|
return 1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSsh && (!enableSshRsa) && (!enableSshPwd))
|
if (enableSsh && (!enableSshRsa) && sshPwdHash.empty())
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: One of (or both) SSH Pwd (-P) and SSH RSA (-K) must be specified with SSH Server (-S)";
|
std::cerr << "ERROR: One of (or both) SSH Pwd (-P) and SSH RSA (-K) must be specified with SSH Server (-X)";
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
exit(1);
|
return 1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableRpc && (!enableSsh))
|
if (enableRpc && (!enableSsh))
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: RPC Mode (-C) requires SSH Server (-S) enabled";
|
std::cerr << "ERROR: RPC Mode (-C) requires SSH Server (-X) enabled";
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
exit(1);
|
return 1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,12 +203,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSshPwd)
|
#else
|
||||||
{
|
std::cerr << "\nRetroshare command line interface." << std::endl;
|
||||||
/* try parse it */
|
|
||||||
/* TODO */
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -372,7 +280,7 @@ int main(int argc, char **argv)
|
||||||
//ssh->adduser("anrsuser", "test");
|
//ssh->adduser("anrsuser", "test");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableSshPwd)
|
if (!sshPwdHash.empty())
|
||||||
{
|
{
|
||||||
ssh->adduserpwdhash(sshUser, sshPwdHash);
|
ssh->adduserpwdhash(sshUser, sshPwdHash);
|
||||||
}
|
}
|
||||||
|
@ -385,8 +293,6 @@ int main(int argc, char **argv)
|
||||||
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
|
// NASTY GLOBAL VARIABLE HACK - NEED TO THINK OF A BETTER SYSTEM.
|
||||||
RpcProtoSystem::mExtPort = extPort;
|
RpcProtoSystem::mExtPort = extPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Start-up libretroshare server threads */
|
/* Start-up libretroshare server threads */
|
||||||
|
@ -470,3 +376,71 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RS_SSH_SERVER
|
||||||
|
void generatePasswordHash()
|
||||||
|
{
|
||||||
|
std::string saltBin;
|
||||||
|
std::string pwdHashRadix64;
|
||||||
|
std::string sshPwdForHash = "";
|
||||||
|
|
||||||
|
std::string passwd1,passwd2 ;
|
||||||
|
|
||||||
|
if(!NotifyTxt().askForPassword("Type your password (at least 8 chars) : ",false,passwd1)) exit(1) ;
|
||||||
|
|
||||||
|
if(passwd1.length() < 8)
|
||||||
|
{
|
||||||
|
std::cerr << "Password must be at least 8 characters long." << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!NotifyTxt().askForPassword("Type your password (checking) : ",false,passwd2)) exit(1) ;
|
||||||
|
|
||||||
|
if(passwd1 != passwd2)
|
||||||
|
{
|
||||||
|
std::cerr << "Passwords differ. Please retry." << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sshPwdForHash = passwd1 ;
|
||||||
|
|
||||||
|
//std::cerr << "Chosen Password : " << sshPwdForHash;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
GenerateSalt(saltBin);
|
||||||
|
if (!GeneratePasswordHash(saltBin, sshPwdForHash, pwdHashRadix64))
|
||||||
|
{
|
||||||
|
std::cerr << "Error Generating Password Hash, password probably too short";
|
||||||
|
std::cerr << pwdHashRadix64;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Generated Password Hash for rs-nogui: ";
|
||||||
|
std::cout << pwdHashRadix64;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
/* checking match */
|
||||||
|
if (CheckPasswordHash(pwdHashRadix64, sshPwdForHash))
|
||||||
|
{
|
||||||
|
std::cerr << "Passed Check Okay!";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "ERROR: Failed CheckPassword!";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::cerr << "Usage:";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
std::cerr << " - for SSH access: ./retroshare-nogui -X -S [port] -L <username> -P " << pwdHashRadix64;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
std::cerr << " - for RPC access: ./retroshare-nogui -C -S [port] -L <username> -P " << pwdHashRadix64;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue