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