macos.rb 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG +572 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +129 -0
- data/Rakefile +9 -0
- data/lib/Array/all_but_last.rb +7 -0
- data/lib/MacOS/Apple80211.rb +68 -0
- data/lib/MacOS/Applications.rb +73 -0
- data/lib/MacOS/Defaults/ComAppleDock.rb +153 -0
- data/lib/MacOS/Defaults/NSGlobalDomain/NSUserKeyEquivalents.rb +109 -0
- data/lib/MacOS/Defaults.rb +126 -0
- data/lib/MacOS/DiskUtil.rb +63 -0
- data/lib/MacOS/Dmg.rb +99 -0
- data/lib/MacOS/HardwarePort.rb +79 -0
- data/lib/MacOS/IfConfig.rb +183 -0
- data/lib/MacOS/Keychain.rb +26 -0
- data/lib/MacOS/LaunchControl.rb +36 -0
- data/lib/MacOS/SystemProfiler.rb +119 -0
- data/lib/MacOS/USBFlashDrive.rb +26 -0
- data/lib/MacOS/Users.rb +16 -0
- data/lib/MacOS/VERSION.rb +6 -0
- data/lib/MacOS/VPN.rb +13 -0
- data/lib/MacOS/Voice.rb +40 -0
- data/lib/MacOS.rb +27 -0
- data/lib/Module/alias_methods.rb +7 -0
- data/lib/Ordinal/Array.rb +8 -0
- data/lib/Ordinal.rb +157 -0
- data/lib/Thoran/Array/AllButLast/all_but_last.rb +28 -0
- data/lib/Thoran/Array/LastX/lastX.rb +33 -0
- data/lib/Thoran/Module/AliasMethods/alias_methods.rb +23 -0
- data/lib/Thoran/String/Capture/capture.rb +28 -0
- data/lib/Version.rb +381 -0
- data/macos.rb.gemspec +59 -0
- data/test/MacOS/Apple80211_test.rb +80 -0
- data/test/MacOS/Applications_test.rb +82 -0
- data/test/MacOS/Defaults/ComAppleDock_test.rb +66 -0
- data/test/MacOS/Defaults/NSGlobalDomain/NSUserKeyEquivalents_test.rb +67 -0
- data/test/MacOS/Defaults_test.rb +144 -0
- data/test/MacOS/DiskUtil_test.rb +48 -0
- data/test/MacOS/Dmg_test.rb +69 -0
- data/test/MacOS/HardwarePort_test.rb +46 -0
- data/test/MacOS/IfConfig_test.rb +144 -0
- data/test/MacOS/Keychain_test.rb +22 -0
- data/test/MacOS/LaunchControl_test.rb +40 -0
- data/test/MacOS/SystemProfiler_test.rb +69 -0
- data/test/MacOS/USBFlashDrive_test.rb +20 -0
- data/test/MacOS/Users_test.rb +10 -0
- data/test/MacOS/VPN_test.rb +18 -0
- data/test/MacOS/Voice_test.rb +46 -0
- data/test/MacOS_test.rb +17 -0
- data/test/VERSION_test.rb +19 -0
- data/test/commands_test.rb +50 -0
- data/test/fixtures/airport-I-deprecated.txt +2 -0
- data/test/fixtures/airport-I.txt +17 -0
- data/test/fixtures/defaults-domains.txt +1 -0
- data/test/fixtures/defaults-export-com.apple.dock.xml +47 -0
- data/test/fixtures/defaults-read-NSUserKeyEquivalents.txt +4 -0
- data/test/fixtures/df-k.txt +6 -0
- data/test/fixtures/diskutil-list-plist.xml +104 -0
- data/test/fixtures/dscl-list-users.txt +8 -0
- data/test/fixtures/ifconfig-a.txt +53 -0
- data/test/fixtures/networksetup-listallhardwareports.txt +39 -0
- data/test/fixtures/say-v.txt +8 -0
- data/test/fixtures/system_profiler-SPAirPortDataType.txt +44 -0
- data/test/fixtures/system_profiler-SPSoftwareDataType.txt +14 -0
- data/test/fixtures/system_profiler-SPUSBDataType.txt +58 -0
- data/test/gemspec_test.rb +50 -0
- data/test/helper.rb +18 -0
- metadata +183 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# MacOS/DiskUtil.rb
|
|
2
|
+
# MacOS::DiskUtil
|
|
3
|
+
|
|
4
|
+
require 'plist'
|
|
5
|
+
|
|
6
|
+
module MacOS
|
|
7
|
+
class DiskUtil
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def xml_volume_plist
|
|
11
|
+
`diskutil list -plist`
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def volume_plist
|
|
15
|
+
Plist.parse_xml(xml_volume_plist)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def volumes_and_partitions
|
|
19
|
+
volume_plist["AllDisksAndPartitions"].select do |dp|
|
|
20
|
+
!dp["Partitions"].empty?
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def volume_partitions(volume)
|
|
25
|
+
volume["Partitions"]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def volumes
|
|
29
|
+
volumes_and_partitions.collect do |volume|
|
|
30
|
+
volume_partitions(volume).collect do |partition|
|
|
31
|
+
{
|
|
32
|
+
device_id: partition["DeviceIdentifier"],
|
|
33
|
+
mount_point: partition["MountPoint"],
|
|
34
|
+
name: partition["VolumeName"],
|
|
35
|
+
size: partition["Size"],
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end.flatten.compact
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def external_volumes
|
|
42
|
+
volumes.reject{|v| v[:mount_point].nil?}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def free_bytes_for_device_id(device_id)
|
|
46
|
+
`df -k`.split("\n").detect do |partition_data|
|
|
47
|
+
if partition_data.split.first.match(device_id)
|
|
48
|
+
return partition_data.split[3].to_i * 1024
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def free_bytes_for_volume_name(volume_name)
|
|
54
|
+
`df -k`.split("\n").detect do |partition_data|
|
|
55
|
+
if partition_data.split.last.match(volume_name)
|
|
56
|
+
return partition_data.split[3].to_i * 1024
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end # class << self
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/MacOS/Dmg.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# MacOS/Dmg.rb
|
|
2
|
+
# MacOS::Dmg
|
|
3
|
+
|
|
4
|
+
# History: Extracted the methods from install_macports to be used in install_homebrew, but didn't finish this and just placed the methods (with some modification) directly into install_homebrew.
|
|
5
|
+
|
|
6
|
+
require 'shellwords'
|
|
7
|
+
|
|
8
|
+
module MacOS
|
|
9
|
+
class Dmg
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :verbose
|
|
13
|
+
|
|
14
|
+
def mount(path_to_dmg)
|
|
15
|
+
puts "hdiutil attach #{Shellwords.escape(path_to_dmg)}" if verbose
|
|
16
|
+
system "hdiutil attach #{Shellwords.escape(path_to_dmg)}"
|
|
17
|
+
end
|
|
18
|
+
alias_method :attach, :mount
|
|
19
|
+
|
|
20
|
+
def run_installer(mount_point:, pkg_name:)
|
|
21
|
+
starting_working_directory = Dir.pwd
|
|
22
|
+
puts "cd #{full_path_to_mount_point(mount_point)}" if verbose
|
|
23
|
+
Dir.chdir(full_path_to_mount_point(mount_point))
|
|
24
|
+
puts "sudo installer -pkg #{Shellwords.escape(pkg_name)} -target '/'" if verbose
|
|
25
|
+
system "sudo installer -pkg #{Shellwords.escape(pkg_name)} -target '/'"
|
|
26
|
+
Dir.chdir(starting_working_directory)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def unmount(mount_point)
|
|
30
|
+
puts "hdiutil detach -Force #{Shellwords.escape(full_path_to_mount_point(mount_point))}" if verbose
|
|
31
|
+
system "hdiutil detach -Force #{Shellwords.escape(full_path_to_mount_point(mount_point))}"
|
|
32
|
+
end
|
|
33
|
+
alias_method :detach, :unmount
|
|
34
|
+
|
|
35
|
+
def install(path_to_dmg:, disk_image_name:, mount_point: nil, package: nil)
|
|
36
|
+
dmg = new(path_to_dmg: path_to_dmg, disk_image_name: disk_image_name, mount_point: mount_point, package: package)
|
|
37
|
+
dmg.mount
|
|
38
|
+
dmg.run_installer
|
|
39
|
+
dmg.unmount
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def full_path_to_mount_point(mount_point)
|
|
45
|
+
File.join('/', 'Volumes', mount_point)
|
|
46
|
+
end
|
|
47
|
+
end # class << self
|
|
48
|
+
|
|
49
|
+
attr_accessor :disk_image_name
|
|
50
|
+
attr_accessor :package
|
|
51
|
+
attr_accessor :path_to_dmg
|
|
52
|
+
|
|
53
|
+
attr_writer :mount_point
|
|
54
|
+
attr_writer :pkg_name
|
|
55
|
+
|
|
56
|
+
def initialize(path_to_dmg:, disk_image_name: nil, mount_point: nil, package: nil)
|
|
57
|
+
@path_to_dmg = path_to_dmg
|
|
58
|
+
@disk_image_name = disk_image_name
|
|
59
|
+
@mount_point = mount_point
|
|
60
|
+
@package = package
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
alias_method :filename, :disk_image_name
|
|
64
|
+
alias_method :dmg_filename, :disk_image_name
|
|
65
|
+
alias_method :image_name, :disk_image_name
|
|
66
|
+
alias_method :filename=, :disk_image_name=
|
|
67
|
+
alias_method :dmg_filename=, :disk_image_name=
|
|
68
|
+
alias_method :image_name=, :disk_image_name=
|
|
69
|
+
|
|
70
|
+
def pkg_name
|
|
71
|
+
@pkg_name || (@package + '.pkg')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def mount_point
|
|
75
|
+
@mount_point || @disk_image_name.split('.').first
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def mount
|
|
79
|
+
MacOS::Dmg.mount(@path_to_dmg)
|
|
80
|
+
end
|
|
81
|
+
alias_method :attach, :mount
|
|
82
|
+
|
|
83
|
+
def run_installer
|
|
84
|
+
MacOS::Dmg.run_installer(pkg_name: pkg_name, mount_point: mount_point)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def unmount
|
|
88
|
+
MacOS::Dmg.unmount(mount_point)
|
|
89
|
+
end
|
|
90
|
+
alias_method :detach, :unmount
|
|
91
|
+
|
|
92
|
+
def install
|
|
93
|
+
mount
|
|
94
|
+
run_installer
|
|
95
|
+
unmount
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# MacOS/HardwarePort.rb
|
|
2
|
+
# MacOS::HardwarePort
|
|
3
|
+
|
|
4
|
+
module MacOS
|
|
5
|
+
class HardwarePort
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
|
|
9
|
+
def parse(output = nil)
|
|
10
|
+
output ||= self.output
|
|
11
|
+
hardware_ports = []
|
|
12
|
+
hardware_port = nil
|
|
13
|
+
output.each_line do |line|
|
|
14
|
+
# p line
|
|
15
|
+
if line == "\n" || line == ""
|
|
16
|
+
hardware_ports << hardware_port if hardware_port
|
|
17
|
+
hardware_port = new
|
|
18
|
+
else
|
|
19
|
+
label, value = line.match(/^(.+): (.+)/)&.captures
|
|
20
|
+
case label
|
|
21
|
+
when 'Hardware Port'; hardware_port.hardware_port = value
|
|
22
|
+
when 'Device'; hardware_port.device = value
|
|
23
|
+
when 'Ethernet Address'; hardware_port.ethernet_address = value
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
hardware_ports
|
|
28
|
+
end
|
|
29
|
+
alias_method :all, :parse
|
|
30
|
+
alias_method :hardware_ports, :parse
|
|
31
|
+
alias_method :ports, :parse
|
|
32
|
+
|
|
33
|
+
def find_by_interface(interface)
|
|
34
|
+
all.detect{|hardware_port| hardware_port.interface == interface}
|
|
35
|
+
end
|
|
36
|
+
alias_method :find_by_device, :find_by_interface
|
|
37
|
+
|
|
38
|
+
def find_by_name(name)
|
|
39
|
+
all.detect{|hardware_port| hardware_port.name == name}
|
|
40
|
+
end
|
|
41
|
+
alias_method :find_by_hardware_port, :find_by_name
|
|
42
|
+
|
|
43
|
+
def find_by_mac_address(mac_address)
|
|
44
|
+
all.detect{|hardware_port| hardware_port.ethernet_address == mac_address}
|
|
45
|
+
end
|
|
46
|
+
alias_method :find_by_ethernet_address, :find_by_mac_address
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def output
|
|
51
|
+
`networksetup -listallhardwareports`
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end # class << self
|
|
55
|
+
|
|
56
|
+
attr_accessor :hardware_port
|
|
57
|
+
attr_accessor :device
|
|
58
|
+
attr_accessor :ethernet_address
|
|
59
|
+
|
|
60
|
+
def initialize(hardware_port: nil, device: nil, ethernet_address: nil)
|
|
61
|
+
@hardware_port = hardware_port
|
|
62
|
+
@device = device
|
|
63
|
+
@ethernet_address = ethernet_address
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def name
|
|
67
|
+
@hardware_port
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def mac_address
|
|
71
|
+
@ethernet_address
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def interface
|
|
75
|
+
@device
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# MacOS/IfConfig.rb
|
|
2
|
+
# MacOS::IfConfig
|
|
3
|
+
|
|
4
|
+
module MacOS
|
|
5
|
+
class IfConfig
|
|
6
|
+
class << self
|
|
7
|
+
def parse(output = nil)
|
|
8
|
+
output ||= self.output
|
|
9
|
+
ifconfigs = []
|
|
10
|
+
ifconfig = nil
|
|
11
|
+
output.each_line do |line|
|
|
12
|
+
if line =~ /^\t/
|
|
13
|
+
case line
|
|
14
|
+
when /ether/
|
|
15
|
+
ifconfig.mac_address = line[/ *ether (.+?) ?$/, 1]
|
|
16
|
+
when /inet /
|
|
17
|
+
if line.match(/broadcast/)
|
|
18
|
+
ifconfig.ipv4_address, ifconfig.netmask, ifconfig.broadcast_address = line.match(/ *inet (\d+(?:\.\d+){3}) netmask (.+) broadcast (.+)$/)&.captures
|
|
19
|
+
elsif line.match(/-->/)
|
|
20
|
+
ipv4_address_from, ipv4_address_to, ifconfig.netmask = line.match(/inet (.+) --> (.+) netmask (.+)$/)&.captures
|
|
21
|
+
ifconfig.ipv4_address = ipv4_address_from
|
|
22
|
+
else
|
|
23
|
+
ifconfig.ipv4_address, ifconfig.netmask = line.match(/ *inet (\d+(?:\.\d+){3}) netmask (.+?) ?$/)&.captures
|
|
24
|
+
end
|
|
25
|
+
when /status\:/
|
|
26
|
+
ifconfig.status = line[/ *status: (.+)$/, 1]
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
ifconfigs << ifconfig if ifconfig
|
|
30
|
+
ifconfig = new
|
|
31
|
+
ifconfig.interface, rest_of_line = line.match(/^(.+?): (.+)$/)&.captures
|
|
32
|
+
if rest_of_line =~ /flags=\w+<([^>]+)>/
|
|
33
|
+
ifconfig.flags = $1.split(',')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
ifconfigs << ifconfig if ifconfig
|
|
38
|
+
ifconfigs
|
|
39
|
+
end
|
|
40
|
+
alias_method :all, :parse
|
|
41
|
+
alias_method :interfaces, :parse
|
|
42
|
+
alias_method :all_interfaces, :parse
|
|
43
|
+
|
|
44
|
+
def interface_names
|
|
45
|
+
all.collect(&:interface_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def active_interfaces
|
|
49
|
+
all.select(&:active?)
|
|
50
|
+
end
|
|
51
|
+
alias_method :active, :active_interfaces
|
|
52
|
+
|
|
53
|
+
def active_interfaces_names
|
|
54
|
+
all.select(&:active?).collect(&:interface_name)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def inactive_interfaces
|
|
58
|
+
all.select(&:inactive?)
|
|
59
|
+
end
|
|
60
|
+
alias_method :inactive, :inactive_interfaces
|
|
61
|
+
|
|
62
|
+
def inactive_interfaces_names
|
|
63
|
+
all.select(&:inactive?).collect(&:interface_name)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def up_interfaces
|
|
67
|
+
all.select(&:up?)
|
|
68
|
+
end
|
|
69
|
+
alias_method :up, :up_interfaces
|
|
70
|
+
|
|
71
|
+
def up_interfaces_names
|
|
72
|
+
all.select(&:up?).collect(&:interface_name)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def mac_addresses
|
|
76
|
+
all.collect(&:mac_address).compact
|
|
77
|
+
end
|
|
78
|
+
alias_method :ethernet_addresses, :mac_addresses
|
|
79
|
+
|
|
80
|
+
def ipv4_addresses
|
|
81
|
+
all.collect(&:ipv4_address).compact
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def find_by_interface(interface)
|
|
85
|
+
all.find{|ifconfig| ifconfig.interface == interface}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def find_by_mac_address(mac_address)
|
|
89
|
+
all.find{|ifconfig| ifconfig.mac_address == mac_address}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def find_by_ipv4_address(ipv4_address)
|
|
93
|
+
all.find{|ifconfig| ifconfig.ipv4_address == ipv4_address}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def all_matching(pattern)
|
|
97
|
+
pattern = Regexp.union(pattern)
|
|
98
|
+
all.select{|ifconfig| ifconfig.name =~ pattern}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def bring_down_interface(interface_name)
|
|
102
|
+
system('sudo', 'ifconfig', interface_name, 'down', exception: true)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def bring_down_matching_interfaces(pattern)
|
|
106
|
+
matching_interfaces = all_matching(pattern).select(&:up?)
|
|
107
|
+
matching_interfaces.each do |ifconfig|
|
|
108
|
+
bring_down_interface(ifconfig.name)
|
|
109
|
+
end
|
|
110
|
+
matching_interfaces.map(&:name)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def destroy_interface(interface_name)
|
|
114
|
+
system('sudo', 'ifconfig', interface_name, 'destroy', exception: true)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def output
|
|
120
|
+
`ifconfig -a`
|
|
121
|
+
end
|
|
122
|
+
end # class << self
|
|
123
|
+
|
|
124
|
+
attr_accessor(
|
|
125
|
+
:broadcast_address,
|
|
126
|
+
:flags,
|
|
127
|
+
:interface,
|
|
128
|
+
:ipv4_address,
|
|
129
|
+
:mac_address,
|
|
130
|
+
:netmask,
|
|
131
|
+
:status
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def initialize(
|
|
135
|
+
broadcast_address: nil,
|
|
136
|
+
flags: nil,
|
|
137
|
+
interface: nil,
|
|
138
|
+
ipv4_address: nil,
|
|
139
|
+
mac_address: nil,
|
|
140
|
+
netmask: nil,
|
|
141
|
+
status: nil
|
|
142
|
+
)
|
|
143
|
+
@broadcast_address = broadcast_address
|
|
144
|
+
@flags = flags
|
|
145
|
+
@interface = interface
|
|
146
|
+
@ipv4_address = ipv4_address
|
|
147
|
+
@mac_address = mac_address
|
|
148
|
+
@netmask = netmask
|
|
149
|
+
@status = status
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def interface_name
|
|
153
|
+
@interface
|
|
154
|
+
end
|
|
155
|
+
alias_method :name, :interface_name
|
|
156
|
+
|
|
157
|
+
def ethernet_address
|
|
158
|
+
@mac_address
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def active?
|
|
162
|
+
@status == 'active'
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def inactive?
|
|
166
|
+
@status == 'inactive'
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# For interfaces with status field (physical), check active status and IP address.
|
|
170
|
+
# For interfaces with flags only (virtual), check UP flag and IP address.
|
|
171
|
+
def up?
|
|
172
|
+
if @status
|
|
173
|
+
active? && @ipv4_address
|
|
174
|
+
else
|
|
175
|
+
(@flags && @flags.include?('UP')) && @ipv4_address
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def virtual?
|
|
180
|
+
@interface =~ /^(utun|awdl|llw|lo|bridge|gif|stf)\d*/
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# MacOS/Keychain.rb
|
|
2
|
+
# MacOS::Keychain
|
|
3
|
+
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'shellwords'
|
|
6
|
+
|
|
7
|
+
module MacOS
|
|
8
|
+
class Keychain
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
def find_generic_password_command(key)
|
|
12
|
+
"security find-generic-password -ga #{Shellwords.escape(key)}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def find_generic_password(key)
|
|
16
|
+
Open3.capture3(find_generic_password_command(key))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def wifi_password(wifi_ssid)
|
|
20
|
+
stdout, stderr, status = find_generic_password(wifi_ssid)
|
|
21
|
+
stderr[/password: "(.+)"/, 1]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # class << self
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# MacOS/LaunchControl.rb
|
|
2
|
+
# MacOS::LaunchControl
|
|
3
|
+
|
|
4
|
+
require 'shellwords'
|
|
5
|
+
|
|
6
|
+
module MacOS
|
|
7
|
+
class LaunchControl
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
def load(path_to_plist)
|
|
12
|
+
system("launchctl load -w #{Shellwords.escape(path_to_plist)}")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def unload(path_to_plist)
|
|
16
|
+
system("launchctl unload -w #{Shellwords.escape(path_to_plist)}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end # class << self
|
|
20
|
+
|
|
21
|
+
attr_accessor :path_to_plist
|
|
22
|
+
|
|
23
|
+
def initialize(path_to_plist = nil)
|
|
24
|
+
@path_to_plist = path_to_plist
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def load
|
|
28
|
+
MacOS::LaunchControl.load(path_to_plist)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def unload(path_to_plist = @path_to_plist)
|
|
32
|
+
MacOS::LaunchControl.unload(path_to_plist)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# MacOS/SystemProfiler.rb
|
|
2
|
+
# MacOS::SystemProfiler
|
|
3
|
+
|
|
4
|
+
# Description: This uses the built-in system_profiler command on MacOS to get access to the version numbers on any
|
|
5
|
+
# version of MacOS which has a system_profiler command and which returns results in a known format.
|
|
6
|
+
|
|
7
|
+
require 'Version'
|
|
8
|
+
|
|
9
|
+
module MacOS
|
|
10
|
+
module SystemProfiler
|
|
11
|
+
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
def system_profiler_output
|
|
15
|
+
`system_profiler SPSoftwareDataType`.force_encoding('UTF-8')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# The value system_profiler gives for a field, such as 'Boot Volume'.
|
|
19
|
+
def field(name)
|
|
20
|
+
system_profiler_output[/#{Regexp.escape(name)}: (?<value>.+)$/, :value]
|
|
21
|
+
end
|
|
22
|
+
private_class_method :field
|
|
23
|
+
|
|
24
|
+
def system_version_data
|
|
25
|
+
field('System Version')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def system_version_string
|
|
29
|
+
earlier_versions = system_version_data.split[3] # OSX 10.4 to 10.9 at least
|
|
30
|
+
later_versions = system_version_data.split[1] # MacOS 10.14 at least
|
|
31
|
+
earlier_versions || later_versions
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def system_version
|
|
35
|
+
Version.new(system_version_string)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def major_system_version
|
|
39
|
+
system_version.major
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def minor_system_version
|
|
43
|
+
system_version.minor
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def tiny_system_version
|
|
47
|
+
system_version.tiny
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def kernel_version_data
|
|
51
|
+
field('Kernel Version')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def kernel_name
|
|
55
|
+
kernel_version_data.split.first
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def kernel_version_string
|
|
59
|
+
kernel_version_data.split.last
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def kernel_version
|
|
63
|
+
Version.new(kernel_version_string)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def boot_volume_data
|
|
67
|
+
field('Boot Volume')
|
|
68
|
+
end
|
|
69
|
+
alias_method :boot_volume_string, :boot_volume_data
|
|
70
|
+
|
|
71
|
+
def boot_mode_data
|
|
72
|
+
field('Boot Mode')
|
|
73
|
+
end
|
|
74
|
+
alias_method :boot_mode_string, :boot_mode_data
|
|
75
|
+
alias_method :boot_mode, :boot_mode_data
|
|
76
|
+
|
|
77
|
+
def computer_name_data
|
|
78
|
+
field('Computer Name')
|
|
79
|
+
end
|
|
80
|
+
alias_method :computer_name_string, :computer_name_data
|
|
81
|
+
alias_method :computer_name, :computer_name_data
|
|
82
|
+
|
|
83
|
+
def username_data
|
|
84
|
+
field('User Name')
|
|
85
|
+
end
|
|
86
|
+
alias_method :username_string, :username_data
|
|
87
|
+
alias_method :username, :username_data
|
|
88
|
+
|
|
89
|
+
def secure_virtual_memory_data
|
|
90
|
+
field('Secure Virtual Memory')
|
|
91
|
+
end
|
|
92
|
+
alias_method :secure_virtual_memory_string, :secure_virtual_memory_data
|
|
93
|
+
alias_method :secure_virtual_memory, :secure_virtual_memory_data
|
|
94
|
+
|
|
95
|
+
def system_integrity_protection_data
|
|
96
|
+
field('System Integrity Protection')
|
|
97
|
+
end
|
|
98
|
+
alias_method :system_integrity_protection_string, :system_integrity_protection_data
|
|
99
|
+
alias_method :system_integrity_protection, :system_integrity_protection_data
|
|
100
|
+
|
|
101
|
+
def time_since_boot_data
|
|
102
|
+
field('Time since boot')
|
|
103
|
+
end
|
|
104
|
+
alias_method :time_since_boot_string, :time_since_boot_data
|
|
105
|
+
alias_method :time_since_boot, :time_since_boot_data
|
|
106
|
+
|
|
107
|
+
# The aliases as module functions too, alias_method making instance methods alone.
|
|
108
|
+
module_function(
|
|
109
|
+
:boot_volume_string,
|
|
110
|
+
:boot_mode_string, :boot_mode,
|
|
111
|
+
:computer_name_string, :computer_name,
|
|
112
|
+
:username_string, :username,
|
|
113
|
+
:secure_virtual_memory_string, :secure_virtual_memory,
|
|
114
|
+
:system_integrity_protection_string, :system_integrity_protection,
|
|
115
|
+
:time_since_boot_string, :time_since_boot
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# MacOS/USBFlashDrive.rb
|
|
2
|
+
# MacOS::USBFlashDrive
|
|
3
|
+
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'shellwords'
|
|
6
|
+
|
|
7
|
+
module MacOS
|
|
8
|
+
class USBFlashDrive
|
|
9
|
+
class << self
|
|
10
|
+
|
|
11
|
+
def system_profiler_usb_data_type_command
|
|
12
|
+
"system_profiler SPUSBDataType"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def raw_system_profiler_output
|
|
16
|
+
Open3.capture3(system_profiler_usb_data_type_command)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def all_mount_points
|
|
20
|
+
stdout, stderr, status = raw_system_profiler_output
|
|
21
|
+
stdout.scan(/Mount Point: (.+)$/).flatten
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # class << self
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/MacOS/Users.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# MacOS/Users.rb
|
|
2
|
+
# MacOS::Users
|
|
3
|
+
|
|
4
|
+
# Description: Lists the real (human) user accounts on the system, excluding system and service accounts.
|
|
5
|
+
|
|
6
|
+
module MacOS
|
|
7
|
+
module Users
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def all
|
|
11
|
+
`dscl . list /users`.split("\n")
|
|
12
|
+
.reject{|username| username =~ /^_/}
|
|
13
|
+
.reject{|username| %w{daemon nobody root}.include?(username)}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/MacOS/VPN.rb
ADDED