1 /* path.c -- return a pathname
2  *
3  * This code is Copyright (c) 2002, by the authors of nmh.  See the
4  * COPYRIGHT file in the root directory of the nmh distribution for
5  * complete copyright information.
6  */
7 
8 #include <h/mh.h>
9 #include <h/utils.h>
10 #include "m_maildir.h"
11 
12 #define	CWD	"./"
13 #define	DOT	"."
14 #define	DOTDOT	".."
15 #define	PWD	"../"
16 
17 static char *pwds;
18 
19 /*
20  * static prototypes
21  */
22 static char *expath(char *,int);
23 static void compath(char *);
24 
25 char *
pluspath(char * name)26 pluspath(char *name)
27 {
28 	return path(name + 1, *name == '+' ? TFOLDER : TSUBCWF);
29 }
30 
31 char *
path(char * name,int flag)32 path(char *name, int flag)
33 {
34     char *cp, *ep;
35 
36     if ((cp = expath (name, flag))
37 	    && (ep = cp + strlen (cp) - 1) > cp
38 	    && *ep == '/')
39 	*ep = '\0';
40 
41     return cp;
42 }
43 
44 
45 static char *
expath(char * name,int flag)46 expath (char *name, int flag)
47 {
48     char *cp, *ep;
49     char buffer[BUFSIZ];
50 
51     if (flag == TSUBCWF) {
52 	snprintf (buffer, sizeof(buffer), "%s/%s", getfolder (1), name);
53 	name = m_mailpath (buffer);
54 	compath (name);
55 	snprintf (buffer, sizeof(buffer), "%s/", m_maildir (""));
56 	if (ssequal (buffer, name)) {
57 	    cp = name;
58 	    name = mh_xstrdup(name + strlen(buffer));
59 	    free (cp);
60 	}
61 	flag = TFOLDER;
62     }
63 
64     if (*name == '/'
65 	    || (flag == TFOLDER
66 		&& (!has_prefix(name, CWD)
67 		    && strcmp (name, DOT)
68 		    && strcmp (name, DOTDOT)
69 		    && !has_prefix(name, PWD))))
70 	return mh_xstrdup(name);
71 
72     if (pwds == NULL)
73 	pwds = pwd ();
74 
75     if (strcmp (name, DOT) == 0 || strcmp (name, CWD) == 0)
76 	return mh_xstrdup(pwds);
77 
78     ep = pwds + strlen (pwds);
79     if ((cp = strrchr(pwds, '/')) == NULL)
80 	cp = ep;
81     else
82 	if (cp == pwds)
83 	    cp++;
84 
85     if (has_prefix(name, CWD))
86 	name += LEN(CWD);
87 
88     if (strcmp (name, DOTDOT) == 0 || strcmp (name, PWD) == 0) {
89 	snprintf (buffer, sizeof(buffer), "%.*s", (int)(cp - pwds), pwds);
90 	return mh_xstrdup(buffer);
91     }
92 
93     if (has_prefix(name, PWD))
94 	name += LEN(PWD);
95     else
96 	cp = ep;
97 
98     snprintf (buffer, sizeof(buffer), "%.*s/%s", (int)(cp - pwds), pwds, name);
99     return mh_xstrdup(buffer);
100 }
101 
102 
103 static void
compath(char * f)104 compath (char *f)
105 {
106     char *cp, *dp;
107 
108     if (*f != '/')
109 	return;
110 
111     for (cp = f; *cp;) {
112 	if (*cp != '/') {
113 	    cp++;
114             continue;
115         }
116 
117         switch (*++cp) {
118             case 0:
119                 if (--cp > f)
120                     *cp = '\0';
121                 return;
122 
123             case '/':
124                 for (dp = cp; *dp == '/'; dp++)
125                     continue;
126                 strcpy (cp--, dp);
127                 continue;
128 
129             case '.':
130                 if (strcmp (cp, DOT) == 0) {
131                     if (cp > f + 1)
132                         cp--;
133                     *cp = '\0';
134                     return;
135                 }
136                 if (strcmp (cp, DOTDOT) == 0) {
137                     for (cp -= 2; cp > f; cp--)
138                         if (*cp == '/')
139                             break;
140                     if (cp <= f)
141                         cp = f + 1;
142                     *cp = '\0';
143                     return;
144                 }
145                 if (has_prefix(cp, PWD)) {
146                     for (dp = cp - 2; dp > f; dp--)
147                         if (*dp == '/')
148                             break;
149                     if (dp <= f)
150                         dp = f;
151                     strcpy (dp, cp + LEN(PWD) - 1);
152                     cp = dp;
153                     continue;
154                 }
155                 if (has_prefix(cp, CWD)) {
156                     strcpy (cp - 1, cp + LEN(CWD) - 1);
157                     cp--;
158                     continue;
159                 }
160                 continue;
161 
162             default:
163                 cp++;
164                 continue;
165         }
166     }
167 }
168