/*
* Copyright (c) 2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: sm-conf-readfile.c,v 1.3 2007/05/20 15:41:56 ca Exp $")
#if SM_LIBCONF_ALONE
#include <limits.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "sm-conf.h"
#include "sm-util.h"
#else /* SM_LIBCONF_ALONE */
#include "sm/limits.h"
#include "sm/string.h"
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/ctype.h"
#include "sm/heap.h"
#include "sm/memops.h"
#include "sm/sm-conf.h"
#endif /* SM_LIBCONF_ALONE */
#include "sm-conf-state.h"
#include "sm-conf-token.h"
#include "sm-conf-parse.h"
/* SM-CONF.C -- high-level API functions */
/* Chunk size for reading input */
#define SMC_BLOCK_SIZE (1024 * 16)
/*
** SM_CONF_READ_FILE -- read configuration text from a file pointer
**
** The application can either open a file itself or
** have this function open it for the application and close it
** after reading.
**
** Parameters:
** smc -- configuration state with a read configuration file
** name -- name of file to open or NULL
** fp -- file pointer of pre-opened file or NULL.
**
** Returns:
** 0 on success,
** otherwise an errno or SM_CONF_ERR_... error number.
*/
int
sm_conf_read_FILE(sm_conf_T *smc, char const *name, FILE *fp)
{
bool close_fp;
size_t cc;
close_fp = false;
if (smc == NULL || (name == NULL && fp == NULL))
return SM_CONF_ERR_INVALID;
SM_IS_CONF(smc);
if (name != NULL && fp == NULL)
{
if ((fp = fopen(name, "r")) == NULL)
{
if (errno != 0)
return errno;
return SM_CONF_ERR_READ_OPEN;
}
close_fp = true;
}
smc->smc_buf_n = 0;
do
{
if (smc->smc_buf_n >= smc->smc_buf_m)
{
if (smc->smc_buf_m == 0)
{
smc->smc_buf = sm_malloc(SMC_BLOCK_SIZE);
if (smc->smc_buf == NULL)
{
if (close_fp)
(void)fclose(fp);
return ENOMEM;
}
smc->smc_mybuf = true;
smc->smc_buf_m = SMC_BLOCK_SIZE;
}
else
{
void *tmp;
tmp = sm_realloc(smc->smc_buf,
smc->smc_buf_m + SMC_BLOCK_SIZE);
if (tmp == NULL)
{
if (close_fp)
(void)fclose(fp);
return ENOMEM;
}
smc->smc_buf = tmp;
smc->smc_buf_m += SMC_BLOCK_SIZE;
}
}
cc = fread(smc->smc_buf + smc->smc_buf_n, 1,
smc->smc_buf_m - smc->smc_buf_n, fp);
if (cc == 0)
break;
smc->smc_buf_n += cc;
} while (cc > 0 && !feof(fp));
if (ferror(fp))
{
fprintf(stderr, "%s: byte %lu: error reading "
"from configuration file: %s\n",
smc->smc_name,
(unsigned long)smc->smc_buf_n,
strerror(errno));
if (close_fp)
(void)fclose(fp);
return SM_CONF_ERR_READ;
}
if (close_fp)
{
if (fclose(fp))
{
fprintf(stderr,
"%s: error closing configuration file: %s\n",
smc->smc_name, strerror(errno));
return -1;
}
}
return sm_conf_parse(smc);
}
syntax highlighted by Code2HTML, v. 0.9.1