Beispiel #1
0
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);
}
Beispiel #2
0
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, &quote, &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, &quote, &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;
}