/* Small pieces for scanning forward on a buffer of RFC-821/822 compliant
addresses */
/* (c) Matti Aarnio 1993-2000 <mea@nic.funet.fi> */
/* All these routines scan over the lexical elements they are after, and
if successfull, return pointer just AFTER such element.
If they fail, they return their input -- thus no scan forward.. */
#ifndef __STDC__
#define const
#endif
#include <string.h>
const char *rfc821_error = 0; /* Error text */
const char *rfc821_error_ptr = 0; /* scan position of the error */
extern char *rfc821_domain(); /* Entry point */
extern char *rfc821_path(); /* Entry point */
extern char *rfc821_path2(); /* Entry point */
extern char *rfc821_adl(); /* Entry point */
static char *rfc821_localpart(); /* static forward definition */
static char *rfc821_dotnum(); /* static forward definition */
static const char *premature_end = "Premature end of input";
static const char *no_input = "No input";
/* ================================================================ */
#define CHAR_ALPHA 0x0001
#define CHAR_ALNUM 0x0002
#define CHAR_SPECL 0x0004
#define CHAR_DIGIT 0x0008
#define CHAR_C 0x0010
#define CHAR_X 0x0020
#define CHAR_Q 0x0040
#define CHAR_XDIGIT 0x0080
#define CHAR_822ATM 0x0100
#define CHAR_XCHAR 0x0200
#define CHR_ENT(a,b,c,d,e,f,g,h,i,j) \
(a?CHAR_ALPHA:0)|(b?CHAR_ALNUM:0)|(c?CHAR_SPECL:0)| \
(d?CHAR_DIGIT:0)|(e?CHAR_C:0)|(f?CHAR_X:0)|(g?CHAR_Q:0)| \
(h?CHAR_XDIGIT:0)|(i?CHAR_822ATM:0)|(j?CHAR_XCHAR:0)
/* Could use 'unsigned short' here, but the Alpha machines dislike
anything smaller than int (32 bit) */
static
#if defined(__alpha)||defined(__alpha__)
int
#else
short
#endif
char_array[] =
{
/* /------------------------------ CHAR_ALPHA
| /--------------------------- CHAR_ALNUM
| | /------------------------ CHAR_SPECL
| | | /--------------------- CHAR_DIGIT
| | | | /------------------ CHAR_C
| | | | | /--------------- CHAR_X
| | | | | | /------------ CHAR_Q
| | | | | | | /--------- CHAR_XDIGIT
| | | | | | | | /------ CHAR_822ATM
| | | | | | | | | /--- CHAR_XCHAR
| | | | | | | | | | */
/* 0: `^@' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 1: `^A' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 2: `^B' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 3: `^C' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 4: `^D' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 5: `^E' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 6: `^F' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 7: `^G' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 8: `^H' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 9: `^I' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 10: `^J' */ CHR_ENT(0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
/* 11: `^K' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 12: `^L' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 13: `^M' */ CHR_ENT(0, 0, 1, 0, 0, 1, 0, 0, 0, 0),
/* 14: `^N' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 15: `^O' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 16: `^P' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 17: `^Q' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 18: `^R' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 19: `^S' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 20: `^T' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 21: `^U' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 22: `^V' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 23: `^W' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 24: `^X' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 25: `^Y' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 26: `^Z' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 27: `^[' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 28: `^\' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 29: `^]' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 30: `^^' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 31: `^_' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 0),
/* 32: ` ' */ CHR_ENT(0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
/* 33: `!' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 34: `"' */ CHR_ENT(0, 0, 1, 0, 0, 1, 0, 0, 1, 1),
/* 35: `#' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 36: `$' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 37: `%' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 38: `&' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 39: `'' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 40: `(' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 41: `)' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 42: `*' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 43: `+' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 0),
/* 44: `,' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 45: `-' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 46: `.' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 1, 1),
/* 47: `/' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 48: `0' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 49: `1' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 50: `2' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 51: `3' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 52: `4' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 53: `5' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 54: `6' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 55: `7' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 56: `8' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 57: `9' */ CHR_ENT(0, 1, 0, 1, 1, 1, 1, 1, 1, 1),
/* 58: `:' */ CHR_ENT(0, 0, 0, 0, 0, 1, 1, 0, 0, 1),
/* 59: `;' */ CHR_ENT(0, 0, 0, 0, 0, 1, 1, 0, 0, 1),
/* 60: `<' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 61: `=' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 0),
/* 62: `>' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 63: `?' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 64: `@' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 1, 1),
/* 65: `A' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 66: `B' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 67: `C' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 68: `D' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 69: `E' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 70: `F' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 71: `G' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 72: `H' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 73: `I' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 74: `J' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 75: `K' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 76: `L' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 77: `M' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 78: `N' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 79: `O' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 80: `P' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 81: `Q' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 82: `R' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 83: `S' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 84: `T' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 85: `U' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 86: `V' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 87: `W' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 88: `X' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 89: `Y' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 90: `Z' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 91: `[' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 92: `\' */ CHR_ENT(0, 0, 1, 0, 0, 1, 0, 0, 0, 1),
/* 93: `]' */ CHR_ENT(0, 0, 1, 0, 0, 1, 1, 0, 0, 1),
/* 94: `^' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 95: `_' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 96: ``' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 97: `a' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 98: `b' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 99: `c' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 100: `d' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 101: `e' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 102: `f' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 1, 1, 1),
/* 103: `g' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 104: `h' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 105: `i' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 106: `j' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 107: `k' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 108: `l' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 109: `m' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 110: `n' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 111: `o' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 112: `p' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 113: `q' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 114: `r' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 115: `s' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 116: `t' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 117: `u' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 118: `v' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 119: `w' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 120: `x' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 121: `y' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 122: `z' */ CHR_ENT(1, 1, 0, 0, 1, 1, 1, 0, 1, 1),
/* 123: `{' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 124: `|' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 125: `}' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 126: `~' */ CHR_ENT(0, 0, 0, 0, 1, 1, 1, 0, 1, 1),
/* 127: `DEL' */ CHR_ENT(0, 0, 0, 0, 0, 1, 1, 0, 0, 0),
/* 128: `\200' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 129: `\201' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 130: `\202' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 131: `\203' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 132: `\204' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 133: `\205' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 134: `\206' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 135: `\207' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 136: `\210' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 137: `\211' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 138: `\212' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 139: `\213' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 140: `\214' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 141: `\215' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 142: `\216' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 143: `\217' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 144: `\220' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 145: `\221' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 146: `\222' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 147: `\223' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 148: `\224' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 149: `\225' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 150: `\226' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 151: `\227' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 152: `\230' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 153: `\231' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 154: `\232' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 155: `\233' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 156: `\234' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 157: `\235' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 158: `\236' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 159: `\237' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 160: `\240' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 161: `\241' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 162: `\242' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 163: `\243' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 164: `\244' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 165: `\245' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 166: `\246' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 167: `\247' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 168: `\250' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 169: `\251' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 170: `\252' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 171: `\253' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 172: `\254' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 173: `\255' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 174: `\256' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 175: `\257' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 176: `\260' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 177: `\261' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 178: `\262' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 179: `\263' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 180: `\264' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 181: `\265' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 182: `\266' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 183: `\267' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 184: `\270' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 185: `\271' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 186: `\272' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 187: `\273' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 188: `\274' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 189: `\275' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 190: `\276' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 191: `\277' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 192: `\300' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 193: `\301' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 194: `\302' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 195: `\303' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 196: `\304' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 197: `\305' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 198: `\306' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 199: `\307' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 200: `\310' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 201: `\311' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 202: `\312' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 203: `\313' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 204: `\314' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 205: `\315' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 206: `\316' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 207: `\317' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 208: `\320' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 209: `\321' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 210: `\322' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 211: `\323' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 212: `\324' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 213: `\325' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 214: `\326' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 215: `\327' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 216: `\330' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 217: `\331' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 218: `\332' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 219: `\333' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 220: `\334' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 221: `\335' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 222: `\336' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 223: `\337' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 224: `\340' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 225: `\341' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 226: `\342' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 227: `\343' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 228: `\344' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 229: `\345' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 230: `\346' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 231: `\347' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 232: `\350' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 233: `\351' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 234: `\352' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 235: `\353' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 236: `\354' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 237: `\355' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 238: `\356' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 239: `\357' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 240: `\360' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 241: `\361' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 242: `\362' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 243: `\363' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 244: `\364' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 245: `\365' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 246: `\366' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 247: `\367' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 248: `\370' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 249: `\371' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 250: `\372' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 251: `\373' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 252: `\374' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 253: `\375' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 254: `\376' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
/* 255: `\377' */ CHR_ENT(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
};
#ifdef __GNUC__
#define __MY_INLINE__ static __inline__
#else
#define __MY_INLINE__ static
#endif
__MY_INLINE__ int is_821_alpha(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_ALPHA);
}
__MY_INLINE__ int is_821_alnum(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_ALNUM);
}
__MY_INLINE__ int is_821_specl(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_SPECL);
}
__MY_INLINE__ int is_821_digit(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_DIGIT);
}
__MY_INLINE__ int is_821_xdigit(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_XDIGIT);
}
__MY_INLINE__ int is_821_C(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_C);
}
__MY_INLINE__ int is_821_X(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_X);
}
__MY_INLINE__ int is_821_Q(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_Q);
}
__MY_INLINE__ int is_822_atomchar(chr)
unsigned int chr;
{
return (char_array[chr] & CHAR_822ATM);
}
/* ================================================================ */
char *rfc822atom(str)
char *str;
{
char *str0 = str;
while (*str != 0) {
if (!is_822_atomchar(*(unsigned char *) str)) {
if (str > str0) /* Stop on ';', for example */
return str;
goto err;
}
++str;
}
if (str == str0) {
err:
rfc821_error_ptr = str;
rfc821_error = "Invalid RFC822 atom";
return str0;
}
return str;
}
char *xtext_string(str)
char *str;
{
/* Verify that the input is valid RFC 1981 XTEXT string! */
char *str0 = str;
while (*str) {
unsigned char c = *str;
if (c == ' ' || c == '\t')
break;
if (char_array[c] & CHAR_XCHAR)
/* ('!' <= c && c <= '~' && c != '+' && c != '=') */
; /* is ok! */
else if (c == '+') {
c = *++str;
if (!(('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))) {
goto err;
}
c = *++str;
if (!(('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))) {
goto err;
}
} else {
goto err;
}
++str;
}
if (str == str0) {
err:
rfc821_error_ptr = str;
rfc821_error = "Invalid character in XTEXT string";
return str0;
}
return str;
}
static
char *rfc821_at_domain(s, strict) /* "@" <domain> */
char *s;
int strict;
{
char *p;
if (!s || !*s)
return s; /* Pathological termination */
if (*s != '@') {
rfc821_error = "<at-domain> missing initial \"@\"";
rfc821_error_ptr = s;
return s;
}
p = rfc821_domain(s + 1, strict);
if (!p || p == s + 1) {
rfc821_error_ptr = s + 1;
rfc821_error = "missing domain entry";
return s;
}
return p;
}
char *rfc821_adl(s, strict) /* <at-domain> | <at-domain> "," <a-d-l> */
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s)
return s; /* Pathological termination */
while ((q = rfc821_at_domain(p, strict)) && (q > p)) {
/* Scanned over an "@"+<domain> */
p = q;
if (*p != ',')
return p;
++p;
}
return s;
}
static
char *rfc821_v6dotnum(s, strict)
char *s;
int strict;
{
/* rfc821_v6dotnum() -- rather heavily mutated from BIND 4.9.4 inet_pton6()
* routine by Matti Aarnio <mea@nic.funet.fi>, 1997 */
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
#ifndef IN6ADDRSZ /* Probably these all set at the same time.. */
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
#endif
const char *curtok;
int ch, saw_xdigit;
int tpcnt, colonidx;
unsigned int val;
char *src = s;
tpcnt = 0;
colonidx = -1;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':') {
rfc821_error_ptr = s;
rfc821_error = "Leading double-colon must have a pair in <v6dotnum>";
return (s);
}
curtok = src;
saw_xdigit = 0;
val = 0;
for ( ;((ch = *src) != '\0' && ch != ']'); ++src) {
if (is_821_xdigit(ch)) {
val <<= 4;
if (ch >= 'a')
ch -= ('a' - 'A');
if (ch >= 'A')
ch -= ('A' + 1 - '9');
val |= (ch - '0');
if (val > 0xffff) {
rfc821_error_ptr = src - 1;
rfc821_error = "Too big value for <v6dotnum> element";
return (s);
}
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonidx >= 0) {
rfc821_error_ptr = src - 2;
rfc821_error = "Illegal intermediate double-colon in <v6dotnum>";
return (s);
}
colonidx = tpcnt;
continue;
}
if (tpcnt + INT16SZ > IN6ADDRSZ) {
rfc821_error_ptr = src - 1;
rfc821_error = "Too many colon-separated components in <v6dotnum>";
return (s);
}
tpcnt += 2;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tpcnt + INADDRSZ) <= IN6ADDRSZ)) {
src = rfc821_dotnum(curtok, strict);
if (src == curtok) {
/* The plain dotnum reported its own errors.. */
return (s);
}
tpcnt += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
rfc821_error_ptr = src - 1;
rfc821_error = "<v6dotnum> error ?";
return (s);
}
if (saw_xdigit) {
if (tpcnt + INT16SZ > IN6ADDRSZ) {
rfc821_error_ptr = src - 1;
rfc821_error = "Too many colon-separated components in <v6dotnum>";
return (s);
}
tpcnt += 2;
}
if (colonidx >= 0) {
tpcnt = IN6ADDRSZ;
}
if (tpcnt != IN6ADDRSZ) {
rfc821_error_ptr = src - 1; /* XX: Really this diagnostics ? */
rfc821_error = "Too few colon-separated components in <v6dotnum>";
return (s);
}
return (src);
}
static
char *rfc821_dotnum(s, strict) /* <snum> "." <snum> "." <snum> "." <snum> */
char *s;
int strict;
{
int i, val, cnt;
char *p = s - 1;
if (*s == 'i' || *s == 'I') {
/* Wow! Possibly IPv6 prefix! */
if (strncasecmp(s, "IPv6:", 5) == 0 /* ||
strncasecmp(s, "IPv6.", 5) == 0 */ ) {
p = rfc821_v6dotnum(s + 5, strict);
if (p == s + 5)
return s;
return p;
} else {
rfc821_error_ptr = s;
rfc821_error = "Bad syntax of <dotnum/v6dotnum> value";
return s;
}
}
for (i = 0; i < 4; ++i) {
val = cnt = 0;
++p;
while (*p && is_821_digit(*p)) {
val *= 10;
val += (*p - '0');
++cnt;
++p;
}
if (val > 255 || cnt < 1 || cnt > 3) {
rfc821_error_ptr = p;
rfc821_error = "Bad syntax of <dotnum> value";
return s;
}
if (i < 3 && (!*p || *p != '.')) {
rfc821_error_ptr = p;
rfc821_error = "Bad syntax of <dotnum>, missing '.'";
return s;
}
}
return p;
}
static
char *rfc821_name(s, strict, allnump)
char *s;
int strict;
int *allnump; /* Return a flag about all-numeric field.. */
{
char c;
char *p = s;
char *bad_name = "RFC821 <name> bad syntax";
int has_alpha = 0;
if (!s || !*s)
return s; /* Pathological termination */
/* The first test should be is_821_alpha(), as per RFC821
we should accept only A-Z,a-Z in the begining, but
3COM spoiled that... Grumble... */
/* So now we allow chars: 0-9, A-Z, a-z, and '-' for valid at
the domain name segment -- but '-' is not ok at the begin. */
/* To note futher; the underscore is not allowed at the DNS,
and thus it should not be allowed at email addresses either. */
/* Our caller will do deeper analysis, wether or not ALL of the
input was numeric: foo@12.34.56.78 If yes, special error
message is reported. For that purpose we count '-' as an alpha */
c = *p;
if (!is_821_alnum(c)) {
rfc821_error_ptr = p;
rfc821_error = bad_name;
return s; /* Don't advance, leave! */
}
while (is_821_alnum(c) || (c == '-')) {
has_alpha |= (is_821_alpha(c) || c == '-');
c = *(++p);
}
*allnump &= !has_alpha;
return p; /* Name ok, return advanced pointer */
}
char *rfc821_domain(s, strict) /* "#" <number> | "[" <dotnum> "]" | <name> | <name> "." <domain> */
char *s;
int strict;
{
char *p = s, *q;
int allnum; /* If all fields are numeric, it isn't domain.. */
if (!s || !*s) {
rfc821_error = "RFC821: No input";
return s; /* Pathological termination */
}
if (*p == '[') {
q = rfc821_dotnum(p + 1, strict);
if (q == p + 1)
return s;
if (*q != ']') {
rfc821_error_ptr = q - 1;
rfc821_error = "RFC821 <dotnum> element missing terminating \"]\"";
return s;
}
return q + 1;
}
if (*p == '#') {
/* Deprecated "#1234234324" -format */
++p;
while (is_821_digit(*p))
++p;
if (p > s + 1)
return p;
rfc821_error_ptr = s;
rfc821_error = "RFC821 Domain \"#numbers\" has inadequate count of numbers";
return s; /* Failure, don't advance */
}
allnum = 1; /* Collect info about all fields being numeric..
To accept "1302.watstar.waterloo.edu" et.al.
but not something which looks like all numbers.. */
if (*p == '.') {
rfc821_error = "A domain-name does not start with a dot (.)";
rfc821_error_ptr = p;
return s;
}
q = rfc821_name(p, strict, &allnum);
while (p && q > p && *q == '.') {
p = q + 1;
if (*p == 0 || *p == '>') {
rfc821_error = "Spurious dot (.) at the end of the domain name";
rfc821_error_ptr = q;
return s;
}
q = rfc821_name(p, strict, &allnum);
}
if (allnum) {
rfc821_error = "Should this be of <dotnum> format ? ( [nn.nn.nn.nn] )";
return s;
}
if (!rfc821_error)
rfc821_error = "bad syntax on domain";
if (!q || p == q)
return s; /* Report whatever <name> reports */
return q; /* Ok */
}
static
char *rfc821_mailbox(s, strict) /* <local-part> "@" <domain> */
char *s; /* Report error */
int strict;
{
char *p = s, *q;
if (!s || !*s) {
/* rfc821_error_ptr = s;
rfc821_error = no_input; */
return s; /* Pathological termination */
}
p = rfc821_localpart(p, strict);
if (p == s) {
/*rfc821_error_ptr = s; */
/*rfc821_error = "No mailbox definition"; */
return s;
}
if (!strict) {
if (*p == 0 || *p == '>') /* If it terminates here, it is
only the <local-part> */
return p;
}
if (*p == ':') {
rfc821_error_ptr = p;
rfc821_error = "Perhaps this should have been a dot (.) instead of colon (:) ?";
return s;
}
if (*p != '@') {
rfc821_error_ptr = p;
rfc821_error = "Missing \"@\" from mailbox definition";
return s;
}
++p;
q = rfc821_domain(p, strict);
if (q == p) {
/* Error report from domain.. */
return s;
}
return q;
}
static
char *rfc821_char(s)
char *s;
{
if (!s || !*s)
return s;
if (*s == '\\') {
if (!is_821_X(*(s + 1)))
return s;
return s + 2;
}
if (is_821_C(*s))
return s + 1;
return s;
}
static
char *rfc821_string(s, strict)
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s)
return s;
while ((q = rfc821_char(p)) && (q > p)) {
p = q;
}
if (*(unsigned char *) q > 127) {
rfc821_error_ptr = q;
rfc821_error = "Improper 8-bit character in string";
return s;
}
if (q == s) {
rfc821_error_ptr = s;
rfc821_error = "Had characters unsuitable for an rfc821-string";
}
return q; /* Advanced or not.. */
}
static
char *rfc821_dot_string(s, strict)
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s)
return s; /* Pathological termination */
q = rfc821_string(p, strict);
if (q == p)
return s; /* Missing string */
while (*q == '.') { /* Well, intermediate dot.. */
p = q + 1;
#if 0
if (!is_821_alnum(*p)) {
rfc821_error_ptr = q;
rfc821_error = "After a dot, something which is not alphanumeric";
return s;
}
#endif
q = rfc821_string(p, strict);
if (q == p) {
if (*q == '@') {
rfc821_error = "Localpart must not end with unquoted dot!";
}
return s; /* Missing string */
}
}
return q;
}
static
char *rfc821_qtext(s, strict)
char *s;
int strict;
{
char *p = s;
int fail = 0;
if (!s || !*s)
return s;
while (*p && !fail) {
if (*p == '\\') {
++p;
if (is_821_X(*p))
++p;
else
fail = 1;
} else if (is_821_Q(*p))
++p;
else
break;
}
if ((unsigned char) *p > 127) {
rfc821_error_ptr = p;
rfc821_error = "Improper 8-bit character in qtext";
return s;
}
if (fail || p == s) {
rfc821_error_ptr = p;
rfc821_error = "RFC821 qtext data failure";
return s;
}
return p;
}
static
char *rfc821_quoted_string(s, strict)
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s)
return s; /* Pathological termination */
if (*p != '"') {
rfc821_error_ptr = p;
rfc821_error = "Quoted string w/o initial quote (\")";
return s;
}
++p;
q = rfc821_qtext(p, strict);
if (p == q) {
/* rfc821_error_ptr = q;
rfc821_error = "Quoted string of 0 length :-("; */
return s;
}
if (*q != '"') {
rfc821_error_ptr = q;
rfc821_error = "Quoted string w/o final quote (\")";
return s;
}
return q + 1;
}
static
char *rfc821_localpart(s, strict) /* <dot-string> | <quoted-string> */
char *s; /* Stretched RFC821 a bit here.. !%-hacks */
int strict;
{
char *p = s, *q;
/* int _ok = 0; */
if (!s || !*s)
return s; /* Pathological termination */
while (*p) {
if (*p == '"') {
q = rfc821_quoted_string(p, strict);
if (q == p)
return s; /* Uh... */
#if 0 /* RFC 2821 -- local part internal hack-syntax interpretation
shall not be done, unless domain is known to be local */
if (*q == '%' || *q == '!') {
p = q + 1;
_ok = (*q == '!' && *p == '_');
if (!is_821_alnum(*p) && !_ok && *p != '"') {
rfc821_error_ptr = q;
if (*q == '%') {
rfc821_error = "After a '%', a non alphanumeric element";
} else {
rfc821_error = "After a '!', a non alphanumeric element";
}
return s;
}
continue;
}
#endif
return q;
}
q = rfc821_dot_string(p, strict);
if (q == p)
return s; /* Uh... */
#if 0 /* RFC 2821 -- local part internal hack-syntax interpretation
shall not be done, unless domain is known to be local */
if (*q == '%' || *q == '!') {
p = q + 1;
_ok = (*q == '!' && *p == '_');
if (!is_821_alnum(*p) && !_ok && *p != '"') {
rfc821_error_ptr = q;
if (*q == '%') {
rfc821_error = "After a '%', a non alphanumeric element";
} else {
rfc821_error = "After a '!', a non alphanumeric element";
}
return s;
}
continue;
}
#endif
return q;
}
return p; /* Run to end of string.. */
}
char *rfc821_path2(s, strict) /* [ <a-d-l> ":" ] <mailbox> */
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s) {
rfc821_error_ptr = s;
rfc821_error = no_input;
return s; /* Pathological termination */
}
if (*p == '@' && (q = rfc821_adl(p, strict)) && (q > p)) {
p = q;
if (*p == '>' || *p == ' ') {
rfc821_error_ptr = p;
rfc821_error = "No local part before leading @-character ?";
return s;
}
if (*p != ':') {
rfc821_error_ptr = p;
rfc821_error = "Missing colon (:) from <@xxx:yyy@zzz>";
return s;
}
++p;
}
q = rfc821_mailbox(p, strict);
if (q == p) {
/* Report whatever mailbox() reports as an error */
return s;
}
return q;
}
char *rfc821_path(s, strict) /* "<" [ <a-d-l> ":" ] <mailbox> ">" */
char *s;
int strict;
{
char *p = s, *q;
if (!s || !*s) {
rfc821_error_ptr = s;
rfc821_error = no_input;
return s; /* Pathological termination */
}
if (*p != '<') {
rfc821_error = "Missing \"<\" from begining";
rfc821_error_ptr = p;
return s;
}
++p;
if (!*p) {
rfc821_error = premature_end;
rfc821_error_ptr = p;
return s;
}
if (*p == '>') {
return p + 1; /* Termination ok */
}
q = rfc821_path2(p, strict);
if (q == p) {
/* Report whatever path2() reports as an error */
return s;
}
if (*q == ' ' || *q == '\t') {
/* Sometimes sending systems have: <foo@foo >, painfull.. */
p = q;
while (*p == ' ' || *p == '\t') ++p;
/* Ok, copy down the rest of the input, and thus save the day..
Purist would just report an error, but lets be lenient, when
it is fairly easy, and painless to do.. */
if (p > q)
strcpy(q, p);
}
if (*q != '>') {
rfc821_error = "Missing \">\" at end";
if (*q)
rfc821_error = "Extra garbage before terminating \">\"";
rfc821_error_ptr = q;
return s;
}
return q + 1;
}
syntax highlighted by Code2HTML, v. 0.9.1