/*
 *  libmodem library, a modem control facility.
 *
 *  modems.c - /etc/modems database routines
 *
 *  Copyright (C) 1994, 1995  Riccardo Facchetti
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  You can contact the author at this e-mail address:
 *
 *  riccardo@cdc8g5.cdc.polimi.it
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <dial/modems.h>
#include <dial/mdmerrno.h>

#include "modemsPriv.h"

#define BUFS    128

char *__modems = "modems.c (C) Riccardo Facchetti, version " LIBMODEM_VER;

static int mdmentry = 0;
static FILE *mdmfp;
static char buffer[BUFS];

/*
 * open/close_mdm: open and close the /etc/modems file
 */
static int open_mdm(void) {
    if ((mdmfp = fopen(MDMFILE, "r")) == NULL)
        return FAILURE;
    return SUCCESS;
}
static void close_mdm(void) {
    fclose(mdmfp);
}

/*
 * getmdmnam: returns a pointer to the modem entry named
 *            (char *) line, NULL if line is not present in /etc/modems
 */
struct modems *getmdmnam(char *line) {
    static struct modems mdm;

    mdmerrno = 0;

    if (open_mdm() == FAILURE) {
        mdmerrno = -ENOMDMFILE;
        return NULL;
    }

    while (fgets(buffer, BUFS, mdmfp) != NULL) {
        buffer[strlen(buffer)-1] = '\0';

        if (buffer[0] == '#' || buffer[0] == '\0' || buffer[0] == '\n')
            continue;

        if (demangle_modem_entry(&mdm, buffer) == FAILURE) {
            mdmerrno = -EMDMBADCONF;
            continue;
        }
        if (!strcmp(mdm.line, line)) {
            close_mdm();
            return(&mdm);
        }
    }
    close_mdm();
    mdmerrno = -ENOMDMLINE;
    return NULL;
}

/*
 * setmdms: set the library for modem sequential search from the first to the
 *          end. See getnextmdm().
 */
void setmdms(void) {
    mdmentry = 0;
}

/*
 * getnextmdm: get the next modem entry in /etc/modems file
 *             returns NULL if we are over the last modem.
 */
struct modems *getnextmdm(void) {
    static struct modems mdm;
    int i = 0;

    mdmerrno = 0;

    if (open_mdm() == FAILURE) {
        mdmerrno = -ENOMDMFILE;
        return NULL;
    }

    while (fgets(buffer, BUFS, mdmfp) != NULL) {
        buffer[strlen(buffer)-1] = '\0';

        if (buffer[0] == '#' || buffer[0] == '\0' || buffer[0] == '\n')
            continue;

        if (i == mdmentry) {
            if (demangle_modem_entry(&mdm, buffer) == FAILURE) {
                mdmerrno = -EMDMBADCONF;
                continue;
            }
            mdmentry++;
            close_mdm();
            return(&mdm);
        }
        i++;
    }
    close_mdm();
    return NULL;
}

/*
 * demangle_modem_entry: get a modems pointer that point to an existing
 * modems structure and a string to demangle. Returns FAILURE or SUCCESS
 */
static int demangle_modem_entry(struct modems *mdm, char *mdmstr) {
    char *ptr, *pptr;

/*
 * mdm->line (char *)
 */
    if ((ptr = strchr(buffer, ':')) == NULL)
        return FAILURE;
    *ptr = '\0';
    strcpy(mdm->line, buffer);
    ptr++;

/*
 * mdm->cp (char *)
 */
     if (*ptr == ':') {
        mdm->cp[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->cp, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->ce (char *)
 */
     if (*ptr == ':') {
        mdm->ce[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->ce, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->at (char *)
 */
     if (*ptr == ':') {
        mdm->at[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->at, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->dl (time_t)
 */
     if (*ptr == ':') {
        mdm->dl = 0;
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        mdm->dl = atol(ptr);
        ptr = pptr+1;
    }

/*
 * mdm->bd (int)
 */
     if (*ptr == ':') {
        mdm->bd = 0;
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        mdm->bd = atoi(ptr);
        ptr = pptr+1;
    }

/*
 * mdm->cs (char *)
 */
     if (*ptr == ':') {
        mdm->cs[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->cs, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->ds (char *)
 */
     if (*ptr == ':') {
        mdm->ds[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->ds, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->de (char *)
 */
     if (*ptr == ':') {
        mdm->de[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->de, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->im (char *)
 */
     if (*ptr == ':') {
        mdm->im[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->im, ptr);
        ptr = pptr+1;
    }

/*
 * mdm->hu (char *)
 *
 * the last field.
 */
     if (*ptr == ':') {
        mdm->hu[0] = '\0';
        *ptr = '\0';
        ptr++;
    }
    else {
        if ((pptr = strchr(ptr, ':')) == NULL)
            return FAILURE;
        *pptr = '\0';
        strcpy(mdm->hu, ptr);
        ptr = pptr+1;
    }

     if (*ptr == '\n' || *ptr == '\0' || *ptr == ':') {
        mdm->fc = 0;
        return SUCCESS;
    }
    else
        mdm->fc = atoi(ptr);

    return SUCCESS;
}
