Blame view

mh/mh_ctx.c 4.34 KB
Wojciech Polak authored
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2 3
   Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2009,
   2010 Free Software Foundation, Inc.
4

Wojciech Polak authored
5
   GNU Mailutils is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3, or (at your option)
8 9
   any later version.

Wojciech Polak authored
10
   GNU Mailutils is distributed in the hope that it will be useful,
11 12 13 14 15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
Wojciech Polak authored
16
   along with GNU Mailutils; if not, write to the Free Software
17 18
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301 USA */
19 20

/* MH context functions. */
21
  
22 23 24 25 26
#include <mh.h>
#include <sys/types.h>
#include <sys/stat.h>

mh_context_t *
27
mh_context_create (const char *name, int copy)
28 29 30 31
{
  mh_context_t *ctx;
  ctx = malloc (sizeof (*ctx));
  if (!ctx)
32
    mh_err_memory (1);
33 34 35 36 37 38
  if (copy)
    ctx->name = name;
  else
    {
      ctx->name = strdup (name);
      if (!ctx->name)
39
        mh_err_memory (1);
40 41 42 43 44
    }
  ctx->header = NULL;
  return ctx;
}

45 46 47 48 49
void
mh_context_destroy (mh_context_t **pctx)
{
  mh_context_t *ctx = *pctx;
  
50
  free ((char*) ctx->name);
51
  if (ctx->header)
52
    mu_header_destroy (&ctx->header);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
  free (ctx);
  *pctx = NULL;
}

void
mh_context_merge (mh_context_t *dst, mh_context_t *src)
{
  if (!dst->header)
    {
      dst->header = src->header;
      src->header = NULL;
    }
  else
    {
      size_t i, count;
      
      mu_header_get_field_count (src->header, &count);
      for (i = 1; i <= count; i++)
	{
72 73
	  const char *name = NULL;
	  const char *value = NULL;
74
	  
75 76
	  mu_header_sget_field_name (src->header, i, &name);
	  mu_header_sget_field_value (src->header, i, &value);
77 78 79 80 81
	  mu_header_set_value (dst->header, name, value, 1);
	}
    }
}

82 83 84 85
int 
mh_context_read (mh_context_t *ctx)
{
  int status;
86
  char *blurb, *p;
87 88
  struct stat st;
  FILE *fp;
89 90 91
  char *buf = NULL;
  size_t size = 0;
  
92
  if (!ctx)
93
    return MU_ERR_OUT_NULL;
94
  
95 96 97 98 99 100 101 102 103 104 105 106 107 108
  if (stat (ctx->name, &st))
    return errno;

  blurb = malloc (st.st_size);
  if (!blurb)
    return ENOMEM;
  
  fp = fopen (ctx->name, "r");
  if (!fp)
    {
      free (blurb);
      return errno;
    }

109 110 111 112 113
  p = blurb;
  while (getline (&buf, &size, fp) > 0)
    {
      char *q;

114
      for (q = buf; *q && mu_isspace (*q); q++)
115 116 117 118
	;
      if (!*q || *q == '#')
	continue;
      
119
      for (q = buf; *q;)
120
	*p++ = *q++;
121
    }
122
  fclose (fp);
123

124
  status = mu_header_create (&ctx->header, blurb, p - blurb);
125
  free (blurb);
126 127 128 129 130 131 132

  return status;
}

int 
mh_context_write (mh_context_t *ctx)
{
133
  mu_stream_t stream;
134
  char buffer[512];
135
  size_t n;
136 137
  FILE *fp;
  
138
  if (!ctx)
139
    return MU_ERR_OUT_NULL;
140

141 142 143
  fp = fopen (ctx->name, "w");
  if (!fp)
    {
144
      mu_error (_("cannot open context file %s: %s"),
145
		ctx->name, strerror (errno));
146
      return MU_ERR_FAILURE;
147 148
    }

149 150
  /* FIXME: Use mu_stream+copy */
  mu_header_get_streamref (ctx->header, &stream);
151
  while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0
152 153 154 155 156
	 && n != 0)
    {
      buffer[n] = '\0';
      fprintf (fp, "%s", buffer);
    }
157
  mu_stream_destroy (&stream);
158 159 160 161
  fclose (fp);
  return 0;
}

162
const char *
163
mh_context_get_value (mh_context_t *ctx, const char *name, const char *defval)
164
{
165
  const char *p;
166

167 168
  if (!ctx || mu_header_sget_value (ctx->header, name, &p))
    p = defval; 
169 170 171 172
  return p;
}

int
173
mh_context_set_value (mh_context_t *ctx, const char *name, const char *value)
174
{
175 176
  if (!ctx)
    return EINVAL;
177 178 179
  if (!ctx->header)
    {
      int rc;
180
      if ((rc = mu_header_create (&ctx->header, NULL, 0)) != 0)
181
	{
182
	  mu_error (_("cannot create context %s: %s"),
183
		    ctx->name,
184
		    mu_strerror (rc));
185 186 187
	  return 1;
	}
    }
188
  return mu_header_set_value (ctx->header, name, value, 1);
189
}
190 191 192 193 194 195 196

int
mh_context_iterate (mh_context_t *ctx, mh_context_iterator fp, void *data)
{
  size_t i, nfields;
  int rc = 0;
  
197 198
  if (!ctx)
    return EINVAL;
199
  mu_header_get_field_count (ctx->header, &nfields);
200 201
  for (i = 1; i <= nfields && rc == 0; i++)
    {
202
      const char *name, *value;
203
      
204 205
      mu_header_sget_field_name (ctx->header, i, &name);
      mu_header_sget_field_value (ctx->header, i, &value);
206 207 208 209 210
      rc = fp (name, value, data);
    }

  return rc;
}