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