popt  1.14
poptconfig.c
Go to the documentation of this file.
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 }

Generated for popt by  doxygen 1.7.6.1