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.
15 ** Find the location of a format or configuration
16 ** file, and return its absolute pathname.
18 ** 1) If it begins with ~user, then expand it.
19 ** 2) Next, if already absolute pathname, then leave unchanged.
20 ** 3) Next, check in mmh directory.
21 ** 4) Next, check in mmh `etc' directory.
22 ** 5) As fall-back, return `file' unchanged.
27 static char epath[PATH_MAX];
32 /* XXX: here was: ``context_read();'' -- why? */
35 if ((cp = strchr(pp = file + 1, '/')))
40 if ((pw = getpwnam(pp)))
49 snprintf(epath, sizeof epath, "%s/%s", pp, cp ? cp : "");
53 if (access(epath, R_OK) != NOTOK)
54 return epath; /* else fall */
59 /* absolute pathname, return it */
63 /* Check mmh directory */
64 snprintf(epath, sizeof epath, "%s/%s", mmhpath, file);
65 if (access(epath, R_OK) != NOTOK)
68 /* Check nmh `etc' directory */
69 snprintf(epath, sizeof epath, "%s/%s", mhetcdir, file);
70 if (access(epath, R_OK) != NOTOK)
79 ** Compactify a path name by removing unneccessary parts.
80 ** Removes trailing slashes. Cares to never remove all characters.
81 ** Modifies f (never enlarges it).
83 ** FIXME: Cannot use strcpy() as the areas overlap!
94 abspath = (*f == '/');
98 /* Skip. Interesting places are only after slashes. */
99 /* We don't care about "./" beginnings */
104 /* Let's see what follows the slash ... */
108 continue; /* ... and thus exit the loop */
111 /* reduce subsequent slashes to one */
112 for (dp = cp; *dp == '/'; dp++) {
117 continue; /* ... at the slash */
120 if (cp[1] == '/' || cp[1] == '\0') {
121 /* one-dot element */
125 } else if ((strncmp(cp, "../", 3) == 0) ||
126 (strcmp(cp, "..") == 0)) {
127 /* dot-dot element */
128 /* crop out previous path element */
129 for (dp=cp-2; dp>f && *dp!='/'; dp--) {
133 /* path starts with "/.." */
140 /* a normal hidden file */
146 /* nothing special */
153 /* We have removed everything, but need something. */
154 strcpy(f, abspath ? "/" : ".");
162 ** Get the default folder
163 ** Return the Inbox profile entry or, as fallback, the compile time default
164 ** Returns a pointer to the abs folpath
169 char *folder = context_find(inbox);
171 if (!folder || !*folder) {
172 folder = defaultfolder; /* the compile time default */
174 if (*folder == '+') {
182 ** Get the current folder
183 ** Return the Current-Folder context entry or, as fallback, the default folder
184 ** Returns a pointer to the abs folpath
186 ** Equivalent to: expandfol("@")
191 char *folder = context_find(curfolder);
193 if (!folder || !*folder) {
194 folder = getdeffol();
201 ** Expand folder path
202 ** Convert rel folpaths (@) into abs folpaths
203 ** dir paths are simply passed through
204 ** Returns the abs folpath (without prefix), in static mem
206 ** TODO: Always copy into the static buffer, or just return the pointer?
211 static char buf[BUFSIZ];
214 /* f = concat(getcurfol(), "/", f+1, NULL); */
215 snprintf(buf, sizeof buf, "%s/%s", getcurfol(), f+1);
217 } else if (*f == '+') {
229 ** Expand directory path
230 ** Convert rel dirpath into abs dirpath
231 ** The argument is assumed to be a dir path relative to the cwd,
232 ** except when beginning with '/' (then it will be passed through).
233 ** Returns the abs dirpath, in static mem
235 ** TODO: Always copy into the static buffer, or just return the pointer?
240 static char buf[BUFSIZ];
246 getcwd(buf, sizeof buf);
248 snprintf(buf+len, sizeof buf - len, "/%s", d);
256 ** Anypath to absolute directory path
257 ** Convert any kind of path into an abs dirpath
258 ** A path without distinguishing prefix is assumed to be an abs folpath
259 ** Abs dirpaths are passed unchanged
260 ** Rel dirpaths ('.') get prefixed with the (abs) cwd
261 ** Return pointer to static memory
263 ** To get the dir path of the mail storage root, call: toabsdir("+")
265 ** TODO: check lengths for copies
270 static char buf[BUFSIZ];
274 strncpy(buf, path, sizeof buf);
278 } else if (*path == '.') {
280 strncpy(buf, expanddir(path), sizeof buf);
287 if (!(pp = context_find("path")) || !*pp) {
288 adios(NULL, "Non-empty profile entry `Path' required");
291 /* Path is relative to $HOME */
292 snprintf(buf, sizeof buf, "%s/", mypath);
297 /* append the mail folder */
298 cp = buf + strlen(buf);
300 strcpy(cp, expandfol(path));