LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - rpc_universal.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 457 203 44.4 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * NaCl testing shell
       9                 :  */
      10                 : 
      11                 : #include <assert.h>
      12                 : #include <string.h>
      13                 : #include <sstream>
      14                 : 
      15                 : #include "native_client/src/include/portability.h"
      16                 : #include "native_client/src/include/portability_io.h"
      17                 : 
      18                 : #include "native_client/src/include/nacl_base.h"
      19                 : 
      20                 : #include "native_client/src/shared/platform/nacl_log.h"
      21                 : #include "native_client/src/shared/platform/nacl_threads.h"
      22                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      23                 : 
      24                 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
      25                 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
      26                 : #include "native_client/src/trusted/desc/nacl_desc_imc_shm.h"
      27                 : #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
      28                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      29                 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
      30                 : #include "native_client/src/trusted/sel_universal/parsing.h"
      31                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      32                 : 
      33                 : #define kMaxCommandLineLength 4096
      34                 : 
      35                 : using std::stringstream;
      36                 : 
      37                 : using nacl::DescWrapperFactory;
      38                 : using nacl::DescWrapper;
      39                 : 
      40              39 : static NaClSrpcImcDescType DescFromPlatformDesc(int fd, int mode) {
      41                 :   return
      42              39 :       (NaClSrpcImcDescType) NaClDescIoDescMake(NaClHostDescPosixMake(fd, mode));
      43                 : }
      44                 : 
      45                 : 
      46              66 : void NaClCommandLoop::AddDesc(NaClSrpcImcDescType desc, string name) {
      47             132 :   NaClLog(1, "adding descriptor %p -> %s\n",
      48              66 :           static_cast<void*>(desc), name.c_str());
      49              66 :   descs_[name] = desc;
      50              66 : }
      51                 : 
      52                 : 
      53               2 : NaClSrpcImcDescType NaClCommandLoop::FindDescByName(string name) const {
      54               2 :   if (descs_.find(name) == descs_.end()) {
      55               0 :     NaClLog(LOG_ERROR, "could not find desc: %s\n", name.c_str());
      56               0 :     return kNaClSrpcInvalidImcDesc;
      57                 :   } else {
      58                 :     // NOTE: descs_[name] is not const
      59               2 :     return descs_.find(name)->second;
      60                 :   }
      61               2 : }
      62                 : 
      63                 : 
      64               6 : string NaClCommandLoop::AddDescUniquify(NaClSrpcImcDescType desc,
      65               6 :                                         string prefix) {
      66                 :   // check whether we have given this descriptor a name already
      67               6 :   for (map<string, NaClSrpcImcDescType>::iterator it = descs_.begin();
      68              16 :        it != descs_.end();
      69              10 :        ++it) {
      70              20 :     if (it->second == desc) return it->first;
      71              10 :   }
      72                 : 
      73               1 :   while (1) {
      74               1 :     stringstream sstr;
      75               3 :     sstr << prefix << "_" << desc_count_;
      76               1 :     ++desc_count_;
      77               1 :     string unique = sstr.str();
      78               4 :     if (descs_.find(unique) == descs_.end()) {
      79               3 :       AddDesc(desc, unique);
      80               1 :       return unique;
      81                 :     }
      82               6 :   }
      83               6 : }
      84                 : 
      85                 : 
      86             429 : void NaClCommandLoop::AddHandler(string name, CommandHandler handler) {
      87             429 :   if (handlers_.find(name) != handlers_.end()) {
      88               0 :     NaClLog(LOG_ERROR, "handler %s already exists\n", name.c_str());
      89               0 :   }
      90             429 :   handlers_[name] = handler;
      91             429 : }
      92                 : 
      93                 : 
      94               0 : void NaClCommandLoop::RegisterNonDeterministicOutput(string content,
      95               0 :                                                      string name) {
      96               0 :   NaClSrpcArg arg;
      97                 :   // we parse and then unparse to canonicalize the string representation
      98                 :   // of content
      99               0 :   if (!ParseArg(&arg, content, true, this)) {
     100               0 :     NaClLog(LOG_ERROR, "malformed argument to RegisterNonDeterministicOutput");
     101               0 :   }
     102               0 :   string data = DumpArg(&arg, this);
     103               0 :   nondeterministic_[data] = name;
     104               0 :   FreeArrayArg(&arg);
     105               0 : }
     106                 : 
     107                 : 
     108              65 : void NaClCommandLoop::SetVariable(string name, string value) {
     109              65 :   vars_[name] = value;
     110              65 : }
     111                 : 
     112                 : 
     113               2 : string NaClCommandLoop::GetVariable(string name) const {
     114               2 :   if (vars_.find(name) == vars_.end()) {
     115               0 :     NaClLog(LOG_ERROR, "unknown variable %s\n", name.c_str());
     116               0 :     return "";
     117                 :   }
     118                 :   // NOTE: vars_[name] is not const
     119               2 :   return vars_.find(name)->second;
     120               2 : }
     121                 : 
     122                 : 
     123               0 : void NaClCommandLoop::AddUpcallRpc(string name, NaClSrpcMethod rpc) {
     124               0 :   if (upcall_installed_) {
     125               0 :     NaClLog(LOG_ERROR, "upcall service is already install - ignoring\n");
     126               0 :     return;
     127                 :   }
     128                 : 
     129               0 :   if (upcall_rpcs_.find(name) != upcall_rpcs_.end()) {
     130               0 :     NaClLog(LOG_ERROR, "rpc %s already exists\n", name.c_str());
     131               0 :   }
     132               0 :   upcall_rpcs_[name] = rpc;
     133               0 : }
     134                 : 
     135                 : 
     136               0 : void NaClCommandLoop::AddUpcallRpcSecondary(string name, NaClSrpcMethod rpc) {
     137               0 :   if (upcall_installed_) {
     138               0 :     NaClLog(LOG_ERROR, "upcall service is already install - ignoring\n");
     139               0 :     return;
     140                 :   }
     141                 : 
     142               0 :   if (upcall_rpcs_secondary_.find(name) != upcall_rpcs_secondary_.end()) {
     143               0 :     NaClLog(LOG_ERROR, "rpc (secondary) %s already exists\n", name.c_str());
     144               0 :   }
     145               0 :   upcall_rpcs_secondary_[name] = rpc;
     146               0 : }
     147                 : 
     148                 : 
     149              90 : void NaClCommandLoop::DumpArgsAndResults(NaClSrpcArg* inv[],
     150              90 :                                          NaClSrpcArg* outv[]) {
     151             344 :   for (size_t j = 0; inv[j] != NULL; ++j) {
     152              82 :     string value = DumpArg(inv[j], this);
     153             328 :     if (nondeterministic_.find(value) != nondeterministic_.end()) {
     154               0 :       value = nondeterministic_.find(value)->second;
     155               0 :     }
     156             164 :     printf("input %d:  %s\n", (int) j, value.c_str());
     157              82 :   }
     158                 : 
     159             306 :   for (size_t j = 0; outv[j] != NULL; ++j) {
     160              63 :     string value = DumpArg(outv[j], this);
     161             252 :     if (nondeterministic_.find(value) != nondeterministic_.end()) {
     162               0 :       value = nondeterministic_.find(value)->second;
     163               0 :     }
     164             126 :     printf("output %d:  %s\n", (int) j, value.c_str());
     165              63 :   }
     166              90 : }
     167                 : 
     168                 : 
     169              90 : static string BuildSignature(string name, NaClSrpcArg** in, NaClSrpcArg** out) {
     170              45 :   string result = name;
     171                 : 
     172              45 :   result.push_back(':');
     173             254 :   for (int i = 0; i < NACL_SRPC_MAX_ARGS; ++i) {
     174             127 :     if (NULL == in[i]) {
     175              45 :       break;
     176                 :     }
     177              82 :     result.push_back(in[i]->tag);
     178              82 :   }
     179                 : 
     180              45 :   result.push_back(':');
     181             216 :   for (int i = 0; i < NACL_SRPC_MAX_ARGS; ++i) {
     182             108 :     if (NULL == out[i]) {
     183              45 :       break;
     184                 :     }
     185              63 :     result.push_back(out[i]->tag);
     186              63 :   }
     187              45 :   return result;
     188              90 : }
     189                 : 
     190                 : 
     191               0 : bool NaClCommandLoop::HandleShowDescriptors(NaClCommandLoop* ncl,
     192               0 :                                             const vector<string>& args) {
     193               0 :   if (args.size() != 1) {
     194               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     195               0 :     return false;
     196                 :   }
     197               0 :   printf("Descriptors:\n");
     198                 :   typedef map<string, NaClSrpcImcDescType>::const_iterator Ci;
     199               0 :   for (Ci it = ncl->descs_.begin(); it != ncl->descs_.end(); ++it) {
     200               0 :     printf("  %p: %s\n", static_cast<void*>(it->second), it->first.c_str());
     201               0 :   }
     202               0 :   return true;
     203               0 : }
     204                 : 
     205                 : 
     206               0 : bool NaClCommandLoop::HandleShowVariables(NaClCommandLoop* ncl,
     207               0 :                                           const vector<string>& args) {
     208               0 :   if (args.size() != 1) {
     209               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     210               0 :     return false;
     211                 :   }
     212               0 :   printf("Variables:\n");
     213                 :   typedef map<string, string>::const_iterator Ci;
     214               0 :   for (Ci it = ncl->vars_.begin(); it != ncl->vars_.end(); ++it) {
     215               0 :     printf("  %s: [%s]\n", it->first.c_str(), it->second.c_str());
     216               0 :   }
     217               0 :   return true;
     218               0 : }
     219                 : 
     220                 : 
     221               0 : bool NaClCommandLoop::HandleSetVariable(NaClCommandLoop* ncl,
     222               0 :                                         const vector<string>& args) {
     223               0 :   if (args.size() != 3) {
     224               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     225               0 :     return false;
     226                 :   }
     227               0 :   ncl->SetVariable(args[1], args[2]);
     228               0 :   return true;
     229               0 : }
     230                 : 
     231                 : 
     232               0 : bool NaClCommandLoop::HandleNondeterministic(NaClCommandLoop* ncl,
     233               0 :                                              const vector<string>& args) {
     234               0 :   if (args.size() != 3) {
     235               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     236               0 :     return false;
     237                 :   }
     238               0 :   ncl->RegisterNonDeterministicOutput(args[1], args[2]);
     239               0 :   return true;
     240               0 : }
     241                 : 
     242                 : 
     243               0 : bool NaClCommandLoop::HandleEcho(NaClCommandLoop* ncl,
     244               0 :                                  const vector<string>& args) {
     245               0 :   UNREFERENCED_PARAMETER(ncl);
     246               0 :   const char* delim = "";
     247               0 :   for (size_t i = 1; i < args.size(); ++i) {
     248               0 :     printf("%s%s", delim, args[i].c_str());
     249               0 :     delim = " ";
     250               0 :   }
     251               0 :   printf("\n");
     252               0 :   return true;
     253                 : }
     254                 : 
     255                 : static NaClSrpcHandlerDesc* MakeDescriptorArray(
     256               0 :   const map<string, NaClSrpcMethod>& method_map) {
     257               0 :   NaClSrpcHandlerDesc* handlers =
     258               0 :     new NaClSrpcHandlerDesc[method_map.size() + 1];
     259                 : 
     260               0 :   NaClSrpcHandlerDesc* curr = handlers;
     261                 :   typedef map<string, NaClSrpcMethod>::const_iterator Ci;
     262               0 :   for (Ci it = method_map.begin(); it != method_map.end(); ++it) {
     263               0 :     curr->entry_fmt = it->first.c_str();
     264               0 :     curr->handler = it->second;
     265               0 :     ++curr;
     266               0 :     NaClLog(1, "adding upcall handler: %s\n",  it->first.c_str());
     267               0 :   }
     268                 :   // terminate the handlers with a zero sentinel
     269               0 :   curr->entry_fmt = 0;
     270               0 :   curr->handler = 0;
     271               0 :   return handlers;
     272                 : }
     273                 : 
     274                 : 
     275               0 : static void Unimplemented(NaClSrpcRpc* rpc,
     276               0 :                           NaClSrpcArg** inputs,
     277               0 :                           NaClSrpcArg** outputs,
     278               0 :                           NaClSrpcClosure* done) {
     279               0 :   UNREFERENCED_PARAMETER(inputs);
     280               0 :   UNREFERENCED_PARAMETER(outputs);
     281               0 :   UNREFERENCED_PARAMETER(done);
     282                 : 
     283               0 :   const char* rpc_name;
     284               0 :   const char* arg_types;
     285               0 :   const char* ret_types;
     286                 : 
     287               0 :   if (NaClSrpcServiceMethodNameAndTypes(rpc->channel->server,
     288                 :                                         rpc->rpc_number,
     289                 :                                         &rpc_name,
     290                 :                                         &arg_types,
     291                 :                                         &ret_types)) {
     292               0 :     NaClLog(LOG_ERROR, "cannot find signature for rpc %d\n", rpc->rpc_number);
     293               0 :   }
     294                 : 
     295                 :   // TODO(robertm): add full argument printing
     296               0 :   printf("invoking: %s (%s) -> %s\n", rpc_name, arg_types, ret_types);
     297               0 : }
     298                 : 
     299                 : 
     300                 : // Makes data available to SecondaryHandlerThread.
     301                 : static NaClSrpcHandlerDesc* SecondaryHandlers = 0;
     302                 : 
     303               0 : void WINAPI SecondaryHandlerThread(void* desc_void) {
     304               0 :   DescWrapper* desc = reinterpret_cast<DescWrapper*>(desc_void);
     305                 : 
     306               0 :   NaClLog(1, "secondary service thread started %p\n", desc_void);
     307               0 :   NaClSrpcServerLoop(desc->desc(), SecondaryHandlers, NULL);
     308               0 :   NaClLog(1, "secondary service thread stopped\n");
     309               0 :   NaClThreadExit();
     310               0 : }
     311                 : 
     312               0 : bool NaClCommandLoop::HandleInstallUpcalls(NaClCommandLoop* ncl,
     313               0 :                                            const vector<string>& args) {
     314               0 :   if (args.size() != 3) {
     315               0 :     NaClLog(LOG_ERROR, "not the right number of args for this command\n");
     316               0 :     return false;
     317                 :   }
     318                 : 
     319               0 :   NaClLog(1, "installing %d primary upcall rpcs",
     320               0 :           (int)ncl->upcall_rpcs_.size());
     321                 :   // Note, we do not care about this leak
     322               0 :   NaClSrpcHandlerDesc* handlers = MakeDescriptorArray(ncl->upcall_rpcs_);
     323                 : 
     324                 :   // Note, we do not care about this leak
     325               0 :   NaClSrpcService* service =
     326               0 :       reinterpret_cast<NaClSrpcService*>(malloc(sizeof *service));
     327               0 :   if (service == NULL || !NaClSrpcServiceHandlerCtor(service, handlers)) {
     328               0 :     NaClLog(LOG_ERROR, "could not create upcall service");
     329               0 :   }
     330               0 :   ncl->channel_->server = service;
     331               0 :   ncl->SetVariable(args[1], service->service_string);
     332                 : 
     333                 :   // NOTE: Make sure there is at least one entry.
     334                 :   // weird things happen otherwise
     335               0 :   ncl->AddUpcallRpcSecondary("Dummy::", &Unimplemented);
     336               0 :   NaClLog(1, "installing %d secondary upcall rpcs",
     337               0 :           (int)ncl->upcall_rpcs_secondary_.size());
     338                 : 
     339               0 :   SecondaryHandlers = MakeDescriptorArray(ncl->upcall_rpcs_secondary_);
     340               0 :   DescWrapperFactory* factory = new DescWrapperFactory();
     341                 :   // NOTE: these are really NaClDescXferableDataDesc. Code was mimicked after
     342                 :   //       the exisiting plugin code
     343               0 :   NaClLog(1, "create socket pair so that client can make pepper upcalls\n");
     344                 : 
     345               0 :   DescWrapper* descs[2] = { NULL, NULL };
     346               0 :   if (0 != factory->MakeSocketPair(descs)) {
     347               0 :     NaClLog(LOG_FATAL, "cannot create socket pair\n");
     348               0 :   }
     349                 : 
     350               0 :   NaClLog(1, "spawning secondary service thread\n");
     351                 : 
     352               0 :   NaClThread thread;
     353               0 :   if (!NaClThreadCtor(
     354                 :         &thread,
     355                 :         SecondaryHandlerThread,
     356                 :         descs[0],
     357                 :         128 << 10)) {
     358               0 :     NaClLog(LOG_FATAL, "cannot create service handler thread\n");
     359               0 :   }
     360                 : 
     361               0 :   ncl->AddDesc(descs[1]->desc(),  args[2]);
     362                 : 
     363               0 :   ncl->upcall_installed_ = true;
     364               0 :   return true;
     365               0 : }
     366                 : 
     367                 : 
     368               0 : static bool HandleStrcpy(NaClCommandLoop* ncl, const vector<string>& args) {
     369               0 :   UNREFERENCED_PARAMETER(ncl);
     370               0 :   if (args.size() < 4) {
     371               0 :     NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
     372               0 :     return false;
     373                 :   }
     374                 : 
     375               0 :   const uintptr_t start = (uintptr_t) ExtractInt64(args[1]);
     376               0 :   const uintptr_t offset = (uintptr_t) ExtractInt64(args[2]);
     377                 :   // skip leading and trailing double quote
     378               0 :   string payload = args[3].substr(1, args[3].size() - 2);
     379               0 :   char* dst = reinterpret_cast<char*>(start + offset);
     380               0 :   NaClLog(1, "copy [%s] to %p\n", args[3].c_str(), dst);
     381                 :   // prevent sanity warning
     382               0 :   strncpy(dst, payload.c_str(), payload.size() + 1);
     383               0 :   return true;
     384               0 : }
     385                 : 
     386                 : 
     387               0 : static bool HandleMemset(NaClCommandLoop* ncl, const vector<string>& args) {
     388               0 :   UNREFERENCED_PARAMETER(ncl);
     389               0 :   if (args.size() < 5) {
     390               0 :     NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
     391               0 :     return false;
     392                 :   }
     393                 : 
     394               0 :   const uintptr_t start = (uintptr_t) ExtractInt64(args[1]);
     395               0 :   const uintptr_t offset = (uintptr_t) ExtractInt64(args[2]);
     396               0 :   const uintptr_t length = (uintptr_t) ExtractInt64(args[3]);
     397               0 :   const int pattern = (int)  ExtractInt32(args[4]);
     398                 : 
     399               0 :   char* dst = reinterpret_cast<char*>(start + offset);
     400               0 :   NaClLog(1, "setting [%p, %p] to 0x%02x\n", dst, dst + length, pattern);
     401               0 :   memset(dst, pattern, length);
     402               0 :   return true;
     403               0 : }
     404                 : 
     405                 : 
     406               0 : static bool HandleChecksum(NaClCommandLoop* ncl, const vector<string>& args) {
     407               0 :   UNREFERENCED_PARAMETER(ncl);
     408               0 :   if (args.size() < 4) {
     409               0 :     NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
     410               0 :     return false;
     411                 :   }
     412                 : 
     413               0 :   const uintptr_t start = (uintptr_t) ExtractInt64(args[1]);
     414               0 :   const uintptr_t offset = (uintptr_t) ExtractInt64(args[2]);
     415               0 :   const size_t length = (size_t) ExtractInt64(args[3]);
     416               0 :   unsigned int sum = 0;
     417               0 :   unsigned char* src = reinterpret_cast<unsigned char*>(start + offset);
     418               0 :   for (size_t i = 0; i < length; ++i) {
     419               0 :     sum += sum << 1;
     420               0 :     sum ^= src[i];
     421               0 :   }
     422                 : 
     423               0 :   printf("CHECKSUM: 0x%08x\n", sum);
     424               0 :   return true;
     425               0 : }
     426                 : 
     427                 : 
     428               0 : static bool HandleHelp(NaClCommandLoop* ncl, const vector<string>& args) {
     429               0 :   UNREFERENCED_PARAMETER(ncl);
     430               0 :   UNREFERENCED_PARAMETER(args);
     431                 :   // TODO(sehr,robertm): we should have a syntax description arg
     432                 :   //                     in the handler install call.
     433               0 :   printf("Commands:\n");
     434               0 :   printf("  # <anything>\n");
     435               0 :   printf("    comment\n");
     436               0 :   printf("  show_descriptors\n");
     437               0 :   printf("    print the table of known descriptors (handles)\n");
     438               0 :   printf("  show_variables\n");
     439               0 :   printf("    print the table of variables and their values\n");
     440               0 :   printf("  set_variable <name> <value>\n");
     441               0 :   printf("    set variable to the given value\n");
     442               0 :   printf("  rpc method_name <in_args> * <out_args>\n");
     443               0 :   printf("    Invoke method_name.\n");
     444               0 :   printf("    Each in_arg is of form 'type(value)', e.g. i(42), s(\"foo\").\n");
     445               0 :   printf("    Each out_arg is of form 'type', e.g. i, s.\n");
     446               0 :   printf("  service\n");
     447               0 :   printf("    print the methods found by service_discovery\n");
     448               0 :   printf("  install_upcalls <name>\n");
     449               0 :   printf("    install upcalls and set variable name to the service_string\n");
     450               0 :   printf("  echo <args>*\n");
     451               0 :   printf("    print rest of line - performs variable substitution\n");
     452               0 :   printf("  quit\n");
     453               0 :   printf("    quit the program\n");
     454               0 :   printf("  help\n");
     455               0 :   printf("    print this menu\n");
     456               0 :   printf("  ?\n");
     457               0 :   printf("    print this menu\n");
     458               0 :   return true;
     459                 : }
     460                 : 
     461              45 : bool NaClCommandLoop::InvokeNexeRpc(string signature,
     462              45 :                                     NaClSrpcArg** in,
     463              45 :                                     NaClSrpcArg** out) {
     464              90 :   const uint32_t rpc_num = NaClSrpcServiceMethodIndex(getService(),
     465              45 :                                                       signature.c_str());
     466                 : 
     467              45 :   if (kNaClSrpcInvalidMethodIndex == rpc_num) {
     468               0 :     NaClLog(LOG_ERROR, "No RPC found of signature: [%s]\n", signature.c_str());
     469               0 :     return false;
     470                 :   }
     471                 : 
     472              45 :   NaClLog(1, "Calling RPC %s (%u)\n", signature.c_str(), (unsigned) rpc_num);
     473                 : 
     474              90 :   const  NaClSrpcError result = NaClSrpcInvokeV(
     475              45 :     getChannel(), rpc_num, in, out);
     476              45 :   NaClLog(1, "Result %d\n", result);
     477                 : 
     478              45 :   if (NACL_SRPC_RESULT_OK != result) {
     479               0 :     NaClLog(LOG_ERROR, "RPC call failed: %s.\n", NaClSrpcErrorString(result));
     480               0 :   }
     481              45 :   return NACL_SRPC_RESULT_OK == result;
     482              45 : }
     483                 : 
     484              45 : static bool HandleRpc(NaClCommandLoop* ncl, const vector<string>& args) {
     485                 :   // we need two args at start and the "*" in out separator
     486              45 :   if (args.size() < 3) {
     487               0 :     NaClLog(LOG_ERROR, "Insufficient arguments to 'rpc' command.\n");
     488               0 :     return false;
     489                 :   }
     490                 : 
     491                 :   // TODO(robertm): use stl find
     492              45 :   size_t in_out_sep;
     493             254 :   for (in_out_sep = 2; in_out_sep < args.size(); ++in_out_sep) {
     494             127 :     if (args[in_out_sep] ==  "*")
     495              45 :       break;
     496              82 :   }
     497                 : 
     498              45 :   if (in_out_sep == args.size()) {
     499               0 :     NaClLog(LOG_ERROR, "Missing input/output argument separator\n");
     500               0 :     return false;
     501                 :   }
     502                 : 
     503              45 :   bool show_results = true;
     504              45 :   size_t arg_start = 2;
     505              45 :   if (args[2] == "hide-results") {
     506               0 :     show_results = false;
     507               0 :     arg_start = 3;
     508               0 :   }
     509                 :   // Build the input parameter values.
     510              45 :   const size_t n_in = in_out_sep - arg_start;
     511              45 :   NaClSrpcArg  in[NACL_SRPC_MAX_ARGS];
     512              45 :   NaClSrpcArg* inv[NACL_SRPC_MAX_ARGS + 1];
     513              45 :   NaClLog(2, "SRPC: Parsing %d input args.\n", (int)n_in);
     514              45 :   BuildArgVec(inv, in, n_in);
     515              45 :   if (!ParseArgs(inv, args, arg_start, true, ncl)) {
     516                 :     // TODO(sehr): reclaim memory here on failure.
     517               0 :     NaClLog(LOG_ERROR, "Bad input args for RPC.\n");
     518               0 :     return false;
     519                 :   }
     520                 : 
     521                 :   // Build the output (rpc return) values.
     522              45 :   const size_t n_out =  args.size() - in_out_sep - 1;
     523              45 :   NaClSrpcArg  out[NACL_SRPC_MAX_ARGS];
     524              45 :   NaClSrpcArg* outv[NACL_SRPC_MAX_ARGS + 1];
     525              45 :   NaClLog(2, "SRPC: Parsing %d output args.\n", (int)n_out);
     526              45 :   BuildArgVec(outv, out, n_out);
     527              45 :   if (!ParseArgs(outv, args, in_out_sep + 1, false, ncl)) {
     528                 :     // TODO(sehr): reclaim memory here on failure.
     529               0 :     NaClLog(LOG_ERROR, "Bad output args for RPC.\n");
     530               0 :     return false;
     531                 :   }
     532                 : 
     533              90 :   const string signature = BuildSignature(args[1], inv, outv);
     534                 : 
     535              45 :   NaClSrpcArg* empty[] = {NULL};
     536              90 :   printf("rpc call initiated %s\n", signature.c_str());
     537              45 :   ncl->DumpArgsAndResults(inv, empty);
     538              45 :   fflush(stdout);
     539              45 :   fflush(stderr);
     540                 : 
     541             180 :   const bool rpc_result = ncl->InvokeNexeRpc(signature, inv, outv);
     542                 : 
     543              90 :   printf("rpc call complete %s\n", signature.c_str());
     544              45 :   if (show_results) {
     545              45 :     ncl->DumpArgsAndResults(empty, outv);
     546              45 :   }
     547                 : 
     548              45 :   if (!rpc_result)
     549               0 :     return false;
     550                 : 
     551                 :   // save output into variables
     552             216 :   for (size_t i = 0; outv[i] != 0; ++i) {
     553              63 :     string value = DumpArg(outv[i], ncl);
     554             126 :     stringstream tag;
     555             126 :     tag << "result" << i;
     556             315 :     ncl->SetVariable(tag.str(), value);
     557             189 :   }
     558              45 :   printf("\n");
     559                 : 
     560                 :   /* Free the storage allocated for array valued parameters and returns. */
     561              45 :   FreeArrayArgs(inv);
     562              45 :   FreeArrayArgs(outv);
     563              45 :   return true;
     564              90 : }
     565                 : 
     566                 : 
     567               0 : static bool HandleService(NaClCommandLoop* ncl, const vector<string>& args) {
     568               0 :   UNREFERENCED_PARAMETER(args);
     569                 :   // TODO(robertm): move this library call into sel_universal
     570               0 :   NaClSrpcServicePrint(ncl->getService());
     571               0 :   return true;
     572                 : }
     573                 : 
     574                 : 
     575              26 : NaClCommandLoop::NaClCommandLoop(NaClSrpcService* service,
     576              26 :                                  NaClSrpcChannel* channel,
     577              78 :                                  NaClSrpcImcDescType default_socket_address) {
     578              13 :   upcall_installed_ = false;
     579              13 :   desc_count_ = 0;
     580              13 :   channel_ = channel;
     581              13 :   service_ = service;
     582                 :   // populate descriptors
     583              65 :   AddDesc((NaClDesc*) NaClDescInvalidMake(), "invalid");
     584              78 :   AddDesc(DescFromPlatformDesc(DUP(0), NACL_ABI_O_RDONLY), "stdin");
     585              78 :   AddDesc(DescFromPlatformDesc(DUP(1), NACL_ABI_O_WRONLY), "stdout");
     586              78 :   AddDesc(DescFromPlatformDesc(DUP(2), NACL_ABI_O_WRONLY), "stderr");
     587              13 :   if (kNaClSrpcInvalidImcDesc != default_socket_address) {
     588              52 :     AddDesc(default_socket_address, "module_socket_address");
     589              13 :   }
     590                 : 
     591                 :   // populate command handlers
     592                 :   // TODO(robertm): for backward compatibility
     593              52 :   AddHandler("show_descriptors", HandleShowDescriptors);
     594              52 :   AddHandler("show_variables", HandleShowVariables);
     595              52 :   AddHandler("set_variable", HandleSetVariable);
     596              52 :   AddHandler("nondeterministic", HandleNondeterministic);
     597              52 :   AddHandler("install_upcalls", HandleInstallUpcalls);
     598              52 :   AddHandler("strcpy", HandleStrcpy);
     599              52 :   AddHandler("memset", HandleMemset);
     600              52 :   AddHandler("checksum", HandleChecksum);
     601              52 :   AddHandler("rpc", HandleRpc);
     602              52 :   AddHandler("echo", HandleEcho);
     603              52 :   AddHandler("help", HandleHelp);
     604              52 :   AddHandler("?", HandleHelp);
     605              52 :   AddHandler("service", HandleService);
     606              26 : }
     607                 : 
     608              13 : NaClCommandLoop::~NaClCommandLoop() {
     609              65 :   NaClDescUnref(descs_["stdin"]);
     610              65 :   NaClDescUnref(descs_["stdout"]);
     611              65 :   NaClDescUnref(descs_["stderr"]);
     612              91 : }
     613                 : 
     614                 : // return codes:
     615                 : // 0  - ok
     616                 : // -1 - failure
     617                 : // 1  - stop processing
     618              58 : int NaClCommandLoop::ProcessOneCommand(const string command) {
     619             116 :   vector<string> tokens;
     620             174 :   Tokenize(command, &tokens);
     621                 : 
     622             116 :   if (tokens.size() == 0) {
     623               6 :     return 0;
     624                 :   }
     625                 : 
     626             156 :   if (tokens[0][0] == '#') {
     627               0 :     return 0;
     628                 :   }
     629                 : 
     630             156 :   if (tokens[0] == "quit") {
     631               0 :     return 1;
     632                 :   }
     633                 : 
     634            1029 :   for (size_t i = 0; i < tokens.size(); ++i) {
     635            2037 :     tokens[i] = SubstituteVars(tokens[i], this);
     636             291 :   }
     637                 : 
     638             260 :   if (handlers_.find(tokens[0]) == handlers_.end()) {
     639               0 :       NaClLog(LOG_ERROR, "Unknown command [%s].\n", tokens[0].c_str());
     640               0 :       return -1;
     641                 :   }
     642                 : 
     643             208 :   if (!handlers_[tokens[0]](this, tokens)) {
     644               0 :     NaClLog(LOG_ERROR, "Command [%s] failed.\n", tokens[0].c_str());
     645               0 :     return -1;
     646                 :   }
     647                 : 
     648             110 :   return 0;
     649              58 : }
     650                 : 
     651               6 : bool NaClCommandLoop::ProcessCommands(const vector<string>& commands) {
     652               6 :   NaClLog(1, "entering processing commands\n");
     653              82 :   for (size_t i = 0; i < commands.size(); ++i) {
     654              35 :     fflush(stdout);
     655              35 :     fflush(stderr);
     656                 : 
     657              70 :     int result = ProcessOneCommand(commands[i]);
     658              35 :     if (result == 1) return true;
     659              35 :     if (result == -1) return false;
     660              35 :   }
     661                 : 
     662               6 :   return true;
     663               6 : }
     664                 : 
     665                 : 
     666               7 : bool NaClCommandLoop::StartInteractiveLoop(bool abort_on_error) {
     667               7 :   int command_count = 0;
     668                 : 
     669               7 :   NaClLog(1, "entering print eval loop\n");
     670               7 :   for (;;) {
     671              30 :     fflush(stdout);
     672              30 :     fflush(stderr);
     673                 : 
     674              30 :     char buffer[kMaxCommandLineLength];
     675                 : 
     676              30 :     fprintf(stderr, "%d> ", command_count);
     677              30 :     ++command_count;
     678                 : 
     679              30 :     if (!fgets(buffer, sizeof(buffer), stdin))
     680               7 :       break;
     681                 : 
     682              92 :     int result = ProcessOneCommand(buffer);
     683              23 :     if (result == 1) break;
     684              23 :     if (result == -1 && abort_on_error) return false;
     685              23 :   }
     686               7 :   NaClLog(1, "exiting print eval loop\n");
     687               7 :   return true;
     688               7 : }

Generated by: LCOV version 1.7