popt 1.13
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 #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 }

Generated for popt by  doxygen 1.7.4