socktest.c revision 3f61fb90d08d4848a7d7dd24180c2b95ebd60bfc
1b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly/* 2b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Copyright 2009 The Android Open Source Project 3b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** 4b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Licensed under the Apache License, Version 2.0 (the "License"); 5b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** you may not use this file except in compliance with the License. 6b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** You may obtain a copy of the License at 7b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** 8b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** http://www.apache.org/licenses/LICENSE-2.0 9b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** 10b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** Unless required by applicable law or agreed to in writing, software 11b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** distributed under the License is distributed on an "AS IS" BASIS, 12b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** See the License for the specific language governing permissions and 14b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly** limitations under the License. 15b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly*/ 16b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 17b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly/** socket testing */ 18b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 19b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdlib.h> 20b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdio.h> 21b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <errno.h> 22b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/uio.h> 23b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <unistd.h> 24b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 25b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <pthread.h> 26b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdio.h> 27b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <stdlib.h> 28b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <errno.h> 29b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <unistd.h> 30b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/socket.h> 31b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/ioctl.h> 32b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <sys/un.h> 33b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <netinet/in.h> 34b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 35b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/bluetooth.h> 36b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/rfcomm.h> 37b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/sco.h> 38b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly#include <bluetooth/l2cap.h> 39b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 40b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyenum sock_type { 41b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly UNIX = 0, 42b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly RFCOMM, 43b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly SCO, 44b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly L2CAP, 45b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly TCP, 46b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}; 47b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 48b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct thread_args { 49b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int fd; 50b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int type; 513f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly int delay; 52b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}; 53b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 54b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_un local_addr_un = {AF_UNIX, "/data/foo"}; 553f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystruct sockaddr_rc local_addr_rc = {AF_BLUETOOTH, *BDADDR_ANY, 4}; 563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystruct sockaddr_sco local_addr_sco = {AF_BLUETOOTH, *BDADDR_LOCAL}; 57b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_l2 local_addr_l2 = {AF_BLUETOOTH, htobs(0x1001), *BDADDR_ANY, 0}; 58b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_in local_addr_in = {AF_INET, 9999, {0}, {0}}; 59b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 60b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_un remote_addr_un ; 61b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_rc remote_addr_rc ; 62b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_sco remote_addr_sco ; 63b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_l2 remote_addr_l2 ; 64b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct sockaddr_in remote_addr_in ; 65b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 66b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _socket(int type) { 67b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 68b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int family = -1; 69b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int typ = -1; 70b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int protocol = -1; 71b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 72b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly switch (type) { 73b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case UNIX: 74b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly family = PF_UNIX; 75b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly typ = SOCK_STREAM; 76b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly protocol = 0; 77b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 78b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case RFCOMM: 79b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly family = PF_BLUETOOTH; 80b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly typ = SOCK_STREAM; 81b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly protocol = BTPROTO_RFCOMM; 82b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 83b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case SCO: 84b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly family = PF_BLUETOOTH; 85b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly typ = SOCK_SEQPACKET; 86b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly protocol = BTPROTO_SCO; 87b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 88b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case L2CAP: 89b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly family = PF_BLUETOOTH; 90b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly typ = SOCK_SEQPACKET; 91b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly protocol = BTPROTO_L2CAP; 92b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 93b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case TCP: 94b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly family = PF_INET; 95b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly typ = SOCK_STREAM; 96b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly protocol = 0; 97b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 98b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 99b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 100b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: socket()\n", gettid()); 101b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = socket(family, typ, protocol); 102b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: socket() = %d\n", gettid(), ret); 103b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 104b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 105b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 106b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 107b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 108b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _close(int fd, int type) { 109b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 110b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 111b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: close(%d)\n", gettid(), fd); 112b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = close(fd); 113b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: close(%d) = %d\n", gettid(), fd, ret); 114b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 115b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 116b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 117b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 118b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 119b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _bind(int fd, int type) { 120b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int len = 0; 121b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 122b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly struct sockaddr *addr = NULL; 123b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 124b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly switch (type) { 125b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case UNIX: 126b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly unlink(local_addr_un.sun_path); 127b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_un; 128b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_un); 129b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 130b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case RFCOMM: 131b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_rc; 132b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_rc); 133b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 134b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case SCO: 135b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_sco; 136b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_sco); 137b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 138b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case L2CAP: 139b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_l2; 140b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_l2); 141b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 142b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case TCP: 143b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_in; 144b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_in); 145b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 146b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 147b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 148b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: bind(%d)\n", gettid(), fd); 149b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = bind(fd, addr, len); 150b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: bind(%d) = %d\n", gettid(), fd, ret); 151b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 152b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 153b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 154b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 155b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 156b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _listen(int fd, int type) { 157b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 158b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 159b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: listen(%d)\n", gettid(), fd); 160b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = listen(fd, 1); 161b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: listen(%d) = %d\n", gettid(), fd, ret); 162b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 163b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 164b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 165b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 166b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 167b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _accept(int fd, int type) { 168b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 169b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int len; 170b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly struct sockaddr *addr = NULL; 171b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 172b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly switch (type) { 173b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case UNIX: 174b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &remote_addr_un; 175b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(remote_addr_un); 176b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 177b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case RFCOMM: 178b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &remote_addr_rc; 179b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(remote_addr_rc); 180b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 181b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case SCO: 182b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &remote_addr_sco; 183b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(remote_addr_sco); 184b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 185b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case L2CAP: 186b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &remote_addr_l2; 187b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(remote_addr_l2); 188b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 189b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case TCP: 190b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &remote_addr_in; 191b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(remote_addr_in); 192b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 193b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 194b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 195b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: accept(%d)\n", gettid(), fd); 196b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = accept(fd, addr, &len); 197b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: accept(%d) = %d\n", gettid(), fd, ret); 198b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 199b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly else { 200b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("\tlen = %d\n", len); 201b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 202b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 203b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 204b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 205b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 206b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _connect(int fd, int type) { 207b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 2083f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly int len = 0; 209b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly struct sockaddr *addr = NULL; 210b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 211b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly switch (type) { 212b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case UNIX: 213b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_un; 214b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_un); 215b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 216b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case RFCOMM: 217b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_rc; 218b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_rc); 219b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 220b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case SCO: 221b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_sco; 222b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_sco); 223b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 224b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case L2CAP: 225b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_l2; 226b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_l2); 227b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 228b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly case TCP: 229b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly addr = (struct sockaddr *) &local_addr_in; 230b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly len = sizeof(local_addr_in); 231b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 232b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 233b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 234b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: connect(%d)\n", gettid(), fd); 235b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = connect(fd, addr, len); 236b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: connect(%d) = %d\n", gettid(), fd, ret); 237b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 238b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 239b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 240b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 241b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 242b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int _write(int fd, int type) { 243b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int ret; 244b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly char buf = 0; 245b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 246b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: write(%d)\n", gettid(), fd); 247b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly ret = write(fd, &buf, 1); 248b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: connect(%d) = %d\n", gettid(), fd, ret); 249b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (ret < 0) printf("\terr %d (%s)\n", errno, strerror(errno)); 250b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 251b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return ret; 252b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 253b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 2543f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_close(struct thread_args *args) { 255b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: START\n", gettid()); 2563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly sleep(args->delay); 2573f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _close(args->fd, args->type); 258b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: END\n", gettid()); 259b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 260b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 2613f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_close_write(struct thread_args *args) { 2623f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly printf("%d: START\n", gettid()); 2633f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly sleep(args->delay); 2643f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _close(args->fd, args->type); 2653f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly sleep(args->delay); 2663f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _write(args->fd, args->type); 2673f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly printf("%d: END\n", gettid()); 2683f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly} 269b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 2703f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic void thread_delay_connect(struct thread_args *args) { 271b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: START\n", gettid()); 2723f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly sleep(args->delay); 2733f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly args->fd = _socket(args->type); 2743f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _connect(args->fd, args->type); 275b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("%d: END\n", gettid()); 276b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 277b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 2783f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_accept_accept_accept(int type) { 2793f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly int fd; 2803f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2813f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly fd = _socket(type); 2823f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (fd < 0) goto error; 2833f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2843f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (_bind(fd, type) < 0) goto error; 2853f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2863f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (_listen(fd, type) < 0) goto error; 2873f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2883f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly while (1) { 2893f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _accept(fd, type); 2903f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly } 2913f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2923f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly return 0; 2933f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 2943f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellyerror: 2953f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly return -1; 2963f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly} 2973f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 298b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int do_accept_and_close(int type) { 299b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int fd; 300b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly pthread_t thread; 3013f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args args = {-1, type, 1}; 302b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 303b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly fd = _socket(type); 304b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (fd < 0) goto error; 305b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 306b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (_bind(fd, type) < 0) goto error; 307b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 308b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (_listen(fd, type) < 0) goto error; 309b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 3103f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly args.fd = fd; 3113f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&thread, NULL, (void *)thread_delay_close, (void *)&args); 312b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 313b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly _accept(fd, type); 314b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 315b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly pthread_join(thread, NULL); 316b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 317b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return 0; 318b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 319b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyerror: 320b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return -1; 321b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 322b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 323b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly// accept in one thread. close then write in another 324b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic int do_accept_close_write(int type) { 325b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int fd; 326b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly pthread_t thread; 3273f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args args = {-1, type, 1}; 328b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 329b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly fd = _socket(type); 330b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (fd < 0) goto error; 331b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 332b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (_bind(fd, type) < 0) goto error; 333b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 334b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (_listen(fd, type) < 0) goto error; 335b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 3363f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly args.fd = fd; 3373f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&thread, NULL, (void *)thread_delay_close_write, (void *)&args); 338b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 339b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly _accept(fd, type); 340b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 341b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly pthread_join(thread, NULL); 342b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 343b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return 0; 344b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 345b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyerror: 346b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return -1; 347b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 348b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 3493f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_poll_poll_shutdown(int type) { 3503f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly#if 0 3513f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly int fd; 3523f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args a1 = {-1, type, 1}; 3533f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args a2 = {-1, type, 2}; 3543f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3553f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly fd = _socket(type); 3563f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3573f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&t1, NULL, (void *)thread_poll, (void *)fd[0]); 3583f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&t2, NULL, (void *)thread_poll, (void *)fd[0]); 3593f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3603f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly sleep(1); 3613f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3623f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _shutdown(fd[1], SHUT_RDWR); 3633f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3643f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_join(t1, NULL); 3653f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_join(t2, NULL); 3663f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly#endif 3673f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly return 0; 3683f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly} 3693f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3703f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly// accept in one thread, connect from two different threads 3713f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellystatic int do_accept_connect_connect(int type) { 3723f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly int fd; 3733f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_t t1; 3743f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_t t2; 3753f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args a1 = {-1, type, 1}; 3763f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly struct thread_args a2 = {-1, type, 2}; 3773f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3783f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly fd = _socket(type); 3793f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (fd < 0) goto error; 3803f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3813f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (_bind(fd, type) < 0) goto error; 3823f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3833f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly if (_listen(fd, type) < 0) goto error; 3843f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3853f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&t1, NULL, (void *)thread_delay_connect, (void *)&a1); 3863f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_create(&t2, NULL, (void *)thread_delay_connect, (void *)&a2); 3873f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3883f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly _accept(fd, type); 3893f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3903f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_join(t1, NULL); 3913f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly pthread_join(t2, NULL); 3923f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3933f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly return 0; 3943f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 3953f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pellyerror: 3963f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly return -1; 3973f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly} 3983f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly 399b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct { 400b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly char *name; 401b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int (*ptr)(int); 402b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} action_table[] = { 4033f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly {"accept_accept_accept", do_accept_accept_accept}, 404b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"accept_and_close", do_accept_and_close}, 405b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"accept_close_write", do_accept_close_write}, 4063f61fb90d08d4848a7d7dd24180c2b95ebd60bfcNick Pelly {"accept_connect_connect", do_accept_connect_connect}, 407b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {NULL, NULL}, 408b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}; 409b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 410b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystruct { 411b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly char *name; 412b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly enum sock_type type; 413b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} type_table[] = { 414b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"unix", UNIX}, 415b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"rfcomm", RFCOMM}, 416b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"sco", SCO}, 417b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"l2cap", L2CAP}, 418b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {"tcp", TCP}, 419b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly {NULL, -1}, 420b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly}; 421b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 422b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellystatic void usage() { 423b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int i; 424b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 425b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("socktest TYPE ACTION\n"); 426b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("\nTYPE:\n"); 427b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly for (i = 0; type_table[i].name; i++) { 428b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("\t%s\n", type_table[i].name); 429b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 430b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("\nACTION:\n"); 431b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly for (i = 0; action_table[i].name; i++) { 432b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("\t%s\n", action_table[i].name); 433b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 434b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 435b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 436b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pellyint main(int argc, char **argv) { 437b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int i; 438b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly int type = -1; 439b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly 440b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (argc != 3) { 441b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly usage(); 442b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return -1; 443b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 444b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly for (i = 0; type_table[i].name; i++) { 445b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (!strcmp(argv[1], type_table[i].name)) { 446b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly type = type_table[i].type; 447b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly break; 448b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 449b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 450b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (type == -1) { 451b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly usage(); 452b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return -1; 453b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 454b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly for (i = 0; action_table[i].name; i++) { 455b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly if (!strcmp(argv[2], action_table[i].name)) { 456b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly printf("TYPE = %s ACTION = %s\n", type_table[type].name, 457b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly action_table[i].name); 458b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return (*action_table[i].ptr)(type); 459b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 460b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly } 461b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly usage(); 462b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly return -1; 463b88063b946e2c8f349e69c7db0a631088f991fc4Nick Pelly} 464