]>
Commit | Line | Data |
---|---|---|
5958d7c0 | 1 | /* |
78403150 | 2 | * Copyright (c) 2000-2014 Apple Inc. All rights reserved. |
5958d7c0 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
78403150 | 5 | * |
009ee3c6 A |
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 | |
11 | * file. | |
78403150 | 12 | * |
009ee3c6 A |
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 | |
5958d7c0 A |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
009ee3c6 A |
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. | |
78403150 | 20 | * |
5958d7c0 A |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ | |
23 | ||
0fae82ee A |
24 | /* |
25 | * Modification History | |
26 | * | |
edebe297 A |
27 | * June 13, 2005 Allan Nathanson <ajn@apple.com> |
28 | * - added SCPreferences support | |
29 | * | |
dbf6a266 A |
30 | * August 4, 2004 Allan Nathanson <ajn@apple.com> |
31 | * - added network configuration (prefs) support | |
32 | * | |
009ee3c6 A |
33 | * September 25, 2002 Allan Nathanson <ajn@apple.com> |
34 | * - added command line history & editing | |
35 | * | |
0fae82ee A |
36 | * July 9, 2001 Allan Nathanson <ajn@apple.com> |
37 | * - added "-r" option for checking network reachability | |
38 | * - added "-w" option to check/wait for the presence of a | |
39 | * dynamic store key. | |
40 | * | |
41 | * June 1, 2001 Allan Nathanson <ajn@apple.com> | |
42 | * - public API conversion | |
43 | * | |
44 | * November 9, 2000 Allan Nathanson <ajn@apple.com> | |
45 | * - initial revision | |
46 | */ | |
47 | ||
6bb65964 | 48 | #include <TargetConditionals.h> |
5958d7c0 | 49 | #include <ctype.h> |
009ee3c6 | 50 | #include <getopt.h> |
5958d7c0 A |
51 | #include <stdio.h> |
52 | #include <stdlib.h> | |
53 | #include <string.h> | |
009ee3c6 | 54 | #include <termios.h> |
5958d7c0 A |
55 | #include <unistd.h> |
56 | #include <sysexits.h> | |
57 | ||
58 | #ifdef DEBUG | |
59 | #include <mach/mach.h> | |
60 | #include <mach/mach_error.h> | |
61 | #endif /* DEBUG */ | |
62 | ||
63 | #include "scutil.h" | |
5958d7c0 A |
64 | #include "commands.h" |
65 | #include "dictionary.h" | |
dbf6a266 | 66 | #include "net.h" |
6bb65964 | 67 | #include "nc.h" |
009ee3c6 | 68 | #include "prefs.h" |
dbf6a266 A |
69 | #include "session.h" |
70 | #include "tests.h" | |
0fae82ee | 71 | |
5958d7c0 | 72 | |
78403150 | 73 | #define LINE_LENGTH 2048 |
5958d7c0 | 74 | |
0fae82ee | 75 | |
edebe297 | 76 | __private_extern__ AuthorizationRef authorization = NULL; |
dbf6a266 | 77 | __private_extern__ InputRef currentInput = NULL; |
d0784775 | 78 | __private_extern__ Boolean doDispatch = FALSE; |
dbf6a266 A |
79 | __private_extern__ int nesting = 0; |
80 | __private_extern__ CFRunLoopRef notifyRl = NULL; | |
81 | __private_extern__ CFRunLoopSourceRef notifyRls = NULL; | |
82 | __private_extern__ SCPreferencesRef prefs = NULL; | |
83 | __private_extern__ SCDynamicStoreRef store = NULL; | |
84 | __private_extern__ CFPropertyListRef value = NULL; | |
85 | __private_extern__ CFMutableArrayRef watchedKeys = NULL; | |
86 | __private_extern__ CFMutableArrayRef watchedPatterns = NULL; | |
009ee3c6 | 87 | |
dbf6a266 | 88 | static const struct option longopts[] = { |
009ee3c6 | 89 | // { "debug", no_argument, NULL, 'd' }, |
d0784775 | 90 | // { "dispatch", no_argument, NULL, 'D' }, |
009ee3c6 A |
91 | // { "verbose", no_argument, NULL, 'v' }, |
92 | // { "SPI", no_argument, NULL, 'p' }, | |
dbf6a266 | 93 | // { "check-reachability", required_argument, NULL, 'r' }, |
009ee3c6 A |
94 | // { "timeout", required_argument, NULL, 't' }, |
95 | // { "wait-key", required_argument, NULL, 'w' }, | |
d0784775 | 96 | // { "watch-reachability", no_argument, NULL, 'W' }, |
dbf6a266 | 97 | { "dns", no_argument, NULL, 0 }, |
009ee3c6 | 98 | { "get", required_argument, NULL, 0 }, |
78403150 | 99 | { "error", required_argument, NULL, 0 }, |
009ee3c6 | 100 | { "help", no_argument, NULL, '?' }, |
17d3ee29 | 101 | { "nc", required_argument, NULL, 0 }, |
dbf6a266 | 102 | { "net", no_argument, NULL, 0 }, |
17d3ee29 | 103 | { "nwi", no_argument, NULL, 0 }, |
edebe297 | 104 | { "prefs", no_argument, NULL, 0 }, |
dbf6a266 | 105 | { "proxy", no_argument, NULL, 0 }, |
5e9ce69e | 106 | { "renew", required_argument, NULL, 0 }, |
009ee3c6 | 107 | { "set", required_argument, NULL, 0 }, |
17d3ee29 A |
108 | { "snapshot", no_argument, NULL, 0 }, |
109 | { "user", required_argument, NULL, 0 }, | |
110 | { "password", required_argument, NULL, 0 }, | |
111 | { "secret", required_argument, NULL, 0 }, | |
5e9ce69e | 112 | { "log", required_argument, NULL, 0 }, |
9de8ab86 | 113 | { "disable-until-needed", no_argument, NULL, 0 }, |
dbf6a266 | 114 | { NULL, 0, NULL, 0 } |
009ee3c6 | 115 | }; |
5958d7c0 A |
116 | |
117 | ||
6bb65964 A |
118 | __private_extern__ |
119 | CFStringRef | |
5e9ce69e | 120 | _copyStringFromSTDIN(CFStringRef prompt, CFStringRef defaultValue) |
6bb65964 A |
121 | { |
122 | char buf[1024]; | |
5e9ce69e A |
123 | int i; |
124 | Boolean is_user_prompt = (prompt != NULL && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)); | |
78403150 | 125 | int len; |
5e9ce69e | 126 | char *modbuf; |
78403150 | 127 | int modlen; |
6bb65964 A |
128 | CFStringRef utf8; |
129 | ||
5e9ce69e A |
130 | /* Print out a prompt to user that entry is desired */ |
131 | if (is_user_prompt) { | |
132 | if (defaultValue != NULL) { | |
133 | SCPrint(TRUE, stdout, CFSTR("%@ [%@]: "), prompt, defaultValue); | |
134 | } else { | |
135 | SCPrint(TRUE, stdout, CFSTR("%@: "), prompt); | |
136 | } | |
137 | } | |
138 | ||
139 | /* Get user input */ | |
6bb65964 A |
140 | if (fgets(buf, sizeof(buf), stdin) == NULL) { |
141 | return NULL; | |
142 | } | |
143 | ||
5e9ce69e | 144 | /* Prepare for trim */ |
78403150 | 145 | len = (int)strlen(buf); |
5e9ce69e A |
146 | modbuf = buf; |
147 | modlen = len; | |
148 | ||
149 | /* Trim new-line */ | |
150 | if ((modlen > 0) && (modbuf[modlen - 1] == '\n')) { | |
151 | modbuf[modlen - 1] = '\0'; | |
152 | modlen--; | |
153 | } | |
154 | ||
155 | /* If nothing was entered at the user prompt, set default */ | |
156 | if (is_user_prompt && defaultValue != NULL && modlen == 0) { | |
157 | CFRetain(defaultValue); | |
158 | return defaultValue; | |
6bb65964 A |
159 | } |
160 | ||
5e9ce69e A |
161 | /* Trim spaces from front */ |
162 | while (modlen > 0 && isspace(modbuf[0])) { | |
163 | modbuf = &modbuf[1]; | |
164 | modlen--; | |
165 | } | |
166 | ||
78403150 | 167 | /* Trim spaces from back */ |
5e9ce69e A |
168 | for (i = modlen - 1; i >= 0; i--) { |
169 | if (isspace(buf[i])) { | |
170 | buf[i] = '\0'; | |
171 | modlen--; | |
172 | } else { | |
173 | break; | |
174 | } | |
175 | } | |
176 | ||
177 | utf8 = CFStringCreateWithBytes(NULL, (UInt8 *)modbuf, modlen, kCFStringEncodingUTF8, TRUE); | |
6bb65964 A |
178 | return utf8; |
179 | } | |
180 | ||
5958d7c0 | 181 | static char * |
009ee3c6 | 182 | getLine(char *buf, int len, InputRef src) |
5958d7c0 | 183 | { |
009ee3c6 | 184 | int n; |
5958d7c0 | 185 | |
009ee3c6 A |
186 | if (src->el) { |
187 | int count; | |
188 | const char *line; | |
5958d7c0 | 189 | |
009ee3c6 A |
190 | line = el_gets(src->el, &count); |
191 | if (line == NULL) | |
192 | return NULL; | |
193 | ||
194 | strncpy(buf, line, len); | |
5958d7c0 | 195 | } else { |
009ee3c6 A |
196 | if (fgets(buf, len, src->fp) == NULL) |
197 | return NULL; | |
198 | } | |
199 | ||
78403150 | 200 | n = (int)strlen(buf); |
009ee3c6 A |
201 | if (buf[n-1] == '\n') { |
202 | /* the entire line fit in the buffer, remove the newline */ | |
203 | buf[n-1] = '\0'; | |
204 | } else if (!src->el) { | |
5958d7c0 A |
205 | /* eat the remainder of the line */ |
206 | do { | |
009ee3c6 A |
207 | n = fgetc(src->fp); |
208 | } while ((n != '\n') && (n != EOF)); | |
209 | } | |
210 | ||
6bb65964 | 211 | if (src->h && (buf[0] != '\0')) { |
009ee3c6 A |
212 | HistEvent ev; |
213 | ||
214 | history(src->h, &ev, H_ENTER, buf); | |
5958d7c0 A |
215 | } |
216 | ||
ba83da55 | 217 | |
5958d7c0 A |
218 | return buf; |
219 | } | |
220 | ||
221 | ||
dbf6a266 | 222 | static char * |
5958d7c0 A |
223 | getString(char **line) |
224 | { | |
225 | char *s, *e, c, *string; | |
226 | int i, isQuoted = 0, escaped = 0; | |
227 | ||
228 | if (*line == NULL) return NULL; | |
229 | if (**line == '\0') return NULL; | |
230 | ||
231 | /* Skip leading white space */ | |
232 | while (isspace(**line)) *line += 1; | |
233 | ||
234 | /* Grab the next string */ | |
235 | s = *line; | |
236 | if (*s == '\0') { | |
237 | return NULL; /* no string available */ | |
238 | } else if (*s == '"') { | |
239 | isQuoted = 1; /* it's a quoted string */ | |
240 | s++; | |
241 | } | |
242 | ||
243 | for (e = s; (c = *e) != '\0'; e++) { | |
244 | if (isQuoted && (c == '"')) | |
245 | break; /* end of quoted string */ | |
246 | if (c == '\\') { | |
247 | e++; | |
248 | if (*e == '\0') | |
249 | break; /* if premature end-of-string */ | |
250 | if ((*e == '"') || isspace(*e)) | |
251 | escaped++; /* if escaped quote or white space */ | |
252 | } | |
253 | if (!isQuoted && isspace(c)) | |
254 | break; /* end of non-quoted string */ | |
255 | } | |
256 | ||
257 | string = malloc(e - s - escaped + 1); | |
258 | ||
259 | for (i = 0; s < e; s++) { | |
260 | string[i] = *s; | |
261 | if (!((s[0] == '\\') && ((s[1] == '"') || isspace(s[1])))) i++; | |
262 | } | |
263 | string[i] = '\0'; | |
264 | ||
265 | if (isQuoted) | |
266 | e++; /* move past end of quoted string */ | |
267 | ||
268 | *line = e; | |
269 | return string; | |
270 | } | |
271 | ||
272 | ||
dbf6a266 | 273 | __private_extern__ |
0fae82ee | 274 | Boolean |
009ee3c6 | 275 | process_line(InputRef src) |
5958d7c0 | 276 | { |
dbf6a266 A |
277 | char *arg; |
278 | int argc = 0; | |
279 | char **argv = NULL; | |
280 | int i; | |
281 | char line[LINE_LENGTH]; | |
282 | char *s = line; | |
283 | ||
284 | // if end-of-file, exit | |
009ee3c6 | 285 | if (getLine(line, sizeof(line), src) == NULL) |
5958d7c0 A |
286 | return FALSE; |
287 | ||
0fae82ee | 288 | if (nesting > 0) { |
a5f60add | 289 | SCPrint(TRUE, stdout, CFSTR("%d> %s\n"), nesting, line); |
5958d7c0 A |
290 | } |
291 | ||
dbf6a266 | 292 | // break up the input line |
5958d7c0 A |
293 | while ((arg = getString(&s)) != NULL) { |
294 | if (argc == 0) | |
295 | argv = (char **)malloc(2 * sizeof(char *)); | |
296 | else | |
dbf6a266 | 297 | argv = (char **)reallocf(argv, ((argc + 2) * sizeof(char *))); |
5958d7c0 A |
298 | argv[argc++] = arg; |
299 | } | |
300 | ||
dbf6a266 A |
301 | if (argc == 0) { |
302 | return TRUE; // if no arguments | |
303 | } | |
5958d7c0 | 304 | |
dbf6a266 A |
305 | /* process the command */ |
306 | if (*argv[0] != '#') { | |
307 | argv[argc] = NULL; // just in case... | |
308 | currentInput = src; | |
309 | do_command(argc, argv); | |
310 | } | |
5958d7c0 | 311 | |
dbf6a266 A |
312 | /* free the arguments */ |
313 | for (i = 0; i < argc; i++) { | |
314 | free(argv[i]); | |
5958d7c0 | 315 | } |
dbf6a266 | 316 | free(argv); |
5958d7c0 | 317 | |
dbf6a266 | 318 | return !termRequested; |
5958d7c0 A |
319 | } |
320 | ||
321 | ||
dbf6a266 | 322 | static void |
0fae82ee A |
323 | usage(const char *command) |
324 | { | |
325 | SCPrint(TRUE, stderr, CFSTR("usage: %s\n"), command); | |
009ee3c6 A |
326 | SCPrint(TRUE, stderr, CFSTR("\tinteractive access to the dynamic store.\n")); |
327 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
6bb65964 | 328 | SCPrint(TRUE, stderr, CFSTR(" or: %s --prefs [preference-file]\n"), command); |
edebe297 A |
329 | SCPrint(TRUE, stderr, CFSTR("\tinteractive access to the [raw] stored preferences.\n")); |
330 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
a40a14f8 A |
331 | SCPrint(TRUE, stderr, CFSTR(" or: %s [-W] -r nodename\n"), command); |
332 | SCPrint(TRUE, stderr, CFSTR(" or: %s [-W] -r address\n"), command); | |
333 | SCPrint(TRUE, stderr, CFSTR(" or: %s [-W] -r local-address remote-address\n"), command); | |
334 | SCPrint(TRUE, stderr, CFSTR("\tcheck reachability of node, address, or address pair (-W to \"watch\").\n")); | |
009ee3c6 | 335 | SCPrint(TRUE, stderr, CFSTR("\n")); |
0fae82ee A |
336 | SCPrint(TRUE, stderr, CFSTR(" or: %s -w dynamic-store-key [ -t timeout ]\n"), command); |
337 | SCPrint(TRUE, stderr, CFSTR("\t-w\twait for presense of dynamic store key\n")); | |
338 | SCPrint(TRUE, stderr, CFSTR("\t-t\ttime to wait for key\n")); | |
339 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
009ee3c6 A |
340 | SCPrint(TRUE, stderr, CFSTR(" or: %s --get pref\n"), command); |
341 | SCPrint(TRUE, stderr, CFSTR(" or: %s --set pref [newval]\n"), command); | |
5e9ce69e | 342 | SCPrint(TRUE, stderr, CFSTR(" or: %s --get filename path key \n"), command); |
009ee3c6 A |
343 | SCPrint(TRUE, stderr, CFSTR("\tpref\tdisplay (or set) the specified preference. Valid preferences\n")); |
344 | SCPrint(TRUE, stderr, CFSTR("\t\tinclude:\n")); | |
edebe297 | 345 | SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName, HostName\n")); |
009ee3c6 A |
346 | SCPrint(TRUE, stderr, CFSTR("\tnewval\tNew preference value to be set. If not specified,\n")); |
347 | SCPrint(TRUE, stderr, CFSTR("\t\tthe new value will be read from standard input.\n")); | |
dbf6a266 A |
348 | SCPrint(TRUE, stderr, CFSTR("\n")); |
349 | SCPrint(TRUE, stderr, CFSTR(" or: %s --dns\n"), command); | |
350 | SCPrint(TRUE, stderr, CFSTR("\tshow DNS configuration.\n")); | |
351 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
352 | SCPrint(TRUE, stderr, CFSTR(" or: %s --proxy\n"), command); | |
353 | SCPrint(TRUE, stderr, CFSTR("\tshow \"proxy\" configuration.\n")); | |
17d3ee29 A |
354 | SCPrint(TRUE, stderr, CFSTR("\n")); |
355 | SCPrint(TRUE, stderr, CFSTR(" or: %s --nwi\n"), command); | |
356 | SCPrint(TRUE, stderr, CFSTR("\tshow network information\n")); | |
5e9ce69e A |
357 | SCPrint(TRUE, stderr, CFSTR("\n")); |
358 | SCPrint(TRUE, stderr, CFSTR(" or: %s --nc\n"), command); | |
359 | SCPrint(TRUE, stderr, CFSTR("\tshow VPN network configuration information. Use --nc help for full command list\n")); | |
dbf6a266 | 360 | |
78403150 A |
361 | if (_sc_debug) { |
362 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
363 | SCPrint(TRUE, stderr, CFSTR(" or: %s --log IPMonitor [off|on]\n"), command); | |
364 | SCPrint(TRUE, stderr, CFSTR("\tmanage logging.\n")); | |
365 | } | |
366 | ||
dbf6a266 A |
367 | if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) { |
368 | SCPrint(TRUE, stderr, CFSTR("\n")); | |
369 | SCPrint(TRUE, stderr, CFSTR(" or: %s --net\n"), command); | |
370 | SCPrint(TRUE, stderr, CFSTR("\tmanage network configuration.\n")); | |
371 | } | |
372 | ||
78403150 A |
373 | SCPrint(TRUE, stderr, CFSTR("\n")); |
374 | SCPrint(TRUE, stderr, CFSTR(" or: %s --error err#\n"), command); | |
375 | SCPrint(TRUE, stderr, CFSTR("\tdisplay a descriptive message for the given error code\n")); | |
376 | ||
0fae82ee A |
377 | exit (EX_USAGE); |
378 | } | |
379 | ||
380 | ||
009ee3c6 A |
381 | static char * |
382 | prompt(EditLine *el) | |
383 | { | |
5e9ce69e | 384 | #if !TARGET_IPHONE_SIMULATOR |
009ee3c6 | 385 | return "> "; |
5e9ce69e A |
386 | #else // !TARGET_IPHONE_SIMULATOR |
387 | return "sim> "; | |
388 | #endif // !TARGET_IPHONE_SIMULATOR | |
009ee3c6 A |
389 | } |
390 | ||
391 | ||
5958d7c0 | 392 | int |
a5f60add | 393 | main(int argc, char * const argv[]) |
5958d7c0 | 394 | { |
9de8ab86 | 395 | Boolean disableUntilNeeded = FALSE; |
edebe297 A |
396 | Boolean doDNS = FALSE; |
397 | Boolean doNet = FALSE; | |
17d3ee29 | 398 | Boolean doNWI = FALSE; |
edebe297 A |
399 | Boolean doPrefs = FALSE; |
400 | Boolean doProxy = FALSE; | |
401 | Boolean doReach = FALSE; | |
17d3ee29 | 402 | Boolean doSnap = FALSE; |
78403150 | 403 | char *error = NULL; |
009ee3c6 | 404 | char *get = NULL; |
5e9ce69e | 405 | char *log = NULL; |
0fae82ee A |
406 | extern int optind; |
407 | int opt; | |
009ee3c6 | 408 | int opti; |
0fae82ee | 409 | const char *prog = argv[0]; |
5e9ce69e | 410 | char *renew = NULL; |
009ee3c6 | 411 | char *set = NULL; |
6bb65964 | 412 | char *nc_cmd = NULL; |
009ee3c6 | 413 | InputRef src; |
0fae82ee A |
414 | int timeout = 15; /* default timeout (in seconds) */ |
415 | char *wait = NULL; | |
a40a14f8 | 416 | Boolean watch = FALSE; |
009ee3c6 | 417 | int xStore = 0; /* non dynamic store command line options */ |
5958d7c0 A |
418 | |
419 | /* process any arguments */ | |
420 | ||
d0784775 | 421 | while ((opt = getopt_long(argc, argv, "dDvprt:w:W", longopts, &opti)) != -1) |
5958d7c0 A |
422 | switch(opt) { |
423 | case 'd': | |
0fae82ee A |
424 | _sc_debug = TRUE; |
425 | _sc_log = FALSE; /* enable framework logging */ | |
5958d7c0 | 426 | break; |
d0784775 A |
427 | case 'D': |
428 | doDispatch = TRUE; | |
429 | break; | |
5958d7c0 | 430 | case 'v': |
0fae82ee A |
431 | _sc_verbose = TRUE; |
432 | _sc_log = FALSE; /* enable framework logging */ | |
433 | break; | |
434 | case 'p': | |
435 | enablePrivateAPI = TRUE; | |
5958d7c0 A |
436 | break; |
437 | case 'r': | |
edebe297 | 438 | doReach = TRUE; |
009ee3c6 | 439 | xStore++; |
0fae82ee A |
440 | break; |
441 | case 't': | |
442 | timeout = atoi(optarg); | |
443 | break; | |
444 | case 'w': | |
445 | wait = optarg; | |
009ee3c6 A |
446 | xStore++; |
447 | break; | |
a40a14f8 A |
448 | case 'W': |
449 | watch = TRUE; | |
450 | break; | |
009ee3c6 | 451 | case 0: |
dbf6a266 | 452 | if (strcmp(longopts[opti].name, "dns") == 0) { |
edebe297 | 453 | doDNS = TRUE; |
dbf6a266 | 454 | xStore++; |
78403150 A |
455 | } else if (strcmp(longopts[opti].name, "error") == 0) { |
456 | error = optarg; | |
457 | xStore++; | |
dbf6a266 | 458 | } else if (strcmp(longopts[opti].name, "get") == 0) { |
009ee3c6 A |
459 | get = optarg; |
460 | xStore++; | |
17d3ee29 A |
461 | } else if (strcmp(longopts[opti].name, "nc") == 0) { |
462 | nc_cmd = optarg; | |
463 | xStore++; | |
dbf6a266 | 464 | } else if (strcmp(longopts[opti].name, "net") == 0) { |
edebe297 A |
465 | doNet = TRUE; |
466 | xStore++; | |
17d3ee29 A |
467 | } else if (strcmp(longopts[opti].name, "nwi") == 0) { |
468 | doNWI = TRUE; | |
469 | xStore++; | |
edebe297 A |
470 | } else if (strcmp(longopts[opti].name, "prefs") == 0) { |
471 | doPrefs = TRUE; | |
dbf6a266 A |
472 | xStore++; |
473 | } else if (strcmp(longopts[opti].name, "proxy") == 0) { | |
edebe297 | 474 | doProxy = TRUE; |
dbf6a266 | 475 | xStore++; |
5e9ce69e A |
476 | } else if (strcmp(longopts[opti].name, "renew") == 0) { |
477 | renew = optarg; | |
478 | xStore++; | |
009ee3c6 A |
479 | } else if (strcmp(longopts[opti].name, "set") == 0) { |
480 | set = optarg; | |
481 | xStore++; | |
17d3ee29 A |
482 | } else if (strcmp(longopts[opti].name, "snapshot") == 0) { |
483 | doSnap = TRUE; | |
6bb65964 | 484 | xStore++; |
5e9ce69e A |
485 | } else if (strcmp(longopts[opti].name, "log") == 0) { |
486 | log = optarg; | |
487 | xStore++; | |
9de8ab86 A |
488 | } else if (strcmp(longopts[opti].name, "disable-until-needed") == 0) { |
489 | disableUntilNeeded = TRUE; | |
490 | xStore++; | |
17d3ee29 A |
491 | } else if (strcmp(longopts[opti].name, "user") == 0) { |
492 | username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); | |
493 | } else if (strcmp(longopts[opti].name, "password") == 0) { | |
494 | password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); | |
495 | } else if (strcmp(longopts[opti].name, "secret") == 0) { | |
496 | sharedsecret = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); | |
009ee3c6 | 497 | } |
5958d7c0 A |
498 | break; |
499 | case '?': | |
500 | default : | |
0fae82ee | 501 | usage(prog); |
a5f60add | 502 | } |
5958d7c0 A |
503 | argc -= optind; |
504 | argv += optind; | |
505 | ||
009ee3c6 A |
506 | if (xStore > 1) { |
507 | // if we are attempting to process more than one type of request | |
0fae82ee A |
508 | usage(prog); |
509 | } | |
5e9ce69e | 510 | |
a40a14f8 | 511 | /* are we checking (or watching) the reachability of a host/address */ |
edebe297 | 512 | if (doReach) { |
a40a14f8 | 513 | if (argc < 1) { |
009ee3c6 A |
514 | usage(prog); |
515 | } | |
a40a14f8 A |
516 | if (watch) { |
517 | do_watchReachability(argc, (char **)argv); | |
518 | } else { | |
519 | do_checkReachability(argc, (char **)argv); | |
520 | } | |
0fae82ee A |
521 | /* NOT REACHED */ |
522 | } | |
523 | ||
524 | /* are we waiting on the presense of a dynamic store key */ | |
525 | if (wait) { | |
526 | do_wait(wait, timeout); | |
527 | /* NOT REACHED */ | |
528 | } | |
529 | ||
dbf6a266 | 530 | /* are we looking up the DNS configuration */ |
edebe297 | 531 | if (doDNS) { |
78403150 A |
532 | if (watch) { |
533 | do_watchDNSConfiguration(argc, (char **)argv); | |
534 | } else { | |
535 | do_showDNSConfiguration(argc, (char **)argv); | |
536 | } | |
dbf6a266 A |
537 | /* NOT REACHED */ |
538 | } | |
539 | ||
17d3ee29 | 540 | if (doNWI) { |
78403150 A |
541 | if (watch) { |
542 | do_watchNWI(argc, (char**)argv); | |
543 | } else { | |
544 | do_showNWI(argc, (char**)argv); | |
545 | } | |
17d3ee29 A |
546 | /* NOT REACHED */ |
547 | } | |
548 | ||
549 | if (doSnap) { | |
5e9ce69e A |
550 | if (!enablePrivateAPI |
551 | #if !TARGET_IPHONE_SIMULATOR | |
552 | || (geteuid() != 0) | |
553 | #endif // !TARGET_IPHONE_SIMULATOR | |
554 | ) { | |
17d3ee29 A |
555 | usage(prog); |
556 | } | |
557 | ||
558 | do_open(0, NULL); /* open the dynamic store */ | |
559 | do_snapshot(argc, (char**)argv); | |
560 | exit(0); | |
561 | } | |
562 | ||
78403150 A |
563 | /* are we translating error #'s to descriptive text */ |
564 | if (error != NULL) { | |
565 | int sc_status = atoi(error); | |
566 | ||
567 | SCPrint(TRUE, stdout, CFSTR("Error: 0x%08x %d %s\n"), | |
568 | sc_status, | |
569 | sc_status, | |
570 | SCErrorString(sc_status)); | |
571 | exit(0); | |
572 | } | |
573 | ||
009ee3c6 A |
574 | /* are we looking up a preference value */ |
575 | if (get) { | |
5e9ce69e A |
576 | if (argc != 2) { |
577 | if (findPref(get) < 0) { | |
578 | usage(prog); | |
579 | } | |
580 | } else { | |
581 | /* need to go back one argument | |
582 | * for the filename */ | |
583 | argc++; | |
584 | argv--; | |
009ee3c6 | 585 | } |
5e9ce69e | 586 | |
009ee3c6 A |
587 | do_getPref(get, argc, (char **)argv); |
588 | /* NOT REACHED */ | |
589 | } | |
590 | ||
dbf6a266 | 591 | /* are we looking up the proxy configuration */ |
edebe297 | 592 | if (doProxy) { |
dbf6a266 A |
593 | do_showProxyConfiguration(argc, (char **)argv); |
594 | /* NOT REACHED */ | |
595 | } | |
596 | ||
009ee3c6 A |
597 | /* are we changing a preference value */ |
598 | if (set) { | |
599 | if (findPref(set) < 0) { | |
600 | usage(prog); | |
601 | } | |
602 | do_setPref(set, argc, (char **)argv); | |
603 | /* NOT REACHED */ | |
604 | } | |
605 | ||
5e9ce69e A |
606 | /* verbose log */ |
607 | if (log != NULL) { | |
608 | if (strcasecmp(log, "IPMonitor")) { | |
609 | usage(prog); | |
610 | } | |
611 | do_log(log, argc, (char * *)argv); | |
612 | /* NOT REACHED */ | |
613 | } | |
78403150 | 614 | |
9de8ab86 A |
615 | /* disableUntilNeeded */ |
616 | if (disableUntilNeeded) { | |
617 | do_disable_until_needed(argc, (char * *)argv); | |
618 | /* NOT REACHED */ | |
619 | } | |
6bb65964 A |
620 | /* network connection commands */ |
621 | if (nc_cmd) { | |
622 | if (find_nc_cmd(nc_cmd) < 0) { | |
623 | usage(prog); | |
624 | } | |
625 | do_nc_cmd(nc_cmd, argc, (char **)argv, watch); | |
626 | /* NOT REACHED */ | |
627 | } | |
628 | ||
edebe297 | 629 | if (doNet) { |
dbf6a266 | 630 | /* if we are going to be managing the network configuration */ |
edebe297 A |
631 | commands = (cmdInfo *)commands_net; |
632 | nCommands = nCommands_net; | |
dbf6a266 A |
633 | |
634 | if (!getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) { | |
635 | usage(prog); | |
636 | } | |
637 | ||
5e9ce69e A |
638 | do_net_init(); /* initialization */ |
639 | do_net_open(argc, (char **)argv); /* open prefs */ | |
edebe297 A |
640 | } else if (doPrefs) { |
641 | /* if we are going to be managing the network configuration */ | |
642 | commands = (cmdInfo *)commands_prefs; | |
643 | nCommands = nCommands_prefs; | |
644 | ||
5e9ce69e A |
645 | do_dictInit(0, NULL); /* start with an empty dictionary */ |
646 | do_prefs_init(); /* initialization */ | |
6bb65964 | 647 | do_prefs_open(argc, (char **)argv); /* open prefs */ |
dbf6a266 A |
648 | } else { |
649 | /* if we are going to be managing the dynamic store */ | |
650 | commands = (cmdInfo *)commands_store; | |
651 | nCommands = nCommands_store; | |
652 | ||
653 | do_dictInit(0, NULL); /* start with an empty dictionary */ | |
654 | do_open(0, NULL); /* open the dynamic store */ | |
655 | } | |
5958d7c0 | 656 | |
5e9ce69e A |
657 | /* are we trying to renew a DHCP lease */ |
658 | if (renew != NULL) { | |
659 | do_renew(renew); | |
660 | /* NOT REACHED */ | |
661 | } | |
662 | ||
009ee3c6 A |
663 | /* allocate command input stream */ |
664 | src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); | |
665 | src->fp = stdin; | |
666 | src->el = NULL; | |
667 | src->h = NULL; | |
668 | ||
669 | if (isatty(fileno(src->fp))) { | |
670 | int editmode = 1; | |
671 | HistEvent ev; | |
672 | struct termios t; | |
673 | ||
674 | if (tcgetattr(fileno(src->fp), &t) != -1) { | |
675 | if ((t.c_lflag & ECHO) == 0) { | |
676 | editmode = 0; | |
677 | } | |
678 | } | |
679 | src->el = el_init(prog, src->fp, stdout, stderr); | |
680 | src->h = history_init(); | |
681 | ||
682 | (void)history(src->h, &ev, H_SETSIZE, INT_MAX); | |
683 | el_set(src->el, EL_HIST, history, src->h); | |
5958d7c0 | 684 | |
009ee3c6 A |
685 | if (!editmode) { |
686 | el_set(src->el, EL_EDITMODE, 0); | |
687 | } | |
5958d7c0 | 688 | |
009ee3c6 A |
689 | el_set(src->el, EL_EDITOR, "emacs"); |
690 | el_set(src->el, EL_PROMPT, prompt); | |
5958d7c0 | 691 | |
009ee3c6 | 692 | el_source(src->el, NULL); |
5958d7c0 | 693 | |
009ee3c6 A |
694 | if ((el_get(src->el, EL_EDITMODE, &editmode) != -1) && editmode != 0) { |
695 | el_set(src->el, EL_SIGNAL, 1); | |
696 | } else { | |
697 | history_end(src->h); | |
698 | src->h = NULL; | |
699 | el_end(src->el); | |
700 | src->el = NULL; | |
701 | } | |
702 | } | |
5958d7c0 | 703 | |
a40a14f8 A |
704 | while (TRUE) { |
705 | Boolean ok; | |
706 | ||
707 | ok = process_line(src); | |
708 | if (!ok) { | |
709 | break; | |
710 | } | |
5958d7c0 A |
711 | } |
712 | ||
009ee3c6 A |
713 | /* close the socket, free resources */ |
714 | if (src->h) history_end(src->h); | |
715 | if (src->el) el_end(src->el); | |
716 | (void)fclose(src->fp); | |
717 | CFAllocatorDeallocate(NULL, src); | |
5958d7c0 A |
718 | |
719 | exit (EX_OK); // insure the process exit status is 0 | |
720 | return 0; // ...and make main fit the ANSI spec. | |
721 | } |