File: context_read.c

package info (click to toggle)
mmh 0.4-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 4,976 kB
  • sloc: ansic: 26,132; sh: 6,871; makefile: 680; awk: 74
file content (202 lines) | stat: -rw-r--r-- 6,084 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
** 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;
}