root/usr/src/lib/libslp/clib/slp_config.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Provides accessors to configuration properties.
 *
 * slp_readConfig:      attempts to locate slp.conf, and reads in all
 *                              properties specified therein.
 * slp_get_mtu:         returns the MTU
 * slp_get_next_onlist: parses a comma separated list of integers (in
 *                              string form), returning one at a time.
 * slp_parse_static_das: parses the list of DAs given in the DAAddresses
 *                              property.
 *
 * Also see the config wrapper macros in slp-internal.h.
 */

#include <stdio.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <slp-internal.h>

/*
 * Reads from fp and dynamically reallocates the buffer if necessary.
 * Returns 1 on success, 0 on read completion, and -1 on failure.
 */
static int super_fgets(char **buf, size_t *bufsize, FILE *fp) {
        char *r, *p;
        size_t real_bufsize, readlen = 0;

        p = *buf;
        real_bufsize = *bufsize;
        for (;;) {
                r = fgets(p, (int)real_bufsize, fp);
                if (feof(fp) && !r)
                        return (0);
                if (!r)
                        return (-1);
                readlen += strlen(r);
                if ((*buf)[readlen - 1] == '\n')
                        return (1);

                /* else buf is too small */
                *bufsize *= 2;
                if (!(*buf = realloc(*buf, *bufsize))) {
                        slp_err(LOG_CRIT, 0, "super_fgets", "out of memory");
                        return (-1);
                }
                p = *buf + readlen;
                real_bufsize = *bufsize - readlen;
        }
}

static void skip_space(char **p) {
        while (*p && **p != '\n' && isspace(**p))
                (*p)++;
}

static void null_space(char *p) {
        for (; *p; p++)
                if (isspace(*p))
                        *p = 0;
}

/*
 * Reads into the local property store all properties defined in
 * the config file.
 */
void slp_readConfig() {
        char *cfile, *buf;
        FILE *fp;
        size_t buflen = 512;

        /* check env for alternate config file */
        fp = NULL;
        if (cfile = getenv("SLP_CONF_FILE"))
                fp = fopen(cfile, "rF");
        if (!fp)
                if (!(fp = fopen(SLP_DEFAULT_CONFIG_FILE, "rF"))) {
                        slp_err(LOG_INFO, 0, "readConfig",
                                "cannot open config file");
                        return;
                }

        if (!(buf = malloc(buflen))) {
                slp_err(LOG_CRIT, 0, "readConfig", "out of memory");
                (void) fclose(fp);
                return;
        }

        while (!feof(fp)) {
                char *val, *p;
                int err;

                /* read a line */
                err = super_fgets(&buf, &buflen, fp);
                if (err == 0) continue;
                if (err == -1) {
                        slp_err(LOG_INFO, 0, "readConfig",
                                "error reading file: %d",
                                ferror(fp));
                        (void) fclose(fp);
                        free(buf);
                        return;
                }

                /* skip comments and newlines */
                p = buf;
                skip_space(&p);
                if (*p == '#' || *p == ';' || *p == '\n')
                        continue;

                /* get property and value */
                if (val = strchr(p, '=')) {
                        *val++ = 0;
                        skip_space(&val);
                        /* remove the trailing newline */
                        val[strlen(val) - 1] = 0;
                }
                null_space(p);

                SLPSetProperty(p, val ? val : "");
        }

        (void) fclose(fp);
        free(buf);
}

/*
 * Config convenience wrappers
 */
size_t slp_get_mtu() {
        size_t size;
        size = atoi(SLPGetProperty(SLP_CONFIG_MTU));
        size = size ? size : SLP_DEFAULT_SENDMTU;

        return (size);
}

/*
 * On the first invocation, *state should == the value of the property
 * to parse.
 * If there are no more timeouts, returns -1, otherwise the timeout.
 * If the value in the property is invalid, returns the default 2000.
 */
int slp_get_next_onlist(char **state) {
        char *p, buf[33];
        size_t l;
        int answer;

        if (!*state)
                return (-1);

        if (**state == ',') {
                (*state)++;     /* skip the ',' */
        }
        p = *state;
        *state = slp_utf_strchr(*state, ',');
        if (!*state)
                l = strlen(p);
        else {
                l = *state - p;
                l = (l > 32 ? 32 : l);
        }
        (void) strncpy(buf, p, l);
        buf[l] = 0;
        answer = atoi(buf);

        return (answer != 0 ? answer : 2000);
}

int slp_get_maxResults() {
        int num = atoi(SLPGetProperty(SLP_CONFIG_MAXRESULTS));

        return (num <= 0 ? -1 : num);
}