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. */
configLine(poptContext con,char * line)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
poptReadConfigFile(poptContext con,const char * fn)95 int poptReadConfigFile(poptContext con, const char * fn)
96 {
97 const char * file, * chptr, * end;
98 char * buf;
99 /*@dependent@*/ char * dst;
100 int fd, rc;
101 off_t fileLength;
102
103 fd = open(fn, O_RDONLY);
104 if (fd < 0)
105 return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
106
107 fileLength = lseek(fd, 0, SEEK_END);
108 if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
109 rc = errno;
110 (void) close(fd);
111 /*@-mods@*/
112 errno = rc;
113 /*@=mods@*/
114 return POPT_ERROR_ERRNO;
115 }
116
117 file = alloca(fileLength + 1);
118 if (read(fd, (char *)file, fileLength) != fileLength) {
119 rc = errno;
120 (void) close(fd);
121 /*@-mods@*/
122 errno = rc;
123 /*@=mods@*/
124 return POPT_ERROR_ERRNO;
125 }
126 if (close(fd) == -1)
127 return POPT_ERROR_ERRNO;
128
129 /*@-boundswrite@*/
130 dst = buf = alloca(fileLength + 1);
131
132 chptr = file;
133 end = (file + fileLength);
134 /*@-infloops@*/ /* LCL: can't detect chptr++ */
135 while (chptr < end) {
136 switch (*chptr) {
137 case '\n':
138 *dst = '\0';
139 dst = buf;
140 while (*dst && isspace(*dst)) dst++;
141 if (*dst && *dst != '#')
142 configLine(con, dst);
143 chptr++;
144 /*@switchbreak@*/ break;
145 case '\\':
146 *dst++ = *chptr++;
147 if (chptr < end) {
148 if (*chptr == '\n')
149 dst--, chptr++;
150 /* \ at the end of a line does not insert a \n */
151 else
152 *dst++ = *chptr++;
153 }
154 /*@switchbreak@*/ break;
155 default:
156 *dst++ = *chptr++;
157 /*@switchbreak@*/ break;
158 }
159 }
160 /*@=infloops@*/
161 /*@=boundswrite@*/
162
163 return 0;
164 }
165
poptReadDefaultConfig(poptContext con,int useEnv)166 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
167 {
168 char * fn, * home;
169 int rc;
170
171 /*@-type@*/
172 if (!con->appName) return 0;
173 /*@=type@*/
174
175 rc = poptReadConfigFile(con, "/etc/popt");
176 if (rc) return rc;
177 #if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
178 if (getuid() != geteuid()) return 0;
179 #endif
180
181 if ((home = getenv("HOME"))) {
182 fn = alloca(strlen(home) + 20);
183 strcpy(fn, home);
184 strcat(fn, "/.popt");
185 rc = poptReadConfigFile(con, fn);
186 if (rc) return rc;
187 }
188
189 return 0;
190 }
191