1 /* mh.h -- main header file for all of nmh
2  */
3 
4 #include <h/nmh.h>
5 
6 /*
7  * Well-used constants
8  */
9 #define	NOTOK        (-1)	/* syscall()s return this on error */
10 #define	OK             0	/*  ditto on success               */
11 #define	DONE           1	/* ternary logic                   */
12 #define ALL           ""
13 
14 #define MAXARGS	    1000	/* max arguments to exec                */
15 #define NFOLDERS    1000	/* max folder arguments on command line */
16 #define DMAXFOLDER     4	/* typical number of digits             */
17 #define MAXFOLDER   1000	/* message increment                    */
18 
19 /*
20  * This macro is for use by scan, for example, so that platforms with
21  * a small BUFSIZ can easily allocate larger buffers.
22  */
23 #define NMH_BUFSIZ  max(BUFSIZ, 8192)
24 
25 #ifndef FALSE
26 #define FALSE false
27 #endif
28 #ifndef TRUE
29 #define TRUE true
30 #endif
31 typedef unsigned char  boolean;  /* not int so we can pack in a structure */
32 
33 /* If we're using gcc then give it some information about
34  * functions that abort.
35  */
36 #if __GNUC__ > 2
37 #define NORETURN __attribute__((__noreturn__))
38 #define NMH_UNUSED(i) (void) i
39 #else
40 #define NORETURN
41 #define NMH_UNUSED(i) i
42 #endif
43 
44 /* DIM gives the number of elements in the one-dimensional array a. */
45 #define DIM(a) (sizeof (a) / sizeof (*(a)))
46 
47 /* LEN gives the strlen() of string constant s, excluding the
48  * terminating NUL. */
49 #define LEN(s) (sizeof (s) - 1)
50 
51 /* FENDNULL fends off NULL by giving an empty string instead. */
52 #define FENDNULL(s) ((s) ? (s) : "")
53 
54 /*
55  * char array that keeps track of size in both bytes and characters
56  * Usage note:
57  *    Don't store return value of charstring_buffer() and use later
58  *    after intervening push_back's; use charstring_buffer_copy()
59  *    instead.
60  */
61 typedef struct charstring *charstring_t;
62 
63 charstring_t charstring_create (size_t);
64 charstring_t charstring_copy (const charstring_t);
65 void charstring_free (charstring_t);
66 /* Append a single-byte character: */
67 void charstring_push_back (charstring_t, const char);
68 /* Append possibly multi-byte character(s): */
69 void charstring_push_back_chars (charstring_t, const char [], size_t, size_t);
70 void charstring_append (charstring_t, const charstring_t);
71 void charstring_append_cstring (charstring_t, const char []);
72 void charstring_clear (charstring_t);
73 /* Don't store return value of charstring_buffer() and use later after
74    intervening push_back's; use charstring_buffer_copy() instead. */
75 const char *charstring_buffer (const charstring_t);
76 /* User is responsible for free'ing result of buffer copy. */
77 char *charstring_buffer_copy (const charstring_t);
78 size_t charstring_bytes (const charstring_t);
79 size_t charstring_chars (const charstring_t);
80 /* Length of the last character in the charstring. */
81 int charstring_last_char_len (const charstring_t);
82 
83 /*
84  * user context/profile structure
85  */
86 struct node {
87     char *n_name;		/* key                  */
88     char *n_field;		/* value                */
89     char  n_context;		/* context, not profile */
90     struct node *n_next;	/* next entry           */
91 };
92 
93 /*
94  * switches structure
95  */
96 #define	AMBIGSW	 (-2)	/* from smatch() on ambiguous switch */
97 #define	UNKWNSW	 (-1)	/* from smatch() on unknown switch   */
98 
99 struct swit {
100 
101     /*
102      * Switch name
103      */
104 
105     char *sw;
106 
107     /* The minchars field is apparently used like this:
108 
109        -# : Switch can be abbreviated to # characters; switch hidden in -help.
110        0  : Switch can't be abbreviated;               switch shown in -help.
111        #  : Switch can be abbreviated to # characters; switch shown in -help. */
112     int minchars;
113 
114     /*
115      * If we pick this switch, return this value from smatch
116      */
117 
118     int swret;
119 };
120 
121 /*
122  * Macros to use when declaring struct swit arrays.
123  *
124  * These macros use a technique known as X-Macros.  In your source code you
125  * use them like this:
126  *
127  * #define FOO_SWITCHES \
128  *    X("switch1", 0, SWITCHSW) \
129  *    X("switch2", 0, SWITCH2SW) \
130  *    X("thirdswitch", 2, SWITCH3SW) \
131  *
132  * The argument to each entry in FOO_SWITCHES are the switch name (sw),
133  * the minchars field (see above) and the return value for this switch.
134  * Note that the last entry in the above definition must either omit the
135  * continuation backslash, or be followed by a blank line.  In the nmh
136  * code the style is to have every line include a backslash and follow
137  * the SWITCHES macro definition by a blank line.
138  *
139  * After you define FOO_SWITCHES, you instantiate it as follows:
140  *
141  * #define X(sw, minchars, id) id,
142  * DEFINE_SWITCH_ENUM(FOO);
143  * #undef X
144  *
145  * #define X(sw, minchars, id) { sw, minchars, id },
146  * DEFINE_SWITCH_ARRAY(FOO);
147  * #undef X
148  *
149  * DEFINE_SWITCH_ENUM defines an extra enum at the end of the list called
150  * LEN_FOO.
151  */
152 
153 #define DEFINE_SWITCH_ENUM(name) \
154     enum { \
155     	name ## _SWITCHES \
156 	LEN_ ## name \
157     }
158 
159 #define DEFINE_SWITCH_ARRAY(name, array) \
160     static struct swit array[] = { \
161     	name ## _SWITCHES \
162 	{ NULL, 0, 0 } \
163     }
164 
165 extern struct swit anoyes[];	/* standard yes/no switches */
166 
167 /*
168  * general folder attributes
169  */
170 #define READONLY   (1<<0)	/* No write access to folder    */
171 #define	SEQMOD	   (1<<1)	/* folder's sequences modified   */
172 #define	ALLOW_NEW  (1<<2)	/* allow the "new" sequence     */
173 #define	OTHERS	   (1<<3)	/* folder has other files	*/
174 
175 #define	FBITS "\020\01READONLY\02SEQMOD\03ALLOW_NEW\04OTHERS"
176 
177 /*
178  * first free slot for user defined sequences
179  * and attributes
180  */
181 #define	FFATTRSLOT  4
182 
183 /*
184  * internal messages attributes (sequences)
185  */
186 #define EXISTS        (0)	/* exists            */
187 #define SELECTED      (1)	/* selected for use  */
188 #define SELECT_EMPTY  (2)	/* "new" message     */
189 #define	SELECT_UNSEEN (3)	/* inc/show "unseen" */
190 
191 #define	MBITS "\020\01EXISTS\02SELECTED\03NEW\04UNSEEN"
192 
193 /* A vector of bits for tracking the sequence membership of a single
194  * message.  Do not access the struct members; use vector.c.
195  * Do not move or copy this struct as it may contain a pointer to
196  * itself;  use bvector_copy(). */
197 struct bvector {
198     unsigned long *bits;
199     size_t maxsize;
200     unsigned long tiny[2];   /* Default fixed-size storage for bits. */
201 };
202 typedef struct bvector *bvector_t;
203 
204 bvector_t bvector_create (void);
205 void bvector_init(struct bvector *bv);
206 void bvector_copy (bvector_t, bvector_t);
207 void bvector_free (bvector_t);
208 void bvector_fini(struct bvector *bv);
209 void bvector_clear (bvector_t, size_t);
210 void bvector_clear_all (bvector_t);
211 void bvector_set (bvector_t, size_t);
212 unsigned int bvector_at (bvector_t, size_t);
213 unsigned long bvector_first_bits (bvector_t);
214 
215 typedef struct svector *svector_t;
216 
217 svector_t svector_create (size_t);
218 void svector_free (svector_t);
219 char *svector_push_back (svector_t, char *);
220 char *svector_at (svector_t, size_t);
221 char **svector_find(svector_t, const char *);
222 char **svector_strs (svector_t);
223 size_t svector_size (svector_t);
224 
225 typedef struct ivector *ivector_t;
226 
227 ivector_t ivector_create (size_t);
228 void ivector_free (ivector_t);
229 int ivector_push_back (ivector_t, int);
230 int ivector_at (ivector_t, size_t);
231 int *ivector_atp (ivector_t, size_t);
232 
233 /*
234  * Primary structure of folder/message information
235  */
236 struct msgs {
237     int lowmsg;		/* Lowest msg number                 */
238     int hghmsg;		/* Highest msg number                */
239     int nummsg;		/* Actual Number of msgs             */
240 
241     int lowsel;		/* Lowest selected msg number        */
242     int hghsel;		/* Highest selected msg number       */
243     int numsel;		/* Number of msgs selected           */
244 
245     int curmsg;		/* Number of current msg if any      */
246 
247     int msgflags;	/* Folder attributes (READONLY, etc) */
248     char *foldpath;	/* Pathname of folder                */
249 
250     /*
251      * Name of sequences in this folder.
252      */
253     svector_t msgattrs;
254 
255     /*
256      * bit flags for whether sequence
257      * is public (0), or private (1)
258      */
259     bvector_t attrstats;
260 
261     /*
262      * These represent the lowest and highest possible
263      * message numbers we can put in the message status
264      * area, without calling folder_realloc().
265      */
266     int	lowoff;
267     int	hghoff;
268 
269     /*
270      * This is an array of bvector_t which we allocate dynamically.
271      * Each bvector_t is a set of bits flags for a particular message.
272      * These bit flags represent general attributes such as
273      * EXISTS, SELECTED, etc. as well as track if message is
274      * in a particular sequence.
275      */
276     size_t num_msgstats;
277     struct bvector *msgstats;	/* msg status */
278 
279     /*
280      * A FILE handle containing an open filehandle for the sequence file
281      * for this folder.  If non-NULL, use it when the sequence file is
282      * written.
283      */
284     FILE *seqhandle;
285 
286     /*
287      * The name of the public sequence file; required by lkfclose()
288      */
289     char *seqname;
290 };
291 
292 /*
293  * Amount of space to allocate for msgstats.  Allocate
294  * the array to have space for messages numbered lo to hi.
295  * Use MSGSTATNUM to load mp->num_msgstats first.
296  */
297 #define MSGSTATNUM(lo, hi) ((size_t) ((hi) - (lo) + 1))
298 #define MSGSTATSIZE(mp) ((mp)->num_msgstats * sizeof *(mp)->msgstats)
299 
300 /*
301  * macros for message and sequence manipulation
302  */
303 #define msgstat(mp,n) ((mp)->msgstats + (n) - mp->lowoff)
304 #define clear_msg_flags(mp,msgnum)   bvector_clear_all (msgstat(mp, msgnum))
305 #define copy_msg_flags(mp,i,j)       bvector_copy (msgstat(mp,i), msgstat(mp,j))
306 #define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum))
307 #define set_msg_flags(mp,ptr,msgnum) bvector_copy (msgstat(mp, msgnum), ptr)
308 
309 #define does_exist(mp,msgnum)     bvector_at (msgstat(mp, msgnum), EXISTS)
310 #define unset_exists(mp,msgnum)   bvector_clear (msgstat(mp, msgnum), EXISTS)
311 #define set_exists(mp,msgnum)     bvector_set (msgstat(mp, msgnum), EXISTS)
312 
313 #define is_selected(mp,msgnum)    bvector_at (msgstat(mp, msgnum), SELECTED)
314 #define unset_selected(mp,msgnum) bvector_clear (msgstat(mp, msgnum), SELECTED)
315 #define set_selected(mp,msgnum)   bvector_set (msgstat(mp, msgnum), SELECTED)
316 
317 #define is_select_empty(mp,msgnum)  \
318         bvector_at (msgstat(mp, msgnum), SELECT_EMPTY)
319 #define set_select_empty(mp,msgnum) \
320         bvector_set (msgstat(mp, msgnum), SELECT_EMPTY)
321 
322 #define is_unseen(mp,msgnum) \
323         bvector_at (msgstat(mp, msgnum), SELECT_UNSEEN)
324 #define unset_unseen(mp,msgnum) \
325         bvector_clear (msgstat(mp, msgnum), SELECT_UNSEEN)
326 #define set_unseen(mp,msgnum) \
327         bvector_set (msgstat(mp, msgnum), SELECT_UNSEEN)
328 
329 #define in_sequence(mp,seqnum,msgnum) \
330         bvector_at (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
331 #define clear_sequence(mp,seqnum,msgnum) \
332         bvector_clear (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
333 #define add_sequence(mp,seqnum,msgnum) \
334         bvector_set (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
335 
336 #define is_seq_private(mp,seqnum) \
337         bvector_at (mp->attrstats, FFATTRSLOT + seqnum)
338 #define make_seq_public(mp,seqnum) \
339         bvector_clear (mp->attrstats, FFATTRSLOT + seqnum)
340 #define make_seq_private(mp,seqnum) \
341         bvector_set (mp->attrstats, FFATTRSLOT + seqnum)
342 #define make_all_public(mp) \
343         mp->attrstats = bvector_create(); bvector_clear_all (mp->attrstats)
344 
345 /*
346  * macros for folder attributes
347  */
348 #define clear_folder_flags(mp) ((mp)->msgflags = 0)
349 
350 #define is_readonly(mp)     ((mp)->msgflags & READONLY)
351 #define set_readonly(mp)    ((mp)->msgflags |= READONLY)
352 
353 #define other_files(mp)     ((mp)->msgflags & OTHERS)
354 #define set_other_files(mp) ((mp)->msgflags |= OTHERS)
355 
356 /*
357  * m_getfld() message parsing
358  */
359 
360 #define NAMESZ  999		/* Limit on component name size.
361 				   RFC 2822 limits line lengths to
362 				   998 characters, so a header name
363 				   can be at most that long.
364 				   m_getfld limits header names to 2
365 				   less than NAMESZ, which is fine,
366 				   because header names must be
367 				   followed by a colon.	 Add one for
368 				   terminating NULL. */
369 
370 #define LENERR  (-2)		/* Name too long error from getfld  */
371 #define FMTERR  (-3)		/* Message Format error             */
372 #define FLD      0		/* Field returned                   */
373 #define FLDPLUS  1		/* Field returned with more to come */
374 #define BODY     3		/* Body  returned with more to come */
375 #define FILEEOF  5		/* Reached end of input file        */
376 
377 typedef struct m_getfld_state *m_getfld_state_t;
378 
379 #define	NOUSE	0		/* draft being re-used */
380 
381 #define TFOLDER 0		/* path() given a +folder */
382 #define TFILE   1		/* path() given a file    */
383 #define	TSUBCWF	2		/* path() given a @folder */
384 
385 #define OUTPUTLINELEN	72	/* default line length for headers */
386 
387 #define LINK	"@"		/* Name of link to file to which you are */
388 				/* replying. */
389 
390 /*
391  * credentials management
392  */
393 typedef struct nmh_creds *nmh_creds_t;
394 
395 /*
396  * miscellaneous macros
397  */
398 #define	pidXwait(pid,cp) pidstatus (pidwait (pid, NOTOK), stdout, cp)
399 
400 #ifndef max
401 # define max(a,b) ((a) > (b) ? (a) : (b))
402 #endif
403 
404 #ifndef min
405 # define min(a,b) ((a) < (b) ? (a) : (b))
406 #endif
407 
408 #ifndef abs
409 # define abs(a) ((a) > 0 ? (a) : -(a))
410 #endif
411 
412 /*
413  * GLOBAL VARIABLES
414  */
415 #define CTXMOD	0x01		/* context information modified */
416 #define	DBITS	"\020\01CTXMOD"
417 extern char ctxflags;
418 
419 extern char *invo_name;		/* command invocation name         */
420 extern char *mypath;		/* user's $HOME                    */
421 extern char *defpath;		/* pathname of user's profile      */
422 extern char *ctxpath;		/* pathname of user's context      */
423 extern struct node *m_defs;	/* list of profile/context entries */
424 
425 /*
426  * These standard strings are defined in config.c.  They are the
427  * only system-dependent parameters in nmh, and thus by redefining
428  * their values and reloading the various modules, nmh will run
429  * on any system.
430  */
431 extern char *buildmimeproc;
432 extern char *catproc;
433 extern char *components;
434 extern char *context;
435 extern char *current;
436 extern char *credentials_file;
437 extern int credentials_no_perm_check;
438 extern char *defaultfolder;
439 extern char *digestcomps;
440 extern char *distcomps;
441 extern char *draft;
442 extern char *fileproc;
443 extern char *foldprot;
444 extern char *formatproc;
445 extern char *forwcomps;
446 extern char *inbox;
447 extern char *incproc;
448 extern char *lproc;
449 extern char *mailproc;
450 extern char *mh_defaults;
451 extern char *mh_profile;
452 extern char *mh_seq;
453 extern char *mhlformat;
454 extern char *mhlforward;
455 extern char *mhlproc;
456 extern char *mhlreply;
457 extern char *moreproc;
458 extern char *msgprot;
459 extern char *nmhaccessftp;
460 extern char *nmhaccessurl;
461 extern char *nmhstorage;
462 extern char *nmhcache;
463 extern char *nmhprivcache;
464 extern char *nsequence;
465 extern char *packproc;
466 extern char *postproc;
467 extern char *pfolder;
468 extern char *psequence;
469 extern char *rcvdistcomps;
470 extern char *rcvstoreproc;
471 extern char *replcomps;
472 extern char *replgroupcomps;
473 extern char *rmmproc;
474 extern char *sendproc;
475 extern char *showmimeproc;
476 extern char *showproc;
477 extern char *usequence;
478 extern char *user_agent;
479 extern char *version_num;
480 extern char *version_str;
481 extern char *whatnowproc;
482 extern char *whomproc;
483 
484 extern void (*done) (int) NORETURN;
485 
486 #include <h/prototypes.h>
487