]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Commands/CommandObjectPlatform.cpp
Import LLDB as of upstream SVN 228549 (git 39760838)
[FreeBSD/FreeBSD.git] / source / Commands / CommandObjectPlatform.cpp
1 //===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 #include "CommandObjectPlatform.h"
13
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Core/DataExtractor.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/PluginManager.h"
22 #include "lldb/Host/StringConvert.h"
23 #include "lldb/Interpreter/Args.h"
24 #include "lldb/Interpreter/CommandInterpreter.h"
25 #include "lldb/Interpreter/CommandOptionValidators.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/OptionGroupFile.h"
28 #include "lldb/Interpreter/OptionGroupPlatform.h"
29 #include "lldb/Target/ExecutionContext.h"
30 #include "lldb/Target/Platform.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Utility/Utils.h"
33
34 using namespace lldb;
35 using namespace lldb_private;
36
37 static mode_t
38 ParsePermissionString(const char* permissions)
39 {
40     if (strlen(permissions) != 9)
41         return (mode_t)(-1);
42     bool user_r,user_w,user_x,
43     group_r,group_w,group_x,
44     world_r,world_w,world_x;
45     
46     user_r = (permissions[0] == 'r');
47     user_w = (permissions[1] == 'w');
48     user_x = (permissions[2] == 'x');
49     
50     group_r = (permissions[3] == 'r');
51     group_w = (permissions[4] == 'w');
52     group_x = (permissions[5] == 'x');
53     
54     world_r = (permissions[6] == 'r');
55     world_w = (permissions[7] == 'w');
56     world_x = (permissions[8] == 'x');
57     
58     mode_t user,group,world;
59     user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
60     group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
61     world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
62     
63     return user | group | world;
64 }
65
66 static OptionDefinition
67 g_permissions_options[] =
68 {
69     {   LLDB_OPT_SET_ALL, false, "permissions-value",   'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber         , "Give out the numeric value for permissions (e.g. 757)" },
70     {   LLDB_OPT_SET_ALL, false, "permissions-string",  's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString  , "Give out the string value for permissions (e.g. rwxr-xr--)." },
71     {   LLDB_OPT_SET_ALL, false, "user-read",           'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to read." },
72     {   LLDB_OPT_SET_ALL, false, "user-write",          'w', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to write." },
73     {   LLDB_OPT_SET_ALL, false, "user-exec",           'x', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to execute." },
74
75     {   LLDB_OPT_SET_ALL, false, "group-read",          'R', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to read." },
76     {   LLDB_OPT_SET_ALL, false, "group-write",         'W', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to write." },
77     {   LLDB_OPT_SET_ALL, false, "group-exec",          'X', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to execute." },
78
79     {   LLDB_OPT_SET_ALL, false, "world-read",          'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to read." },
80     {   LLDB_OPT_SET_ALL, false, "world-write",         't', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to write." },
81     {   LLDB_OPT_SET_ALL, false, "world-exec",          'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to execute." },
82 };
83
84 class OptionPermissions : public lldb_private::OptionGroup
85 {
86 public:
87     OptionPermissions ()
88     {
89     }
90     
91     virtual
92     ~OptionPermissions ()
93     {
94     }
95     
96     virtual lldb_private::Error
97     SetOptionValue (CommandInterpreter &interpreter,
98                     uint32_t option_idx,
99                     const char *option_arg)
100     {
101         Error error;
102         char short_option = (char) GetDefinitions()[option_idx].short_option;
103         switch (short_option)
104         {
105             case 'v':
106             {
107                 bool ok;
108                 uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok);
109                 if (!ok)
110                     error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
111                 else
112                     m_permissions = perms;
113             }
114                 break;
115             case 's':
116             {
117                 mode_t perms = ParsePermissionString(option_arg);
118                 if (perms == (mode_t)-1)
119                     error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
120                 else
121                     m_permissions = perms;
122             }
123             case 'r':
124                 m_permissions |= lldb::eFilePermissionsUserRead;
125                 break;
126             case 'w':
127                 m_permissions |= lldb::eFilePermissionsUserWrite;
128                 break;
129             case 'x':
130                 m_permissions |= lldb::eFilePermissionsUserExecute;
131                 break;
132             case 'R':
133                 m_permissions |= lldb::eFilePermissionsGroupRead;
134                 break;
135             case 'W':
136                 m_permissions |= lldb::eFilePermissionsGroupWrite;
137                 break;
138             case 'X':
139                 m_permissions |= lldb::eFilePermissionsGroupExecute;
140                 break;
141             case 'd':
142                 m_permissions |= lldb::eFilePermissionsWorldRead;
143                 break;
144             case 't':
145                 m_permissions |= lldb::eFilePermissionsWorldWrite;
146                 break;
147             case 'e':
148                 m_permissions |= lldb::eFilePermissionsWorldExecute;
149                 break;
150
151             default:
152                 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
153                 break;
154         }
155         
156         return error;
157     }
158     
159     void
160     OptionParsingStarting (CommandInterpreter &interpreter)
161     {
162         m_permissions = 0;
163     }
164     
165     virtual uint32_t
166     GetNumDefinitions ()
167     {
168         return llvm::array_lengthof(g_permissions_options);
169     }
170     
171     const lldb_private::OptionDefinition*
172     GetDefinitions ()
173     {
174         return g_permissions_options;
175     }
176         
177     // Instance variables to hold the values for command options.
178     
179     uint32_t m_permissions;
180 private:
181     DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
182 };
183
184 //----------------------------------------------------------------------
185 // "platform select <platform-name>"
186 //----------------------------------------------------------------------
187 class CommandObjectPlatformSelect : public CommandObjectParsed
188 {
189 public:
190     CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
191         CommandObjectParsed (interpreter, 
192                              "platform select",
193                              "Create a platform if needed and select it as the current platform.",
194                              "platform select <platform-name>",
195                              0),
196         m_option_group (interpreter),
197         m_platform_options (false) // Don't include the "--platform" option by passing false
198     {
199         m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
200         m_option_group.Finalize();
201     }
202
203     virtual
204     ~CommandObjectPlatformSelect ()
205     {
206     }
207
208     virtual int
209     HandleCompletion (Args &input,
210                       int &cursor_index,
211                       int &cursor_char_position,
212                       int match_start_point,
213                       int max_return_elements,
214                       bool &word_complete,
215                       StringList &matches)
216     {
217         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
218         completion_str.erase (cursor_char_position);
219         
220         CommandCompletions::PlatformPluginNames (m_interpreter, 
221                                                  completion_str.c_str(),
222                                                  match_start_point,
223                                                  max_return_elements,
224                                                  NULL,
225                                                  word_complete,
226                                                  matches);
227         return matches.GetSize();
228     }
229
230     virtual Options *
231     GetOptions ()
232     {
233         return &m_option_group;
234     }
235
236 protected:
237     virtual bool
238     DoExecute (Args& args, CommandReturnObject &result)
239     {
240         if (args.GetArgumentCount() == 1)
241         {
242             const char *platform_name = args.GetArgumentAtIndex (0);
243             if (platform_name && platform_name[0])
244             {
245                 const bool select = true;
246                 m_platform_options.SetPlatformName (platform_name);
247                 Error error;
248                 ArchSpec platform_arch;
249                 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
250                 if (platform_sp)
251                 {
252                     m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
253
254                     platform_sp->GetStatus (result.GetOutputStream());
255                     result.SetStatus (eReturnStatusSuccessFinishResult);
256                 }
257                 else
258                 {
259                     result.AppendError(error.AsCString());
260                     result.SetStatus (eReturnStatusFailed);
261                 }
262             }
263             else
264             {
265                 result.AppendError ("invalid platform name");
266                 result.SetStatus (eReturnStatusFailed);
267             }
268         }
269         else
270         {
271             result.AppendError ("platform create takes a platform name as an argument\n");
272             result.SetStatus (eReturnStatusFailed);
273         }
274         return result.Succeeded();
275     }
276
277     OptionGroupOptions m_option_group;
278     OptionGroupPlatform m_platform_options;
279 };
280
281 //----------------------------------------------------------------------
282 // "platform list"
283 //----------------------------------------------------------------------
284 class CommandObjectPlatformList : public CommandObjectParsed
285 {
286 public:
287     CommandObjectPlatformList (CommandInterpreter &interpreter) :
288         CommandObjectParsed (interpreter,
289                              "platform list",
290                              "List all platforms that are available.",
291                              NULL,
292                              0)
293     {
294     }
295
296     virtual
297     ~CommandObjectPlatformList ()
298     {
299     }
300
301 protected:
302     virtual bool
303     DoExecute (Args& args, CommandReturnObject &result)
304     {
305         Stream &ostrm = result.GetOutputStream();
306         ostrm.Printf("Available platforms:\n");
307         
308         PlatformSP host_platform_sp (Platform::GetHostPlatform());
309         ostrm.Printf ("%s: %s\n", 
310                       host_platform_sp->GetPluginName().GetCString(),
311                       host_platform_sp->GetDescription());
312
313         uint32_t idx;
314         for (idx = 0; 1; ++idx)
315         {
316             const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
317             if (plugin_name == NULL)
318                 break;
319             const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
320             if (plugin_desc == NULL)
321                 break;
322             ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
323         }
324         
325         if (idx == 0)
326         {
327             result.AppendError ("no platforms are available\n");
328             result.SetStatus (eReturnStatusFailed);
329         }
330         else
331             result.SetStatus (eReturnStatusSuccessFinishResult);
332         return result.Succeeded();
333     }
334 };
335
336 //----------------------------------------------------------------------
337 // "platform status"
338 //----------------------------------------------------------------------
339 class CommandObjectPlatformStatus : public CommandObjectParsed
340 {
341 public:
342     CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
343         CommandObjectParsed (interpreter,
344                              "platform status",
345                              "Display status for the currently selected platform.",
346                              NULL,
347                              0)
348     {
349     }
350
351     virtual
352     ~CommandObjectPlatformStatus ()
353     {
354     }
355
356 protected:
357     virtual bool
358     DoExecute (Args& args, CommandReturnObject &result)
359     {
360         Stream &ostrm = result.GetOutputStream();      
361         
362         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
363         PlatformSP platform_sp;
364         if (target)
365         {
366             platform_sp = target->GetPlatform();
367         }
368         if (!platform_sp)
369         {
370             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
371         }
372         if (platform_sp)
373         {
374             platform_sp->GetStatus (ostrm);
375             result.SetStatus (eReturnStatusSuccessFinishResult);            
376         }
377         else
378         {
379             result.AppendError ("no platform us currently selected\n");
380             result.SetStatus (eReturnStatusFailed);            
381         }
382         return result.Succeeded();
383     }
384 };
385
386 //----------------------------------------------------------------------
387 // "platform connect <connect-url>"
388 //----------------------------------------------------------------------
389 class CommandObjectPlatformConnect : public CommandObjectParsed
390 {
391 public:
392     CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
393         CommandObjectParsed (interpreter, 
394                              "platform connect",
395                              "Connect a platform by name to be the currently selected platform.",
396                              "platform connect <connect-url>",
397                              0)
398     {
399     }
400
401     virtual
402     ~CommandObjectPlatformConnect ()
403     {
404     }
405
406 protected:
407     virtual bool
408     DoExecute (Args& args, CommandReturnObject &result)
409     {
410         Stream &ostrm = result.GetOutputStream();      
411         
412         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
413         if (platform_sp)
414         {
415             Error error (platform_sp->ConnectRemote (args));
416             if (error.Success())
417             {
418                 platform_sp->GetStatus (ostrm);
419                 result.SetStatus (eReturnStatusSuccessFinishResult);            
420             }
421             else
422             {
423                 result.AppendErrorWithFormat ("%s\n", error.AsCString());
424                 result.SetStatus (eReturnStatusFailed);            
425             }
426         }
427         else
428         {
429             result.AppendError ("no platform is currently selected\n");
430             result.SetStatus (eReturnStatusFailed);            
431         }
432         return result.Succeeded();
433     }
434     
435     virtual Options *
436     GetOptions ()
437     {
438         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
439         OptionGroupOptions* m_platform_options = NULL;
440         if (platform_sp)
441         {
442             m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
443             if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
444                 m_platform_options->Finalize();
445         }
446         return m_platform_options;
447     }
448
449 };
450
451 //----------------------------------------------------------------------
452 // "platform disconnect"
453 //----------------------------------------------------------------------
454 class CommandObjectPlatformDisconnect : public CommandObjectParsed
455 {
456 public:
457     CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
458         CommandObjectParsed (interpreter, 
459                              "platform disconnect",
460                              "Disconnect a platform by name to be the currently selected platform.",
461                              "platform disconnect",
462                              0)
463     {
464     }
465
466     virtual
467     ~CommandObjectPlatformDisconnect ()
468     {
469     }
470
471 protected:
472     virtual bool
473     DoExecute (Args& args, CommandReturnObject &result)
474     {
475         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
476         if (platform_sp)
477         {
478             if (args.GetArgumentCount() == 0)
479             {
480                 Error error;
481                 
482                 if (platform_sp->IsConnected())
483                 {
484                     // Cache the instance name if there is one since we are 
485                     // about to disconnect and the name might go with it.
486                     const char *hostname_cstr = platform_sp->GetHostname();
487                     std::string hostname;
488                     if (hostname_cstr)
489                         hostname.assign (hostname_cstr);
490
491                     error = platform_sp->DisconnectRemote ();
492                     if (error.Success())
493                     {
494                         Stream &ostrm = result.GetOutputStream();      
495                         if (hostname.empty())
496                             ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString());
497                         else
498                             ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
499                         result.SetStatus (eReturnStatusSuccessFinishResult);            
500                     }
501                     else
502                     {
503                         result.AppendErrorWithFormat ("%s", error.AsCString());
504                         result.SetStatus (eReturnStatusFailed);            
505                     }
506                 }
507                 else
508                 {
509                     // Not connected...
510                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
511                     result.SetStatus (eReturnStatusFailed);            
512                 }
513             }
514             else
515             {
516                 // Bad args
517                 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
518                 result.SetStatus (eReturnStatusFailed);            
519             }
520         }
521         else
522         {
523             result.AppendError ("no platform is currently selected");
524             result.SetStatus (eReturnStatusFailed);            
525         }
526         return result.Succeeded();
527     }
528 };
529
530 //----------------------------------------------------------------------
531 // "platform settings"
532 //----------------------------------------------------------------------
533 class CommandObjectPlatformSettings : public CommandObjectParsed
534 {
535 public:
536     CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
537         CommandObjectParsed (interpreter,
538                              "platform settings",
539                              "Set settings for the current target's platform, or for a platform by name.",
540                              "platform settings",
541                              0),
542         m_options (interpreter),
543         m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
544     {
545         m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
546     }
547     
548     virtual
549     ~CommandObjectPlatformSettings ()
550     {
551     }
552     
553 protected:
554     virtual bool
555     DoExecute (Args& args, CommandReturnObject &result)
556     {
557         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
558         if (platform_sp)
559         {
560             if (m_option_working_dir.GetOptionValue().OptionWasSet())
561                 platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
562         }
563         else
564         {
565             result.AppendError ("no platform is currently selected");
566             result.SetStatus (eReturnStatusFailed);
567         }
568         return result.Succeeded();
569     }
570     
571     virtual Options *
572     GetOptions ()
573     {
574         if (m_options.DidFinalize() == false)
575         {
576             m_options.Append(new OptionPermissions());
577             m_options.Finalize();
578         }
579         return &m_options;
580     }
581 protected:
582     
583     OptionGroupOptions m_options;
584     OptionGroupFile m_option_working_dir;
585
586 };
587
588
589 //----------------------------------------------------------------------
590 // "platform mkdir"
591 //----------------------------------------------------------------------
592 class CommandObjectPlatformMkDir : public CommandObjectParsed
593 {
594 public:
595     CommandObjectPlatformMkDir (CommandInterpreter &interpreter) :
596     CommandObjectParsed (interpreter,
597                          "platform mkdir",
598                          "Make a new directory on the remote end.",
599                          NULL,
600                          0),
601     m_options(interpreter)
602     {
603     }
604     
605     virtual
606     ~CommandObjectPlatformMkDir ()
607     {
608     }
609     
610     virtual bool
611     DoExecute (Args& args, CommandReturnObject &result)
612     {
613         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
614         if (platform_sp)
615         {
616             std::string cmd_line;
617             args.GetCommandString(cmd_line);
618             uint32_t mode;
619             const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
620             if (options_permissions)
621                 mode = options_permissions->m_permissions;
622             else
623                 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
624             Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
625             if (error.Success())
626             {
627                 result.SetStatus (eReturnStatusSuccessFinishResult);
628             }
629             else
630             {
631                 result.AppendError(error.AsCString());
632                 result.SetStatus (eReturnStatusFailed);
633             }
634         }
635         else
636         {
637             result.AppendError ("no platform currently selected\n");
638             result.SetStatus (eReturnStatusFailed);
639         }
640         return result.Succeeded();
641     }
642     
643     virtual Options *
644     GetOptions ()
645     {
646         if (m_options.DidFinalize() == false)
647         {
648             m_options.Append(new OptionPermissions());
649             m_options.Finalize();
650         }
651         return &m_options;
652     }
653     OptionGroupOptions m_options;
654     
655 };
656
657 //----------------------------------------------------------------------
658 // "platform fopen"
659 //----------------------------------------------------------------------
660 class CommandObjectPlatformFOpen : public CommandObjectParsed
661 {
662 public:
663     CommandObjectPlatformFOpen (CommandInterpreter &interpreter) :
664     CommandObjectParsed (interpreter,
665                          "platform file open",
666                          "Open a file on the remote end.",
667                          NULL,
668                          0),
669     m_options(interpreter)
670     {
671     }
672     
673     virtual
674     ~CommandObjectPlatformFOpen ()
675     {
676     }
677     
678     virtual bool
679     DoExecute (Args& args, CommandReturnObject &result)
680     {
681         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
682         if (platform_sp)
683         {
684             Error error;
685             std::string cmd_line;
686             args.GetCommandString(cmd_line);
687             mode_t perms;
688             const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
689             if (options_permissions)
690                 perms = options_permissions->m_permissions;
691             else
692                 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
693             lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
694                                                        File::eOpenOptionRead | File::eOpenOptionWrite |
695                                                        File::eOpenOptionAppend | File::eOpenOptionCanCreate,
696                                                        perms,
697                                                        error);
698             if (error.Success())
699             {
700                 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd);
701                 result.SetStatus (eReturnStatusSuccessFinishResult);
702             }
703             else
704             {
705                 result.AppendError(error.AsCString());
706                 result.SetStatus (eReturnStatusFailed);
707             }
708         }
709         else
710         {
711             result.AppendError ("no platform currently selected\n");
712             result.SetStatus (eReturnStatusFailed);
713         }
714         return result.Succeeded();
715     }
716     virtual Options *
717     GetOptions ()
718     {
719         if (m_options.DidFinalize() == false)
720         {
721             m_options.Append(new OptionPermissions());
722             m_options.Finalize();
723         }
724         return &m_options;
725     }
726     OptionGroupOptions m_options;
727 };
728
729 //----------------------------------------------------------------------
730 // "platform fclose"
731 //----------------------------------------------------------------------
732 class CommandObjectPlatformFClose : public CommandObjectParsed
733 {
734 public:
735     CommandObjectPlatformFClose (CommandInterpreter &interpreter) :
736     CommandObjectParsed (interpreter,
737                          "platform file close",
738                          "Close a file on the remote end.",
739                          NULL,
740                          0)
741     {
742     }
743     
744     virtual
745     ~CommandObjectPlatformFClose ()
746     {
747     }
748     
749     virtual bool
750     DoExecute (Args& args, CommandReturnObject &result)
751     {
752         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
753         if (platform_sp)
754         {
755             std::string cmd_line;
756             args.GetCommandString(cmd_line);
757             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
758             Error error;
759             bool success = platform_sp->CloseFile(fd, error);
760             if (success)
761             {
762                 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
763                 result.SetStatus (eReturnStatusSuccessFinishResult);
764             }
765             else
766             {
767                 result.AppendError(error.AsCString());
768                 result.SetStatus (eReturnStatusFailed);
769             }
770         }
771         else
772         {
773             result.AppendError ("no platform currently selected\n");
774             result.SetStatus (eReturnStatusFailed);
775         }
776         return result.Succeeded();
777     }
778 };
779
780 //----------------------------------------------------------------------
781 // "platform fread"
782 //----------------------------------------------------------------------
783 class CommandObjectPlatformFRead : public CommandObjectParsed
784 {
785 public:
786     CommandObjectPlatformFRead (CommandInterpreter &interpreter) :
787     CommandObjectParsed (interpreter,
788                          "platform file read",
789                          "Read data from a file on the remote end.",
790                          NULL,
791                          0),
792     m_options (interpreter)
793     {
794     }
795     
796     virtual
797     ~CommandObjectPlatformFRead ()
798     {
799     }
800     
801     virtual bool
802     DoExecute (Args& args, CommandReturnObject &result)
803     {
804         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
805         if (platform_sp)
806         {
807             std::string cmd_line;
808             args.GetCommandString(cmd_line);
809             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
810             std::string buffer(m_options.m_count,0);
811             Error error;
812             uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
813             result.AppendMessageWithFormat("Return = %d\n",retcode);
814             result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str());
815             result.SetStatus (eReturnStatusSuccessFinishResult);
816         }
817         else
818         {
819             result.AppendError ("no platform currently selected\n");
820             result.SetStatus (eReturnStatusFailed);
821         }
822         return result.Succeeded();
823     }
824     virtual Options *
825     GetOptions ()
826     {
827         return &m_options;
828     }
829     
830 protected:
831     class CommandOptions : public Options
832     {
833     public:
834         
835         CommandOptions (CommandInterpreter &interpreter) :
836         Options (interpreter)
837         {
838         }
839         
840         virtual
841         ~CommandOptions ()
842         {
843         }
844         
845         virtual Error
846         SetOptionValue (uint32_t option_idx, const char *option_arg)
847         {
848             Error error;
849             char short_option = (char) m_getopt_table[option_idx].val;
850             bool success = false;
851             
852             switch (short_option)
853             {
854                 case 'o':
855                     m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
856                     if (!success)
857                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
858                     break;
859                 case 'c':
860                     m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success);
861                     if (!success)
862                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
863                     break;
864
865                 default:
866                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
867                     break;
868             }
869             
870             return error;
871         }
872         
873         void
874         OptionParsingStarting ()
875         {
876             m_offset = 0;
877             m_count = 1;
878         }
879         
880         const OptionDefinition*
881         GetDefinitions ()
882         {
883             return g_option_table;
884         }
885         
886         // Options table: Required for subclasses of Options.
887         
888         static OptionDefinition g_option_table[];
889         
890         // Instance variables to hold the values for command options.
891         
892         uint32_t m_offset;
893         uint32_t m_count;
894     };
895     CommandOptions m_options;
896 };
897 OptionDefinition
898 CommandObjectPlatformFRead::CommandOptions::g_option_table[] =
899 {
900     {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
901     {   LLDB_OPT_SET_1, false, "count"            , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount        , "Number of bytes to read from the file." },
902     {  0              , false, NULL               ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone         , NULL }
903 };
904
905
906 //----------------------------------------------------------------------
907 // "platform fwrite"
908 //----------------------------------------------------------------------
909 class CommandObjectPlatformFWrite : public CommandObjectParsed
910 {
911 public:
912     CommandObjectPlatformFWrite (CommandInterpreter &interpreter) :
913     CommandObjectParsed (interpreter,
914                          "platform file write",
915                          "Write data to a file on the remote end.",
916                          NULL,
917                          0),
918     m_options (interpreter)
919     {
920     }
921     
922     virtual
923     ~CommandObjectPlatformFWrite ()
924     {
925     }
926     
927     virtual bool
928     DoExecute (Args& args, CommandReturnObject &result)
929     {
930         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
931         if (platform_sp)
932         {
933             std::string cmd_line;
934             args.GetCommandString(cmd_line);
935             Error error;
936             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
937             uint32_t retcode = platform_sp->WriteFile (fd,
938                                                        m_options.m_offset,
939                                                        &m_options.m_data[0],
940                                                        m_options.m_data.size(),
941                                                        error);
942             result.AppendMessageWithFormat("Return = %d\n",retcode);
943             result.SetStatus (eReturnStatusSuccessFinishResult);
944         }
945         else
946         {
947             result.AppendError ("no platform currently selected\n");
948             result.SetStatus (eReturnStatusFailed);
949         }
950         return result.Succeeded();
951     }
952     virtual Options *
953     GetOptions ()
954     {
955         return &m_options;
956     }
957     
958 protected:
959     class CommandOptions : public Options
960     {
961     public:
962         
963         CommandOptions (CommandInterpreter &interpreter) :
964         Options (interpreter)
965         {
966         }
967         
968         virtual
969         ~CommandOptions ()
970         {
971         }
972         
973         virtual Error
974         SetOptionValue (uint32_t option_idx, const char *option_arg)
975         {
976             Error error;
977             char short_option = (char) m_getopt_table[option_idx].val;
978             bool success = false;
979             
980             switch (short_option)
981             {
982                 case 'o':
983                     m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
984                     if (!success)
985                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
986                     break;
987                 case 'd':
988                     m_data.assign(option_arg);
989                     break;
990                     
991                 default:
992                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
993                     break;
994             }
995             
996             return error;
997         }
998         
999         void
1000         OptionParsingStarting ()
1001         {
1002             m_offset = 0;
1003             m_data.clear();
1004         }
1005         
1006         const OptionDefinition*
1007         GetDefinitions ()
1008         {
1009             return g_option_table;
1010         }
1011         
1012         // Options table: Required for subclasses of Options.
1013         
1014         static OptionDefinition g_option_table[];
1015         
1016         // Instance variables to hold the values for command options.
1017         
1018         uint32_t m_offset;
1019         std::string m_data;
1020     };
1021     CommandOptions m_options;
1022 };
1023 OptionDefinition
1024 CommandObjectPlatformFWrite::CommandOptions::g_option_table[] =
1025 {
1026     {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
1027     {   LLDB_OPT_SET_1, false, "data"            , 'd', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeValue        , "Text to write to the file." },
1028     {  0              , false, NULL               ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone         , NULL }
1029 };
1030
1031 class CommandObjectPlatformFile : public CommandObjectMultiword
1032 {
1033 public:
1034     //------------------------------------------------------------------
1035     // Constructors and Destructors
1036     //------------------------------------------------------------------
1037     CommandObjectPlatformFile (CommandInterpreter &interpreter) :
1038     CommandObjectMultiword (interpreter,
1039                             "platform file",
1040                             "A set of commands to manage file access through a platform",
1041                             "platform file [open|close|read|write] ...")
1042     {
1043         LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen  (interpreter)));
1044         LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose  (interpreter)));
1045         LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead  (interpreter)));
1046         LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite  (interpreter)));
1047     }
1048     
1049     virtual
1050     ~CommandObjectPlatformFile ()
1051     {
1052     }
1053     
1054 private:
1055     //------------------------------------------------------------------
1056     // For CommandObjectPlatform only
1057     //------------------------------------------------------------------
1058     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile);
1059 };
1060
1061 //----------------------------------------------------------------------
1062 // "platform get-file remote-file-path host-file-path"
1063 //----------------------------------------------------------------------
1064 class CommandObjectPlatformGetFile : public CommandObjectParsed
1065 {
1066 public:
1067     CommandObjectPlatformGetFile (CommandInterpreter &interpreter) :
1068     CommandObjectParsed (interpreter,
1069                          "platform get-file",
1070                          "Transfer a file from the remote end to the local host.",
1071                          "platform get-file <remote-file-spec> <local-file-spec>",
1072                          0)
1073     {
1074         SetHelpLong(
1075 "Examples: \n\
1076 \n\
1077     platform get-file /the/remote/file/path /the/local/file/path\n\
1078     # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
1079
1080         CommandArgumentEntry arg1, arg2;
1081         CommandArgumentData file_arg_remote, file_arg_host;
1082     
1083         // Define the first (and only) variant of this arg.
1084         file_arg_remote.arg_type = eArgTypeFilename;
1085         file_arg_remote.arg_repetition = eArgRepeatPlain;
1086         // There is only one variant this argument could be; put it into the argument entry.
1087         arg1.push_back (file_arg_remote);
1088         
1089         // Define the second (and only) variant of this arg.
1090         file_arg_host.arg_type = eArgTypeFilename;
1091         file_arg_host.arg_repetition = eArgRepeatPlain;
1092         // There is only one variant this argument could be; put it into the argument entry.
1093         arg2.push_back (file_arg_host);
1094
1095         // Push the data for the first and the second arguments into the m_arguments vector.
1096         m_arguments.push_back (arg1);
1097         m_arguments.push_back (arg2);
1098     }
1099     
1100     virtual
1101     ~CommandObjectPlatformGetFile ()
1102     {
1103     }
1104     
1105     virtual bool
1106     DoExecute (Args& args, CommandReturnObject &result)
1107     {
1108         // If the number of arguments is incorrect, issue an error message.
1109         if (args.GetArgumentCount() != 2)
1110         {
1111             result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n");
1112             result.SetStatus(eReturnStatusFailed);
1113             return false;
1114         }
1115
1116         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1117         if (platform_sp)
1118         {
1119             const char *remote_file_path = args.GetArgumentAtIndex(0);
1120             const char *local_file_path = args.GetArgumentAtIndex(1);
1121             Error error = platform_sp->GetFile(FileSpec(remote_file_path, false),
1122                                                FileSpec(local_file_path, false));
1123             if (error.Success())
1124             {
1125                 result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n",
1126                                                remote_file_path, local_file_path);
1127                 result.SetStatus (eReturnStatusSuccessFinishResult);
1128             }
1129             else
1130             {
1131                 result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString());
1132                 result.SetStatus (eReturnStatusFailed);
1133             }
1134         }
1135         else
1136         {
1137             result.AppendError ("no platform currently selected\n");
1138             result.SetStatus (eReturnStatusFailed);
1139         }
1140         return result.Succeeded();
1141     }
1142 };
1143
1144 //----------------------------------------------------------------------
1145 // "platform get-size remote-file-path"
1146 //----------------------------------------------------------------------
1147 class CommandObjectPlatformGetSize : public CommandObjectParsed
1148 {
1149 public:
1150     CommandObjectPlatformGetSize (CommandInterpreter &interpreter) :
1151     CommandObjectParsed (interpreter,
1152                          "platform get-size",
1153                          "Get the file size from the remote end.",
1154                          "platform get-size <remote-file-spec>",
1155                          0)
1156     {
1157         SetHelpLong(
1158 "Examples: \n\
1159 \n\
1160     platform get-size /the/remote/file/path\n\
1161     # Get the file size from the remote end with path /the/remote/file/path.\n");
1162
1163         CommandArgumentEntry arg1;
1164         CommandArgumentData file_arg_remote;
1165     
1166         // Define the first (and only) variant of this arg.
1167         file_arg_remote.arg_type = eArgTypeFilename;
1168         file_arg_remote.arg_repetition = eArgRepeatPlain;
1169         // There is only one variant this argument could be; put it into the argument entry.
1170         arg1.push_back (file_arg_remote);
1171         
1172         // Push the data for the first argument into the m_arguments vector.
1173         m_arguments.push_back (arg1);
1174     }
1175     
1176     virtual
1177     ~CommandObjectPlatformGetSize ()
1178     {
1179     }
1180     
1181     virtual bool
1182     DoExecute (Args& args, CommandReturnObject &result)
1183     {
1184         // If the number of arguments is incorrect, issue an error message.
1185         if (args.GetArgumentCount() != 1)
1186         {
1187             result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n");
1188             result.SetStatus(eReturnStatusFailed);
1189             return false;
1190         }
1191
1192         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1193         if (platform_sp)
1194         {
1195             std::string remote_file_path(args.GetArgumentAtIndex(0));
1196             user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false));
1197             if (size != UINT64_MAX)
1198             {
1199                 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size);
1200                 result.SetStatus (eReturnStatusSuccessFinishResult);
1201             }
1202             else
1203             {
1204                 result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str());
1205                 result.SetStatus (eReturnStatusFailed);
1206             }
1207         }
1208         else
1209         {
1210             result.AppendError ("no platform currently selected\n");
1211             result.SetStatus (eReturnStatusFailed);
1212         }
1213         return result.Succeeded();
1214     }
1215 };
1216
1217 //----------------------------------------------------------------------
1218 // "platform put-file"
1219 //----------------------------------------------------------------------
1220 class CommandObjectPlatformPutFile : public CommandObjectParsed
1221 {
1222 public:
1223     CommandObjectPlatformPutFile (CommandInterpreter &interpreter) :
1224     CommandObjectParsed (interpreter,
1225                          "platform put-file",
1226                          "Transfer a file from this system to the remote end.",
1227                          NULL,
1228                          0)
1229     {
1230     }
1231     
1232     virtual
1233     ~CommandObjectPlatformPutFile ()
1234     {
1235     }
1236     
1237     virtual bool
1238     DoExecute (Args& args, CommandReturnObject &result)
1239     {
1240         const char* src = args.GetArgumentAtIndex(0);
1241         const char* dst = args.GetArgumentAtIndex(1);
1242
1243         FileSpec src_fs(src, true);
1244         FileSpec dst_fs(dst, false);
1245         
1246         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1247         if (platform_sp)
1248         {
1249             Error error (platform_sp->PutFile(src_fs, dst_fs));
1250             if (error.Success())
1251             {
1252                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1253             }
1254             else
1255             {
1256                 result.AppendError (error.AsCString());
1257                 result.SetStatus (eReturnStatusFailed);
1258             }
1259         }
1260         else
1261         {
1262             result.AppendError ("no platform currently selected\n");
1263             result.SetStatus (eReturnStatusFailed);
1264         }
1265         return result.Succeeded();
1266     }
1267 };
1268
1269 //----------------------------------------------------------------------
1270 // "platform process launch"
1271 //----------------------------------------------------------------------
1272 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed
1273 {
1274 public:
1275     CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
1276         CommandObjectParsed (interpreter,
1277                              "platform process launch",
1278                              "Launch a new process on a remote platform.",
1279                              "platform process launch program",
1280                              eFlagRequiresTarget | eFlagTryTargetAPILock),
1281         m_options (interpreter)
1282     {
1283     }
1284     
1285     virtual
1286     ~CommandObjectPlatformProcessLaunch ()
1287     {
1288     }
1289     
1290     virtual Options *
1291     GetOptions ()
1292     {
1293         return &m_options;
1294     }
1295     
1296 protected:
1297     virtual bool
1298     DoExecute (Args& args, CommandReturnObject &result)
1299     {
1300         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1301         PlatformSP platform_sp;
1302         if (target)
1303         {   
1304             platform_sp = target->GetPlatform();
1305         }   
1306         if (!platform_sp)
1307         {
1308             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1309         }   
1310
1311         if (platform_sp)
1312         {
1313             Error error;
1314             const size_t argc = args.GetArgumentCount();
1315             Target *target = m_exe_ctx.GetTargetPtr();
1316             Module *exe_module = target->GetExecutableModulePointer();
1317             if (exe_module)
1318             {
1319                 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec();
1320                 char exe_path[PATH_MAX];
1321                 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
1322                     m_options.launch_info.GetArguments().AppendArgument (exe_path);
1323                 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1324             }
1325
1326             if (argc > 0)
1327             {
1328                 if (m_options.launch_info.GetExecutableFile ())
1329                 {
1330                     // We already have an executable file, so we will use this
1331                     // and all arguments to this function are extra arguments
1332                     m_options.launch_info.GetArguments().AppendArguments (args);
1333                 }
1334                 else
1335                 {
1336                     // We don't have any file yet, so the first argument is our
1337                     // executable, and the rest are program arguments
1338                     const bool first_arg_is_executable = true;
1339                     m_options.launch_info.SetArguments (args, first_arg_is_executable);
1340                 }
1341             }
1342             
1343             if (m_options.launch_info.GetExecutableFile ())
1344             {
1345                 Debugger &debugger = m_interpreter.GetDebugger();
1346
1347                 if (argc == 0)
1348                     target->GetRunArguments(m_options.launch_info.GetArguments());
1349
1350                 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, 
1351                                                                  debugger,
1352                                                                  target,
1353                                                                  error));
1354                 if (process_sp && process_sp->IsAlive())
1355                 {
1356                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1357                     return true;
1358                 }
1359                 
1360                 if (error.Success())
1361                     result.AppendError ("process launch failed");
1362                 else
1363                     result.AppendError (error.AsCString());
1364                 result.SetStatus (eReturnStatusFailed);
1365             }
1366             else
1367             {
1368                 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
1369                 result.SetStatus (eReturnStatusFailed);
1370                 return false;
1371             }
1372         }
1373         else
1374         {
1375             result.AppendError ("no platform is selected\n");
1376         }
1377         return result.Succeeded();
1378     }
1379     
1380 protected:
1381     ProcessLaunchCommandOptions m_options;
1382 };
1383
1384
1385
1386 //----------------------------------------------------------------------
1387 // "platform process list"
1388 //----------------------------------------------------------------------
1389 class CommandObjectPlatformProcessList : public CommandObjectParsed
1390 {
1391 public:
1392     CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
1393         CommandObjectParsed (interpreter, 
1394                              "platform process list",
1395                              "List processes on a remote platform by name, pid, or many other matching attributes.",
1396                              "platform process list",
1397                              0),
1398         m_options (interpreter)
1399     {
1400     }
1401     
1402     virtual
1403     ~CommandObjectPlatformProcessList ()
1404     {
1405     }
1406     
1407     virtual Options *
1408     GetOptions ()
1409     {
1410         return &m_options;
1411     }
1412     
1413 protected:
1414     virtual bool
1415     DoExecute (Args& args, CommandReturnObject &result)
1416     {
1417         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1418         PlatformSP platform_sp;
1419         if (target)
1420         {   
1421             platform_sp = target->GetPlatform();
1422         }   
1423         if (!platform_sp)
1424         {
1425             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1426         }   
1427         
1428         if (platform_sp)
1429         {
1430             Error error;
1431             if (args.GetArgumentCount() == 0)
1432             {
1433                 
1434                 if (platform_sp)
1435                 {
1436                     Stream &ostrm = result.GetOutputStream();      
1437
1438                     lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
1439                     if (pid != LLDB_INVALID_PROCESS_ID)
1440                     {
1441                         ProcessInstanceInfo proc_info;
1442                         if (platform_sp->GetProcessInfo (pid, proc_info))
1443                         {
1444                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1445                             proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1446                             result.SetStatus (eReturnStatusSuccessFinishResult);
1447                         }
1448                         else
1449                         {
1450                             result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid);
1451                             result.SetStatus (eReturnStatusFailed);
1452                         }
1453                     }
1454                     else
1455                     {
1456                         ProcessInstanceInfoList proc_infos;
1457                         const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
1458                         const char *match_desc = NULL;
1459                         const char *match_name = m_options.match_info.GetProcessInfo().GetName();
1460                         if (match_name && match_name[0])
1461                         {
1462                             switch (m_options.match_info.GetNameMatchType())
1463                             {
1464                                 case eNameMatchIgnore: break;
1465                                 case eNameMatchEquals: match_desc = "matched"; break;
1466                                 case eNameMatchContains: match_desc = "contained"; break;
1467                                 case eNameMatchStartsWith: match_desc = "started with"; break;
1468                                 case eNameMatchEndsWith: match_desc = "ended with"; break;
1469                                 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
1470                             }
1471                         }
1472
1473                         if (matches == 0)
1474                         {
1475                             if (match_desc)
1476                                 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", 
1477                                                               match_desc,
1478                                                               match_name,
1479                                                               platform_sp->GetPluginName().GetCString());
1480                             else
1481                                 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString());
1482                             result.SetStatus (eReturnStatusFailed);
1483                         }
1484                         else
1485                         {
1486                             result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", 
1487                                                             matches,
1488                                                             matches > 1 ? "es were" : " was",
1489                                                             platform_sp->GetName().GetCString());
1490                             if (match_desc)
1491                                 result.AppendMessageWithFormat (" whose name %s \"%s\"", 
1492                                                                 match_desc,
1493                                                                 match_name);
1494                             result.AppendMessageWithFormat ("\n");
1495                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1496                             for (uint32_t i=0; i<matches; ++i)
1497                             {
1498                                 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1499                             }
1500                         }
1501                     }
1502                 }
1503             }
1504             else
1505             {
1506                 result.AppendError ("invalid args: process list takes only options\n");
1507                 result.SetStatus (eReturnStatusFailed);
1508             }
1509         }
1510         else
1511         {
1512             result.AppendError ("no platform is selected\n");
1513             result.SetStatus (eReturnStatusFailed);
1514         }
1515         return result.Succeeded();
1516     }
1517     
1518     class CommandOptions : public Options
1519     {
1520     public:
1521         
1522         CommandOptions (CommandInterpreter &interpreter) :
1523             Options (interpreter),
1524             match_info ()
1525         {
1526         }
1527         
1528         virtual
1529         ~CommandOptions ()
1530         {
1531         }
1532         
1533         virtual Error
1534         SetOptionValue (uint32_t option_idx, const char *option_arg)
1535         {
1536             Error error;
1537             const int short_option = m_getopt_table[option_idx].val;
1538             bool success = false;
1539
1540             switch (short_option)
1541             {
1542                 case 'p':
1543                     match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1544                     if (!success)
1545                         error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
1546                     break;
1547                 
1548                 case 'P':
1549                     match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1550                     if (!success)
1551                         error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
1552                     break;
1553
1554                 case 'u':
1555                     match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1556                     if (!success)
1557                         error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
1558                     break;
1559
1560                 case 'U':
1561                     match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1562                     if (!success)
1563                         error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
1564                     break;
1565
1566                 case 'g':
1567                     match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1568                     if (!success)
1569                         error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
1570                     break;
1571
1572                 case 'G':
1573                     match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1574                     if (!success)
1575                         error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
1576                     break;
1577
1578                 case 'a':
1579                     match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
1580                     break;
1581
1582                 case 'n':
1583                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1584                     match_info.SetNameMatchType (eNameMatchEquals);
1585                     break;
1586
1587                 case 'e':
1588                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1589                     match_info.SetNameMatchType (eNameMatchEndsWith);
1590                     break;
1591
1592                 case 's':
1593                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1594                     match_info.SetNameMatchType (eNameMatchStartsWith);
1595                     break;
1596                     
1597                 case 'c':
1598                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1599                     match_info.SetNameMatchType (eNameMatchContains);
1600                     break;
1601                     
1602                 case 'r':
1603                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1604                     match_info.SetNameMatchType (eNameMatchRegularExpression);
1605                     break;
1606
1607                 case 'A':
1608                     show_args = true;
1609                     break;
1610
1611                 case 'v':
1612                     verbose = true;
1613                     break;
1614
1615                 default:
1616                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1617                     break;
1618             }
1619             
1620             return error;
1621         }
1622         
1623         void
1624         OptionParsingStarting ()
1625         {
1626             match_info.Clear();
1627             show_args = false;
1628             verbose = false;
1629         }
1630         
1631         const OptionDefinition*
1632         GetDefinitions ()
1633         {
1634             return g_option_table;
1635         }
1636         
1637         // Options table: Required for subclasses of Options.
1638         
1639         static OptionDefinition g_option_table[];
1640         
1641         // Instance variables to hold the values for command options.
1642         
1643         ProcessInstanceInfoMatch match_info;
1644         bool show_args;
1645         bool verbose;
1646     };
1647     CommandOptions m_options;
1648 };
1649
1650 namespace
1651 {
1652     PosixPlatformCommandOptionValidator g_posix_validator;
1653 }
1654
1655 OptionDefinition
1656 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
1657 {
1658 { LLDB_OPT_SET_1            , false, "pid"        , 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "List the process info for a specific process ID." },
1659 { LLDB_OPT_SET_2            , true , "name"       , 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that match a string." },
1660 { LLDB_OPT_SET_3            , true , "ends-with"  , 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that end with a string." },
1661 { LLDB_OPT_SET_4            , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that start with a string." },
1662 { LLDB_OPT_SET_5            , true , "contains"   , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that contain a string." },
1663 { LLDB_OPT_SET_6            , true , "regex"      , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1664 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent"     , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "Find processes that have a matching parent process ID." },
1665 { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
1666 { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
1667 { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
1668 { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
1669 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch"       , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture     , "Find processes that have a matching architecture." },
1670 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args"  , 'A', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Show process arguments instead of the process executable basename." },
1671 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose"    , 'v', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Enable verbose output." },
1672 { 0                         , false, NULL         ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone             , NULL }
1673 };
1674
1675 //----------------------------------------------------------------------
1676 // "platform process info"
1677 //----------------------------------------------------------------------
1678 class CommandObjectPlatformProcessInfo : public CommandObjectParsed
1679 {
1680 public:
1681     CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
1682     CommandObjectParsed (interpreter, 
1683                          "platform process info",
1684                          "Get detailed information for one or more process by process ID.",
1685                          "platform process info <pid> [<pid> <pid> ...]",
1686                          0)
1687     {
1688         CommandArgumentEntry arg;
1689         CommandArgumentData pid_args;
1690         
1691         // Define the first (and only) variant of this arg.
1692         pid_args.arg_type = eArgTypePid;
1693         pid_args.arg_repetition = eArgRepeatStar;
1694         
1695         // There is only one variant this argument could be; put it into the argument entry.
1696         arg.push_back (pid_args);
1697         
1698         // Push the data for the first argument into the m_arguments vector.
1699         m_arguments.push_back (arg);
1700     }
1701     
1702     virtual
1703     ~CommandObjectPlatformProcessInfo ()
1704     {
1705     }
1706     
1707 protected:
1708     virtual bool
1709     DoExecute (Args& args, CommandReturnObject &result)
1710     {
1711         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1712         PlatformSP platform_sp;
1713         if (target)
1714         {   
1715             platform_sp = target->GetPlatform();
1716         }   
1717         if (!platform_sp)
1718         {
1719             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1720         }   
1721
1722         if (platform_sp)
1723         {
1724             const size_t argc = args.GetArgumentCount();
1725             if (argc > 0)
1726             {
1727                 Error error;
1728                 
1729                 if (platform_sp->IsConnected())
1730                 {
1731                     Stream &ostrm = result.GetOutputStream();      
1732                     bool success;
1733                     for (size_t i=0; i<argc; ++ i)
1734                     {
1735                         const char *arg = args.GetArgumentAtIndex(i);
1736                         lldb::pid_t pid = StringConvert::ToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1737                         if (success)
1738                         {
1739                             ProcessInstanceInfo proc_info;
1740                             if (platform_sp->GetProcessInfo (pid, proc_info))
1741                             {
1742                                 ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid);
1743                                 proc_info.Dump (ostrm, platform_sp.get());
1744                             }
1745                             else
1746                             {
1747                                 ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid);
1748                             }
1749                             ostrm.EOL();
1750                         }
1751                         else
1752                         {
1753                             result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
1754                             result.SetStatus (eReturnStatusFailed);            
1755                             break;
1756                         }
1757                     }
1758                 }
1759                 else
1760                 {
1761                     // Not connected...
1762                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
1763                     result.SetStatus (eReturnStatusFailed);            
1764                 }
1765             }
1766             else
1767             {
1768                 // No args
1769                 result.AppendError ("one or more process id(s) must be specified");
1770                 result.SetStatus (eReturnStatusFailed);            
1771             }
1772         }
1773         else
1774         {
1775             result.AppendError ("no platform is currently selected");
1776             result.SetStatus (eReturnStatusFailed);            
1777         }
1778         return result.Succeeded();
1779     }
1780 };
1781
1782 class CommandObjectPlatformProcessAttach : public CommandObjectParsed
1783 {
1784 public:
1785     
1786     class CommandOptions : public Options
1787     {
1788     public:
1789         
1790         CommandOptions (CommandInterpreter &interpreter) :
1791         Options(interpreter)
1792         {
1793             // Keep default values of all options in one place: OptionParsingStarting ()
1794             OptionParsingStarting ();
1795         }
1796         
1797         ~CommandOptions ()
1798         {
1799         }
1800         
1801         Error
1802         SetOptionValue (uint32_t option_idx, const char *option_arg)
1803         {
1804             Error error;
1805             char short_option = (char) m_getopt_table[option_idx].val;
1806             bool success = false;
1807             switch (short_option)
1808             {
1809                 case 'p':   
1810                 {
1811                     lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1812                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
1813                     {
1814                         error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
1815                     }
1816                     else
1817                     {
1818                         attach_info.SetProcessID (pid);
1819                     }
1820                 }
1821                     break;
1822                     
1823                 case 'P':
1824                     attach_info.SetProcessPluginName (option_arg);
1825                     break;
1826                     
1827                 case 'n': 
1828                     attach_info.GetExecutableFile().SetFile(option_arg, false);
1829                     break;
1830                     
1831                 case 'w':   
1832                     attach_info.SetWaitForLaunch(true);
1833                     break;
1834                     
1835                 default:
1836                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1837                     break;
1838             }
1839             return error;
1840         }
1841         
1842         void
1843         OptionParsingStarting ()
1844         {
1845             attach_info.Clear();
1846         }
1847         
1848         const OptionDefinition*
1849         GetDefinitions ()
1850         {
1851             return g_option_table;
1852         }
1853         
1854         virtual bool
1855         HandleOptionArgumentCompletion (Args &input,
1856                                         int cursor_index,
1857                                         int char_pos,
1858                                         OptionElementVector &opt_element_vector,
1859                                         int opt_element_index,
1860                                         int match_start_point,
1861                                         int max_return_elements,
1862                                         bool &word_complete,
1863                                         StringList &matches)
1864         {
1865             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1866             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1867             
1868             // We are only completing the name option for now...
1869             
1870             const OptionDefinition *opt_defs = GetDefinitions();
1871             if (opt_defs[opt_defs_index].short_option == 'n')
1872             {
1873                 // Are we in the name?
1874                 
1875                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
1876                 // use the default plugin.
1877                 
1878                 const char *partial_name = NULL;
1879                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
1880                 
1881                 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
1882                 if (platform_sp)
1883                 {
1884                     ProcessInstanceInfoList process_infos;
1885                     ProcessInstanceInfoMatch match_info;
1886                     if (partial_name)
1887                     {
1888                         match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
1889                         match_info.SetNameMatchType(eNameMatchStartsWith);
1890                     }
1891                     platform_sp->FindProcesses (match_info, process_infos);
1892                     const uint32_t num_matches = process_infos.GetSize();
1893                     if (num_matches > 0)
1894                     {
1895                         for (uint32_t i=0; i<num_matches; ++i)
1896                         {
1897                             matches.AppendString (process_infos.GetProcessNameAtIndex(i), 
1898                                                   process_infos.GetProcessNameLengthAtIndex(i));
1899                         }
1900                     }
1901                 }
1902             }
1903             
1904             return false;
1905         }
1906         
1907         // Options table: Required for subclasses of Options.
1908         
1909         static OptionDefinition g_option_table[];
1910         
1911         // Instance variables to hold the values for command options.
1912         
1913         ProcessAttachInfo attach_info;
1914     };
1915     
1916     CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) :
1917     CommandObjectParsed (interpreter,
1918                          "platform process attach",
1919                          "Attach to a process.",
1920                          "platform process attach <cmd-options>"),
1921     m_options (interpreter)
1922     {
1923     }
1924     
1925     ~CommandObjectPlatformProcessAttach ()
1926     {
1927     }
1928     
1929     bool
1930     DoExecute (Args& command,
1931              CommandReturnObject &result)
1932     {
1933         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1934         if (platform_sp)
1935         {
1936             Error err;
1937             ProcessSP remote_process_sp =
1938             platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err);
1939             if (err.Fail())
1940             {
1941                 result.AppendError(err.AsCString());
1942                 result.SetStatus (eReturnStatusFailed);
1943             }
1944             else if (remote_process_sp.get() == NULL)
1945             {
1946                 result.AppendError("could not attach: unknown reason");
1947                 result.SetStatus (eReturnStatusFailed);
1948             }
1949             else
1950                 result.SetStatus (eReturnStatusSuccessFinishResult);
1951         }
1952         else
1953         {
1954             result.AppendError ("no platform is currently selected");
1955             result.SetStatus (eReturnStatusFailed);            
1956         }
1957         return result.Succeeded();
1958     }
1959     
1960     Options *
1961     GetOptions ()
1962     {
1963         return &m_options;
1964     }
1965     
1966 protected:
1967     
1968     CommandOptions m_options;
1969 };
1970
1971
1972 OptionDefinition
1973 CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] =
1974 {
1975     { LLDB_OPT_SET_ALL, false, "plugin",  'P'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
1976     { LLDB_OPT_SET_1,   false, "pid",     'p'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
1977     { LLDB_OPT_SET_2,   false, "name",    'n'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
1978     { LLDB_OPT_SET_2,   false, "waitfor", 'w'  , OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
1979     { 0,                false, NULL     , 0    , 0                              , NULL, NULL, 0, eArgTypeNone, NULL }
1980 };
1981
1982
1983 class CommandObjectPlatformProcess : public CommandObjectMultiword
1984 {
1985 public:
1986     //------------------------------------------------------------------
1987     // Constructors and Destructors
1988     //------------------------------------------------------------------
1989      CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
1990         CommandObjectMultiword (interpreter,
1991                                 "platform process",
1992                                 "A set of commands to query, launch and attach to platform processes",
1993                                 "platform process [attach|launch|list] ...")
1994     {
1995         LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
1996         LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
1997         LoadSubCommand ("info"  , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
1998         LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
1999
2000     }
2001     
2002     virtual
2003     ~CommandObjectPlatformProcess ()
2004     {
2005     }
2006     
2007 private:
2008     //------------------------------------------------------------------
2009     // For CommandObjectPlatform only
2010     //------------------------------------------------------------------
2011     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
2012 };
2013
2014 //----------------------------------------------------------------------
2015 // "platform shell"
2016 //----------------------------------------------------------------------
2017 class CommandObjectPlatformShell : public CommandObjectRaw
2018 {
2019 public:
2020     
2021     class CommandOptions : public Options
2022     {
2023     public:
2024         
2025         CommandOptions (CommandInterpreter &interpreter) :
2026         Options(interpreter),
2027         timeout(10)
2028         {
2029         }
2030         
2031         virtual
2032         ~CommandOptions ()
2033         {
2034         }
2035         
2036         virtual uint32_t
2037         GetNumDefinitions ()
2038         {
2039             return 1;
2040         }
2041         
2042         virtual const OptionDefinition*
2043         GetDefinitions ()
2044         {
2045             return g_option_table;
2046         }
2047         
2048         virtual Error
2049         SetOptionValue (uint32_t option_idx,
2050                         const char *option_value)
2051         {
2052             Error error;
2053             
2054             const char short_option = (char) g_option_table[option_idx].short_option;
2055             
2056             switch (short_option)
2057             {
2058                 case 't':
2059                 {
2060                     bool success;
2061                     timeout = StringConvert::ToUInt32(option_value, 10, 10, &success);
2062                     if (!success)
2063                         error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value);
2064                     break;
2065                 }
2066                 default:
2067                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
2068                     break;
2069             }
2070             
2071             return error;
2072         }
2073         
2074         virtual void
2075         OptionParsingStarting ()
2076         {
2077         }
2078         
2079         // Options table: Required for subclasses of Options.
2080         
2081         static OptionDefinition g_option_table[];
2082         uint32_t timeout;
2083     };
2084     
2085     CommandObjectPlatformShell (CommandInterpreter &interpreter) :
2086     CommandObjectRaw (interpreter, 
2087                       "platform shell",
2088                       "Run a shell command on a the selected platform.",
2089                       "platform shell <shell-command>",
2090                       0),
2091     m_options(interpreter)
2092     {
2093     }
2094     
2095     virtual
2096     ~CommandObjectPlatformShell ()
2097     {
2098     }
2099     
2100     virtual
2101     Options *
2102     GetOptions ()
2103     {
2104         return &m_options;
2105     }
2106     
2107     virtual bool
2108     DoExecute (const char *raw_command_line, CommandReturnObject &result)
2109     {
2110         m_options.NotifyOptionParsingStarting();
2111         
2112         const char* expr = NULL;
2113
2114         // Print out an usage syntax on an empty command line.
2115         if (raw_command_line[0] == '\0')
2116         {
2117             result.GetOutputStream().Printf("%s\n", this->GetSyntax());
2118             return true;
2119         }
2120
2121         if (raw_command_line[0] == '-')
2122         {
2123             // We have some options and these options MUST end with --.
2124             const char *end_options = NULL;
2125             const char *s = raw_command_line;
2126             while (s && s[0])
2127             {
2128                 end_options = ::strstr (s, "--");
2129                 if (end_options)
2130                 {
2131                     end_options += 2; // Get past the "--"
2132                     if (::isspace (end_options[0]))
2133                     {
2134                         expr = end_options;
2135                         while (::isspace (*expr))
2136                             ++expr;
2137                         break;
2138                     }
2139                 }
2140                 s = end_options;
2141             }
2142             
2143             if (end_options)
2144             {
2145                 Args args (raw_command_line, end_options - raw_command_line);
2146                 if (!ParseOptions (args, result))
2147                     return false;
2148             }
2149         }
2150         
2151         if (expr == NULL)
2152             expr = raw_command_line;
2153         
2154         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2155         Error error;
2156         if (platform_sp)
2157         {
2158             const char *working_dir = NULL;
2159             std::string output;
2160             int status = -1;
2161             int signo = -1;
2162             error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout));
2163             if (!output.empty())
2164                 result.GetOutputStream().PutCString(output.c_str());
2165             if (status > 0)
2166             {
2167                 if (signo > 0)
2168                 {
2169                     const char *signo_cstr = Host::GetSignalAsCString(signo);
2170                     if (signo_cstr)
2171                         result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
2172                     else
2173                         result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
2174                 }
2175                 else
2176                     result.GetOutputStream().Printf("error: command returned with status %i\n", status);
2177             }
2178         }
2179         else
2180         {
2181             result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n");
2182             error.SetErrorString("error: cannot run remote shell commands without a platform");
2183         }
2184
2185         if (error.Fail())
2186         {
2187             result.AppendError(error.AsCString());
2188             result.SetStatus (eReturnStatusFailed);
2189         }
2190         else
2191         {
2192             result.SetStatus (eReturnStatusSuccessFinishResult);
2193         }
2194         return true;
2195     }
2196     CommandOptions m_options;
2197 };
2198
2199 OptionDefinition
2200 CommandObjectPlatformShell::CommandOptions::g_option_table[] =
2201 {
2202     { LLDB_OPT_SET_ALL, false, "timeout",      't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,    "Seconds to wait for the remote host to finish running the command."},
2203     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2204 };
2205
2206
2207 //----------------------------------------------------------------------
2208 // "platform install" - install a target to a remote end
2209 //----------------------------------------------------------------------
2210 class CommandObjectPlatformInstall : public CommandObjectParsed
2211 {
2212 public:
2213     CommandObjectPlatformInstall (CommandInterpreter &interpreter) :
2214     CommandObjectParsed (interpreter,
2215                          "platform target-install",
2216                          "Install a target (bundle or executable file) to the remote end.",
2217                          "platform target-install <local-thing> <remote-sandbox>",
2218                          0)
2219     {
2220     }
2221     
2222     virtual
2223     ~CommandObjectPlatformInstall ()
2224     {
2225     }
2226     
2227     virtual bool
2228     DoExecute (Args& args, CommandReturnObject &result)
2229     {
2230         if (args.GetArgumentCount() != 2)
2231         {
2232             result.AppendError("platform target-install takes two arguments");
2233             result.SetStatus(eReturnStatusFailed);
2234             return false;
2235         }
2236         // TODO: move the bulk of this code over to the platform itself
2237         FileSpec src(args.GetArgumentAtIndex(0), true);
2238         FileSpec dst(args.GetArgumentAtIndex(1), false);
2239         if (src.Exists() == false)
2240         {
2241             result.AppendError("source location does not exist or is not accessible");
2242             result.SetStatus(eReturnStatusFailed);
2243             return false;
2244         }
2245         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2246         if (!platform_sp)
2247         {
2248             result.AppendError ("no platform currently selected");
2249             result.SetStatus (eReturnStatusFailed);
2250             return false;
2251         }
2252         
2253         Error error = platform_sp->Install(src, dst);
2254         if (error.Success())
2255         {
2256             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2257         }
2258         else
2259         {
2260             result.AppendErrorWithFormat("install failed: %s", error.AsCString());
2261             result.SetStatus(eReturnStatusFailed);
2262         }
2263         return result.Succeeded();
2264     }
2265 private:
2266
2267 };
2268
2269 //----------------------------------------------------------------------
2270 // CommandObjectPlatform constructor
2271 //----------------------------------------------------------------------
2272 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
2273     CommandObjectMultiword (interpreter,
2274                             "platform",
2275                             "A set of commands to manage and create platforms.",
2276                             "platform [connect|disconnect|info|list|status|select] ...")
2277 {
2278     LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
2279     LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
2280     LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
2281     LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
2282     LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
2283     LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter)));
2284     LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
2285     LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
2286     LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
2287     LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
2288     LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
2289     LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
2290     LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
2291     LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
2292 }
2293
2294 //----------------------------------------------------------------------
2295 // Destructor
2296 //----------------------------------------------------------------------
2297 CommandObjectPlatform::~CommandObjectPlatform()
2298 {
2299 }