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. */ 14static 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 96int 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 163int 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