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

Generated by: LCOV version 1.7