~ubuntu-branches/ubuntu/trusty/procps/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/ignore_erofs.patch/sysctl.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2015-02-10 13:51:14 UTC
  • Revision ID: package-import@ubuntu.com-20150210135114-szpndjnns1ts97jn
Tags: 1:3.3.9-1ubuntu2.2
ignore_erofs.patch: Same as ignore_eaccess but for the case where
part of /proc is read/only. (LP: #1419554)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
 
3
 *
 
4
 * "Copyright 1999 George Staikos
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 *
 
20
 * Changelog:
 
21
 *            v1.01:
 
22
 *                   - added -p <preload> to preload values from a file
 
23
 *            Horms:
 
24
 *                   - added -q to be quiet when modifying values
 
25
 *
 
26
 * Changes by Albert Cahalan, 2002.
 
27
 */
 
28
 
 
29
#include <dirent.h>
 
30
#include <errno.h>
 
31
#include <getopt.h>
 
32
#include <glob.h>
 
33
#include <libgen.h>
 
34
#include <limits.h>
 
35
#include <regex.h>
 
36
#include <stdbool.h>
 
37
#include <stdio.h>
 
38
#include <stdlib.h>
 
39
#include <string.h>
 
40
#include <sys/stat.h>
 
41
#include <sys/types.h>
 
42
#include <unistd.h>
 
43
 
 
44
#include "c.h"
 
45
#include "fileutils.h"
 
46
#include "nls.h"
 
47
#include "xalloc.h"
 
48
#include "proc/procps.h"
 
49
#include "proc/version.h"
 
50
 
 
51
/*
 
52
 *    Globals...
 
53
 */
 
54
static const char PROC_PATH[] = "/proc/sys/";
 
55
static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
 
56
static const char *DEPRECATED[] = {
 
57
        "base_reachable_time",
 
58
        "retrans_time",
 
59
        ""
 
60
};
 
61
static bool IgnoreDeprecated;
 
62
static bool NameOnly;
 
63
static bool PrintName;
 
64
static bool PrintNewline;
 
65
static bool IgnoreError;
 
66
static bool Quiet;
 
67
static char *pattern;
 
68
 
 
69
/* Function prototypes. */
 
70
static int pattern_match(const char *string, const char *pat);
 
71
static int DisplayAll(const char *restrict const path);
 
72
 
 
73
static void slashdot(char *restrict p, char old, char new)
 
74
{
 
75
        int warned = 1;
 
76
        p = strpbrk(p, "/.");
 
77
        if (!p)
 
78
                /* nothing -- can't be, but oh well */
 
79
                return;
 
80
        if (*p == new)
 
81
                /* already in desired format */
 
82
                return;
 
83
        while (p) {
 
84
                char c = *p;
 
85
                if ((*(p + 1) == '/' || *(p + 1) == '.') && warned) {
 
86
                        xwarnx(_("separators should not be repeated: %s"), p);
 
87
                        warned = 0;
 
88
                }
 
89
                if (c == old)
 
90
                        *p = new;
 
91
                if (c == new)
 
92
                        *p = old;
 
93
                p = strpbrk(p + 1, "/.");
 
94
        }
 
95
}
 
96
 
 
97
/*
 
98
 * Display the usage format
 
99
 */
 
100
static void __attribute__ ((__noreturn__))
 
101
    Usage(FILE * out)
 
102
{
 
103
        fputs(USAGE_HEADER, out);
 
104
        fprintf(out,
 
105
              _(" %s [options] [variable[=value] ...]\n"),
 
106
                program_invocation_short_name);
 
107
        fputs(USAGE_OPTIONS, out);
 
108
        fputs(_("  -a, --all            display all variables\n"), out);
 
109
        fputs(_("  -A                   alias of -a\n"), out);
 
110
        fputs(_("  -X                   alias of -a\n"), out);
 
111
        fputs(_("      --deprecated     include deprecated parameters to listing\n"), out);
 
112
        fputs(_("  -b, --binary         print value without new line\n"), out);
 
113
        fputs(_("  -e, --ignore         ignore unknown variables errors\n"), out);
 
114
        fputs(_("  -N, --names          print variable names without values\n"), out);
 
115
        fputs(_("  -n, --values         print only values of a variables\n"), out);
 
116
        fputs(_("  -p, --load[=<file>]  read values from file\n"), out);
 
117
        fputs(_("  -f                   alias of -p\n"), out);
 
118
        fputs(_("      --system         read values from all system directories\n"), out);
 
119
        fputs(_("  -r, --pattern <expression>\n"
 
120
                "                       select setting that match expression\n"), out);
 
121
        fputs(_("  -q, --quiet          do not echo variable set\n"), out);
 
122
        fputs(_("  -w, --write          enable writing a value to variable\n"), out);
 
123
        fputs(_("  -o                   does nothing\n"), out);
 
124
        fputs(_("  -x                   does nothing\n"), out);
 
125
        fputs(_("  -d                   alias of -h\n"), out);
 
126
        fputs(USAGE_SEPARATOR, out);
 
127
        fputs(USAGE_HELP, out);
 
128
        fputs(USAGE_VERSION, out);
 
129
        fprintf(out, USAGE_MAN_TAIL("sysctl(8)"));
 
130
 
 
131
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 
132
}
 
133
 
 
134
/*
 
135
 * Strip the leading and trailing spaces from a string
 
136
 */
 
137
static char *StripLeadingAndTrailingSpaces(char *oneline)
 
138
{
 
139
        char *t;
 
140
 
 
141
        if (!oneline || !*oneline)
 
142
                return oneline;
 
143
 
 
144
        t = oneline;
 
145
        t += strlen(oneline) - 1;
 
146
 
 
147
        while ((*t == ' ' || *t == '\t' || *t == '\n' || *t == '\r') && t != oneline)
 
148
                *t-- = 0;
 
149
 
 
150
        t = oneline;
 
151
 
 
152
        while ((*t == ' ' || *t == '\t') && *t != 0)
 
153
                t++;
 
154
 
 
155
        return t;
 
156
}
 
157
 
 
158
/*
 
159
 * Read a sysctl setting
 
160
 */
 
161
static int ReadSetting(const char *restrict const name)
 
162
{
 
163
        int rc = 0;
 
164
        char *restrict tmpname;
 
165
        char *restrict outname;
 
166
        char inbuf[1025];
 
167
        FILE *restrict fp;
 
168
        struct stat ts;
 
169
 
 
170
        if (!name || !*name) {
 
171
                xwarnx(_("\"%s\" is an unknown key"), name);
 
172
                return -1;
 
173
        }
 
174
 
 
175
        /* used to display the output */
 
176
        outname = xstrdup(name);
 
177
        /* change / to . */
 
178
        slashdot(outname, '/', '.');
 
179
 
 
180
        /* used to open the file */
 
181
        tmpname = xmalloc(strlen(name) + strlen(PROC_PATH) + 2);
 
182
        strcpy(tmpname, PROC_PATH);
 
183
        strcat(tmpname, name);
 
184
        /* change . to / */
 
185
        slashdot(tmpname + strlen(PROC_PATH), '.', '/');
 
186
 
 
187
        /* used to display the output */
 
188
        outname = xstrdup(name);
 
189
        /* change / to . */
 
190
        slashdot(outname, '/', '.');
 
191
 
 
192
        if (stat(tmpname, &ts) < 0) {
 
193
                if (!IgnoreError) {
 
194
                        xwarn(_("cannot stat %s"), tmpname);
 
195
                        rc = -1;
 
196
                }
 
197
                goto out;
 
198
        }
 
199
        if ((ts.st_mode & S_IRUSR) == 0)
 
200
                goto out;
 
201
 
 
202
        if (S_ISDIR(ts.st_mode)) {
 
203
                size_t len;
 
204
                len = strlen(tmpname);
 
205
                tmpname[len] = '/';
 
206
                tmpname[len + 1] = '\0';
 
207
                rc = DisplayAll(tmpname);
 
208
                goto out;
 
209
        }
 
210
 
 
211
        if (pattern && !pattern_match(outname, pattern)) {
 
212
                free(outname);
 
213
                return 0;
 
214
        }
 
215
 
 
216
        fp = fopen(tmpname, "r");
 
217
 
 
218
        if (!fp) {
 
219
                switch (errno) {
 
220
                case ENOENT:
 
221
                        if (!IgnoreError) {
 
222
                                xwarnx(_("\"%s\" is an unknown key"), outname);
 
223
                                rc = -1;
 
224
                        }
 
225
                        break;
 
226
                case EACCES:
 
227
                        xwarnx(_("permission denied on key '%s'"), outname);
 
228
                        rc = -1;
 
229
                        break;
 
230
                default:
 
231
                        xwarn(_("reading key \"%s\""), outname);
 
232
                        rc = -1;
 
233
                        break;
 
234
                }
 
235
        } else {
 
236
                errno = 0;
 
237
                if (fgets(inbuf, sizeof inbuf - 1, fp)) {
 
238
                        /* this loop is required, see
 
239
                         * /sbin/sysctl -a | egrep -6 dev.cdrom.info
 
240
                         */
 
241
                        do {
 
242
                                if (NameOnly) {
 
243
                                        fprintf(stdout, "%s\n", outname);
 
244
                                } else {
 
245
                                        /* already has the \n in it */
 
246
                                        if (PrintName) {
 
247
                                                fprintf(stdout, "%s = %s",
 
248
                                                        outname, inbuf);
 
249
                                                if (inbuf[strlen(inbuf) - 1] != '\n')
 
250
                                                        putchar('\n');
 
251
                                        } else {
 
252
                                                if (!PrintNewline) {
 
253
                                                        char *nlptr =
 
254
                                                            strchr(inbuf, '\n');
 
255
                                                        if (nlptr)
 
256
                                                                *nlptr = '\0';
 
257
                                                }
 
258
                                                fprintf(stdout, "%s", inbuf);
 
259
                                        }
 
260
                                }
 
261
                        } while (fgets(inbuf, sizeof inbuf - 1, fp));
 
262
                } else {
 
263
                        switch (errno) {
 
264
                        case EACCES:
 
265
                                xwarnx(_("permission denied on key '%s'"),
 
266
                                       outname);
 
267
                                rc = -1;
 
268
                                break;
 
269
                        case EISDIR: {
 
270
                                        size_t len;
 
271
                                        len = strlen(tmpname);
 
272
                                        tmpname[len] = '/';
 
273
                                        tmpname[len + 1] = '\0';
 
274
                                        fclose(fp);
 
275
                                        rc = DisplayAll(tmpname);
 
276
                                        goto out;
 
277
                                }
 
278
                        default:
 
279
                                xwarnx(_("reading key \"%s\""), outname);
 
280
                                rc = -1;
 
281
                        case 0:
 
282
                                break;
 
283
                        }
 
284
                }
 
285
                fclose(fp);
 
286
        }
 
287
      out:
 
288
        free(tmpname);
 
289
        free(outname);
 
290
        return rc;
 
291
}
 
292
 
 
293
static int is_deprecated(char *filename)
 
294
{
 
295
        int i;
 
296
        for (i = 0; strlen(DEPRECATED[i]); i++) {
 
297
                if (strcmp(DEPRECATED[i], filename) == 0)
 
298
                        return 1;
 
299
        }
 
300
        return 0;
 
301
}
 
302
 
 
303
/*
 
304
 * Display all the sysctl settings
 
305
 */
 
306
static int DisplayAll(const char *restrict const path)
 
307
{
 
308
        int rc = 0;
 
309
        int rc2;
 
310
        DIR *restrict dp;
 
311
        struct dirent *restrict de;
 
312
        struct stat ts;
 
313
 
 
314
        dp = opendir(path);
 
315
 
 
316
        if (!dp) {
 
317
                xwarnx(_("unable to open directory \"%s\""), path);
 
318
                rc = -1;
 
319
        } else {
 
320
                readdir(dp);    /* skip .  */
 
321
                readdir(dp);    /* skip .. */
 
322
                while ((de = readdir(dp))) {
 
323
                        char *restrict tmpdir;
 
324
                        if (IgnoreDeprecated && is_deprecated(de->d_name))
 
325
                                continue;
 
326
                        tmpdir =
 
327
                            (char *restrict) xmalloc(strlen(path) +
 
328
                                                     strlen(de->d_name) +
 
329
                                                     2);
 
330
                        sprintf(tmpdir, "%s%s", path, de->d_name);
 
331
                        rc2 = stat(tmpdir, &ts);
 
332
                        if (rc2 != 0) {
 
333
                                xwarn(_("cannot stat %s"), tmpdir);
 
334
                        } else {
 
335
                                if (S_ISDIR(ts.st_mode)) {
 
336
                                        strcat(tmpdir, "/");
 
337
                                        DisplayAll(tmpdir);
 
338
                                } else {
 
339
                                        rc |=
 
340
                                            ReadSetting(tmpdir +
 
341
                                                        strlen(PROC_PATH));
 
342
                                }
 
343
                        }
 
344
                        free(tmpdir);
 
345
                }
 
346
                closedir(dp);
 
347
        }
 
348
        return rc;
 
349
}
 
350
 
 
351
/*
 
352
 * Write a sysctl setting
 
353
 */
 
354
static int WriteSetting(const char *setting)
 
355
{
 
356
        int rc = 0;
 
357
        const char *name = setting;
 
358
        const char *value;
 
359
        const char *equals;
 
360
        char *tmpname;
 
361
        char *outname;
 
362
        char *last_dot;
 
363
 
 
364
        FILE *fp;
 
365
        struct stat ts;
 
366
 
 
367
        if (!name)
 
368
                /* probably don't want to display this err */
 
369
                return 0;
 
370
 
 
371
        equals = strchr(setting, '=');
 
372
 
 
373
        if (!equals) {
 
374
                xwarnx(_("\"%s\" must be of the form name=value"),
 
375
                       setting);
 
376
                return -1;
 
377
        }
 
378
 
 
379
        /* point to the value in name=value */
 
380
        value = equals + 1;
 
381
 
 
382
        if (!*name || !*value || name == equals) {
 
383
                xwarnx(_("malformed setting \"%s\""), setting);
 
384
                return -2;
 
385
        }
 
386
 
 
387
        /* used to open the file */
 
388
        tmpname = xmalloc(equals - name + 1 + strlen(PROC_PATH));
 
389
        strcpy(tmpname, PROC_PATH);
 
390
        strncat(tmpname, name, (int) (equals - name));
 
391
        tmpname[equals - name + strlen(PROC_PATH)] = 0;
 
392
        /* change . to / */
 
393
        slashdot(tmpname + strlen(PROC_PATH), '.', '/');
 
394
 
 
395
        /* used to display the output */
 
396
        outname = xmalloc(equals - name + 1);
 
397
        strncpy(outname, name, (int) (equals - name));
 
398
        outname[equals - name] = 0;
 
399
        /* change / to . */
 
400
        slashdot(outname, '/', '.');
 
401
        last_dot = strrchr(outname, '.');
 
402
        if (last_dot != NULL && is_deprecated(last_dot + 1)) {
 
403
                xwarnx(_("%s is deprecated, value not set"), outname);
 
404
                goto out;
 
405
        }
 
406
 
 
407
        if (stat(tmpname, &ts) < 0) {
 
408
                if (!IgnoreError) {
 
409
                        xwarn(_("cannot stat %s"), tmpname);
 
410
                        rc = -1;
 
411
                }
 
412
                goto out;
 
413
        }
 
414
 
 
415
        if ((ts.st_mode & S_IWUSR) == 0) {
 
416
                xwarn(_("setting key \"%s\""), outname);
 
417
                goto out;
 
418
        }
 
419
 
 
420
        if (S_ISDIR(ts.st_mode)) {
 
421
                xwarn(_("setting key \"%s\""), outname);
 
422
                goto out;
 
423
        }
 
424
 
 
425
        fp = fopen(tmpname, "w");
 
426
 
 
427
        if (!fp) {
 
428
                switch (errno) {
 
429
                case ENOENT:
 
430
                        if (!IgnoreError) {
 
431
                                xwarnx(_("\"%s\" is an unknown key"), outname);
 
432
                                rc = -1;
 
433
                        }
 
434
                        break;
 
435
                case EACCES:
 
436
                        xwarnx(_("permission denied on key '%s'"), outname);
 
437
                        rc = 0;
 
438
                        break;
 
439
                default:
 
440
                        xwarn(_("setting key \"%s\""), outname);
 
441
                        rc = -1;
 
442
                        break;
 
443
                }
 
444
        } else {
 
445
                rc = fprintf(fp, "%s\n", value);
 
446
                if (0 < rc)
 
447
                        rc = 0;
 
448
                if (close_stream(fp) != 0)
 
449
                        xwarn(_("setting key \"%s\""), outname);
 
450
                if (rc == 0 && !Quiet) {
 
451
                        if (NameOnly) {
 
452
                                fprintf(stdout, "%s\n", outname);
 
453
                        } else {
 
454
                                if (PrintName) {
 
455
                                        fprintf(stdout, "%s = %s\n",
 
456
                                                outname, value);
 
457
                                } else {
 
458
                                        if (PrintNewline)
 
459
                                                fprintf(stdout, "%s\n", value);
 
460
                                        else
 
461
                                                fprintf(stdout, "%s", value);
 
462
                                }
 
463
                        }
 
464
                }
 
465
        }
 
466
      out:
 
467
        free(tmpname);
 
468
        free(outname);
 
469
        return rc;
 
470
}
 
471
 
 
472
static int pattern_match(const char *string, const char *pat)
 
473
{
 
474
        int status;
 
475
        regex_t re;
 
476
 
 
477
        if (regcomp(&re, pat, REG_EXTENDED | REG_NOSUB) != 0)
 
478
                return (0);
 
479
        status = regexec(&re, string, (size_t) 0, NULL, 0);
 
480
        regfree(&re);
 
481
        if (status != 0)
 
482
                return (0);
 
483
        return (1);
 
484
}
 
485
 
 
486
/*
 
487
 * Preload the sysctl's from the conf file.  We parse the file and then
 
488
 * reform it (strip out whitespace).
 
489
 */
 
490
static int Preload(const char *restrict const filename)
 
491
{
 
492
        char oneline[256];
 
493
        char buffer[256];
 
494
        FILE *fp;
 
495
        char *t;
 
496
        int n = 0;
 
497
        int rc = 0;
 
498
        char *name, *value;
 
499
        glob_t globbuf;
 
500
        int globerr;
 
501
        int j;
 
502
 
 
503
        globerr = glob(filename, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf);
 
504
        if (globerr != 0 && globerr != GLOB_NOMATCH)
 
505
                xerr(EXIT_FAILURE, _("glob failed"));
 
506
 
 
507
        for (j = 0; j < globbuf.gl_pathc; j++) {
 
508
                fp = (globbuf.gl_pathv[j][0] == '-' && !globbuf.gl_pathv[j][1])
 
509
                    ? stdin : fopen(globbuf.gl_pathv[j], "r");
 
510
                if (!fp) {
 
511
                        xwarn(_("cannot open \"%s\""), globbuf.gl_pathv[j]);
 
512
                        return -1;
 
513
                }
 
514
 
 
515
                while (fgets(oneline, sizeof oneline, fp)) {
 
516
                        n++;
 
517
                        t = StripLeadingAndTrailingSpaces(oneline);
 
518
 
 
519
                        if (strlen(t) < 2)
 
520
                                continue;
 
521
 
 
522
                        if (*t == '#' || *t == ';')
 
523
                                continue;
 
524
 
 
525
                        name = strtok(t, "=");
 
526
                        if (!name || !*name) {
 
527
                                xwarnx(_("%s(%d): invalid syntax, continuing..."),
 
528
                                       globbuf.gl_pathv[j], n);
 
529
                                continue;
 
530
                        }
 
531
 
 
532
                        StripLeadingAndTrailingSpaces(name);
 
533
 
 
534
                        if (pattern && !pattern_match(name, pattern))
 
535
                                continue;
 
536
 
 
537
                        value = strtok(NULL, "\n\r");
 
538
                        if (!value || !*value) {
 
539
                                xwarnx(_("%s(%d): invalid syntax, continuing..."),
 
540
                                       globbuf.gl_pathv[j], n);
 
541
                                continue;
 
542
                        }
 
543
 
 
544
                        while ((*value == ' ' || *value == '\t') && *value != 0)
 
545
                                value++;
 
546
 
 
547
                        /* should NameOnly affect this? */
 
548
                        sprintf(buffer, "%s=%s", name, value);
 
549
                        rc |= WriteSetting(buffer);
 
550
                }
 
551
 
 
552
                fclose(fp);
 
553
        }
 
554
        return rc;
 
555
}
 
556
 
 
557
struct pair {
 
558
        char *name;
 
559
        char *value;
 
560
};
 
561
 
 
562
static int sortpairs(const void *A, const void *B)
 
563
{
 
564
        const struct pair *a = *(struct pair * const *) A;
 
565
        const struct pair *b = *(struct pair * const *) B;
 
566
        return strcmp(a->name, b->name);
 
567
}
 
568
 
 
569
static int PreloadSystem(void)
 
570
{
 
571
        unsigned di, i;
 
572
        const char *dirs[] = {
 
573
                "/run/sysctl.d",
 
574
                "/etc/sysctl.d",
 
575
                "/usr/local/lib/sysctl.d",
 
576
                "/usr/lib/sysctl.d",
 
577
                "/lib/sysctl.d",
 
578
        };
 
579
        struct pair **cfgs = NULL;
 
580
        unsigned ncfgs = 0;
 
581
        int rc = 0;
 
582
        struct stat ts;
 
583
        enum { nprealloc = 16 };
 
584
 
 
585
        for (di = 0; di < sizeof(dirs) / sizeof(dirs[0]); ++di) {
 
586
                struct dirent *de;
 
587
                DIR *dp = opendir(dirs[di]);
 
588
                if (!dp)
 
589
                        continue;
 
590
 
 
591
                while ((de = readdir(dp))) {
 
592
                        if (!strcmp(de->d_name, ".")
 
593
                            || !strcmp(de->d_name, ".."))
 
594
                                continue;
 
595
                        if (strlen(de->d_name) < 5
 
596
                            || strcmp(de->d_name + strlen(de->d_name) - 5, ".conf"))
 
597
                                continue;
 
598
                        /* check if config already known */
 
599
                        for (i = 0; i < ncfgs; ++i) {
 
600
                                if (cfgs && !strcmp(cfgs[i]->name, de->d_name))
 
601
                                        break;
 
602
                        }
 
603
                        if (i < ncfgs)
 
604
                                /* already in */
 
605
                                continue;
 
606
 
 
607
                        if (ncfgs % nprealloc == 0)
 
608
                                cfgs =
 
609
                                    xrealloc(cfgs,
 
610
                                             sizeof(struct pair *) * (ncfgs +
 
611
                                                                      nprealloc));
 
612
 
 
613
                        if (cfgs) {
 
614
                                cfgs[ncfgs] =
 
615
                                    xmalloc(sizeof(struct pair) +
 
616
                                            strlen(de->d_name) * 2 + 2 +
 
617
                                            strlen(dirs[di]) + 1);
 
618
                                cfgs[ncfgs]->name =
 
619
                                    (char *)cfgs[ncfgs] + sizeof(struct pair);
 
620
                                strcpy(cfgs[ncfgs]->name, de->d_name);
 
621
                                cfgs[ncfgs]->value =
 
622
                                    (char *)cfgs[ncfgs] + sizeof(struct pair) +
 
623
                                    strlen(cfgs[ncfgs]->name) + 1;
 
624
                                sprintf(cfgs[ncfgs]->value, "%s/%s", dirs[di],
 
625
                                        de->d_name);
 
626
                                ncfgs++;
 
627
                        } else {
 
628
                                xerrx(EXIT_FAILURE, _("internal error"));
 
629
                        }
 
630
 
 
631
                }
 
632
                closedir(dp);
 
633
        }
 
634
        qsort(cfgs, ncfgs, sizeof(struct cfg *), sortpairs);
 
635
 
 
636
        for (i = 0; i < ncfgs; ++i) {
 
637
                if (!Quiet)
 
638
                        printf(_("* Applying %s ...\n"), cfgs[i]->value);
 
639
                rc |= Preload(cfgs[i]->value);
 
640
        }
 
641
 
 
642
 
 
643
        if (stat(DEFAULT_PRELOAD, &ts) < 0 && S_ISREG(ts.st_mode)) {
 
644
                if (!Quiet)
 
645
                        printf(_("* Applying %s ...\n"), DEFAULT_PRELOAD);
 
646
                rc |= Preload(DEFAULT_PRELOAD);
 
647
        }
 
648
        return rc;
 
649
}
 
650
 
 
651
/*
 
652
 * Main...
 
653
 */
 
654
int main(int argc, char *argv[])
 
655
{
 
656
        bool WriteMode = false;
 
657
        bool DisplayAllOpt = false;
 
658
        bool preloadfileOpt = false;
 
659
        int ReturnCode = 0;
 
660
        int c;
 
661
        const char *preloadfile = NULL;
 
662
 
 
663
        enum {
 
664
                DEPRECATED_OPTION = CHAR_MAX + 1,
 
665
                SYSTEM_OPTION
 
666
        };
 
667
        static const struct option longopts[] = {
 
668
                {"all", no_argument, NULL, 'a'},
 
669
                {"deprecated", no_argument, NULL, DEPRECATED_OPTION},
 
670
                {"binary", no_argument, NULL, 'b'},
 
671
                {"ignore", no_argument, NULL, 'e'},
 
672
                {"names", no_argument, NULL, 'N'},
 
673
                {"values", no_argument, NULL, 'n'},
 
674
                {"load", optional_argument, NULL, 'p'},
 
675
                {"quiet", no_argument, NULL, 'q'},
 
676
                {"write", no_argument, NULL, 'w'},
 
677
                {"system", no_argument, NULL, SYSTEM_OPTION},
 
678
                {"pattern", required_argument, NULL, 'r'},
 
679
                {"help", no_argument, NULL, 'h'},
 
680
                {"version", no_argument, NULL, 'V'},
 
681
                {NULL, 0, NULL, 0}
 
682
        };
 
683
 
 
684
#ifdef HAVE_PROGRAM_INVOCATION_NAME
 
685
        program_invocation_name = program_invocation_short_name;
 
686
#endif
 
687
        setlocale(LC_ALL, "");
 
688
        bindtextdomain(PACKAGE, LOCALEDIR);
 
689
        textdomain(PACKAGE);
 
690
        atexit(close_stdout);
 
691
 
 
692
        PrintName = true;
 
693
        PrintNewline = true;
 
694
        IgnoreError = false;
 
695
        Quiet = false;
 
696
        IgnoreDeprecated = true;
 
697
 
 
698
        if (argc < 2)
 
699
                Usage(stderr);
 
700
 
 
701
        while ((c =
 
702
                getopt_long(argc, argv, "bneNwfp::qoxaAXr:Vdh", longopts,
 
703
                            NULL)) != -1) {
 
704
                switch (c) {
 
705
                case 'b':
 
706
                        /* This is "binary" format, which means more for BSD. */
 
707
                        PrintNewline = false;
 
708
                        /* FALL THROUGH */
 
709
                case 'n':
 
710
                        PrintName = false;
 
711
                        break;
 
712
                case 'e':
 
713
                        /*
 
714
                         * For FreeBSD, -e means a "%s=%s\n" format.
 
715
                         * ("%s: %s\n" default). We (and NetBSD) use
 
716
                         * "%s = %s\n" always, and -e to ignore errors.
 
717
                         */
 
718
                        IgnoreError = true;
 
719
                        break;
 
720
                case 'N':
 
721
                        NameOnly = true;
 
722
                        break;
 
723
                case 'w':
 
724
                        WriteMode = true;
 
725
                        break;
 
726
                case 'f':       /* the NetBSD way */
 
727
                case 'p':
 
728
                        preloadfileOpt = true;
 
729
                        if (optarg)
 
730
                                preloadfile = optarg;
 
731
                        break;
 
732
                case 'q':
 
733
                        Quiet = true;
 
734
                        break;
 
735
                case 'o':       /* BSD: binary values too, 1st 16 bytes in hex */
 
736
                case 'x':       /* BSD: binary values too, whole thing in hex */
 
737
                        /* does nothing */ ;
 
738
                        break;
 
739
                case 'a':       /* string and integer values (for Linux, all of them) */
 
740
                case 'A':       /* same as -a -o */
 
741
                case 'X':       /* same as -a -x */
 
742
                        DisplayAllOpt = true;
 
743
                        break;
 
744
                case DEPRECATED_OPTION:
 
745
                        IgnoreDeprecated = false;
 
746
                        break;
 
747
                case SYSTEM_OPTION:
 
748
                        IgnoreError = true;
 
749
                        return PreloadSystem();
 
750
                case 'r':
 
751
                        pattern = xstrdup(optarg);
 
752
                        break;
 
753
                case 'V':
 
754
                        printf(PROCPS_NG_VERSION);
 
755
                        return EXIT_SUCCESS;
 
756
                case 'd':       /* BSD: print description ("vm.kvm_size: Size of KVM") */
 
757
                case 'h':       /* BSD: human-readable (did FreeBSD 5 make -e default?) */
 
758
                case '?':
 
759
                        Usage(stdout);
 
760
                default:
 
761
                        Usage(stderr);
 
762
                }
 
763
        }
 
764
 
 
765
        argc -= optind;
 
766
        argv += optind;
 
767
 
 
768
        if (DisplayAllOpt)
 
769
                return DisplayAll(PROC_PATH);
 
770
 
 
771
        if (preloadfileOpt) {
 
772
                int ret = EXIT_SUCCESS, i;
 
773
                if (!preloadfile) {
 
774
                        if (!argc) {
 
775
                                ret |= Preload(DEFAULT_PRELOAD);
 
776
                        }
 
777
                } else {
 
778
                        /* This happens when -pfile option is
 
779
                         * used without space. */
 
780
                        ret |= Preload(preloadfile);
 
781
                }
 
782
                for (i = 0; i < argc; i++)
 
783
                        ret |= Preload(argv[i]);
 
784
                return ret;
 
785
        }
 
786
 
 
787
        if (argc < 1)
 
788
                xerrx(EXIT_FAILURE, _("no variables specified\n"
 
789
                                      "Try `%s --help' for more information."),
 
790
                      program_invocation_short_name);
 
791
        if (NameOnly && Quiet)
 
792
                xerrx(EXIT_FAILURE, _("options -N and -q cannot coexist\n"
 
793
                                      "Try `%s --help' for more information."),
 
794
                      program_invocation_short_name);
 
795
 
 
796
        for ( ; *argv; argv++) {
 
797
                if (WriteMode || index(*argv, '='))
 
798
                        ReturnCode += WriteSetting(*argv);
 
799
                else
 
800
                        ReturnCode += ReadSetting(*argv);
 
801
        }
 
802
        return ReturnCode;
 
803
}