#include "addrcheck.h"
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
-/* #define DEBUG */
+#if defined(TEST) && !defined(DEBUG)
+# define DEBUG
+#endif
#ifdef DEBUG
# define D(x) x
# include <stdio.h>
#define STRALLOC_INIT { 0 }
+/* --- @probe@ --- *
+ *
+ * Arguments: @int cdb@ = the CDB file descriptor
+ * @int prefix@ = the prefix character (e.g., @'V'@)
+ * @const char *key, int len@ = the key string and its length
+ * @const char *suffix@ = a suffix to append to the key
+ * @const char **kp@ = where to put the full key string
+ * @uint32 *dlen@ = where to put the answer's length
+ *
+ * Returns: Zero if the lookup failed, @+1@ on success, or @-1@ for an
+ * error.
+ *
+ * Use: Probes a CDB file. The key looked up is the character
+ * @prefix@ followed by the first @len@ bytes of @key@, followed
+ * by @suffix@ (if non-null).
+ */
+
static int probe(int cdb, int prefix, const char *key, int len,
const char *suffix, const char **kp, uint32 *dlen)
{
return (rc);
}
+/* --- @localprobe@ --- *
+ *
+ * Arguments: @int cdb@ = the CDB file descriptor
+ * @const char *sender@ = the envelope-sender address
+ * @const char *key, int len@ = the (possibly defaulted) mailbox
+ * name to look up
+ * @const char *suffix@ = a suffix to append to the key (e.g.,
+ * @"-default"@)
+ * @const char *tail@ = the tail of the local address matching
+ * any defaulted extension part
+ * @int *rc@ = where to put the answer
+ *
+ * Returns: Positive if found, zero if not found, negative on error.
+ *
+ * Use: Looks up a local-part in the database. This may involve
+ * invoking a Userv service for the recipient's owner.
+ */
+
static int localprobe(int cdb, const char *sender,
const char *key, int len,
const char *suffix, const char *tail, int *rc)
if (pipe(p) || (kid = fork()) == -1)
return (-1);
if (!kid) {
+ close(0); open("/dev/null", O_RDONLY);
dup2(p[1], 1);
- close(p[0]);
- close(p[1]);
+#ifndef DEBUG
+ close(2); open("/dev/null", O_WRONLY);
+#endif
+ close(p[0]); close(p[1]);
execl("/usr/bin/userv", "/usr/bin/userv",
- "-f", "stdin=/dev/null",
+ "-f", "stdin=/dev/null", "-t", "10",
u.s, serv.s,
tail, sender, key, k + 1,
(char *)0);
_exit(127);
}
close(p[1]);
+ if (wait_pid(&wstat, kid) < 0) { close(p[0]); return (-1); }
+ D( fprintf(stderr, "userv exited with status %d\n", wstat); )
+ if (wstat) { close (p[0]); errno = EAGAIN; return (-1); }
n = read(p[0], &ch, 1);
+ if (n != 1) { close (p[0]); errno = EAGAIN; return (-1); }
close(p[0]);
- if (wait_pid(&wstat, kid) < 0) { return (-1); }
- D( fprintf(stderr, "userv exited with status %d\n", wstat); )
- if (n != 1 || wstat) { errno = EAGAIN; return (-1); }
D( fprintf(stderr, "userv answer was `%c'\n", ch); )
} else if (dlen != 1) {
errno = EIO;
return (1);
}
+/* --- @local@ --- *
+ *
+ * Arguments: @int cdb@ = file descriptor for the CDB
+ * @const char *l@ = pointer to local-part to look up
+ * @int len@ = length of the local-part
+ * @const char *sender@ = envelope sender address
+ * @int *rc@ = where to put the answer
+ *
+ * Returns: Positive if answered, zero if lookup failed, negative on
+ * error.
+ *
+ * Use: Finds out whether @l@ is a valid local-part for a non-virtual
+ * mailbox name. Handles defaulting of extension addresses and
+ * suchlike.
+ */
+
static int local(int cdb, const char *l, int len,
const char *sender, int *rc)
{
return (err);
}
+/* --- @virt@ --- *
+ *
+ * Arguments: @int cdb@ = file descriptor for CDB
+ * @const char *u@ = the local-part of the recipient mailbox
+ * @int ulen@ = length of the local-part
+ * @const char *addr@ = the virtual domain to look up
+ * @int alen@ = length of the virtual domain
+ * @const char *sender@ = the envelope sender address
+ * @int *rc@ = where to put the answer
+ *
+ * Returns: Positive if found, zero if not found, negative on error.
+ *
+ * Use: Looks up the address as a virtual domain. If found, the
+ * local-part is appended to the local mailbox handling the
+ * virtual domain and passed to @local@.
+ */
+
static int virt(int cdb, const char *u, int ulen,
const char *addr, int alen, const char *sender, int *rc)
{
return (1);
}
+/* --- @addrcheck@ --- *
+ *
+ * Arguments: @int cdb@ = file descriptor for CDB to look things up in
+ * @const char *addr@ = the (full) recipient mailbox to look up
+ * @const char *sender@ = the (full) envelope sender address
+ * @int *rc@ = where to put the answer.
+ *
+ * Returns: Nonnegative on success, or @-1@ on failure.
+ *
+ * Use: Determines whether @addr@ is a valid mailbox on this system,
+ * by examining the given CDB file. On exit, @*rc@ is set to
+ * @'+'@ if the mailbox is valid, or @'-'@ if not.
+ */
+
int addrcheck(int cdb, const char *addr, const char *sender, int *rc)
{
int at, len, dot;
int err = 0;
uint32 dlen;
+ static stralloc l = STRALLOC_INIT;
len = str_len(addr);
- at = str_chr(addr, '@');
+ at = str_rchr(addr, '@');
if (!addr[at])
return (local(cdb, addr, len, sender, rc));
return (-1);
if (!err) { *rc = 1; return (0); }
if (dlen != 0) { errno = EINVAL; return (-1); }
-
- return (local(cdb, addr, at, sender, rc));
+ l.len = 0;
+ if (!stralloc_catb(&l, addr, at) ||
+ !stralloc_0(&l))
+ return (-1);
+ return (local(cdb, l.s, l.len - 1, sender, rc));
}
#ifdef TEST