popt 1.13
|
00001 00005 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING 00006 file accompanying popt source distributions, available from 00007 ftp://ftp.rpm.org/pub/rpm/dist. */ 00008 00009 #include "system.h" 00010 #include "poptint.h" 00011 #include <sys/stat.h> 00012 #include <glob.h> 00013 /*@access poptContext @*/ 00014 00015 /*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ 00016 static void configLine(poptContext con, char * line) 00017 /*@modifies con @*/ 00018 { 00019 size_t nameLength; 00020 const char * entryType; 00021 const char * opt; 00022 struct poptItem_s item_buf; 00023 poptItem item = &item_buf; 00024 int i, j; 00025 00026 if (con->appName == NULL) 00027 return; 00028 nameLength = strlen(con->appName); 00029 00030 memset(item, 0, sizeof(*item)); 00031 00032 if (strncmp(line, con->appName, nameLength)) return; 00033 00034 line += nameLength; 00035 if (*line == '\0' || !_isspaceptr(line)) return; 00036 00037 while (*line != '\0' && _isspaceptr(line)) line++; 00038 entryType = line; 00039 while (*line == '\0' || !_isspaceptr(line)) line++; 00040 *line++ = '\0'; 00041 00042 while (*line != '\0' && _isspaceptr(line)) line++; 00043 if (*line == '\0') return; 00044 opt = line; 00045 while (*line == '\0' || !_isspaceptr(line)) line++; 00046 *line++ = '\0'; 00047 00048 while (*line != '\0' && _isspaceptr(line)) line++; 00049 if (*line == '\0') return; 00050 00051 /*@-temptrans@*/ /* FIX: line alias is saved */ 00052 if (opt[0] == '-' && opt[1] == '-') 00053 item->option.longName = opt + 2; 00054 else if (opt[0] == '-' && opt[2] == '\0') 00055 item->option.shortName = opt[1]; 00056 /*@=temptrans@*/ 00057 00058 if (poptParseArgvString(line, &item->argc, &item->argv)) return; 00059 00060 /*@-modobserver@*/ 00061 item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; 00062 for (i = 0, j = 0; i < item->argc; i++, j++) { 00063 const char * f; 00064 if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { 00065 f = item->argv[i] + sizeof("--POPTdesc="); 00066 if (f[0] == '$' && f[1] == '"') f++; 00067 item->option.descrip = f; 00068 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 00069 j--; 00070 } else 00071 if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { 00072 f = item->argv[i] + sizeof("--POPTargs="); 00073 if (f[0] == '$' && f[1] == '"') f++; 00074 item->option.argDescrip = f; 00075 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 00076 item->option.argInfo |= POPT_ARG_STRING; 00077 j--; 00078 } else 00079 if (j != i) 00080 item->argv[j] = item->argv[i]; 00081 } 00082 if (j != i) { 00083 item->argv[j] = NULL; 00084 item->argc = j; 00085 } 00086 /*@=modobserver@*/ 00087 00088 /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ 00089 if (!strcmp(entryType, "alias")) 00090 (void) poptAddItem(con, item, 0); 00091 else if (!strcmp(entryType, "exec")) 00092 (void) poptAddItem(con, item, 1); 00093 /*@=nullstate@*/ 00094 } 00095 /*@=compmempass@*/ 00096 00097 int poptReadConfigFile(poptContext con, const char * fn) 00098 { 00099 char * file = NULL, * chptr, * end; 00100 char * buf = NULL; 00101 /*@dependent@*/ char * dst; 00102 int fd, rc; 00103 off_t fileLength; 00104 00105 fd = open(fn, O_RDONLY); 00106 if (fd < 0) 00107 return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); 00108 00109 fileLength = lseek(fd, 0, SEEK_END); 00110 if (fileLength == -1 || lseek(fd, 0, 0) == -1) { 00111 rc = errno; 00112 (void) close(fd); 00113 errno = rc; 00114 return POPT_ERROR_ERRNO; 00115 } 00116 00117 file = malloc(fileLength + 1); 00118 if (file == NULL || read(fd, (char *)file, fileLength) != fileLength) { 00119 rc = errno; 00120 (void) close(fd); 00121 errno = rc; 00122 if (file) 00123 free(file); 00124 return POPT_ERROR_ERRNO; 00125 } 00126 if (close(fd) == -1) { 00127 free(file); 00128 return POPT_ERROR_ERRNO; 00129 } 00130 00131 dst = buf = malloc(fileLength + 1); 00132 if (dst == NULL) 00133 return POPT_ERROR_ERRNO; 00134 00135 chptr = file; 00136 end = (file + fileLength); 00137 /*@-infloops@*/ /* LCL: can't detect chptr++ */ 00138 while (chptr < end) { 00139 switch (*chptr) { 00140 case '\n': 00141 *dst = '\0'; 00142 dst = buf; 00143 while (*dst && _isspaceptr(dst)) dst++; 00144 if (*dst && *dst != '#') 00145 configLine(con, dst); 00146 chptr++; 00147 /*@switchbreak@*/ break; 00148 case '\\': 00149 *dst++ = *chptr++; 00150 if (chptr < end) { 00151 if (*chptr == '\n') 00152 dst--, chptr++; 00153 /* \ at the end of a line does not insert a \n */ 00154 else 00155 *dst++ = *chptr++; 00156 } 00157 /*@switchbreak@*/ break; 00158 default: 00159 *dst++ = *chptr++; 00160 /*@switchbreak@*/ break; 00161 } 00162 } 00163 /*@=infloops@*/ 00164 00165 free(file); 00166 free(buf); 00167 00168 return 0; 00169 } 00170 00171 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) 00172 { 00173 static const char _popt_sysconfdir[] = POPT_SYSCONFDIR "/popt"; 00174 static const char _popt_etc[] = "/etc/popt"; 00175 char * fn, * home; 00176 struct stat s; 00177 int rc; 00178 00179 if (con->appName == NULL) return 0; 00180 00181 if (strcmp(_popt_sysconfdir, _popt_etc)) { 00182 rc = poptReadConfigFile(con, _popt_sysconfdir); 00183 if (rc) return rc; 00184 } 00185 00186 rc = poptReadConfigFile(con, _popt_etc); 00187 if (rc) return rc; 00188 00189 if (!stat("/etc/popt.d", &s) && S_ISDIR(s.st_mode)) { 00190 glob_t g; 00191 /*@-moduncon -nullpass -type @*/ /* FIX: annotations for glob/globfree */ 00192 if (!glob("/etc/popt.d/*", 0, NULL, &g)) { 00193 int i; 00194 for (i=0; i<g.gl_pathc; i++) { 00195 char *f=g.gl_pathv[i]; 00196 if (strstr(f, ".rpmnew") || strstr(f, ".rpmsave")) 00197 continue; 00198 if (!stat(f, &s)) { 00199 if (!S_ISREG(s.st_mode) && !S_ISLNK(s.st_mode)) 00200 continue; 00201 } 00202 rc = poptReadConfigFile(con, f); 00203 if (rc) return rc; 00204 } 00205 /*@-noeffectuncon@*/ 00206 globfree(&g); 00207 /*@=noeffectuncon@*/ 00208 } 00209 /*@=moduncon =nullpass =type @*/ 00210 } 00211 00212 if ((home = getenv("HOME"))) { 00213 fn = malloc(strlen(home) + 20); 00214 if (fn != NULL) { 00215 strcpy(fn, home); 00216 strcat(fn, "/.popt"); 00217 rc = poptReadConfigFile(con, fn); 00218 free(fn); 00219 } else 00220 rc = POPT_ERROR_ERRNO; 00221 if (rc) return rc; 00222 } 00223 00224 return 0; 00225 }