/*
 * mail.c: Ok, so I gave in.  I added mail checking.  So sue me. 
 *
 * Written By Michael Sandrof
 *
 * Copyright (c) 1990 Michael Sandrof.
 * Copyright (c) 1991, 1992 Troy Rollo.
 * Copyright (c) 1992-2004 Matthew R. Green.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "irc.h"
IRCII_RCSID("@(#)$eterna: mail.c,v 1.49 2005/09/21 22:19:20 mrg Exp $");

#include "newio.h"

#if defined(HAVE_DIRENT_H) || defined(_POSIX_SOURCE)
# include <dirent.h>
# define NLENGTH(d) (my_strlen((d)->d_name)
#else /* DIRENT || _POSIX_SOURCE */
# define dirent direct
# define NLENGTH(d) ((d)->d_namlen)
# ifdef HAVE_SYS_NDIR_H
#  include <sys/ndir.h>
# endif /* HAVE_SYS_NDIR_H */
# ifdef HAVE_SYS_DIR_H
#  include <sys/dir.h>
# endif /* HAVE_SYS_DIR_H */
# ifdef HAVE_NDIR_H
#  include <ndir.h>
# endif /* HAVE_NDIR_H */
#endif /* HAVE_DIRENT_H || _POSIX_VERSION */

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif /* HAVE_FCNTL_H */

#ifdef HAVE_SYS_FCNTL_H
# include <sys/fcntl.h>
#endif /* HAVE_SYS_FCNTL_H */

#include <sys/stat.h>

#include "mail.h"
#include "lastlog.h"
#include "hook.h"
#include "vars.h"
#include "ircaux.h"
#include "output.h"
#include "window.h"

#if defined(AMS_MAIL) || defined(UNIX_MAIL)
static	u_char	*mail_path = (u_char *) 0;

static	void	init_mail(void);
#endif

/* init_mail: this initialized the path to the users mailbox */
static	void
init_mail()
{
#if defined(AMS_MAIL) || defined(UNIX_MAIL)
# ifdef UNIX_MAIL
	u_char	*tmp_mail_path;
# endif

	if (mail_path)
		return; /* why do it 2000 times?  -lynx */

# ifdef UNIX_MAIL
	if ((tmp_mail_path = my_getenv("MAIL")) != NULL)
		malloc_strcpy(&mail_path, tmp_mail_path);
	else
	{
		malloc_strcpy(&mail_path, UP(UNIX_MAIL));
		malloc_strcat(&mail_path, UP("/"));
		malloc_strcat(&mail_path, username);
	}
# else
#  ifdef AMS_MAIL
	malloc_strcpy(&mail_path, my_path);
	malloc_strcat(&mail_path, "/");
	malloc_strcat(&mail_path, AMS_MAIL);
#  endif /* AMS_MAIL */
# endif /* UNIX_MAIL */
#endif /* AMS_MAIL || UNIX_MAIL */
}

#ifdef AMS_MAIL
/*
 * count_files: counts all the visible files in the specified directory and
 * returns that number as the function value 
 */
static	u_int
count_files(dir_name, lasttime)
	u_char	*dir_name;
	time_t	lasttime;
{
	DIR	*dir;
	struct	direct	*dirbuf;
	unsigned int	cnt;
	int	fd;
	u_char	LetterName[BIG_BUFFER_SIZE];
	struct	stat	LetterInfo;
	static	int	VirginProgram = 1;
	int	lastlog_level;

	if ((dir = opendir(dir_name)) == (DIR *) 0)
		return (0);
	cnt = 0;
	lastlog_level = set_lastlog_msg_level(LOG_CRAP);
	save_message_from();
	message_from((u_char *) 0, LOG_CURRENT);
	while ((dirbuf = readdir(dir)) != (struct direct *) 0)
	{
		if (*(dirbuf->d_name) != '.')
		{
			cnt++;
			snprintf(LetterName, sizeof LetterName, "%s/%s", dir_name, dirbuf->d_name);
			if (stat(LetterName, &LetterInfo) == -1)
				continue;
			if (get_int_var(MAIL_VAR) == 2 && LetterInfo.st_ctime>lasttime && !VirginProgram)
			{
				if ((fd = open(LetterName, O_RDONLY)) == -1)
					say("Unable to check headers on new mail");
				else
				{
					while (dgets(LetterName, sizeof LetterName, fd, (u_char *) 0) > 0 && *LetterName != '\n' &&
					    *LetterName != '\0')
					{
						LetterName[my_strlen(LetterName) - - 1] = '\0';
						if (!my_strnicmp(LetterName, "From", 4) || !my_strnicmp(LetterName, "Subject:", 8))
							say("%s", LetterName);
					}
					new_close(fd);
				}
			}
		}
	}
end:
	VirginProgram = 0;
	closedir(dir);
	restore_message_from();
	set_lastlog_msg_level(lastlog_level);
	return (cnt);
}
#endif /* AMS_MAIL */

/*
 * check_mail_status: returns 0 if mail status has not changed, 1 if mail
 * status has changed 
 */
int
check_mail_status()
{

#if defined(AMS_MAIL) || defined(UNIX_MAIL)
	struct	stat	stat_buf;
	static	time_t	old_stat = 0L;

#ifdef DAEMON_UID
	if (getuid() == DAEMON_UID)
		return 0;
#endif /* DAEMON_UID */

	if (!get_int_var(MAIL_VAR))
	{
		old_stat = 0L;
		return (0);
	}
	init_mail();
	if (stat(CP(mail_path), &stat_buf) == -1)
		return (0);
	if (stat_buf.st_ctime > old_stat)
	{
		old_stat = stat_buf.st_ctime;
		return (1);
	}
#endif /* defined(AMS_MAIL) || defined(UNIX_MAIL) */
	return (0);
}

/*
 * check_mail: This here thing counts up the number of pieces of mail and
 * returns it as static string.  If there are no mail messages, null is
 * returned. 
 */
u_char	*
check_mail()
{
#if !defined(AMS_MAIL) && !defined(UNIX_MAIL)
	return	(u_char *) 0;
#else
	static	unsigned int	cnt = 0;
	static	time_t	old_stat = 0L;
	static	u_char	ret_str[8];
	struct	stat	stat_buf;
	unsigned int	new_cnt = 0;
	u_char	tmp[8];
	static	int	VirginProgram = 1;  /* It's its first time */
	int	lastlog_level;
	u_char	buffer[BIG_BUFFER_SIZE];
#ifdef UNIX_MAIL
	int	des;
	int	blanks = 1;
	int	reset_blanks = 0;
#endif /* UNIX_MAIL */

#ifdef DAEMON_UID
	if (getuid()==DAEMON_UID)
		return ((u_char *) 0);
#endif /* DAEMON_UID */

	init_mail();
#ifdef UNIX_MAIL
	if (stat(CP(mail_path), &stat_buf) == -1)
		return ((u_char *) 0);
	lastlog_level = set_lastlog_msg_level(LOG_CRAP);
	save_message_from();
	message_from((u_char *) 0, LOG_CURRENT);
	if (stat_buf.st_ctime > old_stat)
	{
		old_stat = stat_buf.st_ctime;
		if ((des = open(CP(mail_path), O_RDONLY, 0)) >= 0)
		{
			new_cnt = 0;
			while (dgets(buffer, sizeof buffer, des,(u_char *) 0)>0)
			{
				if (buffer[0] == '\n') {
					blanks++;
					continue;
				}
				else
					reset_blanks = 1;
				if (!my_strncmp(MAIL_DELIMITER, buffer, sizeof(MAIL_DELIMITER) - 1) && blanks)
				{
					new_cnt++;
					if (new_cnt > cnt && !VirginProgram && get_int_var(MAIL_VAR) == 2)
					{
						while (dgets(buffer, sizeof buffer, des, (u_char *) 0) > 0 && *buffer != '\0' && *buffer != '\n')
						{
							buffer[my_strlen(buffer)-1] = '\0';
							if (!my_strncmp(buffer, "From:", 5) || !my_strncmp(buffer, "Subject:", 8))
								say("%s", buffer);
						}
					}
				}
				if (reset_blanks)
					reset_blanks = blanks = 0;
			}
			VirginProgram=0;
			new_close(des);
		}
#else
# ifdef AMS_MAIL
		if (stat(mail_path, &stat_buf) == -1)
		{
			set_lastlog_msg_level(lastlog_level);
			return ((u_char *) 0);
		}
		if (stat_buf.st_ctime > old_stat)
		{
			new_cnt = count_files(mail_path, old_stat);
			old_stat = stat_buf.st_ctime;
		}
# endif /* AMS_MAIL */
#endif /* UNIX_MAIL */
		/* yeeeeack */
		if (new_cnt > cnt)
		{
			snprintf(CP(tmp), sizeof tmp, "%d", new_cnt - cnt);
			snprintf(CP(buffer), sizeof buffer, "%d", new_cnt);
			if (do_hook(MAIL_LIST, "%s %s", tmp, buffer) && get_int_var(MAIL_VAR) == 1)
				say("You have new email.");
		}
		cnt = new_cnt;
	}
	set_lastlog_msg_level(lastlog_level);
	restore_message_from();
	if (cnt && (cnt < 65536))
	{
		snprintf(CP(ret_str), sizeof ret_str, "%d", cnt);
		return (ret_str);
	}
	else
		return ((u_char *) 0);
#endif /* !defined(AMS_MAIL) && !defined(UNIX_MAIL) */
}


syntax highlighted by Code2HTML, v. 0.9.1