diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-09-28 13:21:42 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2007-09-28 13:21:42 +0000 | 
| commit | a87f1daabf62c0f45dfb9e1c5f21cec75477d342 (patch) | |
| tree | 9b53596bcaf69e42b21014429f9a4d7ef6086f99 | |
| parent | 536cb174ec2d4937bf14fee7d713018e1bb31404 (diff) | |
Add support for script execution.
| -rw-r--r-- | network/common.c | 95 | ||||
| -rw-r--r-- | network/common.h | 6 | ||||
| -rw-r--r-- | network/connection.c | 6 | ||||
| -rw-r--r-- | network/server.c | 6 | 
4 files changed, 99 insertions, 14 deletions
| diff --git a/network/common.c b/network/common.c index d818829a..dce12415 100644 --- a/network/common.c +++ b/network/common.c @@ -32,17 +32,21 @@  #include <sys/ioctl.h>  #include <sys/socket.h>  #include <sys/stat.h> +#include <sys/wait.h>  #include <net/if.h>  #include <bluetooth/bluetooth.h>  #include <bluetooth/l2cap.h>  #include <bluetooth/bnep.h> +#include <glib.h> +  #include "logging.h"  #include "common.h"  #include "textfile.h"  static int ctl; +static GSList *pids;  #define PANU_UUID	"00001115-0000-1000-8000-00805f9b34fb"  #define NAP_UUID	"00001116-0000-1000-8000-00805f9b34fb" @@ -59,6 +63,27 @@ static struct {  	{ NULL }  }; +struct bnep_data { +	char *devname; +	int pid; +}; + +static void script_exited(GPid pid, gint status, gpointer data) +{ +	struct bnep_data *bnep = data; + +	if (WIFEXITED(status)) +		debug("%d exited with status %d", pid, WEXITSTATUS(status)); +	else +		debug("%d was killed by signal %d", pid, WTERMSIG(status)); + +	g_spawn_close_pid(pid); +	pid = 0; + +	g_free(bnep->devname); +	pids = g_slist_remove(pids, bnep); +} +  uint16_t bnep_service_id(const char *svc)  {  	int i; @@ -183,26 +208,82 @@ int bnep_connadd(int sk, uint16_t role, char *dev)  	return 0;  } -int bnep_if_up(const char *devname, int up) +static void bnep_setup(gpointer data)  { -	int sd, err; +} + +int bnep_if_up(const char *devname, const char *script) +{ +	int sd, err, pid;  	struct ifreq ifr; +	const char *argv[3]; +	struct bnep_data *bnep;  	sd = socket(AF_INET6, SOCK_DGRAM, 0); +	memset(&ifr, 0, sizeof(ifr));  	strcpy(ifr.ifr_name, devname); -	if (up) -		ifr.ifr_flags |= IFF_UP; -	else -		ifr.ifr_flags &= ~IFF_UP; +	ifr.ifr_flags |= IFF_UP; -	if((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) { +	if ((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) {  		err = errno;  		error("Could not bring up %d. %s(%d)", devname, strerror(err),  			err);  		return -err;  	} +	if (!script) +		return 0; + +	argv[0] = script; +	argv[1] = devname; +	argv[2] = NULL; +	if (!g_spawn_async(NULL, (char **) argv, NULL, +				G_SPAWN_DO_NOT_REAP_CHILD, bnep_setup, +				(gpointer) devname, &pid, NULL)) { +		error("Unable to execute %s", argv[0]); +		return -1; +	} + +	bnep = g_new0(struct bnep_data, 1); +	bnep->devname = g_strdup(devname); +	bnep->pid = pid; +	pids = g_slist_append(pids, bnep); +	g_child_watch_add(pid, script_exited, bnep); + +	return pid; +} + +int bnep_if_down(const char *devname) +{ +	int sd, err; +	struct ifreq ifr; +	GSList *l; + +	sd = socket(AF_INET6, SOCK_DGRAM, 0); +	memset(&ifr, 0, sizeof(ifr)); +	strcpy(ifr.ifr_name, devname); + +	ifr.ifr_flags &= ~IFF_UP; + +	if ((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) { +		err = errno; +		error("Could not bring down %d. %s(%d)", devname, strerror(err), +			err); +		return -err; +	} + +	for(l = pids; l; l = g_slist_next(l)) { +		struct bnep_data *bnep = l->data; + +		if (strcmp(devname, bnep->devname) == 0) { +			if (kill(bnep->pid, SIGTERM) < 0) +				error("kill(%d, SIGTERM): %s (%d)", bnep->pid, +					strerror(errno), errno); +			break; +		} +	} +  	return 0;  } diff --git a/network/common.h b/network/common.h index 1d8b57de..de9d753d 100644 --- a/network/common.h +++ b/network/common.h @@ -21,6 +21,9 @@   *   */ +#define MAX_PATH_LENGTH 64 /* D-Bus path */ +#define NETWORK_PATH "/org/bluez/network" +  int bnep_init(void);  int bnep_cleanup(void); @@ -32,6 +35,7 @@ int bnep_kill_connection(bdaddr_t *dst);  int bnep_kill_all_connections(void);  int bnep_connadd(int sk, uint16_t role, char *dev); -int bnep_if_up(const char *devname, int up); +int bnep_if_up(const char *devname, const char *script); +int bnep_if_down(const char *devname);  int read_remote_name(bdaddr_t *src, bdaddr_t *dst, char *buf, size_t size); diff --git a/network/connection.c b/network/connection.c index e6a6c151..fb1b2cdf 100644 --- a/network/connection.c +++ b/network/connection.c @@ -157,7 +157,7 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond,  		goto failed;  	} -	bnep_if_up(nc->dev, TRUE); +	bnep_if_up(nc->dev, nc->script);  	dbus_connection_emit_signal(connection, nc->path,  					NETWORK_CONNECTION_INTERFACE,  					"Connected", @@ -515,7 +515,7 @@ static DBusHandlerResult connection_disconnect(DBusConnection *conn,  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	bnep_if_up(nc->dev, FALSE); +	bnep_if_down(nc->dev);  	bnep_kill_connection(&nc->dst);  	reply = dbus_message_new_method_return(msg); @@ -590,7 +590,7 @@ static void connection_free(struct network_conn *nc)  		g_free(nc->path);  	if (nc->state == CONNECTED) { -		bnep_if_up(nc->dev, FALSE); +		bnep_if_down(nc->dev);  		bnep_kill_connection(&nc->dst);  	} diff --git a/network/server.c b/network/server.c index 76be55b3..b1257760 100644 --- a/network/server.c +++ b/network/server.c @@ -337,14 +337,14 @@ static void authorization_callback(DBusPendingCall *pcall, void *data)  	info("Authorization succedded. New connection: %s", devname);  	response = BNEP_SUCCESS; -	if (bridge_add_interface("pan0", devname) < 0) { +	if (bridge_add_interface(ns->bridge, devname) < 0) {  		error("Can't add %s to the bridge: %s(%d)",  				devname, strerror(errno), errno);  		goto failed;  	} -	bnep_if_up(devname, TRUE); -	bnep_if_up("pan0", TRUE); +	bnep_if_up(devname, NULL); +	bnep_if_up(ns->bridge, NULL);  	ns->clients = g_slist_append(ns->clients, g_strdup(s->address)); | 
