]> diplodocus.org Git - nmh/blobdiff - h/mh.h
lock_file.c: close(2) file descriptor on failure, avoiding leak.
[nmh] / h / mh.h
diff --git a/h/mh.h b/h/mh.h
index 3c2fb061dbc3f2a91c4be13e679fdd56a68ae5d8..069d9cbea09d508b2750f2e9be33aa0726a4bfb7 100644 (file)
--- a/h/mh.h
+++ b/h/mh.h
@@ -1,5 +1,4 @@
-/*
- * mh.h -- main header file for all of nmh
+/* mh.h -- main header file for all of nmh
  */
 
 #include <h/nmh.h>
  */
 
 #include <h/nmh.h>
@@ -9,9 +8,8 @@
  */
 #define        NOTOK        (-1)       /* syscall()s return this on error */
 #define        OK             0        /*  ditto on success               */
  */
 #define        NOTOK        (-1)       /* syscall()s return this on error */
 #define        OK             0        /*  ditto on success               */
-#define        DONE           1        /* trinary logic                   */
+#define        DONE           1        /* ternary logic                   */
 #define ALL           ""
 #define ALL           ""
-#define        Nbby           8        /* number of bits/byte */
 
 #define MAXARGS            1000        /* max arguments to exec                */
 #define NFOLDERS    1000       /* max folder arguments on command line */
 
 #define MAXARGS            1000        /* max arguments to exec                */
 #define NFOLDERS    1000       /* max folder arguments on command line */
  * This macro is for use by scan, for example, so that platforms with
  * a small BUFSIZ can easily allocate larger buffers.
  */
  * This macro is for use by scan, for example, so that platforms with
  * a small BUFSIZ can easily allocate larger buffers.
  */
-#define NMH_BUFSIZ  (BUFSIZ>=8192 ? BUFSIZ : 8192)
-
-#ifndef FALSE
-#define FALSE false
-#endif
-#ifndef TRUE
-#define TRUE true
-#endif
-typedef unsigned char  boolean;  /* not int so we can pack in a structure */
+#define NMH_BUFSIZ  max(BUFSIZ, 8192)
 
 
-/* If we're using gcc then give it some information about
- * functions that abort.
- */
+/* If we're using gcc then tell it extra information so it can do more
+ * compile-time checks. */
 #if __GNUC__ > 2
 #define NORETURN __attribute__((__noreturn__))
 #if __GNUC__ > 2
 #define NORETURN __attribute__((__noreturn__))
-#define NMH_UNUSED(i) (void) i
+#define CONST __attribute__((const))
+#define MALLOC __attribute__((malloc))
+#define NONNULL(...) __attribute__((nonnull(__VA_ARGS__)))
+#define PURE __attribute__((pure))
+#define ENDNULL __attribute__((sentinel))
 #else
 #define NORETURN
 #else
 #define NORETURN
-#define NMH_UNUSED(i) i
+#define CHECK_PRINTF(fmt, arg)
+#define ALLOC_SIZE(...)
+#define CONST
+#define MALLOC
+#define NONNULL(...)
+#define PURE
+#define ENDNULL
 #endif
 
 #endif
 
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#define ALLOC_SIZE(...) __attribute__((alloc_size(__VA_ARGS__)))
+#define CHECK_PRINTF(fmt, arg) __attribute__((format(printf, fmt, arg)))
+#else
+#define ALLOC_SIZE(...)
+#define CHECK_PRINTF(fmt, arg)
+#endif
+
+/* Silence the compiler's "unused variable" warning. */
+#define NMH_UNUSED(i) (void)i
+
+/* DIM gives the number of elements in the one-dimensional array a. */
+#define DIM(a) (sizeof (a) / sizeof (*(a)))
+
 /* LEN gives the strlen() of string constant s, excluding the
  * terminating NUL. */
 #define LEN(s) (sizeof (s) - 1)
 
 /* LEN gives the strlen() of string constant s, excluding the
  * terminating NUL. */
 #define LEN(s) (sizeof (s) - 1)
 
+/* FENDNULL fends off NULL by giving an empty string instead. */
+#define FENDNULL(s) ((s) ? (s) : "")
+
+/* If not specified in a file and PAGER is NULL or empty. */
+#define DEFAULT_PAGER "more"
+
 /*
  * char array that keeps track of size in both bytes and characters
  * Usage note:
 /*
  * char array that keeps track of size in both bytes and characters
  * Usage note:
@@ -57,24 +76,24 @@ typedef unsigned char  boolean;  /* not int so we can pack in a structure */
 typedef struct charstring *charstring_t;
 
 charstring_t charstring_create (size_t);
 typedef struct charstring *charstring_t;
 
 charstring_t charstring_create (size_t);
-charstring_t charstring_copy (const charstring_t);
+charstring_t charstring_copy (const charstring_t) NONNULL(1);
 void charstring_free (charstring_t);
 /* Append a single-byte character: */
 void charstring_free (charstring_t);
 /* Append a single-byte character: */
-void charstring_push_back (charstring_t, const char);
+void charstring_push_back (charstring_t, const char) NONNULL(1);
 /* Append possibly multi-byte character(s): */
 /* Append possibly multi-byte character(s): */
-void charstring_push_back_chars (charstring_t, const char [], size_t, size_t);
-void charstring_append (charstring_t, const charstring_t);
-void charstring_append_cstring (charstring_t, const char []);
-void charstring_clear (charstring_t);
+void charstring_push_back_chars (charstring_t, const char [], size_t, size_t) NONNULL(1);
+void charstring_append (charstring_t, const charstring_t) NONNULL(2);
+void charstring_append_cstring (charstring_t, const char []) NONNULL(2);
+void charstring_clear (charstring_t) NONNULL(1);
 /* Don't store return value of charstring_buffer() and use later after
    intervening push_back's; use charstring_buffer_copy() instead. */
 /* Don't store return value of charstring_buffer() and use later after
    intervening push_back's; use charstring_buffer_copy() instead. */
-const char *charstring_buffer (const charstring_t);
+const char *charstring_buffer (const charstring_t) NONNULL(1);
 /* User is responsible for free'ing result of buffer copy. */
 /* User is responsible for free'ing result of buffer copy. */
-char *charstring_buffer_copy (const charstring_t);
-size_t charstring_bytes (const charstring_t);
-size_t charstring_chars (const charstring_t);
+char *charstring_buffer_copy (const charstring_t) NONNULL(1);
+size_t charstring_bytes (const charstring_t) NONNULL(1) PURE;
+size_t charstring_chars (const charstring_t) NONNULL(1) PURE;
 /* Length of the last character in the charstring. */
 /* Length of the last character in the charstring. */
-int charstring_last_char_len (const charstring_t);
+int charstring_last_char_len (const charstring_t) NONNULL(1);
 
 /*
  * user context/profile structure
 
 /*
  * user context/profile structure
@@ -167,60 +186,64 @@ extern struct swit anoyes[];      /* standard yes/no switches */
 #define        SEQMOD     (1<<1)       /* folder's sequences modified   */
 #define        ALLOW_NEW  (1<<2)       /* allow the "new" sequence     */
 #define        OTHERS     (1<<3)       /* folder has other files       */
 #define        SEQMOD     (1<<1)       /* folder's sequences modified   */
 #define        ALLOW_NEW  (1<<2)       /* allow the "new" sequence     */
 #define        OTHERS     (1<<3)       /* folder has other files       */
-#define        MODIFIED   (1<<4)       /* msh in-core folder modified  */
 
 
-#define        FBITS "\020\01READONLY\02SEQMOD\03ALLOW_NEW\04OTHERS\05MODIFIED"
+#define        FBITS "\020\01READONLY\02SEQMOD\03ALLOW_NEW\04OTHERS"
 
 /*
  * first free slot for user defined sequences
  * and attributes
  */
 
 /*
  * first free slot for user defined sequences
  * and attributes
  */
-#define        FFATTRSLOT  5
+#define        FFATTRSLOT  4
 
 /*
  * internal messages attributes (sequences)
  */
 #define EXISTS        (0)      /* exists            */
 
 /*
  * internal messages attributes (sequences)
  */
 #define EXISTS        (0)      /* exists            */
-#define DELETED       (1)      /* deleted           */
-#define SELECTED      (2)      /* selected for use  */
-#define SELECT_EMPTY  (3)      /* "new" message     */
-#define        SELECT_UNSEEN (4)       /* inc/show "unseen" */
-
-#define        MBITS "\020\01EXISTS\02DELETED\03SELECTED\04NEW\05UNSEEN"
-
-/*
- * type for holding the sequence set of a message
- */
+#define SELECTED      (1)      /* selected for use  */
+#define SELECT_EMPTY  (2)      /* "new" message     */
+#define        SELECT_UNSEEN (3)       /* inc/show "unseen" */
+
+#define        MBITS "\020\01EXISTS\02SELECTED\03NEW\04UNSEEN"
+
+/* A vector of bits for tracking the sequence membership of a single
+ * message.  Do not access the struct members; use vector.c.
+ * Do not move or copy this struct as it may contain a pointer to
+ * itself;  use bvector_copy(). */
+struct bvector {
+    unsigned long *bits;
+    size_t maxsize;
+    unsigned long tiny[2];   /* Default fixed-size storage for bits. */
+};
 typedef struct bvector *bvector_t;
 
 typedef struct bvector *bvector_t;
 
-bvector_t bvector_create (size_t /* initial size in bits, can be 0 */);
-void bvector_copy (bvector_t, bvector_t);
-void bvector_free (bvector_t);
-void bvector_clear (bvector_t, size_t);
-void bvector_clear_all (bvector_t);
-void bvector_set (bvector_t, size_t);
-unsigned int bvector_at (bvector_t, size_t);
-const unsigned long *bvector_bits (bvector_t);
-size_t bvector_maxsize (bvector_t);
+bvector_t bvector_create (void);
+void bvector_init(struct bvector *bv) NONNULL(1);
+void bvector_copy (bvector_t, bvector_t) NONNULL(1, 2);
+void bvector_free (bvector_t) NONNULL(1);
+void bvector_fini(struct bvector *bv) NONNULL(1);
+void bvector_clear (bvector_t, size_t) NONNULL(1);
+void bvector_clear_all (bvector_t) NONNULL(1);
+void bvector_set (bvector_t, size_t) NONNULL(1);
+unsigned int bvector_at (bvector_t, size_t) NONNULL(1) PURE;
+unsigned long bvector_first_bits (bvector_t) NONNULL(1) PURE;
 
 typedef struct svector *svector_t;
 
 svector_t svector_create (size_t);
 
 typedef struct svector *svector_t;
 
 svector_t svector_create (size_t);
-void svector_free (svector_t);
-char *svector_push_back (svector_t, char *);
-char *svector_at (svector_t, size_t);
-char **svector_find(svector_t, const char *);
-char **svector_strs (svector_t);
-size_t svector_size (svector_t);
+void svector_free (svector_t) NONNULL(1);
+char *svector_push_back (svector_t, char *) NONNULL(1);
+char *svector_at (svector_t, size_t) NONNULL(1);
+char **svector_find(svector_t, const char *) NONNULL(1) PURE;
+char **svector_strs (svector_t) NONNULL(1) PURE;
+size_t svector_size (svector_t) NONNULL(1) PURE;
 
 typedef struct ivector *ivector_t;
 
 ivector_t ivector_create (size_t);
 
 typedef struct ivector *ivector_t;
 
 ivector_t ivector_create (size_t);
-void ivector_free (ivector_t);
-int ivector_push_back (ivector_t, int);
-int ivector_at (ivector_t, size_t);
-int *ivector_atp (ivector_t, size_t);
-size_t ivector_size (ivector_t);
+void ivector_free (ivector_t) NONNULL(1);
+int ivector_push_back (ivector_t, int) NONNULL(1);
+int ivector_at (ivector_t, size_t) NONNULL(1);
+int *ivector_atp (ivector_t, size_t) NONNULL(1);
 
 /*
  * Primary structure of folder/message information
 
 /*
  * Primary structure of folder/message information
@@ -266,7 +289,7 @@ struct msgs {
      * in a particular sequence.
      */
     size_t num_msgstats;
      * in a particular sequence.
      */
     size_t num_msgstats;
-    bvector_t *msgstats;       /* msg status */
+    struct bvector *msgstats;  /* msg status */
 
     /*
      * A FILE handle containing an open filehandle for the sequence file
 
     /*
      * A FILE handle containing an open filehandle for the sequence file
@@ -292,7 +315,7 @@ struct msgs {
 /*
  * macros for message and sequence manipulation
  */
 /*
  * macros for message and sequence manipulation
  */
-#define msgstat(mp,n) (mp)->msgstats[(n) - mp->lowoff]
+#define msgstat(mp,n) ((mp)->msgstats + (n) - mp->lowoff)
 #define clear_msg_flags(mp,msgnum)   bvector_clear_all (msgstat(mp, msgnum))
 #define copy_msg_flags(mp,i,j)       bvector_copy (msgstat(mp,i), msgstat(mp,j))
 #define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum))
 #define clear_msg_flags(mp,msgnum)   bvector_clear_all (msgstat(mp, msgnum))
 #define copy_msg_flags(mp,i,j)       bvector_copy (msgstat(mp,i), msgstat(mp,j))
 #define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum))
@@ -318,9 +341,6 @@ struct msgs {
 #define set_unseen(mp,msgnum) \
         bvector_set (msgstat(mp, msgnum), SELECT_UNSEEN)
 
 #define set_unseen(mp,msgnum) \
         bvector_set (msgstat(mp, msgnum), SELECT_UNSEEN)
 
-/* for msh only */
-#define set_deleted(mp,msgnum)     bvector_set (msgstat(mp, msgnum), DELETED)
-
 #define in_sequence(mp,seqnum,msgnum) \
         bvector_at (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
 #define clear_sequence(mp,seqnum,msgnum) \
 #define in_sequence(mp,seqnum,msgnum) \
         bvector_at (msgstat(mp, msgnum), FFATTRSLOT + seqnum)
 #define clear_sequence(mp,seqnum,msgnum) \
@@ -335,7 +355,7 @@ struct msgs {
 #define make_seq_private(mp,seqnum) \
         bvector_set (mp->attrstats, FFATTRSLOT + seqnum)
 #define make_all_public(mp) \
 #define make_seq_private(mp,seqnum) \
         bvector_set (mp->attrstats, FFATTRSLOT + seqnum)
 #define make_all_public(mp) \
-        mp->attrstats = bvector_create(0); bvector_clear_all (mp->attrstats)
+        mp->attrstats = bvector_create(); bvector_clear_all (mp->attrstats)
 
 /*
  * macros for folder attributes
 
 /*
  * macros for folder attributes
@@ -348,8 +368,6 @@ struct msgs {
 #define other_files(mp)     ((mp)->msgflags & OTHERS)
 #define set_other_files(mp) ((mp)->msgflags |= OTHERS)
 
 #define other_files(mp)     ((mp)->msgflags & OTHERS)
 #define set_other_files(mp) ((mp)->msgflags |= OTHERS)
 
-#define        NULLMP  ((struct msgs *) 0)
-
 /*
  * m_getfld() message parsing
  */
 /*
  * m_getfld() message parsing
  */
@@ -364,24 +382,31 @@ struct msgs {
                                   followed by a colon.  Add one for
                                   terminating NULL. */
 
                                   followed by a colon.  Add one for
                                   terminating NULL. */
 
-#define LENERR  (-2)           /* Name too long error from getfld  */
-#define FMTERR  (-3)           /* Message Format error             */
-#define FLD      0             /* Field returned                   */
-#define FLDPLUS  1             /* Field returned with more to come */
-#define BODY     3             /* Body  returned with more to come */
-#define FILEEOF  5             /* Reached end of input file        */
+/* Token type or error returned from m_getfld(), and its internal state
+ * for the next call. */
+/* FLD detects the header's name is too long to fit in the fixed size
+ * array. */
+#define LENERR  (-2)
+/* FLD reaches EOF after the header's name, or the name is followed by
+ * a linefeed rather than a colon and the body buffer isn't large enough
+ * to pretend this header line starts the body. */
+#define FMTERR  (-3)
+/* The initial state, looking for headers.  Returned when the header's
+ * value finishes. */
+#define FLD      0
+/* Another chunk of the header's value has been returned, but there's
+ * more to come. */
+#define FLDPLUS  1
+/* A chunk of the email's body has been returned. */
+#define BODY     3
+/* Either the end of the input file has been reached, or the delimiter
+ * between emails has been found and the caller should
+ * m_getfld_state_reset() to reset the state to FLD for continuing
+ * through the file. */
+#define FILEEOF  5
 
 
-struct m_getfld_state;
 typedef struct m_getfld_state *m_getfld_state_t;
 
 typedef struct m_getfld_state *m_getfld_state_t;
 
-/*
- * Maildrop styles
- */
-#define        MS_DEFAULT      0       /* default (one msg per file) */
-#define        MS_UNKNOWN      1       /* type not known yet         */
-#define        MS_MBOX         2       /* Unix-style "from" lines    */
-#define        MS_MMDF         3       /* string mmdlm2              */
-
 #define        NOUSE   0               /* draft being re-used */
 
 #define TFOLDER 0              /* path() given a +folder */
 #define        NOUSE   0               /* draft being re-used */
 
 #define TFOLDER 0              /* path() given a +folder */
@@ -396,12 +421,6 @@ typedef struct m_getfld_state *m_getfld_state_t;
 /*
  * credentials management
  */
 /*
  * credentials management
  */
-struct nmh_creds {
-    char *host;
-    char *user;
-    char *password;
-};
-
 typedef struct nmh_creds *nmh_creds_t;
 
 /*
 typedef struct nmh_creds *nmh_creds_t;
 
 /*
@@ -434,13 +453,6 @@ extern char *defpath;              /* pathname of user's profile      */
 extern char *ctxpath;          /* pathname of user's context      */
 extern struct node *m_defs;    /* list of profile/context entries */
 
 extern char *ctxpath;          /* pathname of user's context      */
 extern struct node *m_defs;    /* list of profile/context entries */
 
-/* What style to use for generated Message-ID and Content-ID header
-   fields.  The localname style is pid.time@localname, where time is
-   in seconds.  The random style replaces the localname with some
-   (pseudo)random bytes and uses microsecond-resolution time. */
-int save_message_id_style (const char *);
-char *message_id (time_t, int);
-
 /*
  * These standard strings are defined in config.c.  They are the
  * only system-dependent parameters in nmh, and thus by redefining
 /*
  * These standard strings are defined in config.c.  They are the
  * only system-dependent parameters in nmh, and thus by redefining
@@ -503,4 +515,3 @@ extern char *whomproc;
 extern void (*done) (int) NORETURN;
 
 #include <h/prototypes.h>
 extern void (*done) (int) NORETURN;
 
 #include <h/prototypes.h>
-