#include <sys/unix.h>
#include "init.h"
#include "alloc.h"

extern int ERRNO;

char	*args[] = { "login", 0 };

kid *spawn();
void field();
void readline();

int logins;

main( argc, argv )
int	argc;
char	*argv[];
{
	char	line[128];
	kid	*child[32];	/* Maximum offspring */
	int	i, lastchild,
		pid, status;

	signal( SIGINT, SIG_IGN );

	logins = open( "/etc/logins", O_RDONLY );
	while( ERRNO )	/* It might suddenly appear <giggles> */
		logins = open( "/etc/logins", O_RDONLY );

	/* Spawn a login for each active terminal */
	i=0;
	while( i<32 )
	{
		/* Details of terminal device */
		readline( logins, line );
		if( *line == 0 )
			break;

		child[i] = spawn( line, 0 );

		i++;
	}
	lastchild = i;

	/* Now wait for them to terminate, so we can spawn new logins */
	while(1)
	{
		int	syncer();
		signal( SIGALRM, syncer );
		alarm( 30 );
		do {
			pid = wait( &status );
		} while( pid != -1 );
		for(i=0;i<lastchild;i++)
			if( child[i]->pid == pid )
				(void)spawn( &(child[i]->line[0]), child[i] );
	}
}


kid *spawn( line, prev )
char	*line;
char	*prev;
{
	char	part[64];
	int	stdin, stdout, stderr;
	kid	*kid;
	int	pid;

	/* Filename of device interface */
	field( line, part, 0 );

	/* Fork off a login and/or tidy up */
	if( pid = fork() )
	{
		kid = prev ? prev : wmalloc( sizeof(int) + strlen(line) + 1 );
		kid->pid = pid;
		strcpy( &(kid->line[0]), line );
	}
	else
	{
		close(logins);
		/* Usual streams */
		do{ stdin = open( part, O_RDONLY ); }while( ERRNO );
		do{ stdout = open( part, O_WRONLY ); }while( ERRNO );
		do{ stderr = open( part, O_WRONLY ); }while( ERRNO );

		execve( "/bin/login", &args[0], &args[1] );
		_exit(-1);
	}
	
	return( kid );
}


void field( src, dst, num )
char	*src,
	*dst;
int	num;
{
	char	*pos = src;
	while( num && *pos )
		if( *pos++ == ':' )
			num--;
	while( *pos && (*pos!=':') )
		*dst++ = *pos++;
	*dst = 0;
}

void readline( f, dst )
int	f;
char	*dst;
{
	while( read(f,dst,1) && !ERRNO )
		if( *dst == '\n' )
			break;
		else
			dst++;
	*dst = 0;
}

int syncer( num )
int	num;
{
	sync();
	signal( SIGALRM, syncer );
	alarm(30);
}

