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.
25 static char epath[PATH_MAX];
30 /* XXX: here was: ``context_read();'' -- why? */
33 if ((cp = strchr(pp = file + 1, '/')))
38 if ((pw = getpwnam(pp)))
47 snprintf(epath, sizeof epath, "%s/%s", pp, cp ? cp : "");
51 if (access(epath, R_OK) != NOTOK)
52 return epath; /* else fall */
57 /* absolute pathname, return it */
61 /* Check mmh directory */
62 snprintf(epath, sizeof epath, "%s/%s", mmhpath, file);
63 if (access(epath, R_OK) != NOTOK)
66 /* Check nmh `etc' directory */
67 snprintf(epath, sizeof epath, "%s/%s", mhetcdir, file);
68 return (access(epath, R_OK) != NOTOK ? epath : file);
70 /* TODO: What is the ultimate fallback? NULL or file? */
75 ** Compactify a path name by removing unneccessary parts.
76 ** Removes trailing slashes. Cares to never remove all characters.
77 ** Modifies f (never enlarges it).
79 ** FIXME: Cannot use strcpy() as the areas overlap!
90 abspath = (*f == '/');
94 /* Skip. Interesting places are only after slashes. */
95 /* We don't care about "./" beginnings */
100 /* Let's see what follows the slash ... */
104 continue; /* ... and thus exit the loop */
107 /* reduce subsequent slashes to one */
108 for (dp = cp; *dp == '/'; dp++) {
113 continue; /* ... at the slash */
116 if (cp[1] == '/' || cp[1] == '\0') {
117 /* one-dot element */
121 } else if ((strncmp(cp, "../", 3) == 0) ||
122 (strcmp(cp, "..") == 0)) {
123 /* dot-dot element */
124 /* crop out previous path element */
125 for (dp=cp-2; dp>f && *dp!='/'; dp--) {
129 /* path starts with "/.." */
136 /* a normal hidden file */
142 /* nothing special */
149 /* We have removed everything, but need something. */
150 strcpy(f, abspath ? "/" : ".");
158 ** Get the default folder
159 ** Return the Inbox profile entry or, as fallback, the compile time default
160 ** Returns a pointer to the abs folpath
165 char *folder = context_find(inbox);
167 if (!folder || !*folder) {
168 folder = defaultfolder; /* the compile time default */
170 if (*folder == '+') {
178 ** Get the current folder
179 ** Return the Current-Folder context entry or, as fallback, the default folder
180 ** Returns a pointer to the abs folpath
182 ** Equivalent to: expandfol("@")
187 char *folder = context_find(curfolder);
189 if (!folder || !*folder) {
190 folder = getdeffol();
197 ** Expand folder path
198 ** Convert rel folpaths (@) into abs folpaths
199 ** dir paths are simply passed through
200 ** Returns the abs folpath (without prefix), in static mem
202 ** TODO: Always copy into the static buffer, or just return the pointer?
207 static char buf[BUFSIZ];
210 /* f = concat(getcurfol(), "/", f+1, NULL); */
211 snprintf(buf, sizeof buf, "%s/%s", getcurfol(), f+1);
213 } else if (*f == '+') {
225 ** Expand directory path
226 ** Convert rel dirpath into abs dirpath
227 ** The argument is assumed to be a dir path relative to the cwd,
228 ** except when beginning with '/' (then it will be passed through).
229 ** Returns the abs dirpath, in static mem
231 ** TODO: Always copy into the static buffer, or just return the pointer?
236 static char buf[BUFSIZ];
241 getcwd(buf, sizeof buf);
242 int len = strlen(buf);
243 snprintf(buf+len, sizeof buf - len, "/%s", d);
251 ** Anypath to absolute directory path
252 ** Convert any kind of path into an abs dirpath
253 ** A path without distinguishing prefix is assumed to be an abs folpath
254 ** Abs dirpaths are passed unchanged
255 ** Rel dirpaths ('.') get prefixed with the (abs) cwd
256 ** Return pointer to static memory
258 ** To get the dir path of the mail storage root, call: toabsdir("+")
260 ** TODO: check lengths for copies
265 static char buf[BUFSIZ];
269 strncpy(buf, path, sizeof buf);
273 } else if (*path == '.') {
275 strncpy(buf, expanddir(path), sizeof buf);
282 if (!(pp = context_find("path")) || !*pp) {
283 adios(NULL, "Non-empty profile entry `Path' required");
286 /* Path is relative to $HOME */
287 snprintf(buf, sizeof buf, "%s/", mypath);
292 /* append the mail folder */
293 cp = buf + strlen(buf);
295 strcpy(cp, expandfol(path));