1 /*        $NetBSD: mail_queue.h,v 1.4 2025/02/25 19:15:45 christos Exp $        */
2 
3 #ifndef _MAIL_QUEUE_H_INCLUDED_
4 #define _MAIL_QUEUE_H_INCLUDED_
5 
6 /*++
7 /* NAME
8 /*        mail_queue 3h
9 /* SUMMARY
10 /*        mail queue access
11 /* SYNOPSIS
12 /*        #include <mail_queue.h>
13 /* DESCRIPTION
14 /* .nf
15 
16  /*
17   * System library.
18   */
19 #include <sys/time.h>
20 
21  /*
22   * Utility library.
23   */
24 #include <vstring.h>
25 #include <vstream.h>
26 
27  /*
28   * Mail queue names.
29   */
30 #define MAIL_QUEUE_MAILDROP   "maildrop"
31 #define MAIL_QUEUE_HOLD                 "hold"
32 #define MAIL_QUEUE_INCOMING   "incoming"
33 #define MAIL_QUEUE_ACTIVE     "active"
34 #define MAIL_QUEUE_DEFERRED   "deferred"
35 #define MAIL_QUEUE_TRACE      "trace"
36 #define MAIL_QUEUE_DEFER      "defer"
37 #define MAIL_QUEUE_BOUNCE     "bounce"
38 #define MAIL_QUEUE_CORRUPT    "corrupt"
39 #define MAIL_QUEUE_FLUSH      "flush"
40 #define MAIL_QUEUE_SAVED      "saved"
41 
42  /*
43   * Queue file modes.
44   *
45   * 4.4BSD-like systems don't allow (sticky AND executable) together, so we use
46   * group read permission bits instead. These are more portable, but they
47   * also are more likely to be turned on by accident. It would not be the end
48   * of the world.
49   */
50 #define MAIL_QUEUE_STAT_READY (S_IRUSR | S_IWUSR | S_IXUSR)
51 #define MAIL_QUEUE_STAT_CORRUPT         (S_IRUSR)
52 #ifndef MAIL_QUEUE_STAT_UNTHROTTLE
53 #define MAIL_QUEUE_STAT_UNTHROTTLE (S_IRGRP)
54 #define MAIL_QUEUE_STAT_EXPIRE          (S_IXGRP)
55 #endif
56 
57 extern struct VSTREAM *mail_queue_enter(const char *, mode_t, struct timeval *);
58 extern struct VSTREAM *mail_queue_open(const char *, const char *, int, mode_t);
59 extern int mail_queue_rename(const char *, const char *, const char *);
60 extern int mail_queue_remove(const char *, const char *);
61 extern const char *mail_queue_dir(VSTRING *, const char *, const char *);
62 extern const char *mail_queue_path(VSTRING *, const char *, const char *);
63 extern int mail_queue_mkdirs(const char *);
64 extern int mail_queue_name_ok(const char *);
65 extern int mail_queue_id_ok(const char *);
66 
67  /*
68   * MQID - Mail Queue ID format definitions. Needed only by code that creates
69   * or parses queue ID strings.
70   */
71 #ifdef MAIL_QUEUE_INTERNAL
72 
73  /*
74   * System library.
75   */
76 #include <errno.h>
77 
78  /*
79   * Global library.
80   */
81 #include <safe_ultostr.h>
82 
83  /*
84   * The long non-repeating queue ID is encoded in an alphabet of 10 digits,
85   * 21 upper-case characters, and 21 or fewer lower-case characters. The
86   * alphabet is made "safe" by removing all the vowels (AEIOUaeiou). The ID
87   * is the concatenation of:
88   *
89   * - the time in seconds (base 52 encoded, six or more chars),
90   *
91   * - the time in microseconds (base 52 encoded, exactly four chars),
92   *
93   * - the 'z' character to separate the time and inode information,
94   *
95   * - the inode number (base 51 encoded so that it contains no 'z').
96   */
97 #define MQID_LG_SEC_BASE      52        /* seconds safe alphabet base */
98 #define MQID_LG_SEC_PAD       6                   /* seconds minimum field width */
99 #define MQID_LG_USEC_BASE     52        /* microseconds safe alphabet base */
100 #define MQID_LG_USEC_PAD      4         /* microseconds exact field width */
101 #define MQID_LG_TIME_PAD      (MQID_LG_SEC_PAD + MQID_LG_USEC_PAD)
102 #define MQID_LG_INUM_SEP      'z'       /* time-inode separator */
103 #define MQID_LG_INUM_BASE     51        /* inode safe alphabet base */
104 #define MQID_LG_INUM_PAD      0         /* no padding needed */
105 
106 #define MQID_FIND_LG_INUM_SEPARATOR(cp, path) \
107           (((cp) = strrchr((path), MQID_LG_INUM_SEP)) != 0 \
108               && ((cp) - (path) >= MQID_LG_TIME_PAD))
109 
110 #define MQID_GET_INUM(path, inum, long_form, error) do { \
111           char *_cp; \
112           if (((long_form) = MQID_FIND_LG_INUM_SEPARATOR(_cp, (path))) != 0) { \
113               MQID_LG_DECODE_INUM(_cp + 1, (inum), (error)); \
114           } else { \
115               MQID_SH_DECODE_INUM((path) + MQID_SH_USEC_PAD, (inum), (error)); \
116           } \
117     } while (0)
118 
119 #define MQID_LG_ENCODE_SEC(buf, val) \
120           MQID_LG_ENCODE((buf), (val), MQID_LG_SEC_BASE, MQID_LG_SEC_PAD)
121 
122 #define MQID_LG_ENCODE_USEC(buf, val) \
123           MQID_LG_ENCODE((buf), (val), MQID_LG_USEC_BASE, MQID_LG_USEC_PAD)
124 
125 #define MQID_LG_ENCODE_INUM(buf, val) \
126           MQID_LG_ENCODE((buf), (val), MQID_LG_INUM_BASE, MQID_LG_INUM_PAD)
127 
128 #define MQID_LG_DECODE_USEC(str, ulval, error) \
129           MQID_LG_DECODE((str), (ulval), MQID_LG_USEC_BASE, (error))
130 
131 #define MQID_LG_DECODE_INUM(str, ulval, error) \
132           MQID_LG_DECODE((str), (ulval), MQID_LG_INUM_BASE, (error))
133 
134 #define MQID_LG_ENCODE(buf, val, base, padlen) \
135           safe_ultostr((buf), (unsigned long) (val), (base), (padlen), '0')
136 
137 #define MQID_LG_DECODE(str, ulval, base, error) do { \
138           char *_end; \
139           errno = 0; \
140           (ulval) = safe_strtoul((str), &_end, (base)); \
141           (error) = (*_end != 0 || ((ulval) == ULONG_MAX && errno == ERANGE)); \
142     } while (0)
143 
144 #define MQID_LG_GET_HEX_USEC(bp, zp) do { \
145           int _error; \
146           unsigned long _us_val; \
147           vstring_strncpy((bp), (zp) - MQID_LG_USEC_PAD, MQID_LG_USEC_PAD); \
148           MQID_LG_DECODE_USEC(STR(bp), _us_val, _error); \
149           if (_error) \
150               _us_val = 0; \
151           (void) MQID_SH_ENCODE_USEC((bp), _us_val); \
152     } while (0)
153 
154  /*
155   * The short repeating queue ID is encoded in upper-case hexadecimal, and is
156   * the concatenation of:
157   *
158   * - the time in microseconds (exactly five chars),
159   *
160   * - the inode number.
161   */
162 #define MQID_SH_USEC_PAD      5         /* microseconds exact field width */
163 
164 #define MQID_SH_ENCODE_USEC(buf, usec) \
165           vstring_str(vstring_sprintf((buf), "%05X", (int) (usec)))
166 
167 #define MQID_SH_ENCODE_INUM(buf, inum) \
168           vstring_str(vstring_sprintf((buf), "%lX", (unsigned long) (inum)))
169 
170 #define MQID_SH_DECODE_INUM(str, ulval, error) do { \
171         char *_end; \
172           errno = 0; \
173           (ulval) = strtoul((str), &_end, 16); \
174           (error) = (*_end != 0 || ((ulval) == ULONG_MAX && errno == ERANGE)); \
175     } while (0)
176 
177 #endif                                            /* MAIL_QUEUE_INTERNAL */
178 
179 /* LICENSE
180 /* .ad
181 /* .fi
182 /*        The Secure Mailer license must be distributed with this software.
183 /* AUTHOR(S)
184 /*        Wietse Venema
185 /*        IBM T.J. Watson Research
186 /*        P.O. Box 704
187 /*        Yorktown Heights, NY 10598, USA
188 /*
189 /*        Wietse Venema
190 /*        Google, Inc.
191 /*        111 8th Avenue
192 /*        New York, NY 10011, USA
193 /*--*/
194 
195 #endif                                            /* _MAIL_QUEUE_H_INCLUDED_ */
196