1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
/*
* seq_read.c -- read the .mh_sequence file and
* -- initialize sequence information
*
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
* complete copyright information.
*/
#include <h/mh.h>
#include <h/utils.h>
/*
* static prototypes
*/
static int seq_init (struct msgs *, char *, char *);
static int seq_public (struct msgs *, int, int *);
static void seq_private (struct msgs *);
/*
* Get the sequence information for this folder from
* .mh_sequences (or equivalent specified in .mh_profile)
* or context file (for private sequences).
*/
int
seq_read (struct msgs *mp, int lockflag)
{
int failed_to_lock = 0;
/*
* Initialize the list of sequence names. Go ahead and
* add the "cur" sequence to the list of sequences.
*/
svector_push_back (mp->msgattrs, getcpy (current));
make_all_public (mp); /* initially, make all public */
/* If folder is empty, don't scan for sequence information */
if (mp->nummsg == 0)
return OK;
/* Initialize the public sequences */
if (seq_public (mp, lockflag, &failed_to_lock) == NOTOK) {
if (failed_to_lock) return NOTOK;
}
/* Initialize the private sequences */
seq_private (mp);
return OK;
}
/*
* read folder's sequences file for public sequences
*/
static int
seq_public (struct msgs *mp, int lockflag, int *failed_to_lock)
{
int state;
char *cp, seqfile[PATH_MAX];
char name[NAMESZ], field[BUFSIZ];
FILE *fp;
m_getfld_state_t gstate = 0;
/*
* If mh_seq == NULL or if *mh_seq == '\0' (the user has defined
* the "mh-sequences" profile entry, but left it empty),
* then just return, and do not initialize any public sequences.
*/
if (mh_seq == NULL || *mh_seq == '\0')
return OK;
/* get filename of sequence file */
snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq);
if ((fp = lkfopendata (seqfile, lockflag ? "r+" : "r", failed_to_lock))
== NULL)
return NOTOK;
/* Use m_getfld to scan sequence file */
for (;;) {
int fieldsz = sizeof field;
switch (state = m_getfld (&gstate, name, field, &fieldsz, fp)) {
case FLD:
case FLDPLUS:
if (state == FLDPLUS) {
cp = getcpy (field);
while (state == FLDPLUS) {
fieldsz = sizeof field;
state = m_getfld (&gstate, name, field, &fieldsz, fp);
cp = add (field, cp);
}
seq_init (mp, getcpy (name), trimcpy (cp));
free (cp);
} else {
seq_init (mp, getcpy (name), trimcpy (field));
}
continue;
case BODY:
lkfclosedata (fp, seqfile);
adios (NULL, "no blank lines are permitted in %s", seqfile);
/* fall */
case FILEEOF:
break;
default:
lkfclosedata (fp, seqfile);
adios (NULL, "%s is poorly formatted", seqfile);
}
break; /* break from for loop */
}
m_getfld_state_destroy (&gstate);
if (lockflag) {
mp->seqhandle = fp;
mp->seqname = getcpy(seqfile);
} else {
lkfclosedata (fp, seqfile);
}
return OK;
}
/*
* Scan profile/context list for private sequences.
*
* We search the context list for all keys that look like
* "atr-seqname-folderpath", and add them as private sequences.
*/
static void
seq_private (struct msgs *mp)
{
int i, j, alen, plen;
char *cp;
struct node *np;
alen = strlen ("atr-");
plen = strlen (mp->foldpath) + 1;
for (np = m_defs; np; np = np->n_next) {
if (ssequal ("atr-", np->n_name)
&& (j = strlen (np->n_name) - plen) > alen
&& *(np->n_name + j) == '-'
&& strcmp (mp->foldpath, np->n_name + j + 1) == 0) {
cp = getcpy (np->n_name + alen);
*(cp + j - alen) = '\0';
if ((i = seq_init (mp, cp, getcpy (np->n_field))) != -1)
make_seq_private (mp, i);
}
}
}
/*
* Add the name of sequence to the list of folder sequences.
* Then parse the list of message ranges for this
* sequence, and setup the various bit flags for each
* message in the sequence.
*
* Return internal index for the sequence if successful.
* Return -1 on error.
*/
static int
seq_init (struct msgs *mp, char *name, char *field)
{
unsigned int i;
int j, k, is_current;
char *cp, **ap;
/*
* Check if this is "cur" sequence,
* so we can do some special things.
*/
is_current = !strcmp (current, name);
/*
* Search for this sequence name to see if we've seen
* it already. If we've seen this sequence before,
* then clear the bit for this sequence from all the
* mesages in this folder.
*/
for (i = 0; i < svector_size (mp->msgattrs); i++) {
if (!strcmp (svector_at (mp->msgattrs, i), name)) {
for (j = mp->lowmsg; j <= mp->hghmsg; j++)
clear_sequence (mp, i, j);
break;
}
}
/*
* If we've already seen this sequence name, just free the
* name string. Else add it to the list of sequence names.
*/
if (svector_at (mp->msgattrs, i)) {
free (name);
} else {
svector_push_back (mp->msgattrs, name);
}
/*
* Split up the different message ranges at whitespace
*/
for (ap = brkstring (field, " ", "\n"); *ap; ap++) {
if ((cp = strchr(*ap, '-')))
*cp++ = '\0';
if ((j = m_atoi (*ap)) > 0) {
k = cp ? m_atoi (cp) : j;
/*
* Keep mp->curmsg and "cur" sequence in synch. Unlike
* other sequences, this message doesn't need to exist.
* Think about the series of command (rmm; next) to
* understand why this can be the case. But if it does
* exist, we will still set the bit flag for it like
* other sequences.
*/
if (is_current)
mp->curmsg = j;
/*
* We iterate through messages in this range
* and flip on bit for this sequence.
*/
for (; j <= k; j++) {
if (j >= mp->lowmsg && j <= mp->hghmsg && does_exist(mp, j))
add_sequence (mp, i, j);
}
}
}
free (field); /* free string containing message ranges */
return i;
}
|