/*
** context_read.c -- find and read profile and context files
**
** This code is Copyright (c) 2002, by the authors of nmh.  See the
** COPYRIGHT file in the root directory of the nmh distribution for
** complete copyright information.
**
** This function must be called early on in any nmh utility, and
** may only be called once.  It does the following:
**
**  o  Sets the global variables to absolute paths:
**     - "mypath": home directory (HOME)
**     - "mmhpath": mmh directory (MMH)
**     - "defpath": profile file (MMHP)
**     - "ctxpath": context file (MMHC)
**
**  o  Reads in the profile file.  Bails out if it can't.
**
**  o  Makes sure that the mail directory exists, prompting for
**     creation if it doesn't.
**
**  o  Reads the context file.
**
** You might need to adjust uip/mmh.sh if you make changes here.
*/

#include <h/mh.h>    /* mh internals */
#include <h/utils.h>
#include <errno.h>   /* system call errors */
#include <pwd.h>     /* structure for getpwuid() results */
#include <unistd.h>
#include <sys/stat.h>
#include <sysexits.h>

void
context_read(void)
{
	char buf[BUFSIZ];            /* path name buffer                 */
	char *cp;                    /* miscellaneous pointer            */
	char *nd;                    /* nmh directory pointer            */
	struct stat st;              /* stat() results                   */
	struct passwd *pw;           /* getpwuid() results               */
	FILE *ib;                    /* profile and context file pointer */

	/*
	** If this routine _is_ called again (despite the wanings in the
	** comments above), return immediately.
	*/
	if (m_defs) {
		return;
	}

	/*
	** Find user's home directory. Try the HOME environment variable first,
	** the home directory field in the password file if that's not found.
	*/
	if (!(mypath = getenv("HOME"))) {
		if (!(pw = getpwuid(getuid())) || !*pw->pw_dir) {
			adios(EX_OSERR, NULL, "cannot determine your home directory");
		}
		mypath = pw->pw_dir;
	}

	/*
	** set mmhpath
	*/
	if ((cp = getenv("MMH")) && *cp) {
		mmhpath = mh_xstrdup(expanddir(cp));  /* rel to cwd */
		if (stat(mmhpath, &st) != -1 && (st.st_mode & S_IFDIR) == 0) {
			adios(EX_CONFIG, NULL, "`%s' specified by your MMH environment variable is not a directory", cp);
		}
	} else {
		mmhpath = concat(mypath, "/", mmhdir, NULL);
		if (stat(mmhpath, &st) == -1 || (st.st_mode & S_IFDIR) == 0) {
			adios(EX_CONFIG, NULL, "Doesn't look like mmh is set up for your account.  Run `mmh' to do so.");
		}
	}

	/*
	** Find and read user's profile.  Check for the existence of
	** a non-empty MMHP environment variable first.  Look for the
	** profile in the mmh directory otherwise.
	*/
	if ((cp = getenv("MMHP")) && *cp) {
		if (*cp == '/') {
			defpath = mh_xstrdup(cp);
		} else {
			defpath = concat(mmhpath, "/", cp, NULL);
		}
		if (stat(defpath, &st) != -1 && (st.st_mode & S_IFREG) == 0) {
			adios(EX_CONFIG, NULL, "Your profile `%s', specified by the MMHP environment variable, is not a normal file", cp);
		}
		if ((ib = fopen(defpath, "r")) == (FILE *)0) {
			adios(EX_IOERR, NULL, "Unable to read your profile `%s', specified by the MMHP environment variable", defpath);
		}
	} else {
		defpath = concat(mmhpath, "/", profile, NULL);
		if ((ib = fopen(defpath, "r")) == (FILE *)0) {
			adios(EX_CONFIG, NULL, "No profile found. Please create `%s' first.", defpath);
		}
		cp = profile;
	}
	readconfig(&m_defs, ib, cp, 0);
	fclose(ib);

	/*
	** Find the user's mail storage directory, which is specified by
	** the `Path' profile component.  Convert a relative path name
	** to an absolute one rooted in the home directory.
	*/
	if ((cp = context_find("path")) == NULL) {
		adios(EX_CONFIG, NULL, "Your profile `%s' does not contain the required path entry.", defpath);
	}
	if (!*cp) {
		adios(EX_CONFIG, NULL, "The Path entry of your profile `%s' must be non-empty.", defpath);
	}
	if (*cp == '/') {
		nd = cp;
	} else {
		snprintf(nd = buf, sizeof buf, "%s/%s", mypath, cp);
	}
	if (stat(nd, &st) == -1) {
		if (errno != ENOENT) {
			adios(EX_IOERR, nd, "error opening");
		}
		cp = concat("Your mail storage directory `", nd, "' doesn't exist; Create it? ", NULL);
		if (!getanswer(cp)) {
			adios(EX_NOPERM, NULL, "Unable to access the mail storage directory `%s'", nd);
		}
		mh_free0(&cp);
		if (!makedir(nd)) {
			adios(EX_CANTCREAT, nd, "unable to create");
		}
	} else if ((st.st_mode & S_IFDIR) == 0) {
		adios(EX_DATAERR, NULL, "Your mail storage `%s' is not a directory", nd);
	}
	/*
	** Create the default folder (inbox)
	*/
	cp = toabsdir(getdeffol());
	if (stat(cp, &st) == -1) {
		if (!makedir(cp)) {
			adios(EX_CANTCREAT, cp, "Unable to create the default folder");
		}
	} else if ((st.st_mode & S_IFDIR) == 0) {
		adios(EX_DATAERR, NULL, "The default folder `%s' is not a directory", cp);
	}

	/*
	** Open and read user's context file.  The name of the context
	** file comes from the profile unless overridden by the MMHC
	** environment variable.
	*/
	if (!(cp = getenv("MMHC")) || !*cp) {
		if (!(cp = context_find("context")) || !*cp) {
			cp = context;
		}
	}

	/*
	** context is NULL if the use of the context was diabled.
	** We also support users setting explicitly setting
	** MMHC to /dev/null.  (If this wasn't special-cased then the
	** locking would be liable to fail.)
	*/
	if (!context || (strcmp(cp, "/dev/null") == 0)) {
		ctxpath = NULL;
		return;
	}

	if (*cp == '/') {
		ctxpath = mh_xstrdup(cp);
	} else {
		ctxpath = concat(mmhpath, "/", cp, NULL);
	}
	if ((ib = lkfopen(ctxpath, "r"))) {
		readconfig((struct node **) 0, ib, cp, 1);
		lkfclose(ib, ctxpath);
	}

	/* Set editor */
	if (!(cp = getenv("MMHEDITOR")) || !*cp) {
		if (!(cp = context_find("editor")) || !*cp) {
			if (!(cp = getenv("VISUAL")) || !*cp) {
				if (!(cp = getenv("EDITOR")) || !*cp) {
					cp = defaulteditor;
				}
			}
		}
	}
	defaulteditor = cp;

	/* Set pager */
	if (!(cp = getenv("MMHPAGER")) || !*cp) {
		if (!(cp = context_find("pager")) || !*cp) {
			if (!(cp = getenv("PAGER")) || !*cp) {
				cp = defaultpager;
			}
		}
	}
	defaultpager = cp;
}
