char * find_address(char *buf, size_t len, size_t *alen) { char *ptr, *hdr, *first, *last; /* * RFC2822 email addresses are stupidly complicated, so we just do a * naive match which is good enough for 99% of addresses used now. This * code is pretty inefficient. */ /* Duplicate the header as a string to work on it. */ if (len == 0) return (NULL); hdr = xmalloc(len + 1); strlcpy(hdr, buf, len + 1); /* First, replace any sections in "s with spaces. */ ptr = hdr; while (*ptr != '\0') { if (*ptr == '"') { ptr++; while (*ptr != '"' && *ptr != '\0') *ptr++ = ' '; if (*ptr == '\0') break; } ptr++; } /* * Now, look for sections matching: * [< ][A-Za-z0-9._%+-]+@[A-Za-z0-9.\[\]-]+[> ,;]. */ #define isfirst(c) ((c) == '<' || (c) == ' ') #define islast(c) ((c) == '>' || (c) == ' ' || (c) == ',' || (c) == ';') #define isuser(c) (isalnum(c) || \ (c) == '.' || (c) == '_' || (c) == '%' || (c) == '+' || (c) == '-') #define isdomain(c) (isalnum(c) || \ (c) == '.' || (c) == '-' || (c) == '[' || (c) == ']') ptr = hdr + 1; for (;;) { /* Find an @. */ if ((ptr = strchr(ptr, '@')) == NULL) break; /* Find the end. */ last = ptr + 1; while (*last != '\0' && isdomain((u_char) *last)) last++; if (*last != '\0' && !islast((u_char) *last)) { ptr = last + 1; continue; } /* Find the start. */ first = ptr - 1; while (first != hdr && isuser((u_char) *first)) first--; if (first != hdr && !isfirst((u_char) *first)) { ptr = last + 1; continue; } /* If the last is > the first must be < and vice versa. */ if (*last == '>' && *first != '<') { ptr = last + 1; continue; } if (*first == '<' && *last != '>') { ptr = last + 1; continue; } /* If not right at the start, strip first character. */ if (first != hdr) first++; /* Free header copy. */ xfree(hdr); /* Have last and first, return the address. */ *alen = last - first; return (buf + (first - hdr)); } xfree(hdr); return (NULL); }
int main(int argc, const char * const *argv) { int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1, Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0, fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0, touch = -1; int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs; charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL; char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end, **nextline, **outlines = NULL, **line; const char *env, * const whitechars = " \f\n\r\t\v"; errmsg_t errmsg = { '\0' }; lineprop *props = NULL, *firstprop, *nextprop; FILE *errout; /* Process environment variables: */ env = getenv("PARBODY"); if (!env) env = ""; bodychars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARPROTECT"); if (!env) env = ""; protectchars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARQUOTE"); if (!env) env = "> "; quotechars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARINIT"); if (env) { parinit = malloc((strlen(env) + 1) * sizeof (char)); if (!parinit) { strcpy(errmsg,outofmem); goto parcleanup; } strcpy(parinit,env); arg = strtok(parinit,whitechars); while (arg) { parsearg(arg, &help, &version, bodychars, protectchars, quotechars, &hang, &prefix, &repeat, &suffix, &Tab, &width, &body, &cap, &div, &Err, &expel, &fit, &guess, &invis, &just, &last, "e, &Report, &touch, errmsg ); if (*errmsg || help || version) goto parcleanup; arg = strtok(NULL,whitechars); } free(parinit); parinit = NULL; } /* Process command line arguments: */ while (*++argv) { parsearg(*argv, &help, &version, bodychars, protectchars, quotechars, &hang, &prefix, &repeat, &suffix, &Tab, &width, &body, &cap, &div, &Err, &expel, &fit, &guess, &invis, &just, &last, "e, &Report, &touch, errmsg ); if (*errmsg || help || version) goto parcleanup; } if (Tab == 0) { strcpy(errmsg, "<Tab> must not be 0.\n"); goto parcleanup; } if (touch < 0) touch = fit || last; prefixbak = prefix; suffixbak = suffix; /* Main loop: */ for (sawnonblank = oweblank = 0; ; ) { for (;;) { c = getchar(); if (expel && c == '\n') { oweblank = sawnonblank; continue; } if (csmember((char) c, protectchars)) { sawnonblank = 1; if (oweblank) { putchar('\n'); oweblank = 0; } while (c != '\n' && c != EOF) { putchar(c); c = getchar(); } } if (c != '\n') break; putchar(c); } if (c == EOF) break; ungetc(c,stdin); inlines = readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg); if (*errmsg) goto parcleanup; for (endline = inlines; *endline; ++endline); if (endline == inlines) { free(inlines); inlines = NULL; continue; } sawnonblank = 1; if (oweblank) { putchar('\n'); oweblank = 0; } delimit((const char * const *) inlines, (const char * const *) endline, bodychars, repeat, body, div, 0, 0, props); if (expel) marksuperf((const char * const *) inlines, (const char * const *) endline, props); firstline = inlines, firstprop = props; do { if (isbodiless(firstprop)) { if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) { for (end = *firstline; *end; ++end); if (!repeat || firstprop->rc == ' ' && !firstprop->s) { while (end > *firstline && end[-1] == ' ') --end; *end = '\0'; puts(*firstline); } else { n = width - firstprop->p - firstprop->s; if (n < 0) { sprintf(errmsg,impossibility,5); goto parcleanup; } printf("%.*s", firstprop->p, *firstline); for (i = n; i; --i) putchar(firstprop->rc); puts(end - firstprop->s); } } ++firstline, ++firstprop; continue; } for (nextline = firstline + 1, nextprop = firstprop + 1; nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop); ++nextline, ++nextprop); prefix = prefixbak, suffix = suffixbak; setaffixes((const char * const *) firstline, (const char * const *) nextline, firstprop, bodychars, quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix); if (width <= prefix + suffix) { sprintf(errmsg, "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n", width, prefix, suffix); goto parcleanup; } outlines = reformat((const char * const *) firstline, (const char * const *) nextline, afp, fs, hang, prefix, suffix, width, cap, fit, guess, just, last, Report, touch, errmsg); if (*errmsg) goto parcleanup; for (line = outlines; *line; ++line) puts(*line); freelines(outlines); outlines = NULL; firstline = nextline, firstprop = nextprop; } while (firstline < endline); freelines(inlines); inlines = NULL; free(props); props = NULL; } parcleanup: if (bodychars) freecharset(bodychars); if (protectchars) freecharset(protectchars); if (quotechars) freecharset(quotechars); if (parinit) free(parinit); if (inlines) freelines(inlines); if (props) free(props); if (outlines) freelines(outlines); errout = Err ? stderr : stdout; if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg); if (version) fputs("par 1.50\n",errout); if (help) fputs(usagemsg,errout); return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS; }