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