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 12/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ 13static void configLine(poptContext con, char * line) 14 /*@modifies con @*/ 15{ 16 /*@-type@*/ 17 int nameLength = strlen(con->appName); 18 /*@=type@*/ 19 const char * entryType; 20 const char * opt; 21 poptItem item = alloca(sizeof(*item)); 22 int i, j; 23 24/*@-boundswrite@*/ 25 memset(item, 0, sizeof(*item)); 26 27 /*@-type@*/ 28 if (strncmp(line, con->appName, nameLength)) return; 29 /*@=type@*/ 30 31 line += nameLength; 32 if (*line == '\0' || !isspace(*line)) return; 33 34 while (*line != '\0' && isspace(*line)) line++; 35 entryType = line; 36 while (*line == '\0' || !isspace(*line)) line++; 37 *line++ = '\0'; 38 39 while (*line != '\0' && isspace(*line)) line++; 40 if (*line == '\0') return; 41 opt = line; 42 while (*line == '\0' || !isspace(*line)) line++; 43 *line++ = '\0'; 44 45 while (*line != '\0' && isspace(*line)) line++; 46 if (*line == '\0') return; 47 48 /*@-temptrans@*/ /* FIX: line alias is saved */ 49 if (opt[0] == '-' && opt[1] == '-') 50 item->option.longName = opt + 2; 51 else if (opt[0] == '-' && opt[2] == '\0') 52 item->option.shortName = opt[1]; 53 /*@=temptrans@*/ 54 55 if (poptParseArgvString(line, &item->argc, &item->argv)) return; 56 57 /*@-modobserver@*/ 58 item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; 59 for (i = 0, j = 0; i < item->argc; i++, j++) { 60 const char * f; 61 if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { 62 f = item->argv[i] + sizeof("--POPTdesc="); 63 if (f[0] == '$' && f[1] == '"') f++; 64 item->option.descrip = f; 65 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 66 j--; 67 } else 68 if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { 69 f = item->argv[i] + sizeof("--POPTargs="); 70 if (f[0] == '$' && f[1] == '"') f++; 71 item->option.argDescrip = f; 72 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 73 item->option.argInfo |= POPT_ARG_STRING; 74 j--; 75 } else 76 if (j != i) 77 item->argv[j] = item->argv[i]; 78 } 79 if (j != i) { 80 item->argv[j] = NULL; 81 item->argc = j; 82 } 83 /*@=modobserver@*/ 84/*@=boundswrite@*/ 85 86 /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ 87 if (!strcmp(entryType, "alias")) 88 (void) poptAddItem(con, item, 0); 89 else if (!strcmp(entryType, "exec")) 90 (void) poptAddItem(con, item, 1); 91 /*@=nullstate@*/ 92} 93/*@=compmempass@*/ 94 95int poptReadConfigFile(poptContext con, const char * fn) 96{ 97 const char * file, * chptr, * end; 98 char * buf; 99/*@dependent@*/ char * dst; 100 int fd, rc; 101 off_t fileLength; 102 103 fd = open(fn, O_RDONLY); 104 if (fd < 0) 105 return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); 106 107 fileLength = lseek(fd, 0, SEEK_END); 108 if (fileLength == -1 || lseek(fd, 0, 0) == -1) { 109 rc = errno; 110 (void) close(fd); 111 /*@-mods@*/ 112 errno = rc; 113 /*@=mods@*/ 114 return POPT_ERROR_ERRNO; 115 } 116 117 file = alloca(fileLength + 1); 118 if (read(fd, (char *)file, fileLength) != fileLength) { 119 rc = errno; 120 (void) close(fd); 121 /*@-mods@*/ 122 errno = rc; 123 /*@=mods@*/ 124 return POPT_ERROR_ERRNO; 125 } 126 if (close(fd) == -1) 127 return POPT_ERROR_ERRNO; 128 129/*@-boundswrite@*/ 130 dst = buf = alloca(fileLength + 1); 131 132 chptr = file; 133 end = (file + fileLength); 134 /*@-infloops@*/ /* LCL: can't detect chptr++ */ 135 while (chptr < end) { 136 switch (*chptr) { 137 case '\n': 138 *dst = '\0'; 139 dst = buf; 140 while (*dst && isspace(*dst)) dst++; 141 if (*dst && *dst != '#') 142 configLine(con, dst); 143 chptr++; 144 /*@switchbreak@*/ break; 145 case '\\': 146 *dst++ = *chptr++; 147 if (chptr < end) { 148 if (*chptr == '\n') 149 dst--, chptr++; 150 /* \ at the end of a line does not insert a \n */ 151 else 152 *dst++ = *chptr++; 153 } 154 /*@switchbreak@*/ break; 155 default: 156 *dst++ = *chptr++; 157 /*@switchbreak@*/ break; 158 } 159 } 160 /*@=infloops@*/ 161/*@=boundswrite@*/ 162 163 return 0; 164} 165 166int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) 167{ 168 char * fn, * home; 169 int rc; 170 171 /*@-type@*/ 172 if (!con->appName) return 0; 173 /*@=type@*/ 174 175 rc = poptReadConfigFile(con, "/etc/popt"); 176 if (rc) return rc; 177#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) 178 if (getuid() != geteuid()) return 0; 179#endif 180 181 if ((home = getenv("HOME"))) { 182 fn = alloca(strlen(home) + 20); 183 strcpy(fn, home); 184 strcat(fn, "/.popt"); 185 rc = poptReadConfigFile(con, fn); 186 if (rc) return rc; 187 } 188 189 return 0; 190} 191