• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*@access poptContext @*/
12 
13 /*@-compmempass@*/	/* FIX: item->option.longName kept, not dependent. */
configLine(poptContext con,char * line)14 static void configLine(poptContext con, char * line)
15 	/*@modifies con @*/
16 {
17     size_t nameLength;
18     const char * entryType;
19     const char * opt;
20     poptItem item = alloca(sizeof(*item));
21     int i, j;
22 
23     if (con->appName == NULL)
24 	return;
25     nameLength = strlen(con->appName);
26 
27 /*@-boundswrite@*/
28     memset(item, 0, sizeof(*item));
29 
30     if (strncmp(line, con->appName, nameLength)) return;
31 
32     line += nameLength;
33     if (*line == '\0' || !isspace(*line)) return;
34 
35     while (*line != '\0' && isspace(*line)) line++;
36     entryType = line;
37     while (*line == '\0' || !isspace(*line)) line++;
38     *line++ = '\0';
39 
40     while (*line != '\0' && isspace(*line)) line++;
41     if (*line == '\0') return;
42     opt = line;
43     while (*line == '\0' || !isspace(*line)) line++;
44     *line++ = '\0';
45 
46     while (*line != '\0' && isspace(*line)) line++;
47     if (*line == '\0') return;
48 
49     /*@-temptrans@*/ /* FIX: line alias is saved */
50     if (opt[0] == '-' && opt[1] == '-')
51 	item->option.longName = opt + 2;
52     else if (opt[0] == '-' && opt[2] == '\0')
53 	item->option.shortName = opt[1];
54     /*@=temptrans@*/
55 
56     if (poptParseArgvString(line, &item->argc, &item->argv)) return;
57 
58     /*@-modobserver@*/
59     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
60     for (i = 0, j = 0; i < item->argc; i++, j++) {
61 	const char * f;
62 	if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
63 	    f = item->argv[i] + sizeof("--POPTdesc=");
64 	    if (f[0] == '$' && f[1] == '"') f++;
65 	    item->option.descrip = f;
66 	    item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
67 	    j--;
68 	} else
69 	if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
70 	    f = item->argv[i] + sizeof("--POPTargs=");
71 	    if (f[0] == '$' && f[1] == '"') f++;
72 	    item->option.argDescrip = f;
73 	    item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
74 	    item->option.argInfo |= POPT_ARG_STRING;
75 	    j--;
76 	} else
77 	if (j != i)
78 	    item->argv[j] = item->argv[i];
79     }
80     if (j != i) {
81 	item->argv[j] = NULL;
82 	item->argc = j;
83     }
84     /*@=modobserver@*/
85 /*@=boundswrite@*/
86 
87     /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
88     if (!strcmp(entryType, "alias"))
89 	(void) poptAddItem(con, item, 0);
90     else if (!strcmp(entryType, "exec"))
91 	(void) poptAddItem(con, item, 1);
92     /*@=nullstate@*/
93 }
94 /*@=compmempass@*/
95 
poptReadConfigFile(poptContext con,const char * fn)96 int poptReadConfigFile(poptContext con, const char * fn)
97 {
98     const char * file, * 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 	errno = rc;
113 	return POPT_ERROR_ERRNO;
114     }
115 
116     file = alloca(fileLength + 1);
117     if (read(fd, (char *)file, fileLength) != fileLength) {
118 	rc = errno;
119 	(void) close(fd);
120 	errno = rc;
121 	return POPT_ERROR_ERRNO;
122     }
123     if (close(fd) == -1)
124 	return POPT_ERROR_ERRNO;
125 
126 /*@-boundswrite@*/
127     dst = buf = alloca(fileLength + 1);
128 
129     chptr = file;
130     end = (file + fileLength);
131     /*@-infloops@*/	/* LCL: can't detect chptr++ */
132     while (chptr < end) {
133 	switch (*chptr) {
134 	  case '\n':
135 	    *dst = '\0';
136 	    dst = buf;
137 	    while (*dst && isspace(*dst)) dst++;
138 	    if (*dst && *dst != '#')
139 		configLine(con, dst);
140 	    chptr++;
141 	    /*@switchbreak@*/ break;
142 	  case '\\':
143 	    *dst++ = *chptr++;
144 	    if (chptr < end) {
145 		if (*chptr == '\n')
146 		    dst--, chptr++;
147 		    /* \ at the end of a line does not insert a \n */
148 		else
149 		    *dst++ = *chptr++;
150 	    }
151 	    /*@switchbreak@*/ break;
152 	  default:
153 	    *dst++ = *chptr++;
154 	    /*@switchbreak@*/ break;
155 	}
156     }
157     /*@=infloops@*/
158 /*@=boundswrite@*/
159 
160     return 0;
161 }
162 
poptReadDefaultConfig(poptContext con,int useEnv)163 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv)
164 {
165     char * fn, * home;
166     int rc;
167 
168     if (con->appName == NULL) return 0;
169 
170     rc = poptReadConfigFile(con, "/etc/popt");
171     if (rc) return rc;
172 
173     if ((home = getenv("HOME"))) {
174 	fn = alloca(strlen(home) + 20);
175 	strcpy(fn, home);
176 	strcat(fn, "/.popt");
177 	rc = poptReadConfigFile(con, fn);
178 	if (rc) return rc;
179     }
180 
181     return 0;
182 }
183