summaryrefslogtreecommitdiff
path: root/cleopatre/application/libspid/src/config_item.c
blob: 5d78fd2a34b4fa6fc0f1d01b7a127c386758a697 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* SPC300 bundle {{{
 *
 * Copyright (C) 2009 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    application/libspid/src/config_item.c
 * \brief   item management in configuration file
 * \ingroup libspid
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "libspid.h"

#ifdef __UTESTS__
    #include "config_item_utests.h"
#endif  /* __UTESTS__ */

/**
 * Read an item value inside a configuration file; put the value
 * into a provided buffer
 *
 * \param filename full path filename of a configuration file
 * \param label label of wanted item to read
 * \param value pointer to buffer where read value is written
 * \param buffer_len length of value buffer
 * \return error type (LIBSPID_SUCCESS if success)
 * \return LIBSPID_ERROR_PARAM: bad input parameters
 * \return LIBSPID_ERROR_NOT_FOUND: item has not been found
 * \return LIBSPID_ERROR_SYSTEM: system error, see errno
 * \return LIBSPID_ERROR_NO_SPACE: not enough space in buffer
 */

libspid_error_t libspid_config_read_item (const char *filename, const char *label, char *value, int buffer_len)
{
    char buffer[LIBSPID_LINE_MAX_LEN];
    FILE *fp;
    char *strtok_ctx, *ptr, *blank_ptr;

    /* check input parameters */
    if((filename == NULL) || (label == NULL) || (value == NULL) || (buffer_len <= 0))
    {
        return LIBSPID_ERROR_PARAM;
    }
    /* check key validity */
    if ( strstr(label, LIBSPID_CONFIG_DELIMITER) || strchr(label, ' ') || strchr(label, '\t') )
    {
        return LIBSPID_ERROR_PARAM;
    }

    /* open config file */
    if((fp = fopen(filename, "r")) == NULL)
    {
        //syslog(LOG_WARNING, "libspid_read_config_param: cannot open %s (errno=%d)\n", filename, errno);
        return LIBSPID_ERROR_SYSTEM;
    }

    while( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp) )
    {
        /* get the label */
        ptr = strtok_r(buffer, LIBSPID_CONFIG_DELIMITER " \t", &strtok_ctx);
        /* check if it is the wanted label */
        if((ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, label))
            continue;
        /* remove space and '=' before the value */
        ptr += strlen(ptr) + 1;
        while(isblank(*ptr) || (*ptr == *LIBSPID_CONFIG_DELIMITER))
            ptr++;
        ptr = strtok_r(ptr, "\n\r", &strtok_ctx);
        /* init value to empty */
        *value = '\0';
        if(ptr != NULL)
        {
            /* remove spaces at the end of value */
            blank_ptr = ptr + strlen(ptr) - 1;
            while((blank_ptr >= ptr) && isblank(*blank_ptr))
            {
                *blank_ptr = '\0';
                blank_ptr--;
            }
            /* check for buffer space to copy the value */
            if(strlen(ptr) >= buffer_len)
            {
                fclose(fp);
                return LIBSPID_ERROR_NO_SPACE;
            }
            strcpy(value, ptr);
        }
        fclose(fp);
        //syslog(LOG_DEBUG, "libspid_read_config_param: '%s' = '%s'", label, value);
        return LIBSPID_SUCCESS;
    }
    /* label not found */
    fclose(fp);
    return LIBSPID_ERROR_NOT_FOUND;
}

/**
 * Write a value of an item into a configuration file
 *
 * \param filename full path filename of a configuration file
 * \param label label of item value to write; if item does not already exists, it will be added into the configuration file
 * \param value value of item to write
 * \return error type (LIBSPID_SUCCESS if success)
 * \return LIBSPID_ERROR_PARAM: bad input parameters
 * \return LIBSPID_ERROR_SYSTEM: system error, see errno
 * \return LIBSPID_ERROR_NO_SPACE: not enough space in buffer
 */

libspid_error_t libspid_config_write_item(const char *filename, const char *label, const char *value)
{
    char buffer[LIBSPID_LINE_MAX_LEN];
    char out_filename[64];
    char *ptr, *strtok_ctx;
    FILE *fp_in, *fp_out;
    int fd_in;
    int is_found = 0;
    char *tmp_line;

    /* check input parameters */
    if ( (filename == NULL) || (label == NULL) || (strlen(label) <= 0) || (value == NULL) )
    {
        return LIBSPID_ERROR_PARAM;
    }
    /* check key validity */
    if ( strstr(label, LIBSPID_CONFIG_DELIMITER) || strchr(label, ' ') || strchr(label, '\t') )
    {
        return LIBSPID_ERROR_PARAM;
    }

    /* open config file */
    if ( (fd_in = open(filename, O_RDONLY | O_CREAT, 0666)) < 0 )
    {
        //syslog(LOG_WARNING, "libspid_write_config_param: cannot open %s (errno=%d)", filename, errno);
        return LIBSPID_ERROR_SYSTEM;
    }
    fp_in = fdopen(fd_in, "r");
    /* create the modified config file */
    sprintf(out_filename, "%sXXXXXX", filename);
    if ( (fp_out = fdopen(mkstemp(out_filename), "w")) == NULL )
    {
        fclose(fp_in);
        close(fd_in);
        return LIBSPID_ERROR_SYSTEM;
    }
    /* find the label to modify */
    while ( fgets(buffer, LIBSPID_LINE_MAX_LEN - 1, fp_in) )
    {
        tmp_line = strdup(buffer);

        /* get the label */
        ptr = strtok_r(buffer, LIBSPID_CONFIG_DELIMITER " \t", &strtok_ctx);
        /* check if it is the wanted label */
        if ( (ptr == NULL) || (strlen(ptr) <= 0) || (*ptr == '#') || strcmp(ptr, label) )
        {
            /* print line unchanged back to file */
            fprintf(fp_out, tmp_line);
            continue;
        }

        /* check for buffer overload */
        if ( LIBSPID_LINE_MAX_LEN - 1/*'\0'*/ - 1 /*'\n'*/ - ( strlen(ptr) + 1/*' '*/ + 1/*'='*/ + 1/*' '*/ ) < strlen(value) )
        {
            fclose(fp_out);
            fclose(fp_in);
            close(fd_in);
            return LIBSPID_ERROR_NO_SPACE;
        }
        /* write the new value */
        fprintf(fp_out, "%s %s %s\n", ptr, LIBSPID_CONFIG_DELIMITER, value);  /* make line in format "label = value" */
        is_found = 1;

    }
    if (!is_found)
    {
        /* add new 'label = value' at the end of file */
        fprintf(fp_out, "%s %s %s\n", label, LIBSPID_CONFIG_DELIMITER, value);
    }
    fclose(fp_out);
    fclose(fp_in);
    close(fd_in);
    if ( rename(out_filename, filename) < 0 )
    {
        //syslog(LOG_WARNING, "libspid_write_config_param : rename (errno=%d)\n", errno);
    }
    return LIBSPID_SUCCESS;
}