]>
Commit | Line | Data |
---|---|---|
5958d7c0 | 1 | /* |
009ee3c6 | 2 | * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. |
5958d7c0 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
009ee3c6 A |
5 | * |
6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. | |
7 | * | |
8 | * This file contains Original Code and/or Modifications of Original Code | |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
5958d7c0 A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
009ee3c6 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
22 | * | |
5958d7c0 A |
23 | * @APPLE_LICENSE_HEADER_END@ |
24 | */ | |
25 | ||
0fae82ee A |
26 | /* |
27 | * Modification History | |
28 | * | |
29 | * June 1, 2001 Allan Nathanson <ajn@apple.com> | |
30 | * - public API conversion | |
31 | * | |
32 | * January 1, 2001 Allan Nathanson <ajn@apple.com> | |
33 | * - initial revision | |
34 | */ | |
35 | ||
009ee3c6 | 36 | #include <getopt.h> |
5958d7c0 | 37 | #include <unistd.h> |
009ee3c6 | 38 | #include <sysexits.h> |
5958d7c0 | 39 | |
0fae82ee A |
40 | #include <SystemConfiguration/SystemConfiguration.h> |
41 | #include <SystemConfiguration/SCPrivate.h> | |
42 | ||
5958d7c0 | 43 | |
0fae82ee | 44 | Boolean apply = TRUE; |
5958d7c0 A |
45 | |
46 | ||
009ee3c6 A |
47 | static struct option longopts[] = { |
48 | // { "debug", no_argument, 0, 'd' }, | |
49 | // { "verbose", no_argument, 0, 'v' }, | |
50 | // { "do-not-apply", no_argument, 0, 'n' }, | |
51 | { "help", no_argument, 0, '?' }, | |
52 | { 0, 0, 0, 0 } | |
53 | }; | |
54 | ||
55 | ||
5958d7c0 A |
56 | void |
57 | usage(const char *command) | |
58 | { | |
0fae82ee | 59 | SCPrint(TRUE, stderr, CFSTR("usage: %s [-n] new-set-name\n"), command); |
009ee3c6 | 60 | exit (EX_USAGE); |
5958d7c0 A |
61 | } |
62 | ||
63 | ||
64 | int | |
65 | main(int argc, char **argv) | |
66 | { | |
67 | const char *command = argv[0]; | |
68 | extern int optind; | |
69 | int opt; | |
70 | CFStringRef current = NULL; | |
71 | int currentMatched = 0; | |
72 | CFStringRef newSet = NULL; /* set key */ | |
73 | CFStringRef newSetUDN = NULL; /* user defined name */ | |
74 | CFStringRef prefix; | |
0fae82ee | 75 | SCPreferencesRef session; |
5958d7c0 A |
76 | CFDictionaryRef sets; |
77 | CFIndex nSets; | |
a5f60add A |
78 | const void **setKeys = NULL; |
79 | const void **setVals = NULL; | |
5958d7c0 A |
80 | CFIndex i; |
81 | ||
82 | /* process any arguments */ | |
83 | ||
009ee3c6 | 84 | while ((opt = getopt_long(argc, argv, "dvn", longopts, NULL)) != -1) |
5958d7c0 A |
85 | switch(opt) { |
86 | case 'd': | |
0fae82ee A |
87 | _sc_debug = TRUE; |
88 | _sc_log = FALSE; /* enable framework logging */ | |
5958d7c0 A |
89 | break; |
90 | case 'v': | |
0fae82ee | 91 | _sc_verbose = TRUE; |
5958d7c0 A |
92 | break; |
93 | case 'n': | |
94 | apply = FALSE; | |
95 | break; | |
96 | case '?': | |
97 | default : | |
98 | usage(command); | |
99 | } | |
100 | argc -= optind; | |
101 | argv += optind; | |
102 | ||
103 | prefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("/%@/"), kSCPrefSets); | |
104 | ||
105 | newSet = (argc == 1) | |
106 | ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman) | |
107 | : CFSTR(""); | |
108 | ||
0fae82ee A |
109 | session = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL); |
110 | if (!session) { | |
111 | SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n")); | |
5958d7c0 A |
112 | exit (1); |
113 | } | |
114 | ||
115 | /* check if a full path to the new "set" was specified */ | |
116 | if ((CFStringGetLength(newSet) > 0) && CFStringHasPrefix(newSet, prefix)) { | |
117 | CFRange range; | |
118 | CFMutableStringRef str; | |
119 | ||
120 | str = CFStringCreateMutableCopy(NULL, 0, newSet); | |
121 | CFStringDelete(str, CFRangeMake(0, CFStringGetLength(prefix))); | |
122 | ||
123 | range = CFStringFind(str, CFSTR("/"), 0); | |
124 | if (range.location != kCFNotFound) { | |
0fae82ee | 125 | SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available\n."), newSet); |
5958d7c0 A |
126 | exit (1); |
127 | } | |
128 | ||
129 | CFRelease(newSet); | |
130 | newSet = str; | |
131 | } | |
132 | ||
0fae82ee A |
133 | sets = SCPreferencesGetValue(session, kSCPrefSets); |
134 | if (!sets) { | |
135 | SCPrint(TRUE, stderr, CFSTR("SCPreferencesGetValue(...,%s,...) failed\n")); | |
5958d7c0 A |
136 | exit (1); |
137 | } | |
138 | ||
0fae82ee A |
139 | current = SCPreferencesGetValue(session, kSCPrefCurrentSet); |
140 | if (current) { | |
141 | if (CFStringHasPrefix(current, prefix)) { | |
142 | CFMutableStringRef tmp; | |
143 | ||
144 | tmp = CFStringCreateMutableCopy(NULL, 0, current); | |
145 | CFStringDelete(tmp, CFRangeMake(0, CFStringGetLength(prefix))); | |
146 | current = tmp; | |
147 | } else { | |
148 | currentMatched = -1; /* not prefixed */ | |
149 | } | |
150 | } else { | |
151 | current = CFSTR(""); | |
152 | currentMatched = -2; /* not defined */ | |
5958d7c0 A |
153 | } |
154 | ||
155 | nSets = CFDictionaryGetCount(sets); | |
a5f60add A |
156 | if (nSets > 0) { |
157 | setKeys = CFAllocatorAllocate(NULL, nSets * sizeof(CFStringRef), 0); | |
158 | setVals = CFAllocatorAllocate(NULL, nSets * sizeof(CFDictionaryRef), 0); | |
159 | CFDictionaryGetKeysAndValues(sets, setKeys, setVals); | |
160 | } | |
5958d7c0 A |
161 | |
162 | /* check for set with matching name */ | |
009ee3c6 | 163 | for (i = 0; i < nSets; i++) { |
5958d7c0 A |
164 | CFStringRef key = (CFStringRef) setKeys[i]; |
165 | CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; | |
166 | ||
167 | if ((currentMatched >= 0) && CFEqual(key, current)) { | |
168 | currentMatched++; | |
169 | } | |
170 | ||
171 | if (CFEqual(newSet, key)) { | |
172 | newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName); | |
173 | if (newSetUDN) CFRetain(newSetUDN); | |
174 | current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet); | |
175 | goto found; | |
176 | } | |
177 | } | |
178 | ||
179 | /* check for set with matching user-defined name */ | |
009ee3c6 | 180 | for (i = 0; i < nSets; i++) { |
5958d7c0 A |
181 | CFStringRef key = (CFStringRef) setKeys[i]; |
182 | CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; | |
183 | ||
184 | newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName); | |
185 | if ((newSetUDN != NULL) && CFEqual(newSet, newSetUDN)) { | |
186 | CFRelease(newSet); | |
187 | newSet = CFRetain(key); | |
188 | CFRetain(newSetUDN); | |
189 | current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet); | |
190 | goto found; | |
191 | } | |
192 | } | |
193 | ||
009ee3c6 A |
194 | if (argc == 1) { |
195 | SCPrint(TRUE, stderr, CFSTR("Set \"%@\" not available.\n\n"), newSet); | |
5958d7c0 A |
196 | } |
197 | ||
0fae82ee A |
198 | SCPrint(TRUE, stderr, |
199 | CFSTR("Defined sets include:%s\n"), | |
200 | (currentMatched > 0) ? " (* == current set)" : ""); | |
5958d7c0 | 201 | |
009ee3c6 | 202 | for (i = 0; i < nSets; i++) { |
5958d7c0 A |
203 | CFStringRef key = (CFStringRef) setKeys[i]; |
204 | CFDictionaryRef dict = (CFDictionaryRef)setVals[i]; | |
205 | CFStringRef udn = CFDictionaryGetValue(dict, kSCPropUserDefinedName); | |
206 | ||
0fae82ee A |
207 | SCPrint(TRUE, stderr, |
208 | CFSTR(" %s %@\t(%@)\n"), | |
5958d7c0 A |
209 | ((currentMatched > 0) && CFEqual(key, current)) ? "*" : " ", |
210 | key, | |
211 | udn ? udn : CFSTR("")); | |
212 | } | |
213 | ||
214 | switch (currentMatched) { | |
215 | case -2 : | |
0fae82ee | 216 | SCPrint(TRUE, stderr, CFSTR("\nCurrentSet not defined.\n")); |
5958d7c0 A |
217 | break; |
218 | case -1 : | |
0fae82ee | 219 | SCPrint(TRUE, stderr, CFSTR("\nCurrentSet \"%@\" may not be valid\n"), current); |
5958d7c0 A |
220 | break; |
221 | case 0 : | |
0fae82ee | 222 | SCPrint(TRUE, stderr, CFSTR("\nCurrentSet \"%@\" not valid\n"), current); |
5958d7c0 A |
223 | break; |
224 | default : | |
225 | break; | |
226 | } | |
227 | ||
228 | exit (1); | |
229 | ||
230 | found : | |
231 | ||
0fae82ee A |
232 | if (!SCPreferencesSetValue(session, kSCPrefCurrentSet, current)) { |
233 | SCPrint(TRUE, stderr, | |
234 | CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"), | |
5958d7c0 | 235 | kSCPrefCurrentSet, |
0fae82ee | 236 | current); |
5958d7c0 A |
237 | exit (1); |
238 | } | |
239 | ||
0fae82ee A |
240 | if (!SCPreferencesCommitChanges(session)) { |
241 | SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n")); | |
5958d7c0 A |
242 | exit (1); |
243 | } | |
244 | ||
245 | if (apply) { | |
0fae82ee A |
246 | if (!SCPreferencesApplyChanges(session)) { |
247 | SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n")); | |
5958d7c0 A |
248 | exit (1); |
249 | } | |
250 | } | |
251 | ||
0fae82ee | 252 | CFRelease(session); |
5958d7c0 | 253 | |
0fae82ee A |
254 | SCPrint(TRUE, stdout, |
255 | CFSTR("%@ updated to %@ (%@)\n"), | |
5958d7c0 A |
256 | kSCPrefCurrentSet, |
257 | newSet, | |
258 | newSetUDN ? newSetUDN : CFSTR("")); | |
259 | ||
260 | exit (0); | |
261 | return 0; | |
262 | } |