2 * Copyright (c) 2000-2009, 2011, 2012, 2014 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * January 15, 2004 Allan Nathanson <ajn@apple.com>
28 * - limit location changes to "root" (uid==0), users who are
29 * a member of group "admin", and processses which have access
30 * to a local graphics console.
32 * June 1, 2001 Allan Nathanson <ajn@apple.com>
33 * - public API conversion
35 * January 1, 2001 Allan Nathanson <ajn@apple.com>
42 #include <sys/param.h>
43 #include <sys/types.h>
48 #include <SystemConfiguration/SystemConfiguration.h>
49 #include <SystemConfiguration/SCPrivate.h>
52 #include <Security/Authorization.h>
53 #endif /* !TARGET_OS_IPHONE */
56 static Boolean apply
= TRUE
;
59 static const struct option longopts
[] = {
60 // { "debug", no_argument, 0, 'd' },
61 // { "verbose", no_argument, 0, 'v' },
62 // { "do-not-apply", no_argument, 0, 'n' },
63 { "help", no_argument
, 0, '?' },
69 usage(const char *command
)
71 SCPrint(TRUE
, stderr
, CFSTR("usage: %s [-n] new-set-name\n"), command
);
77 main(int argc
, char **argv
)
79 const char *command
= argv
[0];
82 CFStringRef current
= NULL
;
83 int currentMatched
= 0;
84 CFStringRef newSet
= NULL
; /* set key */
85 CFStringRef newSetUDN
= NULL
; /* user defined name */
87 SCPreferencesRef prefs
;
90 const void **setKeys
= NULL
;
91 const void **setVals
= NULL
;
95 AuthorizationRef authorization
= NULL
;
96 AuthorizationFlags flags
= kAuthorizationFlagDefaults
;
97 CFMutableDictionaryRef options
;
99 #endif // !TARGET_OS_IPHONE
101 /* process any arguments */
103 while ((opt
= getopt_long(argc
, argv
, "dvn", longopts
, NULL
)) != -1) {
107 _sc_log
= FALSE
; /* enable framework logging */
123 prefix
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("/%@/"), kSCPrefSets
);
126 newSet
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingMacRoman
);
128 /* check if a full path to the new "set" was specified */
129 if ((CFStringGetLength(newSet
) > 0) && CFStringHasPrefix(newSet
, prefix
)) {
131 CFMutableStringRef str
;
133 str
= CFStringCreateMutableCopy(NULL
, 0, newSet
);
136 CFStringDelete(str
, CFRangeMake(0, CFStringGetLength(prefix
)));
137 newSet
= CFStringCreateCopy(NULL
, newSet
);
140 range
= CFStringFind(newSet
, CFSTR("/"), 0);
141 if (range
.location
!= kCFNotFound
) {
142 SCPrint(TRUE
, stderr
, CFSTR("Set \"%@\" not available\n."), newSet
);
147 newSet
= CFRetain(CFSTR(""));
150 #if !TARGET_OS_IPHONE
151 status
= AuthorizationCreate(NULL
,
152 kAuthorizationEmptyEnvironment
,
155 if (status
!= errAuthorizationSuccess
) {
158 CFSTR("AuthorizationCreate() failed: status = %d\n"),
163 options
= CFDictionaryCreateMutable(NULL
,
165 &kCFTypeDictionaryKeyCallBacks
,
166 &kCFTypeDictionaryValueCallBacks
);
167 CFDictionarySetValue(options
, kSCPreferencesOptionChangeNetworkSet
, kCFBooleanTrue
);
168 prefs
= SCPreferencesCreateWithOptions(NULL
, CFSTR("scselect"), NULL
, authorization
, options
);
171 SCPrint(TRUE
, stderr
, CFSTR("SCPreferencesCreate() failed\n"));
174 #else // !TARGET_OS_IPHONE
175 prefs
= SCPreferencesCreate(NULL
, CFSTR("scselect"), NULL
);
177 SCPrint(TRUE
, stderr
, CFSTR("SCPreferencesCreate() failed\n"));
180 #endif // !TARGET_OS_IPHONE
182 sets
= SCPreferencesGetValue(prefs
, kSCPrefSets
);
184 SCPrint(TRUE
, stderr
, CFSTR("No network sets defined.\n"));
188 current
= SCPreferencesGetValue(prefs
, kSCPrefCurrentSet
);
189 if (current
!= NULL
) {
190 if (CFStringHasPrefix(current
, prefix
)) {
191 CFMutableStringRef tmp
;
193 tmp
= CFStringCreateMutableCopy(NULL
, 0, current
);
194 CFStringDelete(tmp
, CFRangeMake(0, CFStringGetLength(prefix
)));
198 currentMatched
= -1; /* not prefixed */
201 current
= CFRetain(CFSTR(""));
202 currentMatched
= -2; /* not defined */
205 nSets
= CFDictionaryGetCount(sets
);
207 setKeys
= CFAllocatorAllocate(NULL
, nSets
* sizeof(CFStringRef
), 0);
208 setVals
= CFAllocatorAllocate(NULL
, nSets
* sizeof(CFDictionaryRef
), 0);
209 CFDictionaryGetKeysAndValues(sets
, setKeys
, setVals
);
212 /* check for set with matching name */
213 for (i
= 0; i
< nSets
; i
++) {
214 CFStringRef key
= (CFStringRef
) setKeys
[i
];
215 CFDictionaryRef dict
= (CFDictionaryRef
)setVals
[i
];
217 if ((currentMatched
>= 0) && CFEqual(key
, current
)) {
221 if (CFEqual(newSet
, key
)) {
222 newSetUDN
= CFDictionaryGetValue(dict
, kSCPropUserDefinedName
);
223 if (newSetUDN
!= NULL
) CFRetain(newSetUDN
);
228 /* check for set with matching user-defined name */
229 for (i
= 0; i
< nSets
; i
++) {
230 CFStringRef key
= (CFStringRef
) setKeys
[i
];
231 CFDictionaryRef dict
= (CFDictionaryRef
)setVals
[i
];
233 newSetUDN
= CFDictionaryGetValue(dict
, kSCPropUserDefinedName
);
234 if ((newSetUDN
!= NULL
) && CFEqual(newSet
, newSetUDN
)) {
236 newSet
= CFRetain(key
);
243 SCPrint(TRUE
, stderr
, CFSTR("Set \"%@\" not available.\n"), newSet
);
247 SCPrint(TRUE
, stdout
,
248 CFSTR("Defined sets include:%s\n"),
249 (currentMatched
> 0) ? " (* == current set)" : "");
251 for (i
= 0; i
< nSets
; i
++) {
252 CFStringRef key
= (CFStringRef
) setKeys
[i
];
253 CFDictionaryRef dict
= (CFDictionaryRef
)setVals
[i
];
254 CFStringRef udn
= CFDictionaryGetValue(dict
, kSCPropUserDefinedName
);
256 SCPrint(TRUE
, stdout
,
257 CFSTR(" %s %@\t(%@)\n"),
258 ((currentMatched
> 0) && CFEqual(key
, current
)) ? "*" : " ",
260 udn
? udn
: CFSTR(""));
263 switch (currentMatched
) {
265 SCPrint(TRUE
, stdout
, CFSTR("\nCurrent set not defined.\n"));
268 SCPrint(TRUE
, stdout
, CFSTR("\nCurrent set \"%@\" may not be valid\n"), current
);
271 SCPrint(TRUE
, stdout
, CFSTR("\nCurrent set \"%@\" not valid\n"), current
);
283 current
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%@"), prefix
, newSet
);
285 if (!SCPreferencesSetValue(prefs
, kSCPrefCurrentSet
, current
)) {
286 SCPrint(TRUE
, stderr
,
287 CFSTR("SCPreferencesSetValue(...,%@,%@) failed: %s\n"),
290 SCErrorString(SCError()));
294 if (!SCPreferencesCommitChanges(prefs
)) {
295 int sc_status
= SCError();
297 if (sc_status
== kSCStatusAccessError
) {
298 SCPrint(TRUE
, stderr
,
299 CFSTR("Only local console users and administrators can change locations\n"));
302 SCPrint(TRUE
, stderr
,
303 CFSTR("SCPreferencesCommitChanges() failed: %s\n"),
304 SCErrorString(sc_status
));
310 if (!SCPreferencesApplyChanges(prefs
)) {
311 SCPrint(TRUE
, stderr
,
312 CFSTR("SCPreferencesApplyChanges() failed %s\n"),
313 SCErrorString(SCError()));
318 SCPrint(TRUE
, stdout
,
319 CFSTR("%@ updated to %@ (%@)\n"),
322 newSetUDN
? newSetUDN
: CFSTR(""));
326 if (newSetUDN
!= NULL
) CFRelease(newSetUDN
);
330 #if !TARGET_OS_IPHONE
331 AuthorizationFree(authorization
, kAuthorizationFlagDefaults
);
332 // AuthorizationFree(authorization, kAuthorizationFlagDestroyRights);
333 #endif /* !TARGET_OS_IPHONE */