#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <utmp.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define BUILD_PUTUTMP
#include "pututmp.h"
#include "pututmp_internal.h"

struct utmptext
{
	char 	utt_type[32];		 /* type of login */
	char	utt_pid[32];		 /* pid of login-process */
	char	utt_line[UT_LINESIZE+1]; /* devicename of tty -"/dev/" */
	char	utt_id[4+1];		 /* inittab id */
	char	utt_time[32];		 /* login time */
	char	utt_user[UT_NAMESIZE+1]; /* username */
	char	utt_host[UT_HOSTSIZE+1]; /* hostname for remote login... */
	char	utt_addr[32];		 /* IP addr of remote host */
};

void pututline_helper(struct utmp *ut)
{
	int ret=0, status;
	pid_t pid;
	struct sigaction sa, intr, quit;
	sigset_t block, omask;

	if (geteuid()==0) {pututline(ut); return;}

	sa.sa_handler = SIG_IGN;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	sigemptyset(&block);
	sigaddset(&block, SIGCHLD);
	if (sigaction(SIGINT, &sa, &intr)==-1) {ret=errno; goto out0;}
	if (sigaction(SIGQUIT, &sa, &quit)==-1) {ret=errno; goto out1;}
	if (sigprocmask(SIG_BLOCK, &block, &omask)==-1) {ret=errno; goto out2;}
	if ((pid=fork())==-1) {ret=errno; goto out3;}
	if (pid==0)
	{
		struct utmptext utt;
		memset(&utt, 0, sizeof(utt));
	
		sprintf(utt.utt_type, "%i", (int)ut->ut_type);
		sprintf(utt.utt_pid, "%i", (int)ut->ut_pid);
		strncpy(utt.utt_line, ut->ut_line, sizeof(ut->ut_line));
		strncpy(utt.utt_id, ut->ut_id, sizeof(ut->ut_id));
		sprintf(utt.utt_time, "%li", (long)ut->ut_time);
		strncpy(utt.utt_user, ut->ut_user, sizeof(ut->ut_user));
		strncpy(utt.utt_host, ut->ut_host, sizeof(ut->ut_host));
		sprintf(utt.utt_addr, "%i.%i.%i.%i", 
			((unsigned char *)&ut->ut_addr)[0],
			((unsigned char *)&ut->ut_addr)[1],
			((unsigned char *)&ut->ut_addr)[2],
			((unsigned char *)&ut->ut_addr)[3]);
		execl(PUTUTMP, PUTUTMP, "1",
			utt.utt_type,
			utt.utt_pid,
			utt.utt_line,
			utt.utt_id,
			utt.utt_time,
			utt.utt_user,
			utt.utt_host,
			utt.utt_addr,
			NULL);
		exit(1);
	}
	while (waitpid(pid, &status, 0)==-1)
		if (errno!=EINTR) {ret=errno; goto out3;}
	if (sigprocmask(SIG_SETMASK, &omask, NULL)==-1) {ret=errno; goto out2;}
	if (sigaction(SIGQUIT, &quit, NULL)==-1) {ret=errno; goto out1;}
	if (sigaction(SIGINT, &intr, NULL)==-1) {ret=errno; goto out0;}
	return ;

 out3:	sigprocmask(SIG_SETMASK, &omask, NULL);
 out2:	sigaction(SIGQUIT, &quit, NULL);
 out1:	sigaction(SIGINT, &intr, NULL);
 out0:	errno=ret;
}


