~modemmanager/network-manager/ubuntu.0.7.mm

« back to all changes in this revision

Viewing changes to system-settings/plugins/ifcfg-rh/shvar.c

  • Committer: Alexander Sack
  • Date: 2009-01-23 19:37:11 UTC
  • mfrom: (2957.1.31 ubuntu.0.7)
  • Revision ID: asac@jwsdot.com-20090123193711-2i2k6isrzqop2f29
merge 0.7-0ubuntu2 jaunty packaging
rev:2988 from lp:~network-manager/network-manager/ubuntu.0.7

* fix LP: #270584 add the dependency network-manager-dev in
  libnm-glib-dev
  - update debian/control
* update Standards-Version to 3.8.0
  - update debian/control
* (merge) new upstream release NetworkManager 0.7 final
  - rev 3802 lp:~vcs-imports/network-manager/main/
  + fix LP: #288963 Network Manager fails to connect to a system stored
    network with "set_network_cb(): Couldn't set network config: Did not receive
    correct message.." in intrepid
  + fix LP: #288703 Routes lost on DHCP lease renewal (breaks VPN)
* drop probe v250 modem patch; this should be done in udev-extras; until
  that happens we rely on accurate hal-info
  - delete debian/patches/add_probe_for_v250_modems.patch
  - update debian/patches/series
* drop upstreamed patches
  - delete debian/patches/50_gcc43.patch
  - delete debian/patches/lp282207_set_apn_at_syntax.patch
  - delete debian/patches/lp268667_more_ppp_default_options.patch
  - delete debian/patches/lp278631-initscript-polishing.patch
  - update debian/patches/series
* drop unused patch
  - delete debian/patches/41o_completely_deactivate_stage1.patch
* make manual regristration timeout patch out of automatic one (which
  was applied upstream)
  - rename debian/patches/lp303142_more_time_for_automatic_registration.patch
    => debian/patches/lp303142_more_time_for_manual_registration.patch
* add patch to fix ftbfs
  - add debian/patches/ftbfs_nm_netlink_monitor.patch
  - update debian/patches/series
* [libnm-util-dev] dont try to install nm-setting-ip6-config.h - which is
  supposed to be hidden in 0.7 final
  - update debian/libnm-util-dev.install
* prepatch upstream soname version bump for libnm-util
  - add debian/patches/04-ltversioning.patch
  - update debian/patches/series
  ship the libs in libnm-util1
  - update debian/control
  - rename debian/libnm-util0.install => debian/libnm-util1.install
  and bump so shlibs control file info for libnm-util1
  - update debian/rules
* add easy bzr builddeb support with proper upstream-revision (--show-ids)
  - add .bzr-builddeb/default.conf
* install plugin in ppp 2.4.4 and 2.4.5 directory
  - update debian/network-manager.install
* fix LP: #292054 - Some drivers take too long to associate (Was:
  network-manager 0.7 always asks for WPA passphrase); we workaround
  this driver/wpasupplicant bug by giving association more time
  (e.g. 60sec instead of 25sec)
  - add debian/patches/lp292054_tune_supplicant_timeout_60s.patch
  - update debian/patches/series
* fix LP: #256905 - dbus policy file (nm-avahi-autoipd.conf) not properly
  deployed in package; install nm-avahi-autoipd.conf
  - update debian/network-manager.install
* fix LP: #282207 - [Sierra] NM 0.7 does not set APN for AT&T 3G connection;
  apply fix from Jerone Young
  - add debian/patches/lp282207_set_apn_at_syntax.patch
  - update debian/patches/series
* fix LP: #268667 - not all required ppp options get set on command line
  which makes ppp use bad values from /etc/ppp/options; we backport upstream
  fix
  - add debian/patches/lp268667_more_ppp_default_options.patch
  - update debian/patches/series
* fix LP: #291564 - ifupdown network manager does not blacklist/unmanage
  mapped devices in managed=false mode; thanks to Stephan Trebels for the
  patch
  - add debian/patches/lp291564_ifupdown_unmanage_mapping_and_iface.patch
  - update debian/patches/series
* fix LP: #291902 - ifupdown plugin should not export any parsed connection
  configuration when running in managed=false mode; we fix this by exporting
  empty connection list in unmanaged mode
  - add debian/patches/lp291902_IFUPDOWN_dont_export_connection_in_unmanaged_mode.patch
  - update debian/patches/series
* belt-and-braces fix LP: #290468 VPN fails, "/usr/bin/nm-ppp-starter
  missing"; we remove obsolete conffiles in -pptp .preinst; in case user
  modified them they will be renamed to .dpkg-bak; this patch takes care that
  NM doesn't consider files in /etc/NetworkManager/VPN that don't have a
  .name filename suffix.
  - add debian/patches/lp290468_only_consider_name_suffix_VPN_service_files.patch
  - update debian/patches/series
* fix LP: #303142 - 3G [Option] some modems take a while time to register on
  network (CREG); we use g_timeout_add instead of _idle_add to give the
  modem some rest during registration phase.
  - add debian/patches/lp303142_more_time_for_automatic_registration.patch
  - update debian/patches/series

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * shvar.c
 
3
 *
 
4
 * Implementation of non-destructively reading/writing files containing
 
5
 * only shell variable declarations and full-line comments.
 
6
 *
 
7
 * Includes explicit inheritance mechanism intended for use with
 
8
 * Red Hat Linux ifcfg-* files.  There is no protection against
 
9
 * inheritance loops; they will generally cause stack overflows.
 
10
 * Furthermore, they are only intended for one level of inheritance;
 
11
 * the value setting algorithm assumes this.
 
12
 *
 
13
 * Copyright 1999,2000 Red Hat, Inc.
 
14
 *
 
15
 * This is free software; you can redistribute it and/or modify it
 
16
 * under the terms of the GNU General Public License as published by
 
17
 * the Free Software Foundation; either version 2 of the License, or
 
18
 * (at your option) any later version.
 
19
 *
 
20
 * This program is distributed in the hope that it will be useful, but
 
21
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
23
 * General Public License for more details.
 
24
 *
 
25
 * You should have received a copy of the GNU General Public License along
 
26
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
27
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
28
 *
 
29
 */
 
30
 
 
31
#include <fcntl.h>
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <sys/types.h>
 
36
#include <sys/stat.h>
 
37
#include <unistd.h>
 
38
 
 
39
#include "shvar.h"
 
40
 
 
41
/* Open the file <name>, returning a shvarFile on success and NULL on failure.
 
42
   Add a wrinkle to let the caller specify whether or not to create the file
 
43
   (actually, return a structure anyway) if it doesn't exist. */
 
44
static shvarFile *
 
45
svOpenFile(const char *name, gboolean create)
 
46
{
 
47
    shvarFile *s = NULL;
 
48
    int closefd = 0;
 
49
 
 
50
    s = g_malloc0(sizeof(shvarFile));
 
51
 
 
52
    s->fd = -1;
 
53
    if (create)
 
54
        s->fd = open(name, O_RDWR); /* NOT O_CREAT */
 
55
 
 
56
    if (!create || s->fd == -1) {
 
57
        /* try read-only */
 
58
        s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
 
59
        if (s->fd != -1) closefd = 1;
 
60
    }
 
61
    s->fileName = g_strdup(name);
 
62
 
 
63
    if (s->fd != -1) {
 
64
        struct stat buf;
 
65
        char *p, *q;
 
66
 
 
67
        if (fstat(s->fd, &buf) < 0) goto bail;
 
68
        s->arena = g_malloc0(buf.st_size + 1);
 
69
 
 
70
        if (read(s->fd, s->arena, buf.st_size) < 0) goto bail;
 
71
 
 
72
        /* we'd use g_strsplit() here, but we want a list, not an array */
 
73
        for(p = s->arena; (q = strchr(p, '\n')) != NULL; p = q + 1) {
 
74
                s->lineList = g_list_append(s->lineList, g_strndup(p, q - p));
 
75
        }
 
76
 
 
77
        /* closefd is set if we opened the file read-only, so go ahead and
 
78
           close it, because we can't write to it anyway */
 
79
        if (closefd) {
 
80
            close(s->fd);
 
81
            s->fd = -1;
 
82
        }
 
83
 
 
84
        return s;
 
85
    }
 
86
 
 
87
    if (create) {
 
88
        return s;
 
89
    }
 
90
 
 
91
bail:
 
92
    if (s->fd != -1) close(s->fd);
 
93
    if (s->arena) g_free (s->arena);
 
94
    if (s->fileName) g_free (s->fileName);
 
95
    g_free (s);
 
96
    return NULL;
 
97
}
 
98
 
 
99
/* Open the file <name>, return shvarFile on success, NULL on failure */
 
100
shvarFile *
 
101
svNewFile(const char *name)
 
102
{
 
103
    return svOpenFile(name, FALSE);
 
104
}
 
105
 
 
106
/* Create a new file structure, returning actual data if the file exists,
 
107
 * and a suitable starting point if it doesn't. */
 
108
shvarFile *
 
109
svCreateFile(const char *name)
 
110
{
 
111
    return svOpenFile(name, TRUE);
 
112
}
 
113
 
 
114
/* remove escaped characters in place */
 
115
static void
 
116
unescape(char *s) {
 
117
    int len, i;
 
118
 
 
119
    len = strlen(s);
 
120
    if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
 
121
        i = len - 2;
 
122
        if (i == 0)
 
123
          s[0] = '\0';
 
124
        else {
 
125
          memmove(s, s+1, i);
 
126
          s[i+1] = '\0';
 
127
          len = i;
 
128
        }
 
129
    }
 
130
    for (i = 0; i < len; i++) {
 
131
        if (s[i] == '\\') {
 
132
            memmove(s+i, s+i+1, len-(i+1));
 
133
            len--;
 
134
        }
 
135
        s[len] = '\0';
 
136
    }
 
137
}
 
138
 
 
139
 
 
140
/* create a new string with all necessary characters escaped.
 
141
 * caller must free returned string
 
142
 */
 
143
static const char escapees[] = "\"'\\$~`";              /* must be escaped */
 
144
static const char spaces[] = " \t|&;()<>";              /* only require "" */
 
145
static char *
 
146
escape(const char *s) {
 
147
    char *new;
 
148
    int i, j, mangle = 0, space = 0;
 
149
    int newlen, slen;
 
150
    static int esclen, splen;
 
151
 
 
152
    if (!esclen) esclen = strlen(escapees);
 
153
    if (!splen) splen = strlen(spaces);
 
154
    slen = strlen(s);
 
155
 
 
156
    for (i = 0; i < slen; i++) {
 
157
        if (strchr(escapees, s[i])) mangle++;
 
158
        if (strchr(spaces, s[i])) space++;
 
159
    }
 
160
    if (!mangle && !space) return strdup(s);
 
161
 
 
162
    newlen = slen + mangle + 3; /* 3 is extra ""\0 */
 
163
    new = g_malloc0(newlen);
 
164
    if (!new) return NULL;
 
165
 
 
166
    j = 0;
 
167
    new[j++] = '"';
 
168
    for (i = 0; i < slen; i++) {
 
169
        if (strchr(escapees, s[i])) {
 
170
            new[j++] = '\\';
 
171
        }
 
172
        new[j++] = s[i];
 
173
    }
 
174
    new[j++] = '"';
 
175
    g_assert(j == slen + mangle + 2); /* j is the index of the '\0' */
 
176
 
 
177
    return new;
 
178
}
 
179
 
 
180
/* Get the value associated with the key, and leave the current pointer
 
181
 * pointing at the line containing the value.  The char* returned MUST
 
182
 * be freed by the caller.
 
183
 */
 
184
char *
 
185
svGetValue(shvarFile *s, const char *key)
 
186
{
 
187
    char *value = NULL;
 
188
    char *line;
 
189
    char *keyString;
 
190
    int len;
 
191
 
 
192
    g_assert(s);
 
193
    g_assert(key);
 
194
 
 
195
    keyString = g_malloc0(strlen(key) + 2);
 
196
    strcpy(keyString, key);
 
197
    keyString[strlen(key)] = '=';
 
198
    len = strlen(keyString);
 
199
 
 
200
    for (s->current = s->lineList; s->current; s->current = s->current->next) {
 
201
        line = s->current->data;
 
202
        if (!strncmp(keyString, line, len)) {
 
203
            value = g_strdup(line + len);
 
204
            unescape(value);
 
205
            break;
 
206
        }
 
207
    }
 
208
    g_free(keyString);
 
209
 
 
210
    if (value) {
 
211
        if (value[0]) {
 
212
            return value;
 
213
        } else {
 
214
            g_free(value);
 
215
            return NULL;
 
216
        }
 
217
    }
 
218
    if (s->parent) value = svGetValue(s->parent, key);
 
219
    return value;
 
220
}
 
221
 
 
222
/* return 1 if <key> resolves to any truth value (e.g. "yes", "y", "true")
 
223
 * return 0 if <key> resolves to any non-truth value (e.g. "no", "n", "false")
 
224
 * return <default> otherwise
 
225
 */
 
226
int
 
227
svTrueValue(shvarFile *s, const char *key, int def)
 
228
{
 
229
    char *tmp;
 
230
    int returnValue = def;
 
231
 
 
232
    tmp = svGetValue(s, key);
 
233
    if (!tmp) return returnValue;
 
234
 
 
235
    if ( (!strcasecmp("yes", tmp)) ||
 
236
         (!strcasecmp("true", tmp)) ||
 
237
         (!strcasecmp("t", tmp)) ||
 
238
         (!strcasecmp("y", tmp)) ) returnValue = 1;
 
239
    else
 
240
    if ( (!strcasecmp("no", tmp)) ||
 
241
         (!strcasecmp("false", tmp)) ||
 
242
         (!strcasecmp("f", tmp)) ||
 
243
         (!strcasecmp("n", tmp)) ) returnValue = 0;
 
244
 
 
245
    g_free (tmp);
 
246
    return returnValue;
 
247
}
 
248
 
 
249
 
 
250
/* Set the variable <key> equal to the value <value>.
 
251
 * If <key> does not exist, and the <current> pointer is set, append
 
252
 * the key=value pair after that line.  Otherwise, prepend the pair
 
253
 * to the top of the file.  Here's the algorithm, as the C code
 
254
 * seems to be rather dense:
 
255
 *
 
256
 * if (value == NULL), then:
 
257
 *     if val2 (parent): change line to key= or append line key=
 
258
 *     if val1 (this)  : delete line
 
259
 *     else noop
 
260
 * else use this table:
 
261
 *                                val2
 
262
 *             NULL              value               other
 
263
 * v   NULL    append line       noop                append line
 
264
 * a
 
265
 * l   value   noop              noop                noop
 
266
 * 1
 
267
 *     other   change line       delete line         change line
 
268
 *
 
269
 * No changes are ever made to the parent config file, only to the
 
270
 * specific file passed on the command line.
 
271
 *
 
272
 */
 
273
void
 
274
svSetValue(shvarFile *s, const char *key, const char *value)
 
275
{
 
276
    char *newval = NULL, *val1 = NULL, *val2 = NULL;
 
277
    char *keyValue;
 
278
 
 
279
    g_assert(s);
 
280
    g_assert(key);
 
281
    /* value may be NULL */
 
282
 
 
283
    if (value) newval = escape(value);
 
284
    keyValue = g_strdup_printf("%s=%s", key, newval ? newval : "");
 
285
 
 
286
    val1 = svGetValue(s, key);
 
287
    if (val1 && newval && !strcmp(val1, newval)) goto bail;
 
288
    if (s->parent) val2 = svGetValue(s->parent, key);
 
289
 
 
290
    if (!newval || !newval[0]) {
 
291
        /* delete value somehow */
 
292
        if (val2) {
 
293
            /* change/append line to get key= */
 
294
            if (s->current) s->current->data = keyValue;
 
295
            else s->lineList = g_list_append(s->lineList, keyValue);
 
296
            s->modified = 1;
 
297
        } else if (val1) {
 
298
            /* delete line */
 
299
            s->lineList = g_list_remove_link(s->lineList, s->current);
 
300
            g_list_free_1(s->current);
 
301
            s->modified = 1;
 
302
            goto bail; /* do not need keyValue */
 
303
        }
 
304
        goto end;
 
305
    }
 
306
 
 
307
    if (!val1) {
 
308
        if (val2 && !strcmp(val2, newval)) goto end;
 
309
        /* append line */
 
310
        s->lineList = g_list_append(s->lineList, keyValue);
 
311
        s->modified = 1;
 
312
        goto end;
 
313
    }
 
314
 
 
315
    /* deal with a whole line of noops */
 
316
    if (val1 && !strcmp(val1, newval)) goto end;
 
317
 
 
318
    /* At this point, val1 && val1 != value */
 
319
    if (val2 && !strcmp(val2, newval)) {
 
320
        /* delete line */
 
321
        s->lineList = g_list_remove_link(s->lineList, s->current);
 
322
        g_list_free_1(s->current);
 
323
        s->modified = 1;
 
324
        goto bail; /* do not need keyValue */
 
325
    } else {
 
326
        /* change line */
 
327
        if (s->current) s->current->data = keyValue;
 
328
        else s->lineList = g_list_append(s->lineList, keyValue);
 
329
        s->modified = 1;
 
330
    }
 
331
 
 
332
end:
 
333
    if (newval) free(newval);
 
334
    if (val1) free(val1);
 
335
    if (val2) free(val2);
 
336
    return;
 
337
 
 
338
bail:
 
339
    if (keyValue) free (keyValue);
 
340
    goto end;
 
341
}
 
342
 
 
343
/* Write the current contents iff modified.  Returns -1 on error
 
344
 * and 0 on success.  Do not write if no values have been modified.
 
345
 * The mode argument is only used if creating the file, not if
 
346
 * re-writing an existing file, and is passed unchanged to the
 
347
 * open() syscall.
 
348
 */
 
349
int
 
350
svWriteFile(shvarFile *s, int mode)
 
351
{
 
352
    FILE *f;
 
353
    int tmpfd;
 
354
 
 
355
    if (s->modified) {
 
356
        if (s->fd == -1)
 
357
            s->fd = open(s->fileName, O_WRONLY|O_CREAT, mode);
 
358
        if (s->fd == -1)
 
359
            return -1;
 
360
        if (ftruncate(s->fd, 0) < 0)
 
361
            return -1;
 
362
 
 
363
        tmpfd = dup(s->fd);
 
364
        f = fdopen(tmpfd, "w");
 
365
        fseek(f, 0, SEEK_SET);
 
366
        for (s->current = s->lineList; s->current; s->current = s->current->next) {
 
367
            char *line = s->current->data;
 
368
            fprintf(f, "%s\n", line);
 
369
        }
 
370
        fclose(f);
 
371
    }
 
372
 
 
373
    return 0;
 
374
}
 
375
 
 
376
 
 
377
/* Close the file descriptor (if open) and delete the shvarFile.
 
378
 * Returns -1 on error and 0 on success.
 
379
 */
 
380
int
 
381
svCloseFile(shvarFile *s)
 
382
{
 
383
 
 
384
    g_assert(s);
 
385
 
 
386
    if (s->fd != -1) close(s->fd);
 
387
 
 
388
    g_free(s->arena);
 
389
    g_free(s->fileName);
 
390
    g_list_foreach (s->lineList, (GFunc) g_free, NULL);
 
391
    g_list_free(s->lineList); /* implicitly frees s->current */
 
392
    g_free(s);
 
393
    return 0;
 
394
}