-
Notifications
You must be signed in to change notification settings - Fork 12
/
depnotify_user_launcher.py
executable file
·167 lines (147 loc) · 6.27 KB
/
depnotify_user_launcher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/Library/installapplications/Python.framework/Versions/Current/bin/python3
'''depnotify launcher'''
# Written by Erik Gomez
import os
import platform
import plistlib
import subprocess
import tempfile
import time
def get_macos_version():
"""returns a tuple with the (major,minor,revision) numbers"""
# OS X Yosemite return 10.10, so we will be happy with len(...) == 2, then add 0 for last number
try:
mac_ver = tuple(int(n) for n in platform.mac_ver()[0].split('.'))
assert 2 <= len(mac_ver) <= 3
# pylint: disable=broad-except
except Exception:
return None
if len(mac_ver) == 2:
mac_ver = mac_ver + (0, )
return mac_ver
def read_plist(plist_path, macos_version):
"""returns a plist object read from a file path"""
# get a tempfile path for exporting our defaults data
export_fifo = tempfile.mktemp()
# make a fifo for defaults export in a temp file
os.mkfifo(export_fifo)
# export to the fifo
if macos_version[1] >= 9:
subprocess.Popen(
['defaults', 'export', plist_path, export_fifo]).communicate()
# convert the export to xml
plist_string = subprocess.Popen(
['plutil', '-convert', 'xml1', export_fifo, '-o', '-'],
stdout=subprocess.PIPE).stdout.read()
else:
try:
cmd = ['/usr/libexec/PlistBuddy', '-x', '-c', 'print', plist_path]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
plist_string = proc.communicate()[0]
# pylint: disable=broad-except
except Exception:
return None
# parse the xml into a dictionary
user_plist = plistlib.loads(plist_string)
return user_plist
def get_running_processes():
"""Returns a list of paths of running processes"""
proc = subprocess.Popen(['/bin/ps', '-axo' 'comm='],
shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(output, dummy_err) = proc.communicate()
if proc.returncode == 0:
proc_list = [item for item in output.splitlines()
if item.startswith(b'/')]
launchcfmapp = ('/System/Library/Frameworks/Carbon.framework'
'/Versions/A/Support/LaunchCFMApp')
if launchcfmapp in proc_list:
# we have a really old Carbon app
proc = subprocess.Popen(['/bin/ps', '-axwwwo' 'args='],
shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(output, dummy_err) = proc.communicate()
if proc.returncode == 0:
carbon_apps = [item[len(launchcfmapp)+1:]
for item in output.splitlines()
if item.startswith(launchcfmapp)]
if carbon_apps:
proc_list.extend(carbon_apps)
return proc_list
else:
return []
def is_app_running(appname):
"""Tries to determine if the application in appname is currently
running"""
proc_list = get_running_processes()
matching_items = []
if appname.startswith('/'):
# search by exact path
matching_items = [item for item in proc_list
if item == appname]
elif appname.endswith('.app'):
# search by filename
matching_items = [item for item in proc_list
if '/'+ appname + '/Contents/MacOS/' in item]
else:
# check executable name
matching_items = [item for item in proc_list
if item.endswith(bytes('/' + appname, 'utf-8'))]
if not matching_items:
# try adding '.app' to the name and check again
matching_items = [item for item in proc_list
if bytes('/'+ appname + '.app/Contents/MacOS/', 'utf-8') in item]
if matching_items:
# it's running!
return True
# if we get here, we have no evidence that appname is running
return False
def launch_depnotify():
'''Launch DEPNotify'''
dn_path = '/Applications/Utilities/DEPNotify.app'
subprocess.call(['/usr/bin/open', dn_path, '--args', '-munki'])
def kill_depnotify():
'''Kill DEPNotify process'''
subprocess.call(['/usr/bin/killall', 'DEPNotify'])
def main():
'''Launch DEPNotify if IAs didnt do it'''
plist_path = os.path.expanduser(
'~/Library/Preferences/com.apple.dock.plist')
macos_version = get_macos_version()
# If we are modifying the currently logged in user's dock, wait for
# mod-count to be > 1 because dock is still being setup by Apple
if os.stat(plist_path).st_uid == os.stat('/dev/console').st_uid:
plist_to_read = read_plist(plist_path, macos_version)
mod_count = int(plist_to_read.get('mod-count', 0))
seconds_waited = 0
while mod_count < 2 and seconds_waited < 120:
print('Waiting for initial dock setup. mod-count is: %s' % mod_count)
time.sleep(1)
seconds_waited += 1
print('Waited %s seconds so far' % seconds_waited)
plist_to_read = read_plist(plist_path, macos_version)
mod_count = int(plist_to_read.get('mod-count', 0))
if mod_count < 2:
print('Timed out waiting for dock to be setup.')
# Cover both checks since we don't know what OS version will be returned
if macos_version[0] >= 11 or macos_version[1] >= 16:
print('Delaying DEPNotify Launch by 5 seconds due to Big Sur flakiness')
time.sleep(5)
if is_app_running('DEPNotify'):
# Since we no longer use InstallApplications to launch DEPNotify, if
# we are bootstrapping, it is more than likely due to a enrollment
# failure. If a "quit" command is sent to DEPNotify, it will not update
# its status even if the log file is purged. Because of this, we need
# to relaunch DEPNotify so it will refresh.
print('DEPNotify running - relaunching!')
kill_depnotify()
time.sleep(0.5)
launch_depnotify()
else:
print('Launching DEPNotify!')
launch_depnotify()
if __name__ == '__main__':
main()