Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
opentxs::Opentxs Class Reference

#include <opentxs.hpp>

Classes

struct  CommandEntry
 

Public Types

enum  Category {
  catError = 0, catAdmin = 1, catWallet = 2, catMisc = 3,
  catMarkets = 4, catAccounts = 5, catOtherUsers = 6, catInstruments = 7,
  catBaskets = 8, catNyms = 9, catLast = 10
}
 

Public Member Functions

 Opentxs ()
 
virtual ~Opentxs ()
 
int run (int argc, char *argv[])
 

Detailed Description

Definition at line 144 of file opentxs.hpp.

Member Enumeration Documentation

Enumerator
catError 
catAdmin 
catWallet 
catMisc 
catMarkets 
catAccounts 
catOtherUsers 
catInstruments 
catBaskets 
catNyms 
catLast 

Definition at line 152 of file opentxs.hpp.

Constructor & Destructor Documentation

Opentxs::Opentxs ( )

Definition at line 368 of file opentxs.cpp.

369 {
371 }
static EXPORT bool AppInit()
Definition: OTAPI.cpp:179
Opentxs::~Opentxs ( )
virtual

Definition at line 373 of file opentxs.cpp.

374 {
376 }
static EXPORT bool AppCleanup()
Definition: OTAPI.cpp:189

Member Function Documentation

int Opentxs::run ( int  argc,
char *  argv[] 
)

Definition at line 736 of file opentxs.cpp.

737 {
738  if (OTAPI_Wrap::OTAPI() == nullptr) return -1;
739 
741 
742  map<string, string> macros;
743  vector<int> errorLineNumbers;
744  vector<string> errorCommands;
745 
746  OT_ME madeEasy;
747 
748  AnyOption opt;
749  handleCommandLineArguments(argc, argv, opt);
750 
751  if (opt.getArgc() != 0) {
752  return processCommand(madeEasy, opt);
753  }
754 
755  int lineNumber = 0;
756  bool echoCommand = opt.getFlag("echocommand") || opt.getFlag("test");
757  bool echoExpand = opt.getFlag("echoexpand") || opt.getFlag("test");
758  bool noPrompt = opt.getFlag("noprompt") || opt.getFlag("test");
759  int processed = 0;
760  while (true) {
761  // get next command line from input stream
762  if (!noPrompt) {
763  cout << "\nopentxs> ";
764  }
765  string cmd;
766  getline(cin, cmd);
767 
768  // end of file stops processing commands
769  if (cin.eof()) {
770  break;
771  }
772 
773  lineNumber++;
774 
775  // quit/exit the command loop?
776  cmd = trim(cmd);
777  if (echoCommand) {
778  cout << cmd << endl;
779  }
780 
781  if (cmd == "quit" || cmd == "exit") {
782  break;
783  }
784 
785  // empty lines and lines starting with a hash character are seen as
786  // comments
787  if (cmd.size() == 0 || cmd[0] == '#') {
788  continue;
789  }
790 
791  string originalCmd = cmd;
792 
793  // lines starting with a dollar sign character denote the definition of
794  // a macro of the form: $macroName = macroValue
795  // whitespace around the equal sign is optional
796  // <macroName> can be any combination of A-Z, a-z, 0-9, or _
797  // <macroValue> is anything after the equal sign and whitespace-trimmed
798  // note that <macroValue> can be an empty string
799  // note that the dollar sign itself is part of the immediately following
800  // macro name
801  // note that a macro value stays valid for the entire lifetime of the
802  // command loop
803  // note that macro expansion is done on the command line before
804  // processing the line this means that a macro is allowed to contain
805  // command line escape characters
806  // note that macro expansion is recursive until no expansions are found
807  // any more this means that a macro is allowed to contain other macros
808  if (cmd[0] == '$') {
809  // determine the macro name
810  size_t nameLength = 1;
811  while (nameLength < cmd.length() &&
812  (isalnum(cmd[nameLength]) || cmd[nameLength] == '_')) {
813  nameLength++;
814  }
815  string macroName = cmd.substr(0, nameLength);
816 
817  // skip whitespace
818  size_t i = nameLength;
819  while (i < cmd.length() && isspace(cmd[i])) {
820  i++;
821  }
822 
823  if (i == cmd.length() || cmd[i] != '=') {
824  otOut << "\n\n***ERROR***\n"
825  "Expected macro definition of the form: "
826  "$macroName = macroValue\n"
827  "Command was: " << cmd;
828  continue;
829  }
830 
831  // remainder of line after trimming whitespace is macro value
832  string macroValue = cmd.substr(i + 1);
833  macros[macroName] = trim(macroValue);
834  continue;
835  }
836 
837  // now replace any macro in the command line with its value
838  // unknown macro names will cause an error message instead of command
839  // execution
840  // note that all macro names are 'maximum munch'
841  int expansions = 0;
842  for (size_t macro = cmd.find_first_of("$"); macro != string::npos;
843  macro = cmd.find_first_of("$", macro + 1)) {
844  // first see if this is an escaped literal
845  if (macro > 0 && cmd[macro - 1] == '\\') {
846  continue;
847  }
848 
849  // gather rest of macro name 'maximum munch'
850  size_t macroEnd = macro + 1;
851  while (macroEnd < cmd.length() &&
852  (isalnum(cmd[macroEnd]) || cmd[macroEnd] == '_')) {
853  macroEnd++;
854  }
855 
856  // has this macro been defined?
857  string macroName = cmd.substr(macro, macroEnd - macro);
858  auto found = macros.find(macroName);
859  if (found == macros.end()) {
860  otOut << "\n\n***ERROR***\n"
861  "Macro expansion failed.\n"
862  "Unknown macro: " << macroName
863  << "\n"
864  "Command was: " << cmd;
865  expansions = 100;
866  break;
867  }
868 
869  string& macroValue = found->second;
870 
871  // limit to 100 expansions to avoid endless recusion loop
872  expansions++;
873  if (expansions > 100) {
874  otOut << "\n\n***ERROR***\n"
875  "Macro expansion failed.\n"
876  "Too many expansions at macro: " << macroName
877  << "\n"
878  "Command was: " << cmd;
879  break;
880  }
881 
882  // limit to 10000 characters to avoid crazy recursive expansions
883  if (cmd.length() + macroValue.length() > 10000) {
884  otOut << "\n\n***ERROR***\n"
885  "Macro expansion failed.\n"
886  "Command length exceeded at macro: " << macroName
887  << "\n"
888  "Macro value is: " << macroValue
889  << "\n"
890  "Command was: " << cmd;
891  expansions = 100;
892  break;
893  }
894 
895  // expand the command line
896  cmd = cmd.substr(0, macro) + macroValue + cmd.substr(macroEnd);
897  }
898 
899  if (echoExpand && cmd != originalCmd) {
900  otOut << cmd << endl;
901  }
902 
903  // skip command when anything during macro expansion failed
904  if (expansions > 99) {
905  continue;
906  }
907 
908  // '!' indicates that we expect this command to fail
909  // which is very useful for running a test script
910  bool expectFailure = cmd[0] == '!';
911 
912  // Parse command string into its separate parts so it can be passed as
913  // an argc/argv combo
914  // Whitespace separates args as usual.
915  // To include whitespace in an arg surround the entire arg with double
916  // quotes
917  // An unterminated double-quoted arg will auto-terminate at end of line
918  // All characters are taken literal except for: double quote, dollar
919  // sign, and backslash
920  // To take any character literal, precede it with a backslash
921  vector<string> arguments;
922 
923  // add original command name
924  arguments.push_back(argv[0]);
925 
926  // set up buffer that will receive the separate arguments
927  char* buf = new char[cmd.length() + 1];
928  char* arg = buf;
929 
930  // start at actual command
931  size_t i = expectFailure ? 1 : 0;
932  while (i < cmd.length()) {
933  // skip any whitespace
934  while (i < cmd.length() && isspace(cmd[i])) {
935  i++;
936  }
937  if (i == cmd.length()) {
938  // it was trailing whitespace; we're done
939  break;
940  }
941 
942  // remember where we start this new argument in the buffer
943  char* start = arg;
944 
945  // unquoted argument?
946  if (cmd[i] != '"') {
947  // take everything until end of line or next whitespace
948  while (i < cmd.length() && !isspace(cmd[i])) {
949  // unescaped literal character?
950  if (cmd[i] != '\\') {
951  // yep, add to buffer and go for next
952  *arg++ = cmd[i++];
953  continue;
954  }
955 
956  // take next character literal unless it was the end of line
957  // in which case we simply add the backslash as a literal
958  // character
959  *arg++ = i < cmd.length() ? cmd[i++] : '\\';
960  }
961 
962  // end of argument reached, terminate an add to arguments array
963  *arg++ = '\0';
964  arguments.push_back(start);
965 
966  // look for next argument
967  continue;
968  }
969 
970  // double quoted argument, skip the quote
971  i++;
972 
973  // take everything until end of line or next double quote
974  while (i < cmd.length() && cmd[i] != '"') {
975  // unescaped literal character?
976  if (cmd[i] != '\\') {
977  // yep, add to buffer and go for next
978  *arg++ = cmd[i++];
979  continue;
980  }
981 
982  // take next character literal unless it was the end of line
983  // in which case we simply add the backslash as a literal
984  // character
985  *arg++ = i < cmd.length() ? cmd[i++] : '\\';
986  }
987 
988  // end of argument reached, terminate an add to arguments array
989  *arg++ = '\0';
990  arguments.push_back(start);
991 
992  // skip terminating double quote or end of line
993  i++;
994  }
995 
996  // set up a new argc/argv combo
997  int newArgc = arguments.size();
998  char** newArgv = new char* [newArgc];
999  for (int i = 0; i < newArgc; i++) {
1000  newArgv[i] = const_cast<char*>(arguments[i].c_str());
1001  }
1002 
1003  // preprocess the command line
1004  AnyOption opt;
1005  handleCommandLineArguments(newArgc, newArgv, opt);
1006 
1007  cout << "\n";
1008  if (expectFailure != (0 != processCommand(madeEasy, opt))) {
1009  errorLineNumbers.push_back(lineNumber);
1010  errorCommands.push_back(originalCmd);
1011  otOut << "\n\n***ERROR***\n"
1012  << (expectFailure ? "Expected command to fail.\nSucceeding"
1013  : "Failed") << " command was: " << cmd;
1014  }
1015 
1016  delete[] newArgv;
1017  delete[] buf;
1018 
1019  otOut << "\n\n";
1020  processed++;
1021  }
1022 
1023  int failed = errorLineNumbers.size();
1024  cout << "\n\n" << processed << " commands were processed.\n" << failed
1025  << " commands failed.\n" << endl;
1026 
1027  if (opt.getFlag("errorList") || opt.getFlag("test")) {
1028  for (size_t i = 0; i < errorLineNumbers.size(); i++) {
1029  cout << "\nFailed line " << errorLineNumbers[i] << ": "
1030  << errorCommands[i] << endl;
1031  }
1032  }
1033 
1034  return failed == 0 ? 0 : -1;
1035 }
OTLOG_IMPORT OTLogStream otOut
EXPORT bool LoadWallet() const
static EXPORT OT_API * OTAPI()
Definition: OTAPI.cpp:244

The documentation for this class was generated from the following files: