#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>

#define	TRUE		1
#define	FALSE		0


struct speed_struct
{
	int     user_speed;
	speed_t termios_speed;
}
speed_table[] =
{
	{300,		B300},
	{600,		B600},
	{1200,		B1200},
	{2400,		B2400},
	{4800,		B4800},
	{9600,		B9600},
	{19200,		B19200},
	{38400,		B38400},
	{-1,		B0}
};


int setspeed(int fd, int speed)
{
	struct termios term;
	struct speed_struct *s;
	
	for (s = speed_table; s->user_speed != -1; s++)
		if (s->user_speed == speed)
			break;

	if (s->user_speed == -1)
	{
		fprintf(stderr, "Invalid speed %d\n", speed);
		return(FALSE);
	}
	
	if (tcgetattr(fd, &term) == -1)
	{
		perror("tcgetattr");
		return(FALSE);
	}
	
	cfsetispeed(&term, s->termios_speed);
	cfsetospeed(&term, s->termios_speed);
	
	if (tcsetattr(fd, TCSANOW, &term) == -1)
	{
		perror("tcsetattr");
		return(FALSE);
	}
	
	return(TRUE);
}


int setifcall(int fd, char *name)
{
	char call[7];
	int  ct = 0;
	int  ssid = 0;
	char *p = name;
	
	while (ct < 6)
	{
		if (islower(*p)) *p = toupper(*p);

		call[ct] = (*p << 1);
		p++;
		ct++;

		if (*p == '-' || *p == 0) break;
	}
	
	while (ct < 6)
	{
		call[ct] = ' ' << 1;
		ct++;
	}
	
	if (*p != 0)
	{
		if (sscanf(p + 1, "%d", &ssid) != 1 || ssid < 0 || ssid > 15)
		{
			fprintf(stderr, "SSID must follow '-' and be numeric in the range 0-15.\n");
			return(FALSE);
		}
	}

	call[6] = ((ssid + '0') << 1) & 0x1E;
		
	if (ioctl(fd, SIOCSIFHWADDR, call) != 0)
	{
		close(fd);
		perror("SIOCSIFHWADDR");
		return(FALSE);
	}

	return(TRUE);
}
	

int main(int argc, char *argv[])
{
	int  fd;
	int  disc = N_SLIP;
	char buf[64];
	int  v = 4;
	
	if (argc < 4)
	{
		fprintf(stderr,"%s <ttyinterface> <speed> <callsign>.\n", argv[0]);
		return(1);
	}
	
	if ((fd = open(argv[1], O_RDONLY | O_NDELAY)) == -1)
	{
		perror(argv[1]);
		return(1);
	}
	
	if (ioctl(fd, TIOCSETD, &disc) == -1)
	{
		perror("TIOCSETD");
		return(1);
	}
	
	if (ioctl(fd, SIOCGIFNAME, buf) == -1)
	{
		perror("SIOCGIFNAME");
		return(1);
	}

	if (!setspeed(fd, atoi(argv[2])))
		return(1);
	
	if (!setifcall(fd, argv[3]))
		return(1);
	
	/* Now set the encapsulation */
	if (ioctl(fd, SIOCSIFENCAP, &v) == -1)
	{
		perror("SIOCSIFENCAP");
		return(1);
	}
		
	printf("Interface %s bound to tty %s at %s baud with callsign %s\n",
		buf, argv[1], argv[2], argv[3]);	
		
	signal(SIGHUP, SIG_IGN);
	
	while (1)
		sleep(10000);
		
	/* NOT REACHED */
	return(0);
}