#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <linux/ax25.h>

#include "config.h"

#define PMS_PATH	"/usr/local/bin/pms"

int main(int argc, char *argv[])
{
	struct full_sockaddr_ax25 ax;
	char message[80];
	int netrom = 0;
	int port   = 0;
	int s;
	int sz;

	while ((s = getopt(argc, argv, "np:")) != -1) {
		switch (s) {
			case 'n':
				netrom = 1;
				break;
			case 'p':
				port = atoi(optarg) - 1;
				break;
			case ':':
				fprintf(stderr, "axl: -p option requires a numeric argument\n");
				return 1;
			case '?':
				fprintf(stderr, "usage: axl [-n] [-p port]\n");
				return 1;
		}
	}
	
	if (netrom) {
		if (nr_config_load_ports() == -1) {
			fprintf(stderr, "axl: no NET/ROM ports configured\n");
			return 1;
		}

		if (port < 0 || port >= nr_config_num_ports()) {
			fprintf(stderr, "axl: invalid NET/ROM port\n");
			return 1;
		}

		if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
			perror("socket");
			return 1;
		}
	
		sz = convert_call(nr_config_get_addr(port), &ax);
	} else {
		if (ax25_config_load_ports() == -1) {
			fprintf(stderr, "axl: no AX.25 ports configured\n");
			return 1;
		}

		if (port < 0 || port >= ax25_config_num_ports()) {
			fprintf(stderr, "axl: invalid AX.25 port\n");
			return 1;
		}

		if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
			perror("socket");
			return 1;
		}

		sz = convert_call(ax25_config_get_addr(port), &ax);
	}

	if (bind(s, (struct sockaddr *)&ax, sz) == -1) {
		perror("bind");
		return 1;
	}
	
	if (listen(s, 5) == -1) {
		perror("listen");
		return 1;
	}
	
	signal(SIGCLD, SIG_IGN);	/* No zombies */
	
	for (;;) {
		int new;

		if ((new = accept(s, NULL, 0)) == -1) {
			perror("accept");
		} else {
			int pid;

			if ((pid = fork()) == 0) {	
				int win;
				
				if (!netrom) {
					win = ax25_config_get_window(port);
					setsockopt(new, SOL_AX25, AX25_WINDOW, &win, sizeof(win));
				}

				sprintf(message, "Connected to GW4PTS %s Port %d\r", (netrom) ? "NET/ROM" : "AX.25", port + 1);
				write(new, message, strlen(message));

				dup2(new, 0);
				dup2(new, 1);
				dup2(new, 2);

				if (new > 2) close(new);
				if (s > 2)   close(s);

				execl(PMS_PATH, "pms", NULL);

				exit(1);
			}

			close(new);
		}
	}

	close(s);

	return 0;
}
