180709Sjake/* 280709Sjake * sdpcontrol.c 380709Sjake * 480709Sjake * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 580709Sjake * All rights reserved. 680709Sjake * 780709Sjake * Redistribution and use in source and binary forms, with or without 880709Sjake * modification, are permitted provided that the following conditions 980709Sjake * are met: 1080709Sjake * 1. Redistributions of source code must retain the above copyright 1180709Sjake * notice, this list of conditions and the following disclaimer. 1280709Sjake * 2. Redistributions in binary form must reproduce the above copyright 1380709Sjake * notice, this list of conditions and the following disclaimer in the 1480709Sjake * documentation and/or other materials provided with the distribution. 1580709Sjake * 1680709Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1780709Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1880709Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1980709Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2080709Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2180709Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2280709Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2380709Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2480709Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2580709Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2680709Sjake * SUCH DAMAGE. 2780709Sjake * 2880709Sjake * $Id: sdpcontrol.c,v 1.1 2003/09/08 02:27:27 max Exp $ 2980709Sjake * $FreeBSD$ 3080709Sjake */ 3180709Sjake 3280709Sjake#include <assert.h> 3380709Sjake#include <bluetooth.h> 3480709Sjake#include <err.h> 3597446Sjake#include <errno.h> 3680709Sjake#include <sdp.h> 3780709Sjake#include <stdio.h> 3880709Sjake#include <stdlib.h> 39205258Smarius#include <string.h> 40205258Smarius#include <unistd.h> 41182767Smarius#include "sdpcontrol.h" 42182767Smarius 43205258Smarius/* Prototypes */ 44205258Smariusstatic int do_sdp_command (bdaddr_p, char const *, int, 45205258Smarius int, char **); 4680709Sjakestatic struct sdp_command * find_sdp_command (char const *, 4780709Sjake struct sdp_command *); 4880709Sjakestatic void print_sdp_command (struct sdp_command *); 4997027Sjakestatic void usage (void); 5097027Sjake 51205258Smarius/* Main */ 52205258Smariusint 53205258Smariusmain(int argc, char *argv[]) 54205258Smarius{ 55205258Smarius char const *control = SDP_LOCAL_PATH; 56205258Smarius int n, local; 57205258Smarius bdaddr_t bdaddr; 58205258Smarius 59205258Smarius memset(&bdaddr, 0, sizeof(bdaddr)); 60205258Smarius local = 0; 61182767Smarius 6297027Sjake /* Process command line arguments */ 6380709Sjake while ((n = getopt(argc, argv, "a:c:lh")) != -1) { 6497027Sjake switch (n) { 6597027Sjake case 'a': /* bdaddr */ 66205258Smarius if (!bt_aton(optarg, &bdaddr)) { 67205258Smarius struct hostent *he = NULL; 68182767Smarius 69182767Smarius if ((he = bt_gethostbyname(optarg)) == NULL) 70205258Smarius errx(1, "%s: %s", optarg, hstrerror(h_errno)); 71205258Smarius 72205258Smarius memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 73181398Smarius } 74205258Smarius break; 75181398Smarius 7697027Sjake case 'c': /* control socket */ 7797027Sjake control = optarg; 7880709Sjake break; 79102040Sjake 80102040Sjake case 'l': /* local sdpd */ 81102040Sjake local = 1; 82102040Sjake break; 83205258Smarius 84205258Smarius case 'h': 85205258Smarius default: 8697027Sjake usage(); 87102040Sjake /* NOT REACHED */ 88102040Sjake } 8980709Sjake } 9088652Sjake 91102040Sjake argc -= optind; 92102040Sjake argv += optind; 93102040Sjake 94102040Sjake if (*argv == NULL) 95205258Smarius usage(); 96205258Smarius 97205258Smarius return (do_sdp_command(&bdaddr, control, local, argc, argv)); 98205258Smarius} 99205258Smarius 100205258Smarius/* Execute commands */ 101205258Smariusstatic int 102205258Smariusdo_sdp_command(bdaddr_p bdaddr, char const *control, int local, 103205258Smarius int argc, char **argv) 10488652Sjake{ 10588652Sjake char *cmd = argv[0]; 10697027Sjake struct sdp_command *c = NULL; 107112697Sjake void *xs = NULL; 108112697Sjake int e, help; 109102040Sjake 110102040Sjake help = 0; 111102040Sjake if (strcasecmp(cmd, "help") == 0) { 112102040Sjake argc --; 113102040Sjake argv ++; 11488652Sjake 11588652Sjake if (argc <= 0) { 11688652Sjake fprintf(stdout, "Supported commands:\n"); 11788652Sjake print_sdp_command(sdp_commands); 11888652Sjake fprintf(stdout, "\nFor more information use " \ 11988652Sjake "'help command'\n"); 12088652Sjake 12180709Sjake return (OK); 122102040Sjake } 123102040Sjake 12491224Sjake help = 1; 125102040Sjake cmd = argv[0]; 126205258Smarius } 127102040Sjake 128102040Sjake c = find_sdp_command(cmd, sdp_commands); 129205258Smarius if (c == NULL) { 13097027Sjake fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 131205258Smarius return (ERROR); 132102040Sjake } 133205258Smarius 13497027Sjake if (!help) { 135205258Smarius if (!local) { 13697027Sjake if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 13784182Sjake usage(); 138205258Smarius 13997027Sjake xs = sdp_open(NG_HCI_BDADDR_ANY, bdaddr); 140205258Smarius } else 141102040Sjake xs = sdp_open_local(control); 142205258Smarius 143102040Sjake if (xs == NULL) 144205258Smarius errx(1, "Could not create SDP session object"); 145205258Smarius if (sdp_error(xs) == 0) 146205258Smarius e = (c->handler)(xs, -- argc, ++ argv); 147205258Smarius else 148108386Sjake e = ERROR; 14997027Sjake } else 150102040Sjake e = USAGE; 151102040Sjake 15283053Sobrien switch (e) { 15391224Sjake case OK: 15480709Sjake case FAILED: 155108166Sjake break; 15680709Sjake 15780709Sjake case ERROR: 15891224Sjake fprintf(stdout, "Could not execute command \"%s\". %s\n", 15997027Sjake cmd, strerror(sdp_error(xs))); 16080709Sjake break; 161205258Smarius 162102040Sjake case USAGE: 163102040Sjake fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 16480709Sjake break; 16580709Sjake 16680709Sjake default: assert(0); break; 167 } 168 169 sdp_close(xs); 170 171 return (e); 172} /* do_sdp_command */ 173 174/* Try to find command in specified category */ 175static struct sdp_command * 176find_sdp_command(char const *command, struct sdp_command *category) 177{ 178 struct sdp_command *c = NULL; 179 180 for (c = category; c->command != NULL; c++) { 181 char *c_end = strchr(c->command, ' '); 182 183 if (c_end != NULL) { 184 int len = c_end - c->command; 185 186 if (strncasecmp(command, c->command, len) == 0) 187 return (c); 188 } else if (strcasecmp(command, c->command) == 0) 189 return (c); 190 } 191 192 return (NULL); 193} /* find_sdp_command */ 194 195/* Print commands in specified category */ 196static void 197print_sdp_command(struct sdp_command *category) 198{ 199 struct sdp_command *c = NULL; 200 201 for (c = category; c->command != NULL; c++) 202 fprintf(stdout, "\t%s\n", c->command); 203} /* print_sdp_command */ 204 205/* Usage */ 206static void 207usage(void) 208{ 209 fprintf(stderr, 210"Usage: sdpcontrol options command\n" \ 211"Where options are:\n" 212" -a address address to connect to\n" \ 213" -c path path to the control socket (default is %s)\n" \ 214" -h display usage and quit\n" \ 215" -l connect to the local SDP server via control socket\n" \ 216" command one of the supported commands\n", SDP_LOCAL_PATH); 217 exit(255); 218} /* usage */ 219 220