Example #1
0
File: dir.c Project: B-Rich/git
int add_excludes_from_file_to_list(const char *fname,
				   const char *base,
				   int baselen,
				   struct exclude_list *el,
				   int check_index)
{
	struct stat st;
	int fd, i, lineno = 1;
	size_t size = 0;
	char *buf, *entry;

	fd = open(fname, O_RDONLY);
	if (fd < 0 || fstat(fd, &st) < 0) {
		if (errno != ENOENT)
			warn_on_inaccessible(fname);
		if (0 <= fd)
			close(fd);
		if (!check_index ||
		    (buf = read_skip_worktree_file_from_index(fname, &size)) == NULL)
			return -1;
		if (size == 0) {
			free(buf);
			return 0;
		}
		if (buf[size-1] != '\n') {
			buf = xrealloc(buf, size+1);
			buf[size++] = '\n';
		}
	}
	else {
		size = xsize_t(st.st_size);
		if (size == 0) {
			close(fd);
			return 0;
		}
		buf = xmalloc(size+1);
		if (read_in_full(fd, buf, size) != size) {
			free(buf);
			close(fd);
			return -1;
		}
		buf[size++] = '\n';
		close(fd);
	}

	el->filebuf = buf;
	entry = buf;
	for (i = 0; i < size; i++) {
		if (buf[i] == '\n') {
			if (entry != buf + i && entry[0] != '#') {
				buf[i - (i && buf[i-1] == '\r')] = 0;
				trim_trailing_spaces(entry);
				add_exclude(entry, base, baselen, el, lineno);
			}
			lineno++;
			entry = buf + i + 1;
		}
	}
	return 0;
}
Example #2
0
void
j_yearly(int year)
{
	int col, *dp, i, month, row, which_cal;
	int days[12][MAXDAYS];
	char *p, lineout[80];

	(void)snprintf(lineout, sizeof(lineout), "%d", year);
	center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
	(void)printf("\n\n");
	for (i = 0; i < 12; i++)
		day_array(i + 1, year, days[i]);
	(void)memset(lineout, ' ', sizeof(lineout) - 1);
	lineout[sizeof(lineout) - 1] = '\0';
	for (month = 0; month < 12; month += 2) {
		center(month_names[month], J_WEEK_LEN, J_HEAD_SEP);
		center(month_names[month + 1], J_WEEK_LEN, 0);
		(void)printf("\n%s%*s%s\n", day_headings,
		    J_HEAD_SEP, "", day_headings);

		for (row = 0; row < 6; row++) {
			for (which_cal = 0; which_cal < 2; which_cal++) {
				p = lineout + which_cal * (J_WEEK_LEN + 2);
				dp = &days[month + which_cal][row * 7];
				for (col = 0; col < 7; col++, p += J_DAY_LEN)
					ascii_day(p, *dp++);
			}
			*p = '\0';
			trim_trailing_spaces(lineout);
			(void)printf("%s\n", lineout);
		}
	}
	(void)printf("\n");
}
Example #3
0
File: rfc822.c Project: gpg/geam
/****************
 * Note: For program supplied (and therefore syntactically correct)
 *	 header lines, rfc822_add_header() may be used.
 */
int
insert_header( RFC822 msg, char *line, size_t length )
{
    HDR_LINE hdr;

    if( !length ) {
        msg->in_body = 1;
        return transition_to_body(msg);
    }
    trim_trailing_spaces(line);
    /* Hmmm: should we check for invalid header data here? */

    hdr = malloc( sizeof( *hdr ) + strlen(line) );
    if( !hdr )
        return RFC822ERR_NOMEM;
    hdr->next = NULL;
    hdr->cont = (*line == ' ' || *line == '\t');
    strcpy(hdr->line, line );

    *msg->hdr_lines_head = hdr;
    msg->hdr_lines_head = &hdr->next;

    /* lets help the caller to prevent mail loops
     * It is okay to use length here, also this value
     * not correct due to the space trimming */
    if( length >= 9 && !memicmp(line, "Received:", 9) )
        do_callback( msg, RFC822EVT_RCVD_SEEN );
    return 0;
}
Example #4
0
void
monthly(int month, int year)
{
	int col, row, len, days[MAXDAYS], firstday;
	char *p, lineout[30];

	day_array(month, year, days);
	(void)snprintf(lineout, sizeof(lineout), "%s %d",
	    month_names[month - 1], year);
	len = strlen(lineout);
	(void)printf("%*s%s\n%s\n",
	    ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
	    lineout, day_headings);
	for (row = 0; row < 6; row++) {
		firstday = SPACE;
		for (col = 0, p = lineout; col < 7; col++,
		    p += julian ? J_DAY_LEN : DAY_LEN) {
			if (firstday == SPACE && days[row * 7 + col] != SPACE)
				firstday = days[row * 7 + col];
			ascii_day(p, days[row * 7 + col]);
		}
		*p = '\0';
		trim_trailing_spaces(lineout);
		(void)printf("%-20s", lineout);
		if (wflag && firstday != SPACE)
			printf(" [%2d]", week(firstday, month, year));
		printf("\n");
	}
}
Example #5
0
void
j_yearly(int day, int year) {
	int col, *dp, i, month, row, which_cal;
	int days[12][MAXDAYS];
	char *p, lineout[80];

	snprintf(lineout, sizeof(lineout), "%d", year);
	center(lineout, J_WEEK_LEN*2 + J_HEAD_SEP - 1, 0);
	printf("\n\n");

	for (i = 0; i < 12; i++)
		day_array(day, i + 1, year, days[i]);
	memset(lineout, ' ', sizeof(lineout) - 1);
	lineout[sizeof(lineout) - 1] = '\0';
	for (month = 0; month < 12; month += 2) {
		center(full_month[month], J_WEEK_LEN-1, J_HEAD_SEP+1);
		center(full_month[month + 1], J_WEEK_LEN-1, 0);
		printf("\n%s%*s %s\n", j_day_headings, J_HEAD_SEP, "",
		    j_day_headings);
		for (row = 0; row < 6; row++) {
			p = lineout;
			for (which_cal = 0; which_cal < 2; which_cal++) {
				dp = &days[month + which_cal][row * 7];
				for (col = 0; col < 7; col++)
					p = ascii_day(p, *dp++);
				p += sprintf(p, "  ");
			}
			*p = '\0';
			trim_trailing_spaces(lineout);
			my_putstring(lineout);
			putchar('\n');
		}
	}
	printf("\n");
}
Example #6
0
void
do_monthly(int day, int month, int year, struct fmt_st *out) {
	int col, row, days[MAXDAYS];
	char *p, lineout[FMT_ST_CHARS];
	int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1;

	day_array(day, month, year, days);

	/*
	 * %s is the month name, %d the year number.
	 * you can change the order and/or add something here; eg for
	 * Basque the translation should be: "%2$dko %1$s", and
	 * the Vietnamese should be "%s na(m %d", etc.
	 */
	snprintf(lineout, sizeof(lineout), _("%s %d"),
			full_month[month - 1], year);
	center_str(lineout, out->s[0], ARRAY_SIZE(out->s[0]), width);

	snprintf(out->s[1], FMT_ST_CHARS, "%s",
		julian ? j_day_headings : day_headings);
	for (row = 0; row < 6; row++) {
		int has_hl = 0;
		for (col = 0, p = lineout; col < 7; col++) {
			int xd = days[row * 7 + col];
			if (xd != SPACE && (xd & TODAY_FLAG))
				has_hl = 1;
			p = ascii_day(p, xd);
		}
		*p = '\0';
		trim_trailing_spaces(lineout);
		snprintf(out->s[row+2], FMT_ST_CHARS, "%s", lineout);
		if (has_hl)
			Hrow = out->s[row+2];
	}
}
Example #7
0
void
yearly(int year)
{
	int col, *dp, i, month, row, which_cal, week_len, wn, firstday;
	int days[12][MAXDAYS];
	char *p, lineout[81];

	week_len = WEEK_LEN;
	if (wflag)
		week_len += WEEKNUMBER_LEN;
	(void)snprintf(lineout, sizeof(lineout), "%d", year);
	center(lineout, week_len * 3 + HEAD_SEP * 2, 0);
	(void)printf("\n\n");
	for (i = 0; i < 12; i++)
		day_array(i + 1, year, days[i]);
	(void)memset(lineout, ' ', sizeof(lineout) - 1);
	lineout[sizeof(lineout) - 1] = '\0';
	for (month = 0; month < 12; month += 3) {
		center(month_names[month], week_len, HEAD_SEP);
		center(month_names[month + 1], week_len, HEAD_SEP);
		center(month_names[month + 2], week_len, 0);
		(void)printf("\n%s%*s%s%*s%s\n", day_headings,
		    HEAD_SEP + (wflag ? WEEKNUMBER_LEN : 0), "", day_headings,
		    HEAD_SEP + (wflag ? WEEKNUMBER_LEN : 0), "", day_headings);

		for (row = 0; row < 6; row++) {
			for (which_cal = 0; which_cal < 3; which_cal++) {
				p = lineout + which_cal * (week_len + 2);
				
				dp = &days[month + which_cal][row * 7];
				firstday = SPACE;
				for (col = 0; col < 7; col++, p += DAY_LEN) {
					if (firstday == SPACE && *dp != SPACE)
						firstday = *dp;
					ascii_day(p, *dp++);
				}
				if (wflag && firstday != SPACE) {
					wn = week(firstday,
					    month + which_cal + 1, year);
					(void)snprintf(p, 5, "[%2d]", wn);
					p += strlen(p);
					*p = ' ';
				} else
					memset(p, ' ', 4);
			}
			*p = '\0';
			trim_trailing_spaces(lineout);
			(void)printf("%s\n", lineout);
		}
	}
	(void)printf("\n");
}
Example #8
0
char *
gnupg_get_help_string (const char *key, int only_current_locale)
{
  static const char *locname;
  char *result;

  if (!locname)
    {
      char *buffer, *p;
      int count = 0;
      const char *s = gnupg_messages_locale_name ();
      buffer = xtrystrdup (s);
      if (!buffer)
        locname = "";
      else
        {
          for (p = buffer; *p; p++)
            if (*p == '.' || *p == '@' || *p == '/' /*(safeguard)*/)
              *p = 0;
            else if (*p == '_')
              {
                if (count++)
                  *p = 0;  /* Also cut at a underscore in the territory.  */
              }
          locname = buffer;
        }
    }

  if (!key || !*key)
    return NULL;

  result = findkey_locale (key, locname, only_current_locale, 
                           gnupg_sysconfdir ());
  if (!result)
    result = findkey_locale (key, locname, only_current_locale,
                             gnupg_datadir ());

  if (result)
    trim_trailing_spaces (result);

  return result;
}
Example #9
0
/* helper for the rfc2253 string parser */
static const unsigned char *
parse_dn_part (struct dn_array_s *array, const unsigned char *string)
{
  static struct {
    const char *label;
    const char *oid;
  } label_map[] = {
    /* Warning: When adding new labels, make sure that the buffer
       below we be allocated large enough. */
    {"EMail",        "1.2.840.113549.1.9.1" },
    {"T",            "2.5.4.12" },
    {"GN",           "2.5.4.42" },
    {"SN",           "2.5.4.4" },
    {"NameDistinguisher", "0.2.262.1.10.7.20"},
    {"ADDR",         "2.5.4.16" },
    {"BC",           "2.5.4.15" },
    {"D",            "2.5.4.13" },
    {"PostalCode",   "2.5.4.17" },
    {"Pseudo",       "2.5.4.65" },
    {"SerialNumber", "2.5.4.5" },
    {NULL, NULL}
  };
  const unsigned char *s, *s1;
  size_t n;
  char *p;
  int i;

  /* Parse attributeType */
  for (s = string+1; *s && *s != '='; s++)
    ;
  if (!*s)
    return NULL; /* error */
  n = s - string;
  if (!n)
    return NULL; /* empty key */

  /* We need to allocate a few bytes more due to the possible mapping
     from the shorter OID to the longer label. */
  array->key = p = xtrymalloc (n+10);
  if (!array->key)
    return NULL;
  memcpy (p, string, n);
  p[n] = 0;
  trim_trailing_spaces (p);

  if (digitp (p))
    {
      for (i=0; label_map[i].label; i++ )
        if ( !strcmp (p, label_map[i].oid) )
          {
            strcpy (p, label_map[i].label);
            break;
          }
    }
  string = s + 1;

  if (*string == '#')
    { /* hexstring */
      string++;
      for (s=string; hexdigitp (s); s++)
        s++;
      n = s - string;
      if (!n || (n & 1))
        return NULL; /* Empty or odd number of digits. */
      n /= 2;
      array->value = p = xtrymalloc (n+1);
      if (!p)
        return NULL;
      for (s1=string; n; s1 += 2, n--, p++)
        {
          *(unsigned char *)p = xtoi_2 (s1);
          if (!*p)
            *p = 0x01; /* Better print a wrong value than truncating
                          the string. */
        }
      *p = 0;
   }
  else
    { /* regular v3 quoted string */
      for (n=0, s=string; *s; s++)
        {
          if (*s == '\\')
            { /* pair */
              s++;
              if (*s == ',' || *s == '=' || *s == '+'
                  || *s == '<' || *s == '>' || *s == '#' || *s == ';'
                  || *s == '\\' || *s == '\"' || *s == ' ')
                n++;
              else if (hexdigitp (s) && hexdigitp (s+1))
                {
                  s++;
                  n++;
                }
              else
                return NULL; /* invalid escape sequence */
            }
          else if (*s == '\"')
            return NULL; /* invalid encoding */
          else if (*s == ',' || *s == '=' || *s == '+'
                   || *s == '<' || *s == '>' || *s == ';' )
            break;
          else
            n++;
        }

      array->value = p = xtrymalloc (n+1);
      if (!p)
        return NULL;
      for (s=string; n; s++, n--)
        {
          if (*s == '\\')
            {
              s++;
              if (hexdigitp (s))
                {
                  *(unsigned char *)p++ = xtoi_2 (s);
                  s++;
                }
              else
                *p++ = *s;
            }
          else
            *p++ = *s;
        }
      *p = 0;
    }
  return s;
}
Example #10
0
/*
 * Process "[attach/include filename content-type content-encoding]" line.
 */
static SEND_BODYPART *process_attach_line(char *cmdline)
{
    char *fld;
    char *cmd = NULL;
    char *fname = NULL;
    char *cont_type = NULL;
    char *cont_encoding = NULL;
    char buf[SLEN];
    const char *actual_type;
    SEND_BODYPART *part;
    int fldno, len;

    len = strlen(trim_trailing_spaces(cmdline));
    if (cmdline[0] != '[' || cmdline[len-1] != ']') {
	show_error("malformed \"[attach/include ...]\" line");
	return (SEND_BODYPART *) NULL;
    }
    cmdline[len-1] = '\0';
    ++cmdline;

    for (fldno = 0 ; (fld = strtok(cmdline, " \t")) != NULL ; ++fldno) {
	cmdline = NULL;
	switch (fldno) {
	case 0:		/* attach/include */
	    cmd = fld;
	    break;
	case 1:		/* filename */
	    fname = fld;
	    break;
	case 2:		/* content-type */
	    cont_type = fld;
	    break;
	case 3:		/* content-encoding */
	    cont_encoding = fld;
	    break;
	default:	/* too many fields */
	    break;
	}
    }

    switch (fldno) {
    case 0:
	show_error("malformed \"[attach/include ...]\" line");
	return (SEND_BODYPART *) NULL;
    case 1:
	show_error("filename missing from \"[%s ...]\" line", cmd);
	return (SEND_BODYPART *) NULL;
    case 2:
	cont_type = NULL;
	/*FALLTHRU */
    case 3:
	cont_encoding = NULL;
	/*FALLTHRU*/
    case 4:
	break;
    default:
	show_error("too many fields in \"[%s ...]\" line", cmd);
	return (SEND_BODYPART *) NULL;
    }

    if (cont_encoding != NULL && !encoding_is_reasonable(cont_encoding))
	return (SEND_BODYPART *) NULL;

    if ((part = newpart_mimepart(fname)) == NULL)
	return (SEND_BODYPART *) NULL;

    if (cont_type == NULL)
	bodypart_guess_content(part, BP_CONT_TYPE);
    else
	bodypart_set_content(part, BP_CONT_TYPE, cont_type);

    if (cont_encoding == NULL)
	bodypart_guess_content(part, BP_CONT_ENCODING);
    else
/*	bodypart_set_content(part, BP_CONT_ENCODING, cont_type);*/
     bodypart_set_content(part, BP_CONT_ENCODING, cont_encoding);

    actual_type = bodypart_get_content(part, BP_CONT_TYPE);
    if (actual_type == NULL || strncasecmp(actual_type, "text", 4) != 0) {
	bodypart_guess_content(part, BP_CONT_DESCRIPTION);
	bodypart_guess_content(part, BP_CONT_MD5);
    }

    sprintf(buf, "%s; filename=\"%s\"",
		(*cmd == 'i' ? "inline" : "attachment"), basename(fname));
    bodypart_set_content(part, BP_CONT_DISPOSITION, buf);

    bodypart_integrity_check(part);
    return part;
}
Example #11
0
/* Parse a DN and return an array-ized one.  This is not a validating
   parser and it does not support any old-stylish syntax; gpgme is
   expected to return only rfc2253 compatible strings. */
static const unsigned char *
parse_dn_part (DnPair *array, const unsigned char *string)
{
  const unsigned char *s, *s1;
  size_t n;
  char *p;

  /* parse attributeType */
  for (s = string+1; *s && *s != '='; s++)
    ;
  if (!*s)
    return NULL; /* error */
  n = s - string;
  if (!n)
    return NULL; /* empty key */
  p = (char*)malloc (n+1);
  
  
  memcpy (p, string, n);
  p[n] = 0;
  trim_trailing_spaces ((char*)p);
  // map OIDs to their names:
  for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
    if ( !strcasecmp ((char*)p, oidmap[i].oid) ) {
      free( p );
      p = strdup( oidmap[i].name );
      break;
    }
  array->key = p;
  string = s + 1;

  if (*string == '#')
    { /* hexstring */
      string++;
      for (s=string; hexdigitp (s); s++)
        s++;
      n = s - string;
      if (!n || (n & 1))
        return NULL; /* empty or odd number of digits */
      n /= 2;
      array->value = p = (char*)malloc (n+1);
      
      
      for (s1=string; n; s1 += 2, n--)
        *p++ = xtoi_2 (s1);
      *p = 0;
   }
  else
    { /* regular v3 quoted string */
      for (n=0, s=string; *s; s++)
        {
          if (*s == '\\')
            { /* pair */
              s++;
              if (*s == ',' || *s == '=' || *s == '+'
                  || *s == '<' || *s == '>' || *s == '#' || *s == ';' 
                  || *s == '\\' || *s == '\"' || *s == ' ')
                n++;
              else if (hexdigitp (s) && hexdigitp (s+1))
                {
                  s++;
                  n++;
                }
              else
                return NULL; /* invalid escape sequence */
            }
          else if (*s == '\"')
            return NULL; /* invalid encoding */
          else if (*s == ',' || *s == '=' || *s == '+'
                   || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
            break; 
          else
            n++;
        }

      array->value = p = (char*)malloc (n+1);
      
      
      for (s=string; n; s++, n--)
        {
          if (*s == '\\')
            { 
              s++;
              if (hexdigitp (s))
                {
                  *p++ = xtoi_2 (s);
                  s++;
                }
              else
                *p++ = *s;
            }
          else
            *p++ = *s;
        }
      *p = 0;
    }
  return s;
}
Example #12
0
/* Try to find KEY in the file FNAME.  */
static char *
findkey_fname (const char *key, const char *fname)
{
  gpg_error_t err = 0;
  FILE *fp;
  int lnr = 0;
  int c;
  char *p, line[256];
  int in_item = 0;
  membuf_t mb = MEMBUF_ZERO;

  fp = fopen (fname, "r");
  if (!fp)
    {
      if (errno != ENOENT)
        {
          err = gpg_error_from_syserror ();
          log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
        }
      return NULL;
    }

  while (fgets (line, DIM(line)-1, fp))
    {
      lnr++;
      
      if (!*line || line[strlen(line)-1] != '\n')
        {
          /* Eat until end of line. */
          while ( (c=getc (fp)) != EOF && c != '\n')
            ;
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                           : GPG_ERR_INCOMPLETE_LINE);
          log_error (_("file `%s', line %d: %s\n"),
                     fname, lnr, gpg_strerror (err));
        }
      else
        line[strlen(line)-1] = 0; /* Chop the LF. */
      
    again:
      if (!in_item)
        {
          /* Allow for empty lines and spaces while not in an item. */
          for (p=line; spacep (p); p++)
            ;
          if (!*p || *p == '#')
            continue;
          if (*line != '.' || spacep(line+1))
            {
              log_info (_("file `%s', line %d: %s\n"),
                        fname, lnr, _("ignoring garbage line"));
              continue;
            }
          trim_trailing_spaces (line);
          in_item = 1;
          if (!strcmp (line+1, key))
            {
              /* Found.  Start collecting.  */
              init_membuf (&mb, 1024);
            }
          continue;
        }

      /* If in an item only allow for comments in the first column
         and provide ". " as an escape sequence to allow for
         leading dots and hash marks in the actual text.  */
      if (*line == '#')
        continue;
      if (*line == '.')
        { 
          if (spacep(line+1))
            p = line + 2;
          else
            {
              trim_trailing_spaces (line);
              in_item = 0;
              if (is_membuf_ready (&mb))
                break;        /* Yep, found and collected the item.  */
              if (!line[1])
                continue;     /* Just an end of text dot. */
              goto again;     /* A new key line.  */
            }
        }
      else
        p = line;

      if (is_membuf_ready (&mb))
        {
          put_membuf_str (&mb, p);
          put_membuf (&mb, "\n", 1);
        }

    }
  if ( !err && ferror (fp) )
    {
      err = gpg_error_from_syserror ();
      log_error (_("error reading `%s', line %d: %s\n"),
                 fname, lnr, gpg_strerror (err));
    }
  
  fclose (fp);
  if (is_membuf_ready (&mb))
    {
      /* We have collected something.  */
      if (err)
        {
          xfree (get_membuf (&mb, NULL));
          return NULL;
        }
      else
        {
          put_membuf (&mb, "", 1);  /* Terminate string.  */
          return get_membuf (&mb, NULL);
        }
    }
  else
    return NULL;
}
Example #13
0
/* Parse the policy flags by reading them from STREAM and storing them
 * into FLAGS.  If IGNORE_UNKNOWN is iset unknown keywords are
 * ignored.  */
gpg_error_t
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
{
  enum tokens {
    TOK_SUBMISSION_ADDRESS,
    TOK_MAILBOX_ONLY,
    TOK_DANE_ONLY,
    TOK_AUTH_SUBMIT,
    TOK_MAX_PENDING,
    TOK_PROTOCOL_VERSION
  };
  static struct {
    const char *name;
    enum tokens token;
  } keywords[] = {
    { "submission-address", TOK_SUBMISSION_ADDRESS },
    { "mailbox-only", TOK_MAILBOX_ONLY },
    { "dane-only",    TOK_DANE_ONLY    },
    { "auth-submit",  TOK_AUTH_SUBMIT  },
    { "max-pending",  TOK_MAX_PENDING  },
    { "protocol-version", TOK_PROTOCOL_VERSION }
  };
  gpg_error_t err = 0;
  int lnr = 0;
  char line[1024];
  char *p, *keyword, *value;
  int i, n;

  memset (flags, 0, sizeof *flags);

  while (es_fgets (line, DIM(line)-1, stream) )
    {
      lnr++;
      n = strlen (line);
      if (!n || line[n-1] != '\n')
        {
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                           : GPG_ERR_INCOMPLETE_LINE);
          break;
        }
      trim_trailing_spaces (line);
      /* Skip empty and comment lines. */
      for (p=line; spacep (p); p++)
        ;
      if (!*p || *p == '#')
        continue;

      if (*p == ':')
        {
          err = gpg_error (GPG_ERR_SYNTAX);
          break;
        }

      keyword = p;
      value = NULL;
      if ((p = strchr (p, ':')))
        {
          /* Colon found: Keyword with value.  */
          *p++ = 0;
          for (; spacep (p); p++)
            ;
          if (!*p)
            {
              err = gpg_error (GPG_ERR_MISSING_VALUE);
              break;
            }
          value = p;
        }

      for (i=0; i < DIM (keywords); i++)
        if (!ascii_strcasecmp (keywords[i].name, keyword))
          break;
      if (!(i < DIM (keywords)))
        {
          if (ignore_unknown)
            continue;
          err = gpg_error (GPG_ERR_INV_NAME);
          break;
	}

      switch (keywords[i].token)
        {
        case TOK_SUBMISSION_ADDRESS:
          if (!value || !*value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          xfree (flags->submission_address);
          flags->submission_address = xtrystrdup (value);
          if (!flags->submission_address)
            {
              err = gpg_error_from_syserror ();
              goto leave;
            }
          break;
        case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
        case TOK_DANE_ONLY:    flags->dane_only = 1;    break;
        case TOK_AUTH_SUBMIT:  flags->auth_submit = 1;  break;
        case TOK_MAX_PENDING:
          if (!value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          /* FIXME: Define whether these are seconds, hours, or days
           * and decide whether to allow other units.  */
          flags->max_pending = atoi (value);
          break;
        case TOK_PROTOCOL_VERSION:
          if (!value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          flags->protocol_version = atoi (value);
          break;
        }
    }

  if (!err && !es_feof (stream))
    err = gpg_error_from_syserror ();

 leave:
  if (err)
    log_error ("error reading '%s', line %d: %s\n",
               es_fname_get (stream), lnr, gpg_strerror (err));

  return err;
}