]> diplodocus.org Git - nmh/blob - sbr/path.c
Fix invalid pointer arithmetic.
[nmh] / sbr / path.c
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
26 /* Return value must be free(3)'d. */
27 char *
28 pluspath(char *name)
29 {
30 return path(name + 1, *name == '+' ? TFOLDER : TSUBCWF);
31 }
32
33
34 /* Return value must be free(3)'d. */
35 char *
36 path(char *name, int flag)
37 {
38 char *p, *last;
39
40 p = expath(name, flag);
41 last = p + strlen(p) - 1;
42 if (last > p && *last == '/')
43 *last = '\0';
44
45 return p;
46 }
47
48
49 /* Return value must be free(3)'d. */
50 static char *
51 expath (char *name, int flag)
52 {
53 char *cp, *ep;
54 char buffer[BUFSIZ];
55
56 if (flag == TSUBCWF) {
57 snprintf (buffer, sizeof(buffer), "%s/%s", getfolder (1), name);
58 name = m_mailpath (buffer);
59 compath (name);
60 snprintf (buffer, sizeof(buffer), "%s/", m_maildir (""));
61 if (ssequal (buffer, name)) {
62 cp = name;
63 name = mh_xstrdup(name + strlen(buffer));
64 free (cp);
65 }
66 flag = TFOLDER;
67 }
68
69 if (*name == '/'
70 || (flag == TFOLDER
71 && (!has_prefix(name, CWD)
72 && strcmp (name, DOT)
73 && strcmp (name, DOTDOT)
74 && !has_prefix(name, PWD))))
75 return mh_xstrdup(name);
76
77 if (pwds == NULL)
78 pwds = pwd ();
79
80 if (strcmp (name, DOT) == 0 || strcmp (name, CWD) == 0)
81 return mh_xstrdup(pwds);
82
83 ep = pwds + strlen (pwds);
84 if ((cp = strrchr(pwds, '/')) == NULL)
85 cp = ep;
86 else if (cp == pwds)
87 cp++;
88
89 if (has_prefix(name, CWD))
90 name += LEN(CWD);
91
92 if (strcmp (name, DOTDOT) == 0 || strcmp (name, PWD) == 0) {
93 snprintf (buffer, sizeof(buffer), "%.*s", (int)(cp - pwds), pwds);
94 return mh_xstrdup(buffer);
95 }
96
97 if (has_prefix(name, PWD))
98 name += LEN(PWD);
99 else
100 cp = ep;
101
102 snprintf (buffer, sizeof(buffer), "%.*s/%s", (int)(cp - pwds), pwds, name);
103 return mh_xstrdup(buffer);
104 }
105
106
107 static void
108 compath (char *f)
109 {
110 char *cp, *dp;
111
112 if (*f != '/')
113 return;
114
115 for (cp = f; *cp;) {
116 if (*cp != '/') {
117 cp++;
118 continue;
119 }
120
121 switch (*++cp) {
122 case 0:
123 if (--cp > f)
124 *cp = '\0';
125 return;
126
127 case '/':
128 for (dp = cp; *dp == '/'; dp++)
129 continue;
130 strcpy (cp--, dp);
131 continue;
132
133 case '.':
134 if (strcmp (cp, DOT) == 0) {
135 if (cp > f + 1)
136 cp--;
137 *cp = '\0';
138 return;
139 }
140 if (strcmp (cp, DOTDOT) == 0) {
141 for (cp -= 2; cp > f; cp--)
142 if (*cp == '/')
143 break;
144 if (cp <= f)
145 cp = f + 1;
146 *cp = '\0';
147 return;
148 }
149 if (has_prefix(cp, PWD)) {
150 for (dp = cp - 2; dp > f; dp--)
151 if (*dp == '/')
152 break;
153 if (dp <= f)
154 dp = f;
155 strcpy (dp, cp + LEN(PWD) - 1);
156 cp = dp;
157 continue;
158 }
159 if (has_prefix(cp, CWD)) {
160 strcpy (cp - 1, cp + LEN(CWD) - 1);
161 cp--;
162 continue;
163 }
164 continue;
165
166 default:
167 cp++;
168 continue;
169 }
170 }
171 }