Home | History | Annotate | Download | only in libpopt
      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. */
     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 
     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 
    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