Doc.
[rsync/rsync.git] / popt-1.2 / poptconfig.c
1 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
2    file accompanying popt source distributions, available from 
3    ftp://ftp.redhat.com/pub/code/popt */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8
9 #include <ctype.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #if HAVE_ALLOCA_H
17 # include <alloca.h>
18 #endif
19
20 #include "popt.h"
21 #include "poptint.h"
22
23 static void configLine(poptContext con, char * line) {
24     int nameLength = strlen(con->appName);
25     char * opt;
26     struct poptAlias alias;
27     char * entryType;
28     char * longName = NULL;
29     char shortName = '\0';
30     
31     if (strncmp(line, con->appName, nameLength)) return;
32     line += nameLength;
33     if (!*line || !isspace(*line)) return;
34     while (*line && isspace(*line)) line++;
35     entryType = line;
36
37     while (!*line || !isspace(*line)) line++;
38     *line++ = '\0';
39     while (*line && isspace(*line)) line++;
40     if (!*line) return;
41     opt = line;
42
43     while (!*line || !isspace(*line)) line++;
44     *line++ = '\0';
45     while (*line && isspace(*line)) line++;
46     if (!*line) return;
47
48     if (opt[0] == '-' && opt[1] == '-')
49         longName = opt + 2;
50     else if (opt[0] == '-' && !opt[2])
51         shortName = opt[1];
52
53     if (!strcmp(entryType, "alias")) {
54         if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
55         alias.longName = longName, alias.shortName = shortName;
56         poptAddAlias(con, alias, 0);
57     } else if (!strcmp(entryType, "exec")) {
58         con->execs = realloc(con->execs, 
59                                 sizeof(*con->execs) * (con->numExecs + 1));
60         if (longName)
61             con->execs[con->numExecs].longName = strdup(longName);
62         else
63             con->execs[con->numExecs].longName = NULL;
64
65         con->execs[con->numExecs].shortName = shortName;
66         con->execs[con->numExecs].script = strdup(line);
67         
68         con->numExecs++;
69     }
70 }
71
72 int poptReadConfigFile(poptContext con, char * fn) {
73     char * file, * chptr, * end;
74     char * buf, * dst;
75     int fd, rc;
76     int fileLength;
77
78     fd = open(fn, O_RDONLY);
79     if (fd < 0) {
80         if (errno == ENOENT)
81             return 0;
82         else 
83             return POPT_ERROR_ERRNO;
84     }
85
86     fileLength = lseek(fd, 0, SEEK_END);
87     lseek(fd, 0, 0);
88
89     file = alloca(fileLength + 1);
90     if ((fd = read(fd, file, fileLength)) != fileLength) {
91         rc = errno;
92         close(fd);
93         errno = rc;
94         return POPT_ERROR_ERRNO;
95     }
96     close(fd);
97
98     dst = buf = alloca(fileLength + 1);
99
100     chptr = file;
101     end = (file + fileLength);
102     while (chptr < end) {
103         switch (*chptr) {
104           case '\n':
105             *dst = '\0';
106             dst = buf;
107             while (*dst && isspace(*dst)) dst++;
108             if (*dst && *dst != '#') {
109                 configLine(con, dst);
110             }
111             chptr++;
112             break;
113           case '\\':
114             *dst++ = *chptr++;
115             if (chptr < end) {
116                 if (*chptr == '\n') 
117                     dst--, chptr++;     
118                     /* \ at the end of a line does not insert a \n */
119                 else
120                     *dst++ = *chptr++;
121             }
122             break;
123           default:
124             *dst++ = *chptr++;
125         }
126     }
127
128     return 0;
129 }
130
131 int poptReadDefaultConfig(poptContext con, int useEnv) {
132     char * fn, * home;
133     int rc;
134
135     if (!con->appName) return 0;
136
137     rc = poptReadConfigFile(con, "/etc/popt");
138     if (rc) return rc;
139     if (getuid() != geteuid()) return 0;
140
141     if ((home = getenv("HOME"))) {
142         fn = alloca(strlen(home) + 20);
143         strcpy(fn, home);
144         strcat(fn, "/.popt");
145         rc = poptReadConfigFile(con, fn);
146         if (rc) return rc;
147     }
148
149     return 0;
150 }
151