11#! /usr/bin/env bash
22
3- # set -e
4- # set -x
5-
63startup_dirs=(/Library/LaunchAgents /Library/LaunchDaemons ~ /Library/LaunchAgents ~ /Library/LaunchDaemons)
74system_dirs=(/System/Library/LaunchAgents /System/Library/LaunchDaemons)
85
@@ -12,6 +9,10 @@ YELLOW='\033[1;33m'
129NC=' \033[0m'
1310BOLD=' \033[1m'
1411
12+ #
13+ # --------------------------------------------------------------------------------------------------------------------------------------
14+ #
15+
1516function join_by { local IFS=" $1 " ; shift ; echo " $* " ; }
1617
1718function usage {
@@ -50,7 +51,182 @@ function getScriptUser {
5051 grep ' <key>UserName</key>' -C1 " $scriptPath " | tail -n1 | cut -d ' >' -f 2 | cut -d ' <' -f 1
5152}
5253
53- function listItems {
54+ function getKernelExtensions {
55+ kmutil showloaded --no-kernel-components --list-only --sort --show loaded 2> /dev/null | tr -s ' ' | grep -v ' com\.apple\.'
56+ }
57+
58+ function listKernelExtensions {
59+ local filter=" $1 "
60+
61+ getKernelExtensions | while IFS= read -r kextLine; do
62+
63+ kextLoaded=" $( echo " $kextLine " | cut -d ' ' -f 3) "
64+ kextName=" $( echo " $kextLine " | cut -d ' ' -f 7) "
65+ kextVersion=" $( echo " $kextLine " | grep -o ' \((.*)\)' ) "
66+
67+ if [ " $filter " == " disabled" ] && [ " $kextLoaded " != " 0" ]; then
68+ continue
69+ fi
70+
71+ if [ " $filter " == " enabled" ] && [ " $kextLoaded " == " 0" ]; then
72+ continue
73+ fi
74+
75+ if [ -n " $filter " ] && [ " $filter " != " system" ] && [ " $filter " != " enabled" ] && [ " $filter " != " disabled" ]; then
76+ if [[ " $kextName " != * " $filter " * ]]; then
77+ continue
78+ fi
79+ fi
80+
81+ kernelPath=" $( kextfind -system-extensions " $kextName " 2> /dev/null) "
82+ if [ -z " $kernelPath " ]; then
83+ kernelPath=" n/a"
84+ fi
85+
86+ local loaded
87+ if [ " $kextLoaded " == " 0" ]; then
88+ loaded=" ${GREEN}${BOLD} disabled${NC} "
89+ else
90+ loaded=" ${RED} Always${NC} "
91+ fi
92+
93+ echo -e " ${BOLD} > ${kextName}${NC} ${kextVersion} "
94+ echo -e " Type : ${RED} kernel extension${NC} "
95+ echo -e " User : ${RED} root${NC} "
96+ echo -e " Launch: ${loaded} "
97+ echo " File : ${kernelPath} "
98+
99+ done
100+ }
101+
102+ function disableKernelExtensions {
103+ local filter=" $1 "
104+
105+ getKernelExtensions | while IFS= read -r kextLine; do
106+
107+ kextLoaded=" $( echo " $kextLine " | cut -d ' ' -f 3) "
108+ kextName=" $( echo " $kextLine " | cut -d ' ' -f 7) "
109+
110+ if ! [[ " $kextName " =~ $filter ]]; then
111+ continue
112+ fi
113+
114+ if [ " $kextLoaded " == " 0" ]; then
115+ # error "kernel extension is already unloaded"
116+ continue
117+ fi
118+
119+ if ! kmutil load -b " $kextName " 1> /dev/null; then
120+ error " could not disable kernel extension"
121+ fi
122+
123+ echo -e " ${GREEN} Disabled ${STRONG}${kextName}${NC} "
124+ done
125+ }
126+
127+ function enableKernelExtensions {
128+ local filter=" $1 "
129+
130+ getKernelExtensions | while IFS= read -r kextLine; do
131+
132+ kextLoaded=" $( echo " $kextLine " | cut -d ' ' -f 3) "
133+ kextName=" $( echo " $kextLine " | cut -d ' ' -f 7) "
134+
135+ if ! [[ " $kextName " =~ $filter ]]; then
136+ continue
137+ fi
138+
139+ if ! [ " $kextLoaded " == " 0" ]; then
140+ # error "kernel extension is already loaded"
141+ continue
142+ fi
143+
144+ if ! kmutil unload -b " $kextName " 1> /dev/null; then
145+ error " could not disable kernel extension"
146+ fi
147+
148+ echo -e " ${GREEN} Enabled ${STRONG}${kextName}${NC} "
149+ done
150+ }
151+
152+ function getSystemExtensions {
153+ systemextensionsctl list 2> /dev/null | tail -n+2 | grep -v ' ^---' | grep -v ' ^enabled' | tr -s ' '
154+ }
155+
156+ function listSystemExtensions {
157+ local filter=" $1 "
158+
159+ getSystemExtensions | while IFS= read -r extLine; do
160+
161+ fullName=" $( echo " $extLine " | cut -d$' \t ' -f 4) "
162+ extName=" $( echo " $fullName " | cut -d ' ' -f 1) "
163+ extVersion=" $( echo " $fullName " | grep -o ' \((.*)\)' ) "
164+
165+ if [ -n " $filter " ] && ! [[ " $extName " =~ $filter ]]; then
166+ continue
167+ fi
168+
169+ local loaded
170+ if [ " $( echo " $extLine " | cut -d$' \t ' -f 2) " == " *" ]; then
171+ loaded=" ${ORANGE} enabled${NC} "
172+ else
173+ loaded=" ${GREEN} disabled${NC} "
174+ fi
175+
176+ echo -e " ${BOLD} > ${extName}${NC} ${extVersion} "
177+ echo -e " Type : system extension"
178+ echo -e " User : $( whoami) "
179+ echo -e " Launch: ${loaded} "
180+ echo " File : n/a"
181+ done
182+ }
183+
184+ function enableSystemExtensions {
185+ local filter=" $1 "
186+
187+ getSystemExtensions | while IFS= read -r extLine; do
188+
189+ extName=" $( echo " $extLine " | cut -d$' \t ' -f 4 | cut -d ' ' -f 1) "
190+
191+ if ! [[ " $extName " =~ $filter ]]; then
192+ continue
193+ fi
194+
195+ if [ " $( echo " $extLine " | cut -d$' \t ' -f 2) " == " *" ]; then
196+ # error "this system extension is already enabled"
197+ continue
198+ fi
199+
200+ # TODO: implement load system extension via CLI
201+ error " enabling system extensions is not yet implemented"
202+ done
203+ }
204+
205+ function disableSystemExtensions {
206+ local filter=" $1 "
207+
208+ getSystemExtensions | while IFS= read -r extLine; do
209+
210+ extName=" $( echo " $extLine " | cut -d$' \t ' -f 4 | cut -d ' ' -f 1) "
211+
212+ if ! [[ " $extName " =~ $filter ]]; then
213+ continue
214+ fi
215+
216+ if ! [ " $( echo " $extLine " | cut -d$' \t ' -f 2) " == " *" ]; then
217+ # error "this system extension is already disabled"
218+ continue
219+ fi
220+
221+ if ! systemextensionsctl uninstall ' -' " $extName " ; then
222+ error " could not disable system extension"
223+ fi
224+
225+ echo -e " ${GREEN} Enabled ${STRONG}${extName}${NC} "
226+ done
227+ }
228+
229+ function listLaunchItems {
54230 local filter=" $2 "
55231
56232 itemDirectories=(" ${startup_dirs[@]} " )
@@ -186,7 +362,7 @@ function listItems {
186362 done< <( find " ${itemDirectories[@]} " -type f -iname ' *.plist*' -print0 2> /dev/null)
187363}
188364
189- function enableItems {
365+ function enableLaunchItems {
190366 disabled_items=" $( launchctl print-disabled user/" $( id -u) " ) "
191367
192368 while IFS= read -r -d ' ' startupFile; do
@@ -220,7 +396,7 @@ function enableItems {
220396 done< <( find " ${startup_dirs[@]} " " ${system_dirs[@]} " \( -iname " *$1 *.plist" -o -iname " *$1 *.plist.disabled" \) -print0 2> /dev/null)
221397}
222398
223- function disableItems {
399+ function disableLaunchItems {
224400 disabled_items=" $( launchctl print-disabled user/" $( id -u) " ) "
225401
226402 while IFS= read -r -d ' ' startupFile; do
@@ -254,6 +430,10 @@ function disableItems {
254430 done< <( find " ${startup_dirs[@]} " " ${system_dirs[@]} " \( -iname " *$1 *.plist" -o -iname " *$1 *.plist.disabled" \) -print0 2> /dev/null)
255431}
256432
433+ #
434+ # --------------------------------------------------------------------------------------------------------------------------------------
435+ #
436+
257437if [ $# -lt 1 ] || [ $# -gt 2 ]; then
258438 usage
259439fi
@@ -265,20 +445,29 @@ case "$1" in
265445 usage
266446 fi
267447 fi
268- listItems " $1 " " $2 "
448+ listLaunchItems " $1 " " $2 "
449+ listKernelExtensions " $2 "
450+ listSystemExtensions " $2 "
269451 ;;
452+
270453 " disable" )
271454 if [ $# -ne 2 ]; then
272455 usage
273456 fi
274- disableItems " $2 "
457+ disableLaunchItems " $2 "
458+ disableKernelExtensions " $2 "
459+ disableSystemExtensions " $2 "
275460 ;;
461+
276462 " enable" )
277463 if [ $# -ne 2 ]; then
278464 usage
279465 fi
280- enableItems " $2 "
466+ enableLaunchItems " $2 "
467+ enableKernelExtensions " $2 "
468+ enableSystemExtensions " $2 "
281469 ;;
470+
282471 * )
283472 usage
284473 ;;
0 commit comments