/* * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * * August 5, 2004 Allan Nathanson * - initial revision */ #include "scutil.h" #include "net.h" #include "net_set.h" #include "net_service.h" /* -------------------- */ static CFComparisonResult _compare_sets(const void *val1, const void *val2, void *context) { CFStringRef id1; CFStringRef id2; CFStringRef name1; CFStringRef name2; SCNetworkSetRef s1 = (SCNetworkSetRef)val1; SCNetworkSetRef s2 = (SCNetworkSetRef)val2; name1 = SCNetworkSetGetName(s1); name2 = SCNetworkSetGetName(s2); if (name1 != NULL) { if (name2 != NULL) { return CFStringCompare(name1, name2, 0); } else { return kCFCompareLessThan; } } if (name2 != NULL) { return kCFCompareGreaterThan; } id1 = SCNetworkSetGetSetID(s1); id2 = SCNetworkSetGetSetID(s2); return CFStringCompare(id1, id2, 0); } static CFArrayRef _copy_sets() { CFArrayRef sets; CFMutableArrayRef sorted; sets = SCNetworkSetCopyAll(prefs); if (sets == NULL) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); return NULL; } sorted = CFArrayCreateMutableCopy(NULL, 0, sets); CFArraySortValues(sorted, CFRangeMake(0, CFArrayGetCount(sorted)), _compare_sets, NULL); CFRelease(sets); sets = CFArrayCreateCopy(NULL, sorted); CFRelease(sorted); return sets; } static SCNetworkSetRef _find_set(char *match) { Boolean allowIndex = TRUE; CFIndex i; CFIndex n; CFStringRef select_name = NULL; SCNetworkSetRef selected = NULL; if (sets == NULL) { if (prefs == NULL) { SCPrint(TRUE, stdout, CFSTR("network configuration not open\n")); return NULL; } sets = _copy_sets(); if (sets == NULL) { return NULL; } allowIndex = FALSE; } // try to select the set by its setID select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8); n = CFArrayGetCount(sets); for (i = 0; i < n; i++) { SCNetworkSetRef set; CFStringRef setID; set = CFArrayGetValueAtIndex(sets, i); setID = SCNetworkSetGetSetID(set); if (CFEqual(select_name, setID)) { selected = set; goto done; } } // try to select the set by its name for (i = 0; i < n; i++) { SCNetworkSetRef set; CFStringRef setName; set = CFArrayGetValueAtIndex(sets, i); setName = SCNetworkSetGetName(set); if ((setName != NULL) && CFEqual(select_name, setName)) { if (selected == NULL) { selected = set; } else { // if multiple sets match selected = NULL; SCPrint(TRUE, stdout, CFSTR("multiple sets match\n")); goto done; } } } if (selected != NULL) { goto done; } // try to select the set by its name (case insensitive) for (i = 0; i < n; i++) { SCNetworkSetRef set; CFStringRef setName; set = CFArrayGetValueAtIndex(sets, i); setName = SCNetworkSetGetName(set); if ((setName != NULL) && CFStringCompare(select_name, setName, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { if (selected == NULL) { selected = set; } else { // if multiple sets match selected = NULL; SCPrint(TRUE, stdout, CFSTR("multiple sets match\n")); goto done; } } } if (selected != NULL) { goto done; } // try to select the set by its index if (allowIndex) { char *end; char *str = match; long val; errno = 0; val = strtol(str, &end, 10); if ((*str != '\0') && (*end == '\0') && (errno == 0)) { if ((val > 0) && (val <= n)) { selected = CFArrayGetValueAtIndex(sets, val - 1); } } } if (selected != NULL) { goto done; } SCPrint(TRUE, stdout, CFSTR("no match, which set?\n")); done : if (select_name != NULL) CFRelease(select_name); return selected; } /* -------------------- */ __private_extern__ void create_set(int argc, char **argv) { SCNetworkSetRef set; CFStringRef setName; if (prefs == NULL) { SCPrint(TRUE, stdout, CFSTR("network configuration not open\n")); return; } set = SCNetworkSetCreate(prefs); if (set == NULL) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); return; } if ((argc > 0) && (strlen(argv[0]) > 0)) { Boolean ok; setName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); argv++; argc--; ok = SCNetworkSetSetName(set, setName); CFRelease(setName); if (!ok) { SCPrint(TRUE, stdout, CFSTR("set not created: %s\n"), SCErrorString(SCError())); (void) SCNetworkSetRemove(set); CFRelease(set); return; } } net_changed = TRUE; if (net_set != NULL) CFRelease(net_set); net_set = set; setName = SCNetworkSetGetName(set); if (setName != NULL) { SCPrint(TRUE, stdout, CFSTR("set \"%@\" (%@) created and selected\n"), setName, SCNetworkSetGetSetID(set)); } else { SCPrint(TRUE, stdout, CFSTR("set ID \"%@\" created and selected\n"), SCNetworkSetGetSetID(set)); } if (net_service != NULL) { CFRelease(net_service); net_service = NULL; SCPrint(TRUE, stdout, CFSTR("& no service selected\n")); } if (net_protocol != NULL) { CFRelease(net_protocol); net_protocol = NULL; SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n")); } if (net_interface != NULL) { CFRelease(net_interface); net_interface = NULL; SCPrint(TRUE, stdout, CFSTR("& no interface selected\n")); } if (sets != NULL) { CFRelease(sets); sets = NULL; } return; } __private_extern__ void remove_set(int argc, char **argv) { SCNetworkSetRef set = NULL; CFStringRef setName; if (argc == 1) { set = _find_set(argv[0]); } else { if (net_set != NULL) { set = net_set; } } if (set == NULL) { return; } CFRetain(set); if (!SCNetworkSetRemove(set)) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); goto done; } net_changed = TRUE; setName = SCNetworkSetGetName(set); if (setName != NULL) { SCPrint(TRUE, stdout, CFSTR("set \"%@\" removed\n"), setName); } else { SCPrint(TRUE, stdout, CFSTR("set ID \"%@\" removed\n"), SCNetworkSetGetSetID(set)); } if (CFEqual(set, net_set)) { if (net_service != NULL) { CFRelease(net_service); net_service = NULL; SCPrint(TRUE, stdout, CFSTR("& no service selected\n")); } if (net_protocol != NULL) { CFRelease(net_protocol); net_protocol = NULL; SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n")); } if (net_interface != NULL) { CFRelease(net_interface); net_interface = NULL; SCPrint(TRUE, stdout, CFSTR("& no interface selected\n")); } } if (sets != NULL) { CFRelease(sets); sets = NULL; } done : CFRelease(set); return; } __private_extern__ void select_set(int argc, char **argv) { SCNetworkSetRef set; CFStringRef setName; set = _find_set(argv[0]); if (set == NULL) { return; } if (net_set != NULL) CFRelease(net_set); net_set = CFRetain(set); setName = SCNetworkSetGetName(set); if (setName != NULL) { SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName); } else { SCPrint(TRUE, stdout, CFSTR("set ID \"%@\" selected\n"), SCNetworkSetGetSetID(set)); } if (net_service != NULL) { CFRelease(net_service); net_service = NULL; SCPrint(TRUE, stdout, CFSTR("& no service selected\n")); } if (net_protocol != NULL) { CFRelease(net_protocol); net_protocol = NULL; SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n")); } if (net_interface != NULL) { CFRelease(net_interface); net_interface = NULL; SCPrint(TRUE, stdout, CFSTR("& no interface selected\n")); } return; } __private_extern__ void set_set(int argc, char **argv) { Boolean ok; if (net_set == NULL) { SCPrint(TRUE, stdout, CFSTR("set not selected\n")); return; } if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("set what?\n")); return; } while (argc > 0) { char *command; command = argv[0]; argv++; argc--; if (strcmp(command, "name") == 0) { CFStringRef setName; if (argc < 1) { SCPrint(TRUE, stdout, CFSTR("name not specified\n")); return; } setName = (strlen(argv[0]) > 0) ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8) : NULL; argv++; argc--; ok = SCNetworkSetSetName(net_set, setName); if (setName != NULL) CFRelease(setName); if (!ok) { SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError())); return; } net_changed = TRUE; if (sets != NULL) { /* * since the (displayed) ordering may have changed, refresh sets */ char *setID; setID = _SC_cfstring_to_cstring(SCNetworkSetGetSetID(net_set), NULL, 0, kCFStringEncodingUTF8); CFRelease(net_set); net_set = NULL; CFRelease(sets); sets = NULL; net_set = _find_set(setID); if (net_set != NULL) { CFRetain(net_set); } CFAllocatorDeallocate(NULL, setID); } } else { SCPrint(TRUE, stdout, CFSTR("set what?\n")); } } return; } __private_extern__ void show_set(int argc, char **argv) { CFArrayRef services; SCNetworkSetRef set = NULL; CFStringRef setName; if (argc == 1) { set = _find_set(argv[0]); } else { if (net_set != NULL) { set = net_set; } else { SCPrint(TRUE, stdout, CFSTR("set not selected\n")); return; } } if (set == NULL) { return; } SCPrint(TRUE, stdout, CFSTR("set id = %@\n"), SCNetworkSetGetSetID(set)); setName = SCNetworkSetGetName(set); SCPrint(TRUE, stdout, CFSTR("name = %@\n"), (setName != NULL) ? setName : CFSTR("")); services = SCNetworkSetCopyServices(set); if (services != NULL) { CFIndex i; CFIndex n; CFIndex nOrder = 0; CFArrayRef order; CFMutableArrayRef sorted = (CFMutableArrayRef)services; order = SCNetworkSetGetServiceOrder(set); if (order != NULL) { nOrder = CFArrayGetCount(order); } n = CFArrayGetCount(services); if (n > 1) { sorted = CFArrayCreateMutableCopy(NULL, 0, services); CFArraySortValues(sorted, CFRangeMake(0, CFArrayGetCount(sorted)), _compare_services, (void *)order); } SCPrint(TRUE, stdout, CFSTR("services =\n")); for (i = 0; i < n; i++) { CFIndex orderIndex = kCFNotFound; SCNetworkServiceRef service; CFStringRef serviceName; CFStringRef serviceID; service = CFArrayGetValueAtIndex(sorted, i); serviceID = SCNetworkServiceGetServiceID(service); serviceName = SCNetworkServiceGetName(service); if (serviceName == NULL) serviceName = CFSTR(""); if (order != NULL) { orderIndex = CFArrayGetFirstIndexOfValue(order, CFRangeMake(0, nOrder), serviceID); } if (orderIndex != kCFNotFound) { SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)\n"), ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ', orderIndex + 1, serviceName, 30 - CFStringGetLength(serviceName), " ", serviceID); } else { SCPrint(TRUE, stdout, CFSTR("%c : %@%-*s (%@)\n"), ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ', serviceName, 30 - CFStringGetLength(serviceName), " ", serviceID); } } CFRelease(services); if (sorted != services) CFRelease(sorted); } if (_sc_debug) { SCPrint(TRUE, stdout, CFSTR("\n%@\n"), set); } return; } __private_extern__ void show_sets(int argc, char **argv) { SCNetworkSetRef current; CFIndex i; CFIndex n; if (prefs == NULL) { SCPrint(TRUE, stdout, CFSTR("network configuration not open\n")); return; } if (sets == NULL) { sets = _copy_sets(); if (sets == NULL) { return; } } current = SCNetworkSetCopyCurrent(prefs); n = CFArrayGetCount(sets); for (i = 0; i < n; i++) { SCNetworkSetRef set; CFStringRef setID; CFStringRef setName; set = CFArrayGetValueAtIndex(sets, i); setID = SCNetworkSetGetSetID(set); setName = SCNetworkSetGetName(set); if (setName == NULL) setName = CFSTR(""); SCPrint(TRUE, stdout, CFSTR(" %c%c%2d: %@%-*s (%@)\n"), ((current != NULL) && CFEqual(set, current)) ? '*' : ' ', ((net_set != NULL) && CFEqual(set, net_set)) ? '>' : ' ', i + 1, setName, 30 - CFStringGetLength(setName), " ", setID); } if (current != NULL) CFRelease(current); return; }