/*
 *  hap -- a mail notification program
 * 
 *  copyright 1995 by Eric Fischer, etaoin@uchicago.edu
 * 
 *  copies of hap may be redistributed under the terms of the
 *  GNU public license, copies of which are available from
 *  the Free Software Foundation, 59 Temple Place, Boston, MA
 *  02111 USA.
 *
 */

#include "hap.h"

/****************************************************************************

   FILE LOOKUP STUFF

****************************************************************************/

/* try the mail spool directory named 'spool' and see if there's a file
   with our name on it in there.  return a pointer to the full name of the
   file (spool + our name) if it's there, 0 if not.  pointers are only
   good until the next call, so copy them if you want to keep them.
*/

char *
stry (spool, me)
	char *spool;
	char *me;
{
	static char *ya = 0;

	/* try the /whatever/me/me case

	   I've never actually seen a system that does it this way, but
	   somewhere I heard there were computers like this.  Doesn't cost
	   much to check, anyway...
	*/

	if (ya) free (ya), ya = 0;
	ya = xmalloc (strlen (spool) + strlen (me) + 1 + strlen (me) + 1);

	strcpy (ya, spool);
	strcat (ya, me);
	strcat (ya, "/");
	strcat (ya, me);

	if (getsize (ya) != -1) return ya;

	/* try the /whatever/me case */

	if (ya) free (ya), ya = 0;
	ya = xmalloc (strlen (spool) + strlen (me) + 1);

	strcpy (ya, spool);
	strcat (ya, me);

	if (getsize (ya) != -1) return ya;
	return 0;
}

/* try to find the mail spool.  Why can't people agree on somewhere to
   keep this?  Anyway, try all the usual possibilities, first looking for
   real files, then if there's no actual file to be found, looking for
   directories that might plausibly contain mail files.  If none of those
   can be found either, give up and guess /usr/spool/mail.
*/

char *
getspoolname (me)
	char *me;
{
	char *x;

	if ((x = stry ("/usr/spool/mail/", me))) return x;
	if ((x = stry ("/var/spool/mail/", me))) return x;
	if ((x = stry ("/usr/mail/", me)))       return x;
	if ((x = stry ("/var/mail/", me)))       return x;

	if (exs("/usr/spool/mail")) return conc("/usr/spool/mail/", me); 
	if (exs("/var/spool/mail")) return conc("/var/spool/mail/", me);
	if (exs("/usr/mail"))       return conc("/usr/mail/", me);
	if (exs("/var/mail"))       return conc("/var/mail/", me);

	/* we have no clue, take a guess... */

	return conc ("/usr/spool/mail/", me);
}

/* given a filename, either return it unchanged or if it's an alias
   for a mail spool, expand it into a full path to the mail.

   THIS FUNCTION ALLOCATES MEMORY and does NOT return a pointer to
   static data which is overwritten with each call.
*/

char *
expandname (name)
	char *name;
{
	if (name[0] != '%') {
		return strdupe (name);
	} else {
		if (name[1] == 0) {
			char *x = getenv ("MAIL");

			if (x) return x;
			else return strdupe (getspoolname (whoami()));
		} else {
			return strdupe (getspoolname (name + 1));
		}
	}
}

/* return the last-modified time of the file named filename.  This
   is used to see if an mh folder has changed.
*/

time_t
getmtime (filename)
	char *filename;
{
	struct stat buf;

	if (stat (filename, &buf) == -1) return -1;
	return buf.st_mtime;
}

/* returns the size of the file whose path is given in 'filename'.
   if it doesn't exist, return -1. */

long
getsize (filename)
	char *filename;
{
	struct stat buf;

	if (stat (filename, &buf) == -1) return -1;
	return buf.st_size;
}

/* return true if filename is a directory; 0 if not */

int
checkdir(filename)
	char *filename;
{
	struct stat buf;

	if (stat (filename, &buf) == -1) return 0;
	return buf.st_mode & S_IFDIR;
}

/* returns whether the file 'filename' exists. */

int
exs (filename)
	char *filename;
{
	struct stat buf;

	if (stat (filename, &buf) == -1) return 0;
	return 1;
}

/* get last access time of the file descriptor fd */

time_t
getlasttime (fd)
	int fd;
{
	struct stat buf;

	if (fstat (fd, &buf) == -1) return -1;
	return buf.st_atime;
}

/* check permissions on the file descriptor fd.  If group-writeable,
   return false, otherwise true.  (reversed so we can idle with
   while (mesgy()).)  this is for the -m option.
*/

int
mesgy (fd)
	int fd;
{
	struct stat buf;
	mode_t mode;

	/* if it's broken, just leave -- better to overwrite the screen
	   than to loop forever...
	*/

	if (fstat (fd, &buf) != 0) return 0;

	mode = (buf.st_mode & 070) >> 3;  /* group permissions */

	if (mode & 2) return 0;  /* if group-writeable, stop looping */
	else return 1;
}

