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