Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / local / lbl / sbr / t.c
1 /* m_gmsg.c - read a folder */
2
3 #include "../h/mh.h"
4 #include <stdio.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #ifndef BSD42
8 #ifndef SYS5
9 #include <ndir.h>
10 #else   SYS5
11 #include <dir.h>
12 #endif  SYS5
13 #else   BSD42
14 #include <sys/dir.h>
15 #endif  BSD42
16
17
18 #define NINFO   (MAXFOLDER / 5) /* PLEASE be non-trivial... */
19 struct info {
20     int     msgno;
21     int   stats;
22 };
23
24 static int m_getatr(), m_setatr();
25
26 static int  len;
27 static struct info *head;
28
29 /* \f */
30
31 struct msgs *
32 m_gmsg(name)
33         register char *name;
34 {
35 #ifdef  COMPAT
36     register int    cur,
37                     fd;
38 #endif  COMPAT
39     register int    i,
40                     j;
41     register struct info *rover,
42                          *tail;
43 #ifdef  COMPAT
44     register char  *cp;
45     char    buffer[BUFSIZ];
46 #endif  COMPAT
47     register struct msgs   *mp;
48     register struct direct *dp;
49     register    DIR * dd;
50     struct stat st;
51
52     if ((dd = opendir (name = m_mailpath (name))) == NULL) {
53         free (name);
54         return NULL;
55     }
56     (void) fstat (dd -> dd_fd, &st);
57
58     mp = (struct msgs  *) malloc (MSIZE (mp, 0, 0));
59     if (mp == NULL)
60         adios (NULLCP, "unable to allocate folder storage");
61     mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
62     mp -> curmsg = 0;
63     mp -> lowsel = mp -> hghsel = mp -> numsel = 0;
64     mp -> foldpath = name;
65     mp -> msgflags = NULL;
66     if (st.st_uid != getuid () || access (name, 02) == NOTOK)
67         mp -> msgflags |= READONLY;
68 #ifdef  COMPAT
69     cur = 0;
70 #endif  COMPAT
71     j = strlen (SBACKUP);
72     if (head == NULL)
73         if ((head = (struct info *)
74                 malloc ((unsigned) ((len = NINFO) * sizeof *head))) == NULL)
75             adios (NULLCP, "unable to allocate info storage");
76     tail = (rover = head) + len;
77
78     while (dp = readdir (dd))
79         if (i = m_atoi (dp -> d_name)) {
80             if (rover >= tail) {
81                 register int curlen = tail - head;
82
83                 if ((tail = (struct info *) realloc ((char *) head,
84                              (unsigned) ((len += NINFO) * sizeof *head)))
85                         == NULL)
86                     adios (NULLCP, "unable to allocate info storage");
87                 else
88                     rover = tail + curlen, head = tail, tail += len;
89             }
90             if (i > mp -> hghmsg)
91                 mp -> hghmsg = i;
92             mp -> nummsg++;
93             if (mp -> lowmsg == 0 || i < mp -> lowmsg)
94                 mp -> lowmsg = i;
95             rover -> msgno = i;
96             rover -> stats = EXISTS;
97 #ifdef  notdef
98             rover -> stats &= ~DELETED;
99 #endif  notdef
100             rover++;
101         }
102         else
103             switch (dp -> d_name[0]) {
104                 case '.': 
105                     continue;
106
107                 case ',': 
108 #ifdef  notdef
109                     if ((i = m_atoi (dp -> d_name + 1)) {
110                         register struct info *l;
111
112                         for (l = head; l < rover; l++)
113                             if (l -> msgno == i) {
114                                 if (!(l -> stats & EXISTS))
115                                     l -> stats |= DELETED;
116                                 break;
117                             }
118                     }
119 #endif  notdef
120                     continue;
121
122 #ifdef  MHE
123                 case '+': 
124                     continue;
125 #endif  MHE
126
127 #ifdef  UCI
128                 case '_': 
129                 case '#': 
130                     continue;
131 #endif  UCI
132
133                 default: 
134 #ifdef  COMPAT
135                     if (strcmp (dp -> d_name, current) == 0) {
136                         cur++;
137                         continue;
138                     }
139 #endif  COMPAT
140                     if (strcmp (dp -> d_name, LINK) == 0
141                             || strncmp (dp -> d_name, SBACKUP, j) == 0)
142                         continue;
143                     mp -> msgflags |= OTHERS;
144                     continue;
145             }
146
147     closedir (dd);
148
149 /* \f */
150
151 #ifdef  COMPAT
152     (void) sprintf (buffer, "%s-%s", current, name);
153     if (cp = m_find (buffer)) {
154         i = m_atoi (cp);
155         (void) m_delete(buffer);
156         if (i > 0)
157             mp -> curmsg = i;
158     }
159     if (mp -> curmsg == 0 && cur && (fd = open (current, 0)) != NOTOK) {
160             if ((i = read (fd, buffer, sizeof buffer)) > 0) {
161                 if (cp = index (buffer, '\n'))
162                     *cp = NULL;
163                 if ((i = m_atoi (buffer)) > 0)
164                     mp -> curmsg = i;
165             }
166             (void) close (fd);
167         }
168     if (cur && !(mp -> msgflags & READONLY)){   /* sneaky... */
169         (void) sprintf (buffer, "%s/%s", name, current);
170         (void) unlink (buffer);
171     }
172 #endif  COMPAT
173
174 #ifndef MTR
175     mp -> lowoff = 1;
176 #else   MTR
177     mp -> lowoff = mp -> lowmsg;
178 #endif  MTR
179     mp -> hghoff = mp -> hghmsg + 1;/* for "new" in m_convert */
180
181     mp = (struct msgs  *)
182                 realloc ((char *) mp, MSIZE (mp, mp -> lowoff, mp -> hghoff));
183     if (mp == NULL)
184         adios (NULLCP, "unable to allocate folder storage");
185 #ifndef MTR
186     for (i = mp -> lowmsg; i <= mp -> hghmsg; i++)
187         mp -> msgstats[i] = 0;
188 #else   MTR
189     mp -> msgstats = (int *)
190                 calloc ((unsigned) 1, MSIZEX (mp, mp -> lowmsg, mp -> hghmsg));
191     if (mp -> msgstats == NULL)
192         adios (NULLCP, "unable to allocate messages storage");
193     mp -> msgstats = (mp -> msgbase = mp -> msgstats) - mp -> lowoff;
194     if (mp -> msgstats < 0)
195         adios (NULLCP, "m_gmsg() botch -- you lose big");
196 #endif  MTR
197     for (tail = head; tail < rover; tail++)
198         mp -> msgstats[tail -> msgno] = tail -> stats;
199     m_getatr (mp);
200
201     return mp;
202 }
203
204 /* \f */
205
206 static int
207 m_getatr(mp)
208         register struct msgs *mp;
209 {
210     int     alen,
211             bits,
212             i,
213             j,
214             plen,
215             state;
216     register char  *cp;
217     char    name[NAMESZ],
218             field[BUFSIZ];
219     register struct node   *np;
220     register    FILE * fp;
221
222     bits = FFATTRSLOT;
223
224     mp -> msgattrs[i = 0] = getcpy (current);
225     mp -> msgattrs[++i] = NULL;
226     mp -> attrstats = 0;        /* initially, all public */
227
228     m_getdefs ();
229     if (mh_seq == NULL || *mh_seq == NULL)
230         goto private_only;
231
232     (void) sprintf (field, "%s/%s", mp -> foldpath, mh_seq);
233     if (fp = fopen (field, "r")) {
234         for (state = FLD;;) {
235             switch (state = m_getfld (state, name, field, sizeof field, fp)) {
236                 case FLD: 
237                 case FLDEOF: 
238                     (void) m_setatr (mp, getcpy (name), trimcpy (field));
239                     if (state == FLDEOF)
240                         break;
241                     continue;
242
243                 case BODY: 
244                 case BODYEOF: 
245                     adios (NULLCP,
246                             "no blank lines are permitted in %s/%s",
247                             mp -> foldpath, mh_seq);/* fall */
248
249                 case FILEEOF:
250                     break;
251
252                 default: 
253                     adios (NULLCP, "%s/%s is poorly formatted",
254                             mp -> foldpath, mh_seq);
255             }
256             break;
257         }
258         (void) fclose (fp);
259     }
260
261 private_only: ;
262     alen = strlen ("atr-");
263     plen = strlen (mp -> foldpath) + 1;
264
265     for (np = m_defs; np; np = np -> n_next)
266         if (ssequal ("atr-", np -> n_name)
267                 && (j = strlen (np -> n_name) - plen) > alen
268                 && *(np -> n_name + j) == '-'
269                 && strcmp (mp -> foldpath, np -> n_name + j + 1) == 0) {
270             cp = getcpy (np -> n_name + alen);
271             *(cp + j - alen) = NULL;
272             if ((i = m_setatr (mp, cp, getcpy (np -> n_field))) != NOTOK)
273                 mp -> attrstats |= 1 << (bits + i);/* private */
274         }
275 }
276
277 /* \f */
278
279 static int
280 m_setatr(mp, name, field)
281         register struct msgs *mp;
282         register char *name, *field;
283 {
284     int     bits,
285             hack;
286     register int    i,
287                     j,
288                     k;
289     register char  *cp,
290                   **ap;
291
292     bits = FFATTRSLOT;
293     hack = strcmp (current, name) == 0;/* hack... */
294
295     for (i = 0; mp -> msgattrs[i]; i++)
296         if (strcmp (mp -> msgattrs[i], name) == 0) {
297             for (j = mp -> lowmsg; j <= mp -> hghmsg; j++)
298                 mp -> msgstats[j] &= ~(1 << (bits + i));
299             break;
300         }
301     if (i >= NATTRS) {
302         free (name);
303         free (field);
304         return NOTOK;
305     }
306
307     if (mp -> msgattrs[i] == NULL) {
308         mp -> msgattrs[i] = name;
309         mp -> msgattrs[i + 1] = NULL;
310     }
311     else
312         free (name);
313
314     for (ap = brkstring (field, " ", "\n");
315             *ap;
316             ap++) {
317         if (cp = index (*ap, '-'))
318             *cp++ = NULL;
319         if ((j = m_atoi (*ap)) > 0) {
320 #ifdef  notdef
321             if (hack && j >= mp -> lowmsg && j <= mp -> hghmsg
322                     && (mp -> msgstats[j] & EXISTS))
323                 mp -> curmsg = j;
324 #else   not notdef
325             if (hack)
326                 mp -> curmsg = j;
327 #endif  not notdef
328             for (k = cp ? m_atoi (cp) : j; j <= k; j++)
329                 if (j >= mp -> lowmsg && j <= mp -> hghmsg
330                         && (mp -> msgstats[j] & EXISTS))
331                     mp -> msgstats[j] |= 1 << (bits + i);
332         }
333     }
334     free (field);
335
336     return i;
337 }