#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <signal.h>
#include <netinet/in.h>

char *makeEnv(char *name, char *value)
{
    char *result;

    result = malloc((unsigned) (strlen(name) + strlen(value) + 2));
    if (!result)
	exit(1);
    sprintf(result, "%s=%s", name, value);
    return result;
}

int main()
{
    int len;
    struct passwd *pwd;
    struct timeval tv;
    struct stat st;
    fd_set rfds;
    struct sockaddr_in from;
    socklen_t fromlen;
    char *mbox, *pt1, buff[100], mailinfo[100];
    char *env[4];

    fromlen = sizeof(from);
    if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
	fprintf(stderr, "comsat: getsockname: %s.\n", strerror(errno));
	exit(1);
    }

    signal(SIGCHLD, SIG_IGN);

    close(1);
    open("/dev/tty12", O_RDWR); dup2(1, 2);
    fcntl(0, F_SETFL, O_NONBLOCK);
    for (;;) {
	/* while (waitpid(-1, 0, WNOHANG) > 0); */
	FD_ZERO(&rfds);
	FD_SET(0, &rfds);
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	if (select (1, &rfds, 0, 0, &tv) <= 0)
	    break;
	if ((len = recv(0, buff, sizeof(buff) - 1, 0)) <= 0)
	    break;
	buff[len] = 0;
	printf("comsatd: '%s'\n", buff);
	if (!(pt1 = strchr(buff, '@')))
	    continue;
	*pt1++ = 0;
	if (!(mbox = strchr(pt1, ':')))
	    continue;
	if (mbox == pt1)
	    continue;
	mbox++;
	if (mbox[0] != '/')
	    continue;
	if (!strcmp(mbox, "/dev/null"))
	    continue;
	if (!strncmp(mbox, "/var/spool/mail/", 16))
	    strcpy(mbox + 5, mbox + 11);
	if (!(pwd = getpwnam(buff)))
	    continue;
	snprintf(mailinfo, sizeof(mailinfo), "%s/.mailinfo", pwd->pw_dir);
	if (stat(mailinfo, &st))
	    continue;
	if (!fork()) {
	    endpwent();
	    close(0);
	    open("/dev/null", O_RDONLY);
	    initgroups(pwd->pw_name, pwd->pw_gid);
	    if (!setgid(pwd->pw_gid) && !setuid(pwd->pw_uid)) {
		env[0] = makeEnv("HOME", pwd->pw_dir);
		env[1] = makeEnv("USER", pwd->pw_name);
		env[2] = makeEnv("LOGNAME", pwd->pw_name);
		env[3] = 0;
		execle(mailinfo, mailinfo, mbox, 0, env);
	    }
	    exit(1);
	}
    }
    endpwent();
    return 0;
}

