]> git.saurik.com Git - apple/configd.git/blame - scutil.tproj/scutil.c
configd-802.40.13.tar.gz
[apple/configd.git] / scutil.tproj / scutil.c
CommitLineData
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 88static 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__
119CFStringRef
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 181static char *
009ee3c6 182getLine(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 222static char *
5958d7c0
A
223getString(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 274Boolean
009ee3c6 275process_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 322static void
0fae82ee
A
323usage(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
381static char *
382prompt(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 392int
a5f60add 393main(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}