2 ** path.c -- return or convert paths
4 ** This code is Copyright (c) 2002, by the authors of nmh. See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
14 ** Find the location of a format or configuration
15 ** file, and return its absolute pathname.
17 ** 1) If it begins with ~user, then expand it.
18 ** 2) Next, if already absolute pathname, then leave unchanged.
19 ** 3) Next, check in mmh directory.
20 ** 4) Next, check in mmh `etc' directory.
21 ** 5) As fall-back, return `file' unchanged.
26 static char epath[PATH_MAX];
31 /* XXX: here was: ``context_read();'' -- why? */
34 if ((cp = strchr(pp = file + 1, '/')))
39 if ((pw = getpwnam(pp)))
48 snprintf(epath, sizeof epath, "%s/%s", pp, cp ? cp : "");
52 if (access(epath, R_OK) != NOTOK)
53 return epath; /* else fall */
58 /* absolute pathname, return it */
62 /* Check mmh directory */
63 snprintf(epath, sizeof epath, "%s/%s", mmhpath, file);
64 if (access(epath, R_OK) != NOTOK)
67 /* Check nmh `etc' directory */
68 snprintf(epath, sizeof epath, "%s/%s", mhetcdir, file);
69 if (access(epath, R_OK) != NOTOK)
78 ** Compactify a path name by removing unneccessary parts.
79 ** Removes trailing slashes. Cares to never remove all characters.
80 ** Modifies f (never enlarges it).
82 ** FIXME: Cannot use strcpy() as the areas overlap!
93 abspath = (*f == '/');
97 /* Skip. Interesting places are only after slashes. */
98 /* We don't care about "./" beginnings */
103 /* Let's see what follows the slash ... */
107 continue; /* ... and thus exit the loop */
110 /* reduce subsequent slashes to one */
111 for (dp = cp; *dp == '/'; dp++) {
116 continue; /* ... at the slash */
119 if (cp[1] == '/' || cp[1] == '\0') {
120 /* one-dot element */
124 } else if ((strncmp(cp, "../", 3) == 0) ||
125 (strcmp(cp, "..") == 0)) {
126 /* dot-dot element */
127 /* crop out previous path element */
128 for (dp=cp-2; dp>f && *dp!='/'; dp--) {
132 /* path starts with "/.." */
139 /* a normal hidden file */
145 /* nothing special */
152 /* We have removed everything, but need something. */
153 strcpy(f, abspath ? "/" : ".");
161 ** Get the default folder
162 ** Return the Inbox profile entry or, as fallback, the compile time default
163 ** Returns a pointer to the abs folpath
168 char *folder = context_find(inbox);
170 if (!folder || !*folder) {
171 folder = defaultfolder; /* the compile time default */
173 if (*folder == '+') {
181 ** Get the current folder
182 ** Return the Current-Folder context entry or, as fallback, the default folder
183 ** Returns a pointer to the abs folpath
185 ** Equivalent to: expandfol("@")
190 char *folder = context_find(curfolder);
192 if (!folder || !*folder) {
193 folder = getdeffol();
200 ** Expand folder path
201 ** Convert rel folpaths (@) into abs folpaths
202 ** dir paths are simply passed through
203 ** Returns the abs folpath (without prefix), in static mem
205 ** TODO: Always copy into the static buffer, or just return the pointer?
210 static char buf[BUFSIZ];
213 /* f = concat(getcurfol(), "/", f+1, NULL); */
214 snprintf(buf, sizeof buf, "%s/%s", getcurfol(), f+1);
216 } else if (*f == '+') {
228 ** Expand directory path
229 ** Convert rel dirpath into abs dirpath
230 ** The argument is assumed to be a dir path relative to the cwd,
231 ** except when beginning with '/' (then it will be passed through).
232 ** Returns the abs dirpath, in static mem
234 ** TODO: Always copy into the static buffer, or just return the pointer?
239 static char buf[BUFSIZ];
245 getcwd(buf, sizeof buf);
247 snprintf(buf+len, sizeof buf - len, "/%s", d);
255 ** Anypath to absolute directory path
256 ** Convert any kind of path into an abs dirpath
257 ** A path without distinguishing prefix is assumed to be an abs folpath
258 ** Abs dirpaths are passed unchanged
259 ** Rel dirpaths ('.') get prefixed with the (abs) cwd
260 ** Return pointer to static memory
262 ** To get the dir path of the mail storage root, call: toabsdir("+")
264 ** TODO: check lengths for copies
269 static char buf[BUFSIZ];
273 strncpy(buf, path, sizeof buf);
277 } else if (*path == '.') {
279 strncpy(buf, expanddir(path), sizeof buf);
286 if (!(pp = context_find("path")) || !*pp) {
287 adios(NULL, "Non-empty profile entry `Path' required");
290 /* Path is relative to $HOME */
291 snprintf(buf, sizeof buf, "%s/", mypath);
296 /* append the mail folder */
297 cp = buf + strlen(buf);
299 strcpy(cp, expandfol(path));