1121054Semax/* 2121054Semax * sdpcontrol.c 3121054Semax * 4121054Semax * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5121054Semax * All rights reserved. 6121054Semax * 7121054Semax * Redistribution and use in source and binary forms, with or without 8121054Semax * modification, are permitted provided that the following conditions 9121054Semax * are met: 10121054Semax * 1. Redistributions of source code must retain the above copyright 11121054Semax * notice, this list of conditions and the following disclaimer. 12121054Semax * 2. Redistributions in binary form must reproduce the above copyright 13121054Semax * notice, this list of conditions and the following disclaimer in the 14121054Semax * documentation and/or other materials provided with the distribution. 15121054Semax * 16121054Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17121054Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18121054Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19121054Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20121054Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21121054Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22121054Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23121054Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24121054Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25121054Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26121054Semax * SUCH DAMAGE. 27121054Semax * 28121054Semax * $Id: sdpcontrol.c,v 1.1 2003/09/08 02:27:27 max Exp $ 29121054Semax * $FreeBSD$ 30121054Semax */ 31121054Semax 32121054Semax#include <assert.h> 33121054Semax#include <bluetooth.h> 34121054Semax#include <err.h> 35121054Semax#include <errno.h> 36121054Semax#include <sdp.h> 37121054Semax#include <stdio.h> 38121054Semax#include <stdlib.h> 39121054Semax#include <string.h> 40121054Semax#include <unistd.h> 41121054Semax#include "sdpcontrol.h" 42121054Semax 43121054Semax/* Prototypes */ 44124317Semaxstatic int do_sdp_command (bdaddr_p, char const *, int, 45124317Semax int, char **); 46121054Semaxstatic struct sdp_command * find_sdp_command (char const *, 47121054Semax struct sdp_command *); 48121054Semaxstatic void print_sdp_command (struct sdp_command *); 49121054Semaxstatic void usage (void); 50121054Semax 51121054Semax/* Main */ 52121054Semaxint 53121054Semaxmain(int argc, char *argv[]) 54121054Semax{ 55124317Semax char const *control = SDP_LOCAL_PATH; 56124317Semax int n, local; 57124317Semax bdaddr_t bdaddr; 58121054Semax 59121054Semax memset(&bdaddr, 0, sizeof(bdaddr)); 60124758Semax local = 0; 61121054Semax 62121054Semax /* Process command line arguments */ 63124317Semax while ((n = getopt(argc, argv, "a:c:lh")) != -1) { 64121054Semax switch (n) { 65124317Semax case 'a': /* bdaddr */ 66121054Semax if (!bt_aton(optarg, &bdaddr)) { 67121054Semax struct hostent *he = NULL; 68121054Semax 69121054Semax if ((he = bt_gethostbyname(optarg)) == NULL) 70121054Semax errx(1, "%s: %s", optarg, hstrerror(h_errno)); 71121054Semax 72121054Semax memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 73121054Semax } 74121054Semax break; 75121054Semax 76124317Semax case 'c': /* control socket */ 77124317Semax control = optarg; 78124317Semax break; 79124317Semax 80124317Semax case 'l': /* local sdpd */ 81124317Semax local = 1; 82124317Semax break; 83124317Semax 84121054Semax case 'h': 85121054Semax default: 86121054Semax usage(); 87121054Semax /* NOT REACHED */ 88121054Semax } 89121054Semax } 90121054Semax 91121054Semax argc -= optind; 92121054Semax argv += optind; 93121054Semax 94121054Semax if (*argv == NULL) 95121054Semax usage(); 96121054Semax 97124317Semax return (do_sdp_command(&bdaddr, control, local, argc, argv)); 98121054Semax} 99121054Semax 100121054Semax/* Execute commands */ 101121054Semaxstatic int 102124317Semaxdo_sdp_command(bdaddr_p bdaddr, char const *control, int local, 103124317Semax int argc, char **argv) 104121054Semax{ 105121054Semax char *cmd = argv[0]; 106121054Semax struct sdp_command *c = NULL; 107121054Semax void *xs = NULL; 108121054Semax int e, help; 109121054Semax 110121054Semax help = 0; 111121054Semax if (strcasecmp(cmd, "help") == 0) { 112121054Semax argc --; 113121054Semax argv ++; 114121054Semax 115121054Semax if (argc <= 0) { 116121054Semax fprintf(stdout, "Supported commands:\n"); 117121054Semax print_sdp_command(sdp_commands); 118121054Semax fprintf(stdout, "\nFor more information use " \ 119121054Semax "'help command'\n"); 120121054Semax 121121054Semax return (OK); 122121054Semax } 123121054Semax 124121054Semax help = 1; 125121054Semax cmd = argv[0]; 126121054Semax } 127121054Semax 128121054Semax c = find_sdp_command(cmd, sdp_commands); 129121054Semax if (c == NULL) { 130121054Semax fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 131121054Semax return (ERROR); 132121054Semax } 133121054Semax 134121054Semax if (!help) { 135124317Semax if (!local) { 136124317Semax if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) 137124317Semax usage(); 138121054Semax 139124317Semax xs = sdp_open(NG_HCI_BDADDR_ANY, bdaddr); 140124317Semax } else 141124317Semax xs = sdp_open_local(control); 142124317Semax 143124317Semax if (xs == NULL) 144121054Semax errx(1, "Could not create SDP session object"); 145121054Semax if (sdp_error(xs) == 0) 146121054Semax e = (c->handler)(xs, -- argc, ++ argv); 147121054Semax else 148121054Semax e = ERROR; 149121054Semax } else 150121054Semax e = USAGE; 151121054Semax 152121054Semax switch (e) { 153121054Semax case OK: 154121054Semax case FAILED: 155121054Semax break; 156121054Semax 157121054Semax case ERROR: 158121054Semax fprintf(stdout, "Could not execute command \"%s\". %s\n", 159121054Semax cmd, strerror(sdp_error(xs))); 160121054Semax break; 161121054Semax 162121054Semax case USAGE: 163121054Semax fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 164121054Semax break; 165121054Semax 166121054Semax default: assert(0); break; 167121054Semax } 168121054Semax 169121054Semax sdp_close(xs); 170121054Semax 171121054Semax return (e); 172121054Semax} /* do_sdp_command */ 173121054Semax 174121054Semax/* Try to find command in specified category */ 175121054Semaxstatic struct sdp_command * 176121054Semaxfind_sdp_command(char const *command, struct sdp_command *category) 177121054Semax{ 178121054Semax struct sdp_command *c = NULL; 179121054Semax 180121054Semax for (c = category; c->command != NULL; c++) { 181121054Semax char *c_end = strchr(c->command, ' '); 182121054Semax 183121054Semax if (c_end != NULL) { 184121054Semax int len = c_end - c->command; 185121054Semax 186121054Semax if (strncasecmp(command, c->command, len) == 0) 187121054Semax return (c); 188121054Semax } else if (strcasecmp(command, c->command) == 0) 189121054Semax return (c); 190121054Semax } 191121054Semax 192121054Semax return (NULL); 193121054Semax} /* find_sdp_command */ 194121054Semax 195121054Semax/* Print commands in specified category */ 196121054Semaxstatic void 197121054Semaxprint_sdp_command(struct sdp_command *category) 198121054Semax{ 199121054Semax struct sdp_command *c = NULL; 200121054Semax 201121054Semax for (c = category; c->command != NULL; c++) 202121054Semax fprintf(stdout, "\t%s\n", c->command); 203121054Semax} /* print_sdp_command */ 204121054Semax 205121054Semax/* Usage */ 206121054Semaxstatic void 207121054Semaxusage(void) 208121054Semax{ 209124317Semax fprintf(stderr, 210124317Semax"Usage: sdpcontrol options command\n" \ 211124317Semax"Where options are:\n" 212133178Semax" -a address address to connect to\n" \ 213124317Semax" -c path path to the control socket (default is %s)\n" \ 214124317Semax" -h display usage and quit\n" \ 215124317Semax" -l connect to the local SDP server via control socket\n" \ 216124317Semax" command one of the supported commands\n", SDP_LOCAL_PATH); 217121054Semax exit(255); 218121054Semax} /* usage */ 219121054Semax 220