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.
16 ** Find the location of a format or configuration
17 ** file, and return its absolute pathname.
19 ** 1) If it begins with ~user, then expand it.
20 ** 2) Next, if already absolute pathname, then leave unchanged.
21 ** 3) Next, check in mmh directory.
22 ** 4) Next, check in mmh `etc' directory.
23 ** 5) As fall-back, return `file' unchanged.
28 static char epath[PATH_MAX];
33 /* XXX: here was: ``context_read();'' -- why? */
36 if ((cp = strchr(pp = file + 1, '/')))
41 if ((pw = getpwnam(pp)))
50 snprintf(epath, sizeof epath, "%s/%s", pp, cp ? cp : "");
54 if (access(epath, R_OK) != NOTOK)
55 return epath; /* else fall */
60 /* absolute pathname, return it */
64 /* Check mmh directory */
65 snprintf(epath, sizeof epath, "%s/%s", mmhpath, file);
66 if (access(epath, R_OK) != NOTOK)
69 /* Check nmh `etc' directory */
70 snprintf(epath, sizeof epath, "%s/%s", mhetcdir, file);
71 if (access(epath, R_OK) != NOTOK)
80 ** Compactify a path name by removing unneccessary parts.
81 ** Removes trailing slashes. Cares to never remove all characters.
82 ** Modifies f (never enlarges it).
84 ** FIXME: Cannot use strcpy() as the areas overlap!
95 abspath = (*f == '/');
99 /* Skip. Interesting places are only after slashes. */
100 /* We don't care about "./" beginnings */
105 /* Let's see what follows the slash ... */
109 continue; /* ... and thus exit the loop */
112 /* reduce subsequent slashes to one */
113 for (dp = cp; *dp == '/'; dp++) {
118 continue; /* ... at the slash */
121 if (cp[1] == '/' || cp[1] == '\0') {
122 /* one-dot element */
126 } else if ((strncmp(cp, "../", 3) == 0) ||
127 (strcmp(cp, "..") == 0)) {
128 /* dot-dot element */
129 /* crop out previous path element */
130 for (dp=cp-2; dp>f && *dp!='/'; dp--) {
134 /* path starts with "/.." */
141 /* a normal hidden file */
147 /* nothing special */
154 /* We have removed everything, but need something. */
155 strcpy(f, abspath ? "/" : ".");
163 ** Get the default folder
164 ** Return the Inbox profile entry or, as fallback, the compile time default
165 ** Returns a pointer to the abs folpath
170 char *folder = context_find(inbox);
172 if (!folder || !*folder) {
173 folder = defaultfolder; /* the compile time default */
175 if (*folder == '+') {
183 ** Get the current folder
184 ** Return the Current-Folder context entry or, as fallback, the default folder
185 ** Returns a pointer to the abs folpath
187 ** Equivalent to: expandfol("@")
192 char *folder = context_find(curfolder);
194 if (!folder || !*folder) {
195 folder = getdeffol();
202 ** Expand folder path
203 ** Convert rel folpaths (@) into abs folpaths
204 ** dir paths are simply passed through
205 ** Returns the abs folpath (without prefix), in static mem
207 ** TODO: Always copy into the static buffer, or just return the pointer?
212 static char buf[BUFSIZ];
215 /* f = concat(getcurfol(), "/", f+1, NULL); */
216 snprintf(buf, sizeof buf, "%s/%s", getcurfol(), f+1);
218 } else if (*f == '+') {
230 ** Expand directory path
231 ** Convert rel dirpath into abs dirpath
232 ** The argument is assumed to be a dir path relative to the cwd,
233 ** except when beginning with '/' (then it will be passed through).
234 ** Returns the abs dirpath, in static mem
236 ** TODO: Always copy into the static buffer, or just return the pointer?
241 static char buf[BUFSIZ];
247 getcwd(buf, sizeof buf);
249 snprintf(buf+len, sizeof buf - len, "/%s", d);
257 ** Anypath to absolute directory path
258 ** Convert any kind of path into an abs dirpath
259 ** A path without distinguishing prefix is assumed to be an abs folpath
260 ** Abs dirpaths are passed unchanged
261 ** Rel dirpaths ('.') get prefixed with the (abs) cwd
262 ** Return pointer to static memory
264 ** To get the dir path of the mail storage root, call: toabsdir("+")
266 ** TODO: check lengths for copies
271 static char buf[BUFSIZ];
275 strncpy(buf, path, sizeof buf);
279 } else if (*path == '.') {
281 strncpy(buf, expanddir(path), sizeof buf);
288 if (!(pp = context_find("path")) || !*pp) {
289 adios(EX_CONFIG, NULL, "Non-empty profile entry `Path' required");
292 /* Path is relative to $HOME */
293 snprintf(buf, sizeof buf, "%s/", mypath);
298 /* append the mail folder */
299 cp = buf + strlen(buf);
301 strcpy(cp, expandfol(path));