Merge branch 'master' of ctdb into 'master' of samba
[sfrench/samba-autobuild/.git] / ctdb / lib / popt / poptconfig.c
1 /** \ingroup popt
2  * \file popt/poptconfig.c
3  */
4
5 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
6    file accompanying popt source distributions, available from 
7    ftp://ftp.rpm.org/pub/rpm/dist. */
8
9 #include "system.h"
10 #include "poptint.h"
11
12 /*@-compmempass@*/      /* FIX: item->option.longName kept, not dependent. */
13 static void configLine(poptContext con, char * line)
14         /*@modifies con @*/
15 {
16     /*@-type@*/
17     int nameLength = strlen(con->appName);
18     /*@=type@*/
19     const char * entryType;
20     const char * opt;
21     poptItem item = alloca(sizeof(*item));
22     int i, j;
23     
24 /*@-boundswrite@*/
25     memset(item, 0, sizeof(*item));
26
27     /*@-type@*/
28     if (strncmp(line, con->appName, nameLength)) return;
29     /*@=type@*/
30
31     line += nameLength;
32     if (*line == '\0' || !isspace(*line)) return;
33
34     while (*line != '\0' && isspace(*line)) line++;
35     entryType = line;
36     while (*line == '\0' || !isspace(*line)) line++;
37     *line++ = '\0';
38
39     while (*line != '\0' && isspace(*line)) line++;
40     if (*line == '\0') return;
41     opt = line;
42     while (*line == '\0' || !isspace(*line)) line++;
43     *line++ = '\0';
44
45     while (*line != '\0' && isspace(*line)) line++;
46     if (*line == '\0') return;
47
48     /*@-temptrans@*/ /* FIX: line alias is saved */
49     if (opt[0] == '-' && opt[1] == '-')
50         item->option.longName = opt + 2;
51     else if (opt[0] == '-' && opt[2] == '\0')
52         item->option.shortName = opt[1];
53     /*@=temptrans@*/
54
55     if (poptParseArgvString(line, &item->argc, &item->argv)) return;
56
57     /*@-modobserver@*/
58     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
59     for (i = 0, j = 0; i < item->argc; i++, j++) {
60         const char * f;
61         if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
62             f = item->argv[i] + sizeof("--POPTdesc=");
63             if (f[0] == '$' && f[1] == '"') f++;
64             item->option.descrip = f;
65             item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
66             j--;
67         } else
68         if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
69             f = item->argv[i] + sizeof("--POPTargs=");
70             if (f[0] == '$' && f[1] == '"') f++;
71             item->option.argDescrip = f;
72             item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
73             item->option.argInfo |= POPT_ARG_STRING;
74             j--;
75         } else
76         if (j != i)
77             item->argv[j] = item->argv[i];
78     }
79     if (j != i) {
80         item->argv[j] = NULL;
81         item->argc = j;
82     }
83     /*@=modobserver@*/
84 /*@=boundswrite@*/
85         
86     /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
87     if (!strcmp(entryType, "alias"))
88         (void) poptAddItem(con, item, 0);
89     else if (!strcmp(entryType, "exec"))
90         (void) poptAddItem(con, item, 1);
91     /*@=nullstate@*/
92 }
93 /*@=compmempass@*/
94
95 int poptReadConfigFile(poptContext con, const char * fn)
96 {
97     char * file;
98     const char * chptr, * end;
99     char * buf;
100 /*@dependent@*/ char * dst;
101     int fd, rc;
102     off_t fileLength;
103
104     fd = open(fn, O_RDONLY);
105     if (fd < 0)
106         return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
107
108     fileLength = lseek(fd, 0, SEEK_END);
109     if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
110         rc = errno;
111         (void) close(fd);
112         /*@-mods@*/
113         errno = rc;
114         /*@=mods@*/
115         return POPT_ERROR_ERRNO;
116     }
117
118     file = alloca(fileLength + 1);
119     if (read(fd, (char *)file, fileLength) != fileLength) {
120         rc = errno;
121         (void) close(fd);
122         /*@-mods@*/
123         errno = rc;
124         /*@=mods@*/
125         return POPT_ERROR_ERRNO;
126     }
127     if (close(fd) == -1)
128         return POPT_ERROR_ERRNO;
129
130 /*@-boundswrite@*/
131     dst = buf = alloca(fileLength + 1);
132
133     chptr = file;
134     end = (file + fileLength);
135     /*@-infloops@*/     /* LCL: can't detect chptr++ */
136     while (chptr < end) {
137         switch (*chptr) {
138           case '\n':
139             *dst = '\0';
140             dst = buf;
141             while (*dst && isspace(*dst)) dst++;
142             if (*dst && *dst != '#')
143                 configLine(con, dst);
144             chptr++;
145             /*@switchbreak@*/ break;
146           case '\\':
147             *dst++ = *chptr++;
148             if (chptr < end) {
149                 if (*chptr == '\n') 
150                     dst--, chptr++;     
151                     /* \ at the end of a line does not insert a \n */
152                 else
153                     *dst++ = *chptr++;
154             }
155             /*@switchbreak@*/ break;
156           default:
157             *dst++ = *chptr++;
158             /*@switchbreak@*/ break;
159         }
160     }
161     /*@=infloops@*/
162 /*@=boundswrite@*/
163
164     return 0;
165 }
166
167 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
168 {
169     char * fn, * home;
170     int rc;
171
172     /*@-type@*/
173     if (!con->appName) return 0;
174     /*@=type@*/
175
176     rc = poptReadConfigFile(con, "/etc/popt");
177     if (rc) return rc;
178 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
179     if (getuid() != geteuid()) return 0;
180 #endif
181
182     if ((home = getenv("HOME"))) {
183         fn = alloca(strlen(home) + 20);
184         strcpy(fn, home);
185         strcat(fn, "/.popt");
186         rc = poptReadConfigFile(con, fn);
187         if (rc) return rc;
188     }
189
190     return 0;
191 }