mirror of
https://github.com/RetroShare/RetroShare.git
synced 2026-09-12 19:50:17 +05:00
Merge pull request #3290 from defnax/account-creation-service
⚙️Added account creation for retroshare service - v2
This commit is contained in:
commit
360da46e96
@ -24,6 +24,15 @@
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "retroshare/rsinit.h"
|
||||
#include "retroshare/rstor.h"
|
||||
@ -70,6 +79,36 @@ std::string colored(int color,const std::string& s)
|
||||
}
|
||||
}
|
||||
|
||||
/** A terminal that dies mid-prompt -- an ssh session dropping, a container
|
||||
* losing its tty -- turns every following read into an immediate EOF. Every
|
||||
* prompt below re-asks on empty or mismatched input, so without a bound that
|
||||
* becomes a loop nobody can interrupt. Kept outside the terminal-login guard:
|
||||
* the web interface password prompt has its own build option. */
|
||||
static constexpr int MAX_PROMPT_ATTEMPTS = 3;
|
||||
|
||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||
/** On POSIX rs_getpass() reads stdin, so this tests the very channel it uses.
|
||||
* On Windows it reads the console directly through _getch(), so this is a
|
||||
* conservative proxy: a service with no console has no interactive stdin
|
||||
* either. */
|
||||
static bool hasInteractiveStdin()
|
||||
{
|
||||
#ifdef WINDOWS_SYS
|
||||
return _isatty(_fileno(stdin)) != 0;
|
||||
#else
|
||||
return isatty(fileno(stdin)) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string trimmed(const std::string& s)
|
||||
{
|
||||
const std::string blanks = " \t\r\n";
|
||||
const auto first = s.find_first_not_of(blanks);
|
||||
if(first == std::string::npos) return std::string();
|
||||
return s.substr(first, s.find_last_not_of(blanks) - first + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void eventHandler(std::shared_ptr<const RsEvent> e)
|
||||
{
|
||||
auto fe = dynamic_cast<const RsSystemEvent*>(e.get());
|
||||
@ -80,6 +119,18 @@ static void eventHandler(std::shared_ptr<const RsEvent> e)
|
||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||
if(fe->mEventCode == RsSystemEventCode::PASSWORD_REQUESTED)
|
||||
{
|
||||
// The core asks for the passphrase through this event on every login,
|
||||
// including -U <hexid> from systemd or docker where there is nothing to
|
||||
// ask. Answering nothing lets attemptLogin() fail with a proper status;
|
||||
// prompting an absent terminal cannot succeed and only hides the cause.
|
||||
if(!hasInteractiveStdin())
|
||||
{
|
||||
RsErr() << "A passphrase is required but stdin is not a terminal. "
|
||||
"Run retroshare-service interactively, or unlock the "
|
||||
"profile through the JSON API." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string question1 = fe->passwd_request_title + colored(COLOR_GREEN,"Please enter your PGP password for key:\n ") + fe->passwd_request_key_details + " :";
|
||||
std::string password = RsUtil::rs_getpass(question1.c_str()) ;
|
||||
|
||||
@ -124,6 +175,210 @@ void signalHandler(int signal)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||
enum class CreateAccountResult { Unknown = 0x00, Created = 0x01, Cancelled = 0x02, Failed = 0x03 };
|
||||
|
||||
/** Ask the user for a PGP profile to sign the new node with.
|
||||
* Returns false when the user cancelled. A null pgpId on return means "make a
|
||||
* new profile", which is what createLocationV2() does with a null id. */
|
||||
static bool askPgpProfile(RsPgpId& pgpId)
|
||||
{
|
||||
pgpId.clear();
|
||||
|
||||
std::list<RsPgpId> pgpIds;
|
||||
RsAccounts::GetPGPLogins(pgpIds);
|
||||
|
||||
if(pgpIds.empty()) return true; // nothing to reuse, nothing to ask
|
||||
|
||||
std::vector<RsPgpId> choices(pgpIds.begin(), pgpIds.end());
|
||||
|
||||
std::cout << std::endl
|
||||
<< colored(COLOR_GREEN, "Existing profiles on this machine:")
|
||||
<< std::endl << std::endl;
|
||||
|
||||
int profileCountDigits = static_cast<int>( ceil(log(choices.size() + 1)/log(10.0)) );
|
||||
|
||||
for(size_t i = 0; i < choices.size(); ++i)
|
||||
{
|
||||
std::string name, email;
|
||||
RsAccounts::GetPGPLoginDetails(choices[i], name, email);
|
||||
std::cout << colored(COLOR_GREEN, " [" + RsUtil::NumberToString(i+1, false, '0', profileCountDigits) + "]") << " "
|
||||
<< colored(COLOR_BLUE, choices[i].toStdString()) << ": "
|
||||
<< colored(COLOR_PURPLE, name) << std::endl;
|
||||
}
|
||||
|
||||
std::cout << colored(COLOR_GREEN, " [n]") << " "
|
||||
<< colored(COLOR_YELLOW, "Create a new profile") << std::endl << std::endl
|
||||
<< colored(COLOR_YELLOW,
|
||||
"A new profile is a new identity: your existing friends "
|
||||
"will not recognise it,\nand you will have to exchange "
|
||||
"certificates with them again. Reuse a profile above\n"
|
||||
"to simply add this machine as another node to that profile.")
|
||||
<< std::endl << std::endl;
|
||||
|
||||
for(int attempt = 0; keepRunning && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
std::cout << colored(COLOR_GREEN, "Profile to use, or 'n' for a new one: ");
|
||||
std::cout.flush();
|
||||
|
||||
std::string inputStr;
|
||||
if(!std::getline(std::cin, inputStr))
|
||||
{
|
||||
RsErr() << "Unable to read the profile selection from the terminal." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
inputStr = trimmed(inputStr);
|
||||
|
||||
if(inputStr == "n" || inputStr == "N") return true;
|
||||
|
||||
char* inputEnd = nullptr;
|
||||
unsigned long selection = std::strtoul(inputStr.c_str(), &inputEnd, 10);
|
||||
if(inputEnd != inputStr.c_str() && *inputEnd == '\0' &&
|
||||
selection >= 1 && selection <= choices.size())
|
||||
{
|
||||
pgpId = choices[selection - 1];
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << colored(COLOR_RED, "Invalid selection. Please try again.") << std::endl;
|
||||
}
|
||||
|
||||
if(keepRunning)
|
||||
RsErr() << "Too many invalid selections, giving up." << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static CreateAccountResult doTerminalCreateAccount()
|
||||
{
|
||||
if(!hasInteractiveStdin())
|
||||
{
|
||||
RsErr() << "Account creation requires an interactive terminal." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
|
||||
std::cout << std::endl
|
||||
<< colored(COLOR_GREEN, "=== Create New RetroShare Account ===") << std::endl << std::endl;
|
||||
|
||||
RsPgpId pgpId;
|
||||
if(!askPgpProfile(pgpId))
|
||||
return keepRunning ? CreateAccountResult::Failed : CreateAccountResult::Cancelled;
|
||||
|
||||
const bool reusingProfile = !pgpId.isNull();
|
||||
|
||||
// Only asked when a profile is created: reusing one keeps its name, and
|
||||
// createLocationV2() ignores pgpName as soon as pgpId is not null.
|
||||
std::string pgpName;
|
||||
if(!reusingProfile)
|
||||
{
|
||||
for(int attempt = 0; keepRunning && pgpName.empty() && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
std::cout << colored(COLOR_GREEN, "Please enter your new profile name: ");
|
||||
std::cout.flush();
|
||||
if(!std::getline(std::cin, pgpName))
|
||||
{
|
||||
RsErr() << "Unable to read the account name from the terminal." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
pgpName = trimmed(pgpName);
|
||||
if (pgpName.empty())
|
||||
std::cout << colored(COLOR_RED, "Name cannot be empty!") << std::endl;
|
||||
}
|
||||
if (!keepRunning) return CreateAccountResult::Cancelled;
|
||||
if (pgpName.empty())
|
||||
{
|
||||
RsErr() << "No account name given, giving up." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
}
|
||||
|
||||
std::string locationName;
|
||||
for(int attempt = 0; keepRunning && locationName.empty() && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
std::cout << colored(COLOR_GREEN, "Please enter Node/Location Name (e.g. Laptop, Home): ");
|
||||
std::cout.flush();
|
||||
if(!std::getline(std::cin, locationName))
|
||||
{
|
||||
RsErr() << "Unable to read the location name from the terminal." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
locationName = trimmed(locationName);
|
||||
if (locationName.empty())
|
||||
std::cout << colored(COLOR_RED, "Location name cannot be empty!") << std::endl;
|
||||
}
|
||||
if (!keepRunning) return CreateAccountResult::Cancelled;
|
||||
if (locationName.empty())
|
||||
{
|
||||
RsErr() << "No location name given, giving up." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
|
||||
std::string pass1, pass2;
|
||||
bool passphraseAccepted = false;
|
||||
for(int attempt = 0; keepRunning && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
pass1 = RsUtil::rs_getpass(colored(COLOR_GREEN,
|
||||
reusingProfile ? "Please enter the passphrase of that profile: "
|
||||
: "Please enter passphrase for new account: "));
|
||||
|
||||
if(reusingProfile)
|
||||
{
|
||||
// Nothing to confirm: the passphrase already exists and a typo is
|
||||
// caught by the key itself rather than by a second prompt.
|
||||
if(!pass1.empty()) { passphraseAccepted = true; break; }
|
||||
std::cout << colored(COLOR_RED, "Passphrase cannot be empty! Please try again.") << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
pass2 = RsUtil::rs_getpass(colored(COLOR_GREEN, "Please enter the same passphrase again: "));
|
||||
|
||||
if (pass1 != pass2)
|
||||
{
|
||||
std::cout << colored(COLOR_RED, "Passphrases do not match! Please try again.") << std::endl;
|
||||
continue;
|
||||
}
|
||||
if (pass1.empty())
|
||||
{
|
||||
std::cout << colored(COLOR_RED, "Passphrase cannot be empty! Please try again.") << std::endl;
|
||||
continue;
|
||||
}
|
||||
passphraseAccepted = true;
|
||||
break;
|
||||
}
|
||||
if (!keepRunning) return CreateAccountResult::Cancelled;
|
||||
if (!passphraseAccepted)
|
||||
{
|
||||
RsErr() << "No usable passphrase given, giving up." << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
|
||||
if(reusingProfile)
|
||||
std::cout << colored(COLOR_YELLOW, "Generating certificate for the new node...") << std::endl;
|
||||
else
|
||||
std::cout << colored(COLOR_YELLOW, "Generating profile key and node certificate (this may take a few seconds)...") << std::endl;
|
||||
|
||||
RsPeerId locationId;
|
||||
std::error_condition err = rsLoginHelper->createLocationV2(locationId, pgpId, locationName, pgpName, pass1);
|
||||
|
||||
if (err)
|
||||
{
|
||||
RsErr() << colored(COLOR_RED, "Account creation failed: " + err.message()) << std::endl;
|
||||
return CreateAccountResult::Failed;
|
||||
}
|
||||
|
||||
std::cout << std::endl
|
||||
<< colored(COLOR_GREEN, "Account successfully created and logged in!") << std::endl;
|
||||
std::cout << colored(COLOR_GREEN, " Node ID : ") << colored(COLOR_YELLOW, locationId.toStdString()) << std::endl;
|
||||
std::cout << colored(COLOR_GREEN, " Profile ID : ") << colored(COLOR_BLUE, pgpId.toStdString()) << std::endl << std::endl;
|
||||
|
||||
return CreateAccountResult::Created;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
signal(SIGINT, signalHandler);
|
||||
@ -209,7 +464,7 @@ int main(int argc, char* argv[])
|
||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||
as >> parameter( 'U', "user-id", prefUserString, "ID",
|
||||
"[node Id] Selected account to use and asks for passphrase"
|
||||
". Use \"-U list\" in order to list available accounts.",
|
||||
". Use \"-U list\" to list accounts, or \"-U create\" to create a new account.",
|
||||
false );
|
||||
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
||||
|
||||
@ -249,9 +504,11 @@ int main(int argc, char* argv[])
|
||||
std::string webui_pass1;
|
||||
if(askWebUiPassword)
|
||||
{
|
||||
std::string webui_pass2 = "N";
|
||||
std::string webui_pass2 = "";
|
||||
|
||||
while(keepRunning)
|
||||
// Same bound as the account prompts: -W on a service with no terminal
|
||||
// re-asks a question that can never be answered.
|
||||
for(int attempt = 0; keepRunning && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
webui_pass1 = RsUtil::rs_getpass( colored(COLOR_GREEN,"Please register a password for the web interface: "));
|
||||
webui_pass2 = RsUtil::rs_getpass( colored(COLOR_GREEN,"Please enter the same password again : "));
|
||||
@ -259,6 +516,7 @@ int main(int argc, char* argv[])
|
||||
if(webui_pass1 != webui_pass2)
|
||||
{
|
||||
std::cout << colored(COLOR_RED,"Passwords do not match!") << std::endl;
|
||||
webui_pass1.clear();
|
||||
continue;
|
||||
}
|
||||
if(webui_pass1.empty())
|
||||
@ -269,6 +527,10 @@ int main(int argc, char* argv[])
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(askWebUiPassword && webui_pass1.empty())
|
||||
RsErr() << "No web interface password given, the web interface will "
|
||||
"not be started." << std::endl;
|
||||
}
|
||||
#ifdef RS_SERVICE_TERMINAL_WEBUI_PASSWORD
|
||||
if(askWebUiPassword && !webui_pass1.empty())
|
||||
@ -351,83 +613,154 @@ int main(int argc, char* argv[])
|
||||
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
||||
if(!prefUserString.empty()) // Login from terminal requested
|
||||
{
|
||||
if(prefUserString == "list")
|
||||
bool alreadyLoggedIn = false;
|
||||
|
||||
if(prefUserString == "create")
|
||||
{
|
||||
switch(doTerminalCreateAccount())
|
||||
{
|
||||
case CreateAccountResult::Created: alreadyLoggedIn = true; break;
|
||||
case CreateAccountResult::Cancelled: return 0;
|
||||
case CreateAccountResult::Failed: return -RsInit::ERR_UNKNOWN;
|
||||
case CreateAccountResult::Unknown:
|
||||
default:
|
||||
RsErr() << "An unexpected error occurred during account creation." << std::endl;
|
||||
return -RsInit::ERR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else if(prefUserString == "list")
|
||||
{
|
||||
std::vector<RsLoginHelper::Location> locations;
|
||||
rsLoginHelper->getLocations(locations);
|
||||
|
||||
if(locations.size() == 0)
|
||||
{
|
||||
RsErr() << colored(COLOR_RED,"No available accounts. You cannot use option -U list") << std::endl;
|
||||
return -RsInit::ERR_NO_AVAILABLE_ACCOUNT;
|
||||
}
|
||||
|
||||
std::cout << std::endl << std::endl
|
||||
<< colored(COLOR_GREEN,"Available accounts:") << std::endl<<std::endl;
|
||||
|
||||
int accountCountDigits = static_cast<int>( ceil(log(locations.size())/log(10.0)) );
|
||||
|
||||
for( uint32_t i=0; i<locations.size(); ++i )
|
||||
std::cout << colored(COLOR_GREEN," [" + RsUtil::NumberToString(i+1,false,'0',accountCountDigits)+"]") << " "
|
||||
<< colored(COLOR_YELLOW,locations[i].mLocationId.toStdString())<< " "
|
||||
<< colored(COLOR_BLUE,"(" + locations[i].mPgpId.toStdString()+ "): ")
|
||||
<< colored(COLOR_PURPLE,locations[i].mPgpName + " (" + locations[i].mLocationName + ")" )
|
||||
<< std::endl;
|
||||
|
||||
std::cout << std::endl;
|
||||
uint32_t nacc = 0;
|
||||
while(keepRunning && (nacc < 1 || nacc >= locations.size()))
|
||||
std::cout << std::endl << std::endl;
|
||||
if(locations.empty())
|
||||
std::cout << colored(COLOR_YELLOW,"No existing RetroShare accounts found.")
|
||||
<< std::endl << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << colored(COLOR_GREEN,"Please enter account number: ");
|
||||
std::cout << colored(COLOR_GREEN,"Available accounts:") << std::endl<<std::endl;
|
||||
|
||||
int accountCountDigits = static_cast<int>( ceil(log(locations.size() + 1)/log(10.0)) );
|
||||
|
||||
for( uint32_t i=0; i<locations.size(); ++i )
|
||||
std::cout << colored(COLOR_GREEN," [" + RsUtil::NumberToString(i+1,false,'0',accountCountDigits)+"]") << " "
|
||||
<< colored(COLOR_YELLOW,locations[i].mLocationId.toStdString())<< " "
|
||||
<< colored(COLOR_BLUE,"(" + locations[i].mPgpId.toStdString()+ "): ")
|
||||
<< colored(COLOR_PURPLE,locations[i].mPgpName + " (" + locations[i].mLocationName + ")" )
|
||||
<< std::endl;
|
||||
|
||||
}
|
||||
|
||||
// "-U list" is documented as a way to list accounts, so on a
|
||||
// non-interactive stdin print the list and stop there rather than
|
||||
// advertising a [c] entry nobody can type. The error is kept for
|
||||
// the case it actually describes: no account to list.
|
||||
if(!hasInteractiveStdin())
|
||||
{
|
||||
if(locations.empty())
|
||||
{
|
||||
RsErr() << "No available account, and stdin is not a terminal "
|
||||
"to create one." << std::endl;
|
||||
return -RsInit::ERR_NO_AVAILABLE_ACCOUNT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::cout << colored(COLOR_GREEN," [c]") << " "
|
||||
<< colored(COLOR_YELLOW,"Create new profile/node") << std::endl
|
||||
<< std::endl;
|
||||
|
||||
bool selectionMade = false;
|
||||
for(int attempt = 0; keepRunning && attempt < MAX_PROMPT_ATTEMPTS; ++attempt)
|
||||
{
|
||||
std::cout << colored(COLOR_GREEN,"Please enter account number or 'c' to create: ");
|
||||
std::cout.flush();
|
||||
|
||||
std::string inputStr;
|
||||
std::getline(std::cin, inputStr);
|
||||
|
||||
nacc = static_cast<uint32_t>(atoi(inputStr.c_str())-1);
|
||||
if(nacc < locations.size())
|
||||
if(!std::getline(std::cin, inputStr))
|
||||
{
|
||||
prefUserString = locations[nacc].mLocationId.toStdString();
|
||||
RsErr() << "Unable to read an account selection from the terminal." << std::endl;
|
||||
return -RsInit::ERR_NO_AVAILABLE_ACCOUNT;
|
||||
}
|
||||
|
||||
inputStr = trimmed(inputStr);
|
||||
|
||||
if(inputStr == "c" || inputStr == "C")
|
||||
{
|
||||
switch(doTerminalCreateAccount())
|
||||
{
|
||||
case CreateAccountResult::Created: alreadyLoggedIn = true; break;
|
||||
case CreateAccountResult::Cancelled: return 0;
|
||||
case CreateAccountResult::Failed: return -RsInit::ERR_UNKNOWN;
|
||||
case CreateAccountResult::Unknown:
|
||||
default:
|
||||
RsErr() << "An unexpected error occurred during account creation." << std::endl;
|
||||
return -RsInit::ERR_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
nacc=0; // allow to continue if something goes wrong.
|
||||
|
||||
char* inputEnd = nullptr;
|
||||
unsigned long selection = std::strtoul(inputStr.c_str(), &inputEnd, 10);
|
||||
if(inputEnd != inputStr.c_str() && *inputEnd == '\0' &&
|
||||
selection >= 1 && selection <= locations.size())
|
||||
{
|
||||
prefUserString = locations[selection - 1].mLocationId.toStdString();
|
||||
selectionMade = true;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << colored(COLOR_RED,"Invalid selection. Please try again.") << std::endl;
|
||||
}
|
||||
|
||||
// Ctrl-C at a prompt: on glibc signal() installs the handler with
|
||||
// SA_RESTART, so the blocked read is restarted and keepRunning is
|
||||
// only seen once the user also presses Enter. Without this, control
|
||||
// fell through with prefUserString still "list" and the user who
|
||||
// just cancelled was told their location id was invalid.
|
||||
if(!keepRunning) return 0;
|
||||
|
||||
if(!alreadyLoggedIn && !selectionMade)
|
||||
{
|
||||
RsErr() << "No account selected, giving up." << std::endl;
|
||||
return -RsInit::ERR_NO_AVAILABLE_ACCOUNT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RsPeerId ssl_id(prefUserString);
|
||||
if(ssl_id.isNull())
|
||||
if(!alreadyLoggedIn)
|
||||
{
|
||||
RsErr() << colored(COLOR_RED,"Invalid User location id: a hexadecimal ID is expected.")
|
||||
<< std::endl;
|
||||
return -EINVAL;
|
||||
}
|
||||
RsPeerId ssl_id(prefUserString);
|
||||
if(ssl_id.isNull())
|
||||
{
|
||||
RsErr() << colored(COLOR_RED,"Invalid User location id: a hexadecimal ID, 'list', or 'create' is expected.")
|
||||
<< std::endl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
//RsServiceNotify* notify = new RsServiceNotify();
|
||||
//rsNotify->registerNotifyClient(notify);
|
||||
// supply empty passwd so that it is properly asked 3 times on console
|
||||
RsInit::LoadCertificateStatus result = rsLoginHelper->attemptLogin(ssl_id, "");
|
||||
|
||||
// supply empty passwd so that it is properly asked 3 times on console
|
||||
RsInit::LoadCertificateStatus result = rsLoginHelper->attemptLogin(ssl_id, "");
|
||||
|
||||
switch(result)
|
||||
{
|
||||
case RsInit::OK: break;
|
||||
case RsInit::ERR_ALREADY_RUNNING:
|
||||
RsErr() << "Another RetroShare using the same profile is already "
|
||||
"running on your system. Please close that instance "
|
||||
"first." << std::endl << "Lock file: "
|
||||
<< RsInit::lockFilePath() << std::endl;
|
||||
return -RsInit::ERR_ALREADY_RUNNING;
|
||||
case RsInit::ERR_CANT_ACQUIRE_LOCK:
|
||||
RsErr() << "An unexpected error occurred when Retroshare tried to "
|
||||
"acquire the single instance lock file." << std::endl
|
||||
<< "Lock file: " << RsInit::lockFilePath() << std::endl;
|
||||
return -RsInit::ERR_CANT_ACQUIRE_LOCK;
|
||||
case RsInit::ERR_UNKNOWN: // Fall-throug
|
||||
default:
|
||||
RsErr() << "Cannot login. Check your passphrase." << std::endl
|
||||
<< std::endl;
|
||||
return -result;
|
||||
switch(result)
|
||||
{
|
||||
case RsInit::OK: break;
|
||||
case RsInit::ERR_ALREADY_RUNNING:
|
||||
RsErr() << "Another RetroShare using the same profile is already "
|
||||
"running on your system. Please close that instance "
|
||||
"first." << std::endl << "Lock file: "
|
||||
<< RsInit::lockFilePath() << std::endl;
|
||||
return -RsInit::ERR_ALREADY_RUNNING;
|
||||
case RsInit::ERR_CANT_ACQUIRE_LOCK:
|
||||
RsErr() << "An unexpected error occurred when Retroshare tried to "
|
||||
"acquire the single instance lock file." << std::endl
|
||||
<< "Lock file: " << RsInit::lockFilePath() << std::endl;
|
||||
return -RsInit::ERR_CANT_ACQUIRE_LOCK;
|
||||
case RsInit::ERR_UNKNOWN: // Fall-through
|
||||
default:
|
||||
RsErr() << "Cannot login. Check your passphrase." << std::endl
|
||||
<< std::endl;
|
||||
return -result;
|
||||
}
|
||||
}
|
||||
|
||||
if(RsAccounts::isTorAuto())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user