/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2002-2004  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation;
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
 *  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
 *  CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *  ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
 *  COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
 *  SOFTWARE IS DISCLAIMED.
 *
 *
 *  $Id$
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>

extern int optind, opterr, optopt;
extern char *optarg;

/* IO cancelation */
static volatile sig_atomic_t __io_canceled;

static inline void io_init(void)
{
	__io_canceled = 0;
}

static inline void io_cancel(void)
{
	__io_canceled = 1;
}

/* Signal functions */
static void sig_hup(int sig)
{
	return;
}

static void sig_term(int sig)
{
	syslog(LOG_INFO, "Closing RFCOMM channel");
	io_cancel();
}

/* Read exactly len bytes (Signal safe)*/
static inline int read_n(int fd, char *buf, int len)
{
	register int t = 0, w;

	while (!__io_canceled && len > 0) {
		if ((w = read(fd, buf, len)) < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
			return -1;
		}
		if (!w)
			return 0;
		len -= w;
		buf += w;
		t += w;
	}

	return t;
}

/* Write exactly len bytes (Signal safe)*/
static inline int write_n(int fd, char *buf, int len)
{
	register int t = 0, w;

	while (!__io_canceled && len > 0) {
		if ((w = write(fd, buf, len)) < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
			return -1;
		}
		if (!w)
			return 0;
		len -= w;
		buf += w;
		t += w;
	}

	return t;
}

/* Create the RFCOMM connection */
static int create_connection(bdaddr_t *bdaddr, uint8_t channel)
{
	struct sockaddr_rc remote_addr, local_addr;
	int fd, err;

	if ((fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
		return fd;

	memset(&local_addr, 0, sizeof(local_addr));
	local_addr.rc_family = AF_BLUETOOTH;
	bacpy(&local_addr.rc_bdaddr, BDADDR_ANY);
	if ((err = bind(fd, (struct sockaddr *)&local_addr, sizeof(local_addr))) < 0) {
		close(fd);
		return err;
	}

	memset(&remote_addr, 0, sizeof(remote_addr));
	remote_addr.rc_family = AF_BLUETOOTH;
	bacpy(&remote_addr.rc_bdaddr, bdaddr);
	remote_addr.rc_channel = channel;
	if ((err = connect(fd, (struct sockaddr *)&remote_addr, sizeof(remote_addr))) < 0) {
		close(fd);
		return err;
	}

	syslog(LOG_INFO, "RFCOMM channel %d connected", channel);

	return fd;
}

/* Process the data from socket and pseudo tty */
static int process_data(int fd)
{
	struct pollfd p[2];
	char buf[1024];
	int err, r;

	p[0].fd = 0;
	p[0].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
	
	p[1].fd = fd;
	p[1].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;

	err = 0;

	while (!__io_canceled) {
		p[0].revents = 0;
		p[1].revents = 0;
		
		err = poll(p, 2, -1);
		if (err < 0)
			break;

		err = 0;

		if (p[0].revents) {
			if (p[0].revents & (POLLERR | POLLHUP | POLLNVAL))
			  break;
			r = read(0, buf, sizeof(buf));
			if (r < 0) {
				if (errno != EINTR && errno != EAGAIN) {
					err = r;
					break;
				}
			}

			err = write_n(fd, buf, r);
			if (err < 0)
				break;
		}

		if (p[1].revents) {
			if (p[1].revents & (POLLERR | POLLHUP | POLLNVAL))
				break;
			r = read(fd, buf, sizeof(buf));
			if (r < 0) {
				if (errno != EINTR && errno != EAGAIN) {
					err = r;
					break;
				}
			}

			err = write_n(1, buf, r);
			if (err < 0)
				break;
		}
	}

	return err;
}

static void usage(void)
{
	printf("Usage:\tppporc <bdaddr> [channel]\n");
}

int main(int argc, char** argv)
{
	struct sigaction sa;
	int fd, err, opt;

	bdaddr_t bdaddr;
	uint8_t channel;

	/* Parse command line options */
	while ((opt = getopt(argc, argv, "h")) != EOF) {
		switch(opt) {
		case 'h':
			usage();
			exit(0);
		}
	}

	argc -= optind;
	argv += optind;

	switch (argc) {
	case 1:
		str2ba(argv[0], &bdaddr);
		channel = 1;
		break;
	case 2:
		str2ba(argv[0], &bdaddr);
		channel = atoi(argv[1]);
		break;
	default:
		usage();
		exit(0);
	}

	/* Initialize syslog */
	openlog("ppporc", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
	syslog(LOG_INFO, "PPP over RFCOMM");

	/* Initialize signals */
	memset(&sa, 0, sizeof(sa));
	sa.sa_flags   = SA_NOCLDSTOP;
	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = sig_hup;
	sigaction(SIGHUP, &sa, NULL);

	syslog(LOG_INFO, "Connecting to %s", argv[0]);

	if ((fd = create_connection(&bdaddr, channel)) < 0) {
		syslog(LOG_ERR, "Can't connect to remote device (%s)", strerror(errno));
		return fd;
	}

	err = process_data(fd);

	close(fd);

	return err;
}
