/* * 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 #include #include #include #include #include #include #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); }