File: seq_read.c

package info (click to toggle)
nmh 1.6-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 6,204 kB
  • ctags: 3,851
  • sloc: ansic: 48,922; sh: 16,422; makefile: 559; perl: 509; lex: 402; awk: 74
file content (241 lines) | stat: -rw-r--r-- 6,018 bytes parent folder | download | duplicates (2)
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;
}