1+ #! /bin/bash
2+
3+ # # region ############################################## Static Variables
4+
5+ binDefaults=" /usr/bin/defaults"
6+ binReload=" /System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings"
7+ version=" 1.0"
8+
9+ # # endregion ########################################### End Static Variables
10+
11+ # # region ############################################## Functions
12+
13+ function normalizeValue() {
14+ local val
15+
16+ val=$1
17+
18+ case " $val " in
19+ 1 | yes | TRUE | True | true ) val=" -bool true" ;;
20+ 0 | no | FALSE | False | false ) val=" -bool false" ;;
21+ esac
22+
23+ echo " $val " && return 0
24+ }
25+
26+ function output::usage() {
27+ local help
28+ help=$( defaults help)
29+ echo " $help " | tail -n + 1 | head -n 2
30+ echo " Command line interface to a specific user's defaults. Automatically refreshes defaults after writing."
31+ echo " Syntax:"
32+ echo " "
33+ echo " 'defaults-user' -version Displays the version number"
34+ echo " 'defaults-user' -help Displays this help"
35+ echo " 'defaults-user' [ -currentHost | -host <hostname> ] [ -user <username> ] [ -quiet ] followed by one of the following:"
36+ echo " "
37+ echo " $help " | tail -n +6 | head -n 22
38+ echo " <user> is a valid macOS user. If not specified, the currently logged in console user will be used."
39+ echo " Exits with an error if no user is specified and no user is logged in."
40+ echo " "
41+ echo " $help " | tail -n +28
42+ echo " "
43+ echo " If no value type is specified, the -bool flag is automatically added for boolean-like values."
44+ echo " "
45+ }
46+
47+ function output::version() {
48+ echo " user-defaults v${version} "
49+ }
50+
51+ # /*!
52+ # Public: Shows the username of the current console user, if any is logged in.
53+ # */
54+ function user::console() {
55+ echo " show State:/Users/ConsoleUser" | /usr/sbin/scutil | /usr/bin/awk ' /Name :/ && ! /loginwindow/ { print $3 }'
56+ }
57+
58+
59+ function _isJamf() {
60+ local cName firstCharFirstArg
61+ cName=$( /usr/sbin/scutil --get ComputerName)
62+ firstCharFirstArg=$( /usr/bin/printf ' %s' " $1 " | /usr/bin/cut -c 1)
63+ if [ " $firstCharFirstArg " == " /" ] && [ " $2 " == " $cName " ]; then
64+ return 0
65+ else
66+ return 1
67+ fi
68+ }
69+
70+ # # endregion ########################################### End Functions
71+
72+ # # region ############################################## Jamf Detection & Argument Shifting
73+
74+ if _isJamf " $@ " ; then
75+ # shellcheck disable=SC2034
76+ jamfMountPoint=" $1 "
77+ # shellcheck disable=SC2034
78+ jamfHostName=" $2 "
79+ # shellcheck disable=SC2034
80+ jamfUser=" $3 "
81+ targetUser=" $jamfUser "
82+ # Remove Jamf Arguments
83+ shift 3
84+ # Blank first Output Line for Prettier Jamf Logs
85+ echo " "
86+ fi
87+
88+ # # endregion ########################################### End Jamf Detection and Arg Shifting
89+
90+ # # region ############################################## Argument Handling
91+
92+ isQuiet=false
93+ isType=false
94+ args=()
95+ while [ " $1 " != " " ]; do
96+ # See if user specified a type
97+ case " $1 " in
98+ -string | -data | -int | -integer | -float | -bool | -boolean | -date ) isType=true; isSingle=true ;;
99+ -array | -array-add | -dict | -dict-add ) isType=true; isSingle=false ;;
100+ esac
101+
102+ # Check for our added flags
103+ case " $1 " in
104+ -u | -user | --user ) targetUser=" $2 " ; shift ;;
105+ -q | -quiet | --quiet ) isQuiet=true; ;;
106+ -currentHost ) host=" current" ; ;;
107+ -host ) host=" $2 " ; shift ;;
108+ -h | --help | help ) output::usage; exit ;; # quit and show usage
109+ --version ) output::version; exit ;; # quit and show usage
110+ * ) args+=(" $1 " ) # if no match, add it to the positional args
111+ esac
112+ shift # move to next kv pair
113+ done
114+
115+ # # endregion ########################################### End Argument Handling
116+
117+ # # region ############################################## Main Code
118+
119+ prefix=" sudo -u $targetUser "
120+ action=" ${args[0]} "
121+
122+ if [ " $action " == " write" ] && $isSingle ; then
123+ # Get Particulars
124+ domain=" ${args[1]} "
125+ key=" ${args[2]} "
126+ if $isType ; then
127+ type=" ${args[3]} "
128+ value=" ${args[4]} "
129+ else
130+ type=" "
131+ value=$( normalizeValue " ${args[3]} " )
132+ fi
133+
134+ # Normalize Domain
135+ if [ " $domain " == " .GlobalPreferences" ]; then
136+ domain=" -g"
137+ fi
138+
139+ command=(" $prefix " " $binDefaults " " write" " $host " " $domain " " $key " " $type " " $value " )
140+ else
141+ # Here we are just prefixing
142+ command=(" $prefix " " $binDefaults " " $host " )
143+ for arg in " ${args[@]} "
144+ do
145+ command+=(" $arg " )
146+ done
147+ fi
148+
149+ # Build the normalized command
150+ commandStr=" "
151+ for part in " ${command[@]} " ; do
152+ if [ -n " $part " ]; then
153+ if [ -n " $commandStr " ]; then
154+ commandStr=" $commandStr $part "
155+ else
156+ commandStr=" $part "
157+ fi
158+ fi
159+ done
160+
161+ # Output if Applicable
162+ if $isQuiet ; then
163+ if $commandStr /dev/null 2>&1 ; then
164+ if echo " $action " | grep -q ' write\|array\|array-add\|dict\|dict-add' ; then
165+ $prefix $binReload -u
166+ fi
167+
168+ exit 0
169+ fi
170+ else
171+ if $commandStr ; then
172+ if echo " $action " | grep -q ' write\|array\|array-add\|dict\|dict-add' ; then
173+ $prefix $binReload -u
174+ fi
175+
176+ exit 0
177+ else
178+ exit $?
179+ fi
180+ fi
181+
182+ # # endregion ########################################### End Main Code
0 commit comments