ronin-post_ex 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.document +6 -0
  3. data/.github/workflows/ruby.yml +31 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +1 -0
  6. data/.ruby-version +1 -0
  7. data/.yardopts +1 -0
  8. data/API_SPEC.md +235 -0
  9. data/COPYING.txt +165 -0
  10. data/ChangeLog.md +23 -0
  11. data/Gemfile +36 -0
  12. data/README.md +245 -0
  13. data/Rakefile +34 -0
  14. data/examples/bind_shell.rb +19 -0
  15. data/gemspec.yml +25 -0
  16. data/lib/ronin/post_ex/cli/shell_shell.rb +66 -0
  17. data/lib/ronin/post_ex/cli/system_shell.rb +811 -0
  18. data/lib/ronin/post_ex/remote_dir.rb +190 -0
  19. data/lib/ronin/post_ex/remote_file/stat.rb +174 -0
  20. data/lib/ronin/post_ex/remote_file.rb +417 -0
  21. data/lib/ronin/post_ex/remote_process.rb +170 -0
  22. data/lib/ronin/post_ex/resource.rb +144 -0
  23. data/lib/ronin/post_ex/sessions/bind_shell.rb +60 -0
  24. data/lib/ronin/post_ex/sessions/remote_shell_session.rb +48 -0
  25. data/lib/ronin/post_ex/sessions/reverse_shell.rb +67 -0
  26. data/lib/ronin/post_ex/sessions/rpc_session.rb +779 -0
  27. data/lib/ronin/post_ex/sessions/session.rb +73 -0
  28. data/lib/ronin/post_ex/sessions/shell_session.rb +618 -0
  29. data/lib/ronin/post_ex/system/fs.rb +650 -0
  30. data/lib/ronin/post_ex/system/process.rb +422 -0
  31. data/lib/ronin/post_ex/system/shell.rb +1037 -0
  32. data/lib/ronin/post_ex/system.rb +191 -0
  33. data/lib/ronin/post_ex/version.rb +26 -0
  34. data/lib/ronin/post_ex.rb +22 -0
  35. data/ronin-post_ex.gemspec +61 -0
  36. data/spec/sessions/bind_shell_spec.rb +31 -0
  37. data/spec/sessions/remote_shell_session_spec.rb +28 -0
  38. data/spec/sessions/reverse_shell_spec.rb +49 -0
  39. data/spec/sessions/rpc_session_spec.rb +500 -0
  40. data/spec/sessions/session_spec.rb +61 -0
  41. data/spec/sessions/shell_session_spec.rb +482 -0
  42. data/spec/spec_helper.rb +9 -0
  43. data/spec/system_spec.rb +66 -0
  44. metadata +155 -0
@@ -0,0 +1,811 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-post_ex - a Ruby API for Post-Exploitation.
4
+ #
5
+ # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-post_ex is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-post_ex is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-post_ex. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/core/cli/command_shell'
22
+ require 'ronin/post_ex/cli/shell_shell'
23
+ require 'ronin/post_ex/remote_file'
24
+
25
+ module Ronin
26
+ module PostEx
27
+ module CLI
28
+ #
29
+ # A shell for {System}.
30
+ #
31
+ class SystemShell < Core::CLI::CommandShell
32
+
33
+ shell_name 'ronin-post_ex'
34
+
35
+ #
36
+ # Initializes the file-system shell.
37
+ #
38
+ # @param [System] system
39
+ # The file-system resource.
40
+ #
41
+ # @param [Hash{Symbol => Object}] kwargs
42
+ # Additional keyword arguments.
43
+ #
44
+ def initialize(system, **kwargs)
45
+ super(**kwargs)
46
+
47
+ @system = system
48
+
49
+ @files = {}
50
+ @next_file_id = 1
51
+ end
52
+
53
+ command 'fs.chdir', method_name: 'fs_chdir',
54
+ usage: 'DIR',
55
+ summary: 'Changes the current working directory'
56
+
57
+ #
58
+ # Changes the working directory.
59
+ #
60
+ # @param [String] path
61
+ # The new working directory.
62
+ #
63
+ # @see System::FS#chdir
64
+ #
65
+ def fs_chdir(path)
66
+ @system.fs.chdir(path)
67
+ puts "Current working directory is now: #{@system.fs.pwd}"
68
+ end
69
+
70
+ command 'fs.pwd', method_name: 'fs_pwd',
71
+ summary: 'Prints the current working directory'
72
+
73
+ #
74
+ # Prints the current working directory.
75
+ #
76
+ # @see System::FS#getcwd
77
+ #
78
+ def fs_pwd
79
+ puts "Current working directory: #{@system.fs.getcwd}"
80
+ end
81
+
82
+ command 'fs.readfile', method_name: 'fs_readfile',
83
+ usage: 'FILE',
84
+ summary: 'Reads the contents of a given FILE'
85
+
86
+ #
87
+ # Reads data from a file.
88
+ #
89
+ # @param [String] path
90
+ # The file to read from.
91
+ #
92
+ # @see System::FS#read
93
+ #
94
+ def fs_readfile(path)
95
+ write(@system.fs.readfile(path))
96
+ end
97
+
98
+ command 'fs.readlink', method_name: 'fs_readlink',
99
+ usage: 'SYMLINK',
100
+ summary: 'Reads the destination path of a symlink'
101
+
102
+ #
103
+ # Reads the destination of a link.
104
+ #
105
+ # @param [String] path
106
+ # The path to the link.
107
+ #
108
+ # @see System::FS#readlink
109
+ #
110
+ def fs_readlink(path)
111
+ puts @system.fs.readlink(path)
112
+ end
113
+
114
+ command 'fs.readdir', method_name: 'fs_readdir',
115
+ usage: 'DIR',
116
+ summary: 'Reads the contents of a given directory'
117
+
118
+ #
119
+ # Reads the entries of a directory.
120
+ #
121
+ # @param [String] path
122
+ # The path to the directory.
123
+ #
124
+ # @see System::FS#readdir
125
+ #
126
+ def fs_readdir(path)
127
+ @system.fs.readdir(path).each do |entry|
128
+ puts entry
129
+ end
130
+ end
131
+
132
+ command 'fs.hexdump', usage: 'FILE',
133
+ summary: 'Hexdumps a given file'
134
+
135
+ #
136
+ # Hexdumps a file.
137
+ #
138
+ # @param [String] path
139
+ # The file to hexdump.
140
+ #
141
+ # @see System::FS#hexdump
142
+ #
143
+ def hexdump(path)
144
+ @system.fs.hexdump(path,self)
145
+ end
146
+
147
+ command 'fs.copy', method_name: 'file_copy',
148
+ usage: 'SRC DEST',
149
+ summary: 'Copies the SRC file to the DEST path'
150
+
151
+ #
152
+ # Copies a file to a destination.
153
+ #
154
+ # @param [String] src
155
+ # The file to copy.
156
+ #
157
+ # @param [String] dest
158
+ # The destination to copy the file to.
159
+ #
160
+ # @see System::FS#copy
161
+ #
162
+ def fs_copy(src,dest)
163
+ @system.fs.copy(src,dest)
164
+
165
+ puts "Copied #{@system.fs.expand_path(src)} -> #{@fs.expand_path(dest)}"
166
+ end
167
+
168
+ command 'fs.unlink', method_name: 'file_unlink',
169
+ usage: 'FILE',
170
+ summary: 'Deletes a given file'
171
+
172
+ #
173
+ # Removes a file.
174
+ #
175
+ # @param [String] path
176
+ # The file to be removed.
177
+ #
178
+ # @see System::FS#unlink
179
+ #
180
+ def file_unlink(path)
181
+ @system.fs.unlink(path)
182
+
183
+ puts "Removed #{@system.fs.expand_path(path)}"
184
+ end
185
+
186
+ command 'fs.rmdir', method_name: 'fs_rmdir',
187
+ usage: 'DIR',
188
+ summary: 'Removes a given directory'
189
+
190
+ #
191
+ # Removes an empty directory.
192
+ #
193
+ # @param [String] path
194
+ # The file to be removed.
195
+ #
196
+ # @see System::FS#rmdir
197
+ #
198
+ def fs_rmdir(path)
199
+ @system.fs.rmdir(path)
200
+
201
+ puts "Removed directory #{@system.fs.expand_path(path)}"
202
+ end
203
+
204
+ command 'fs.mv', method_name: 'fs_mv',
205
+ usage: 'SRC DEST',
206
+ summary: 'Moves or renames a given file or directory'
207
+
208
+ #
209
+ # Moves a file or directory.
210
+ #
211
+ # @param [String] src
212
+ # The file or directory to move.
213
+ #
214
+ # @param [String] dest
215
+ # The destination to move the file or directory to.
216
+ #
217
+ # @see System::FS#move
218
+ #
219
+ def fs_mv(src,dest)
220
+ @system.fs.move(src,dest)
221
+
222
+ puts "Moved #{@system.fs.expand_path(src)} -> #{@fs.expand_path(dest)}"
223
+ end
224
+
225
+ command 'fs.link', method_name: 'fs_link',
226
+ usage: 'SRC DEST',
227
+ summary: 'Creates a link from the source to the destination'
228
+
229
+ #
230
+ # Creates a link to a file or directory.
231
+ #
232
+ # @param [String] src
233
+ # The file or directory to link to.
234
+ #
235
+ # @param [String] dest
236
+ # The path of the new link.
237
+ #
238
+ # @see System::FS#link
239
+ #
240
+ def fs_link(src,dest)
241
+ @system.fs.link(src,dest)
242
+
243
+ puts "Linked #{@system.fs.expand_path(src)} -> #{@fs.expand_path(dest)}"
244
+ end
245
+
246
+ command 'fs.chown', method_name: 'fs_chown',
247
+ usage: 'USER PATH',
248
+ summary: 'Changes the owner of a given file or directory'
249
+
250
+ #
251
+ # Changes ownership of a file or directory.
252
+ #
253
+ # @param [String] user
254
+ # The desired new user.
255
+ #
256
+ # @param [String] path
257
+ # The path of the file or directory.
258
+ #
259
+ # @see System::FS#chown
260
+ #
261
+ def fs_chown(user,path)
262
+ @system.fs.chown(user,path)
263
+
264
+ puts "Changed ownership of #{@system.fs.expand_path(path)} to #{user}"
265
+ end
266
+
267
+ command 'fs.chgrp', method_name: 'fs_chgrp',
268
+ usage: 'GROUP PATH',
269
+ summary: 'Changes the group of a given file or directory'
270
+
271
+ #
272
+ # Changes group ownership of a file or directory.
273
+ #
274
+ # @param [String] group
275
+ # The desired new group.
276
+ #
277
+ # @param [String] path
278
+ # The path of the file or directory.
279
+ #
280
+ # @see System::FS#chgrp
281
+ #
282
+ def fs_chgrp(group,path)
283
+ @system.fs.chgrp(group,path)
284
+
285
+ puts "Changed group ownership of #{@system.fs.expand_path(path)} to #{group}"
286
+ end
287
+
288
+ command 'fs.chmod', method_name: 'fs_chmod',
289
+ usage: 'MODE PATH',
290
+ summary: 'Changes the permission mode of a given file or directory'
291
+
292
+ #
293
+ # Changes the permissions of a file or directory.
294
+ #
295
+ # @param [String] mode
296
+ # The desired new octal permission mode.
297
+ #
298
+ # @param [String] path
299
+ # The path of the file or directory.
300
+ #
301
+ # @see System::FS#chmod
302
+ #
303
+ def fs_chmod(mode,path)
304
+ @system.fs.chmod(mode.to_i(8),path)
305
+
306
+ puts "Changed permissions on #{@system.fs.expand_path(path)} to #{mode}"
307
+ end
308
+
309
+ command 'fs.stat', method_name: 'fs_stat',
310
+ usage: 'PATH',
311
+ summary: 'Prints file system information about a given file or directory'
312
+
313
+ #
314
+ # Stats a file or directory.
315
+ #
316
+ # @param [String] path
317
+ # The file or directory to stat.
318
+ #
319
+ # @see System::FS#stat
320
+ #
321
+ def fs_stat(path)
322
+ stat = @system.fs.stat(path)
323
+ end
324
+
325
+ command 'file.open', method_name: 'file_open',
326
+ usage: 'PATH [MODE]',
327
+ summary: 'Opens a file for reading or writing'
328
+
329
+ #
330
+ # Opens a file.
331
+ #
332
+ # @param [String] path
333
+ # The path to the file.
334
+ #
335
+ # @param [String] mode
336
+ # Optional open mode.
337
+ #
338
+ # @see System::FS#open
339
+ #
340
+ def file_open(path,mode="r")
341
+ file = @system.fs.open(path,mode)
342
+ file_id = @next_file_id
343
+
344
+ @files[file_id] = file
345
+ @next_file_id += 1
346
+
347
+ puts "Opened file ##{file_id} for #{file.path}"
348
+ end
349
+
350
+ command 'files', summary: 'Lists opened files'
351
+
352
+ #
353
+ # Lists opened files.
354
+ #
355
+ def files
356
+ @files.each_with_index do |file,index|
357
+ if file
358
+ id = index + 1
359
+
360
+ puts " [#{id}] #{file.path}"
361
+ end
362
+ end
363
+ end
364
+
365
+ command 'file.seek', method_name: 'file_seek',
366
+ usage: 'FILE_ID POS [SEEK_SET | SEEK_CUR | SEEK_END | SEEK_DATA | SEEK_HOLE]',
367
+ summary: 'Seeks to a position within the file'
368
+
369
+ # Mapping of String whence values to Integer values.
370
+ WHENCE = {
371
+ 'SEEK_SET' => RemoteFile::SEEK_SET,
372
+ 'SEEK_CUR' => RemoteFile::SEEK_CUR,
373
+ 'SEEK_END' => RemoteFile::SEEK_END,
374
+ 'SEEK_DATA' => RemoteFile::SEEK_DATA,
375
+ 'SEEK_HOLE' => RemoteFile::SEEK_HOLE
376
+ }
377
+
378
+ #
379
+ # Seeks to a position within an opened file.
380
+ #
381
+ # @param [String] file_id
382
+ # The file ID number.
383
+ #
384
+ # @param [String] pos
385
+ # The position to seek to.
386
+ #
387
+ # @param [String] whence
388
+ # Where to seek relative from. Acceptable values are:
389
+ # * `"SET"`
390
+ # * `"CUR"`
391
+ # * `"END"`
392
+ # * `"DATA"`
393
+ # * `"HOLE"`
394
+ #
395
+ # @see RemoteFile#seek
396
+ #
397
+ def file_seek(file_id,pos,whence='SEEK_SET')
398
+ unless WHENCE.has_key?(whence)
399
+ print_error "unknown file.seek whence value (#{whence}), must be #{WHENCE.keys.join(', ')}"
400
+ return false
401
+ end
402
+
403
+ file_id = file_id.to_i
404
+ pos = pos.to_i
405
+ whence = WHENCE[whence]
406
+
407
+ if (file = @files[file_id])
408
+ file.seek(pos,whence)
409
+ puts file.pos
410
+ else
411
+ print_error "unknown file id: #{file_id}"
412
+ end
413
+ end
414
+
415
+ command 'file.read', method_name: 'file_read',
416
+ usage: 'FILE_ID LENGTH',
417
+ summary: 'Reads LENGTH of data from an opened file'
418
+
419
+ #
420
+ # Reads data from an opened file.
421
+ #
422
+ # @param [String] file_id
423
+ # The file ID number.
424
+ #
425
+ # @param [String] length
426
+ # The length of data to read.
427
+ #
428
+ # @see RemoteFile#read
429
+ #
430
+ def file_read(file_id,length)
431
+ file_id = file_id.to_i
432
+ length = length.to_i
433
+
434
+ if (file = @files[file_id])
435
+ puts(file.read(length))
436
+ else
437
+ print_error "unknown file id: #{file_id}"
438
+ end
439
+ end
440
+
441
+ command 'file.write', method_name: 'file_write',
442
+ usage: 'FILE_ID DATA',
443
+ summary: 'Writes data to an opened file'
444
+
445
+ #
446
+ # Writes data from to an opened file.
447
+ #
448
+ # @param [String] file_id
449
+ # The file ID number.
450
+ #
451
+ # @param [String] data
452
+ # The data to write.
453
+ #
454
+ # @see RemoteFile#write
455
+ #
456
+ def file_write(file_id,data)
457
+ file_id = file_id.to_i
458
+ length = length.to_i
459
+
460
+ if (file = @files[file_id])
461
+ puts file.write(length)
462
+ else
463
+ print_error "unknown file id: #{file_id}"
464
+ end
465
+ end
466
+
467
+ command 'file.close', method_name: 'file_close',
468
+ usage: 'FILE_ID',
469
+ summary: 'Closes an open file'
470
+
471
+ #
472
+ # Closes an opened file.
473
+ #
474
+ # @param [String] file_id
475
+ # The file ID number.
476
+ #
477
+ # @see RemoteFile#close
478
+ #
479
+ def file_close(file_id)
480
+ file_id = file_id.to_i
481
+ length = length.to_i
482
+
483
+ if (file = @files[file_id])
484
+ file.close
485
+ @files.delete(file_id)
486
+
487
+ puts "Closed file ##{file_id} for #{file.path}"
488
+ else
489
+ print_error "unknown file id: #{file_id}"
490
+ end
491
+ end
492
+
493
+ command 'process.pid', method_name: 'process_pid',
494
+ summary: "Prints the process'es PID"
495
+
496
+ #
497
+ # Prints the process'es PID.
498
+ #
499
+ # @see System::Process#getpid
500
+ #
501
+ def process_pid
502
+ puts @system.process.getpid
503
+ end
504
+
505
+ command 'process.ppid', method_name: 'process_ppid',
506
+ summary: "Prints the process'es PPID"
507
+
508
+ #
509
+ # Prints the process'es PPID.
510
+ #
511
+ # @see System::Process#getppid
512
+ #
513
+ def process_ppid
514
+ puts @system.process.getppid
515
+ end
516
+
517
+ command 'process.uid', method_name: 'process_uid',
518
+ summary: "Prints the process'es UID"
519
+
520
+ #
521
+ # Prints the process'es UID.
522
+ #
523
+ # @see System::Process#getuid
524
+ #
525
+ def process_uid
526
+ puts @system.process.getuid
527
+ end
528
+
529
+ command 'process.setuid', method_name: 'process_setuid',
530
+ usage: 'UID',
531
+ summary: "Sets the process'es UID"
532
+
533
+ #
534
+ # Sets the process'es UID.
535
+ #
536
+ # @param [String] new_uid
537
+ #
538
+ # @see System::Process#setuid
539
+ #
540
+ def process_setuid(new_uid)
541
+ @system.process.setuid(new_uid.to_i)
542
+ end
543
+
544
+ command 'process.euid', method_name: 'process_euid',
545
+ usage: 'EUID',
546
+ summary: "Prints the process'es EUID"
547
+
548
+ #
549
+ # Prints the process'es EUID.
550
+ #
551
+ # @see System::Process#geteuid
552
+ #
553
+ def process_euid
554
+ puts @system.process.geteuid
555
+ end
556
+
557
+ command 'process.seteuid', method_name: 'process_seteuid',
558
+ usage: 'EUID',
559
+ summary: "Sets the process'es EUID"
560
+
561
+ #
562
+ # Sets the process'es EUID.
563
+ #
564
+ # @param [String] new_euid
565
+ #
566
+ # @see System::Process#seteuid
567
+ #
568
+ def process_seteuid(new_euid)
569
+ @system.process.seteuid(new_euid.to_i)
570
+ end
571
+
572
+ command 'process.gid', method_name: 'process_gid',
573
+ usage: 'COMMAND',
574
+ summary: "Prints the process'es GID"
575
+
576
+ #
577
+ # Prints the process'es GID.
578
+ #
579
+ # @see System::Process#getgid
580
+ #
581
+ def process_gid
582
+ puts @system.process.getgid
583
+ end
584
+
585
+ command 'process.setgid', method_name: 'process_setgid',
586
+ usage: 'GID',
587
+ summary: "Sets the process'es GID"
588
+
589
+ #
590
+ # Sets the process'es GID.
591
+ #
592
+ # @param [String] new_gid
593
+ #
594
+ # @see System::Process#setgid
595
+ #
596
+ def process_setgid(new_gid)
597
+ @system.process.setgid(new_gid.to_i)
598
+ end
599
+
600
+ command 'process.egid', method_name: 'process_egid',
601
+ summary: "Prints the process'es EGID"
602
+
603
+ #
604
+ # Prints the process'es EGID.
605
+ #
606
+ # @see System::Process#getegid
607
+ #
608
+ def process_egid
609
+ puts @system.process.getegid
610
+ end
611
+
612
+ command 'process.setegid', method_name: 'process_setegid',
613
+ usage: 'EGID',
614
+ summary: "Sets the process'es EGID"
615
+
616
+ #
617
+ # Sets the process'es EGID.
618
+ #
619
+ # @param [String] new_egid
620
+ #
621
+ # @see System::Process#setegid
622
+ #
623
+ def process_setegid(new_egid)
624
+ @system.process.setegid(new_egid.to_i)
625
+ end
626
+
627
+ command 'process.sid', method_name: 'process_sid',
628
+ summary: "Prints the process'es SID"
629
+
630
+ #
631
+ # Prints the process'es SID.
632
+ #
633
+ # @see System::Process#getsid
634
+ #
635
+ def process_sid
636
+ puts @system.process.getsid
637
+ end
638
+
639
+ command 'process.setsid', method_name: 'process_setsid',
640
+ usage: 'SID',
641
+ summary: "Prints the process'es SID"
642
+
643
+ #
644
+ # Sets the process'es SID.
645
+ #
646
+ # @param [String] new_sid
647
+ #
648
+ # @see System::Process#setsid
649
+ #
650
+ def process_setsid(new_sid)
651
+ @system.process.setsid(new_sid.to_i)
652
+ end
653
+
654
+ command 'process.env', method_name: 'process_env',
655
+ summary: "Prints the process'es environment variables"
656
+
657
+ #
658
+ # Prints the process'es environment variables.
659
+ #
660
+ # @see System::Process#environ
661
+ #
662
+ def process_env
663
+ @system.process.env.each do |name,value|
664
+ puts "#{name}=#{value}"
665
+ end
666
+ end
667
+
668
+ command 'process.getenv', method_name: 'process_getenv',
669
+ usage: 'NAME',
670
+ summary: 'Prints an environment variable from the process'
671
+
672
+ #
673
+ # Prints a specific environment variable from the process.
674
+ #
675
+ # @param [String] name
676
+ # The environment variable name.
677
+ #
678
+ # @see System::Process#getenv
679
+ #
680
+ def process_getenv(name)
681
+ puts @system.process.getenv(name)
682
+ end
683
+
684
+ command 'process.setenv', method_name: 'process_setenv',
685
+ usage: 'NAME=VALUE',
686
+ summary: 'Sets an environment variable for the process'
687
+
688
+ #
689
+ # Sets a specific environment variable from the process.
690
+ #
691
+ # @param [String] name_and_value
692
+ # The environment variable name.
693
+ #
694
+ # @see System::Process#getenv
695
+ #
696
+ def process_setenv(name_and_value)
697
+ name, value = name_and_value.split('=',2)
698
+
699
+ @system.process.setenv(name,value)
700
+ end
701
+
702
+ command 'process.unsetenv', method_name: 'process_getenv',
703
+ usage: 'NAME',
704
+ summary: 'Unsets an environment variable for the process'
705
+
706
+ #
707
+ # Unsets a process environment variable.
708
+ #
709
+ # @param [String] name
710
+ # The environment variable to unset.
711
+ #
712
+ # @see System::Process#unsetenv
713
+ #
714
+ def process_unsetenv(name)
715
+ @system.process.unsetenv(name)
716
+ end
717
+
718
+ command 'process.kill', method_name: 'process_kill',
719
+ usage: 'PID [SIGNAL]',
720
+ summary: 'Kills a process'
721
+
722
+ #
723
+ # Kills a process.
724
+ #
725
+ # @param [String] pid
726
+ # The process PID to kill.
727
+ #
728
+ # @param [String] signal
729
+ # The signal to send the process.
730
+ #
731
+ def process_kill(pid,signal='KILL')
732
+ @system.process.kill(pid.to_i,signal)
733
+ end
734
+
735
+ command 'process.spawn', method_name: 'process_spawn',
736
+ usage: 'PROGRAM [ARGS ...]',
737
+ summary: 'Spawns a new process'
738
+
739
+ #
740
+ # Spawns a new process.
741
+ #
742
+ # @param [String] program
743
+ # The program name.
744
+ #
745
+ # @param [Array<String>] arguments
746
+ # Additional command arguments.
747
+ #
748
+ # @see System::Process#spawn
749
+ #
750
+ def process_spawn(program,*arguments)
751
+ pid = @system.process.spawn(program,*arguments)
752
+
753
+ puts "PID: #{pid}"
754
+ end
755
+
756
+ command 'shell.exec', method_name: 'shell_exec',
757
+ usage: 'COMMAND',
758
+ summary: 'Executes a command in the shell'
759
+
760
+ #
761
+ # Executes a shell command.
762
+ #
763
+ # @param [String] command
764
+ # The command to execute.
765
+ #
766
+ # @see System::Shell#run
767
+ #
768
+ def shell_exec(command)
769
+ puts @system.shell.run(command)
770
+ end
771
+
772
+ command 'shell', method_name: 'shell',
773
+ summary: 'Spawns an interactive command shell'
774
+
775
+ #
776
+ # Spawns an interactive command sub-shell.
777
+ #
778
+ # @see ShellShell
779
+ #
780
+ def shell
781
+ ShellShell.start(@system.shell)
782
+ end
783
+
784
+ command 'sys.time', method_name: 'sys_time',
785
+ summary: "Prints the system's current time"
786
+
787
+ #
788
+ # Prints the system's current time.
789
+ #
790
+ # @see System#time
791
+ #
792
+ def sys_time
793
+ puts @system.time
794
+ end
795
+
796
+ command 'sys.hostname', method_name: 'sys_hostname',
797
+ summary: "Prints the system's hostname"
798
+
799
+ #
800
+ # Prints the system's hostname.
801
+ #
802
+ # @see System#hostname
803
+ #
804
+ def sys_hostname
805
+ puts @system.hostname
806
+ end
807
+
808
+ end
809
+ end
810
+ end
811
+ end