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