/*
 *	Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *	This will be free software, but only when it is finished.
 *
 *	Also Guy Middleton, and Matti Aarnio have hacked this piece -- 1993
 */


/*LINTLIBRARY*/

#include <stdio.h>
#include "hostenv.h"
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/socket.h>
#include "mail.h"


#ifdef	MOUNTED_GETMNT /* DEC Ultrix */
#include <sys/param.h>
#include <sys/mount.h>
#endif

#ifdef	MOUNTED_GETMNTINFO /* DEC OSF/1 */
#include <sys/types.h>
#include <sys/mount.h>
#endif

#ifdef MOUNTED_GETMNTENT2
#include <sys/mnttab.h>
#include <sys/mntent.h>
#define	MNTTYPE	struct mnttab
#endif

#ifdef MOUNTED_GETMNTENT1
#include <mntent.h>
#define	MNTTYPE	struct mntent
#endif

/* XXX: AIX vmount() ??  Any others missing ?? */

extern char *strchr();

/* Sort of 'forward' definition */
static char	*getmntpt();


/*
 * Given a name like /usr/src/etc/foo.c returns the mount point
 * for the file system it lives in, or NULL in case of any error.
 */
#ifdef MOUNTED_GETMNT /* Ultrix */
static char *
getmntpt(file, dir)
	char	*file, **dir;
{
	int	mountind, nummount;
	static struct fs_data	mounts[1];
	struct stat	filestat, dirstat;

	if (stat(file, &filestat) < 0) {
		perror(file);
		return(NULL);
	}
	mountind = 0;
	while ((nummount = getmountent(&mountind, mounts, 1)) > 0) {
		if ((stat(mounts[0].fd_path, &dirstat) >= 0) &&
		   (filestat.st_dev == dirstat.st_dev)) {
			*dir = mounts[0].fd_path;
			return mounts[0].fd_devname;
		}
	}
	if (nummount == -1)
		perror("Can't get mount information");
	return NULL;
}
#endif

#ifdef MOUNTED_GETMNTINFO /* DEC OSF/1 */
static char *
getmntpt(file, dir)
	char	*file, **dir;
{
	int	nummount, i;
	struct	statfs *mounts;
	static struct statfs mntfs;
	struct stat	filestat, dirstat;

	if (stat(file, &filestat) < 0) {
		perror(file);
		return(NULL);
	}

	mounts = NULL;
	if ((nummount = getmntinfo(&mounts, MNT_NOWAIT)) == 0) {
		perror("Can't get mount information");
		return NULL;
	}

	for (i=0; i<nummount; i++) {
		if ((stat(mounts[i].f_mntonname, &dirstat) >= 0) &&
		   (filestat.st_dev == dirstat.st_dev)) {
			memcpy(&mntfs, &mounts[i], sizeof mntfs);
			*dir = mntfs.f_mntonname;
			return mntfs.f_mntfromname;
		}
	}
	return NULL;
}
#endif

#if defined(MOUNTED_GETMNTENT1) || defined(MOUNTED_GETMNTENT2)
static char *
getmntpt(file, dir)
	char	*file, **dir;
{
	FILE	*mntp;
	MNTTYPE	*mnt;
	static MNTTYPE	rmnt;
	struct stat	filestat, dirstat;

	if (stat(file, &filestat) < 0) {
		perror(file);
		return(NULL);
	}
#ifdef	MOUNTED_GETMNTENT2
	mnt = &rmnt;
	if ((mntp = fopen(MNTTAB, "r")) == NULL) {
		perror(MNTTAB);
		return(NULL);
	}
	while (getmntent(mntp, mnt) == 0) {
		if (strcmp(mnt->mnt_fstype, MNTTYPE_SWAP) == 0)
			continue;
		if ((stat(mnt->mnt_mountp, &dirstat) >= 0) &&
		   (filestat.st_dev == dirstat.st_dev)) {
			fclose(mntp);
			*dir = mnt->mnt_mountp;
			return mnt->mnt_special;
		}
	}
	fclose(mntp);
#else /* MOUNTED_GETMNTENT1 */
	if ((mntp = setmntent(MOUNTED, "r")) == NULL) {
		perror(MOUNTED);
		return(NULL);
	}
	while ((mnt = getmntent(mntp)) != 0) {
		if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
		    strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
			continue;
		if ((stat(mnt->mnt_dir, &dirstat) >= 0) &&
		   (filestat.st_dev == dirstat.st_dev)) {
			endmntent(mntp);
			*dir = mnt->mnt_dir;
			return mnt->mnt_fsname;
		}
	}
	endmntent(mntp);
#endif
	return NULL;
}
#endif

char *
whathost(file)
	char	*file;
{
	struct stat	statb;
	char		*mnt, *cp, *dir;
#ifndef	MAXHOSTNAMELEN
#define	MAXHOSTNAMELEN 64
#endif	/* MAXHOSTNAMELEN */
	static char	hostname[MAXHOSTNAMELEN+1];

	if (stat(file, &statb) < 0)
		return NULL;
	if ((statb.st_mode & S_IFMT & (S_IFREG|S_IFDIR))
	    && (mnt = getmntpt(file, &dir)) != NULL) {
		if ((cp = strchr(mnt, ':')) == 0)
			return "localhost";
		/* file is remote - use locking daemon! */
		*cp++ = '\0';
		strcpy(hostname, mnt);
		return hostname;
	}
	return NULL;
}
