1/** \ingroup popt 2 * \file popt/poptconfig.c 3 */ 4 5/* (C) 1998-2000 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, unsigned 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 = (poptItem) alloca(sizeof(*item)); 22 int i, j; 23 24 memset(item, 0, sizeof(*item)); 25 26 /*@-type@*/ 27 if (strncmp(line, con->appName, nameLength)) return; 28 /*@=type@*/ 29 30 line += nameLength; 31 if (*line == '\0' || !isspace(*line)) return; 32 33 while (*line != '\0' && isspace(*line)) line++; 34 entryType = line; 35 while (*line == '\0' || !isspace(*line)) line++; 36 *line++ = '\0'; 37 38 while (*line != '\0' && isspace(*line)) line++; 39 if (*line == '\0') return; 40 opt = line; 41 while (*line == '\0' || !isspace(*line)) line++; 42 *line++ = '\0'; 43 44 while (*line != '\0' && isspace(*line)) line++; 45 if (*line == '\0') return; 46 47 /*@-temptrans@*/ /* FIX: line alias is saved */ 48 if (opt[0] == '-' && opt[1] == '-') 49 item->option.longName = opt + 2; 50 else if (opt[0] == '-' && opt[2] == '\0') 51 item->option.shortName = opt[1]; 52 /*@=temptrans@*/ 53 54 if (poptParseArgvString(line, &item->argc, &item->argv)) return; 55 56 /*@-modobserver@*/ 57 item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; 58 for (i = 0, j = 0; i < item->argc; i++, j++) { 59 const char * f; 60 if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { 61 f = item->argv[i] + sizeof("--POPTdesc="); 62 if (f[0] == '$' && f[1] == '"') f++; 63 item->option.descrip = f; 64 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 65 j--; 66 } else 67 if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { 68 f = item->argv[i] + sizeof("--POPTargs="); 69 if (f[0] == '$' && f[1] == '"') f++; 70 item->option.argDescrip = f; 71 item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; 72 item->option.argInfo |= POPT_ARG_STRING; 73 j--; 74 } else 75 if (j != i) 76 item->argv[j] = item->argv[i]; 77 } 78 if (j != i) { 79 item->argv[j] = NULL; 80 item->argc = j; 81 } 82 /*@=modobserver@*/ 83 84 /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ 85 if (!strcmp(entryType, "alias")) 86 (void) poptAddItem(con, item, 0); 87 else if (!strcmp(entryType, "exec")) 88 (void) poptAddItem(con, item, 1); 89 /*@=nullstate@*/ 90} 91/*@=compmempass@*/ 92 93int poptReadConfigFile(poptContext con, const char * fn) 94{ 95 const unsigned char * file, * chptr, * end; 96 unsigned char * buf; 97/*@dependent@*/ unsigned char * dst; 98 int fd, rc; 99 off_t fileLength; 100 101 fd = open(fn, O_RDONLY); 102 if (fd < 0) 103 return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); 104 105 fileLength = lseek(fd, 0, SEEK_END); 106 if (fileLength == -1 || lseek(fd, 0, 0) == -1) { 107 rc = errno; 108 (void) close(fd); 109 /*@-mods@*/ 110 errno = rc; 111 /*@=mods@*/ 112 return POPT_ERROR_ERRNO; 113 } 114 115 file = alloca(fileLength + 1); 116 if (read(fd, (char *)file, fileLength) != fileLength) { 117 rc = errno; 118 (void) close(fd); 119 /*@-mods@*/ 120 errno = rc; 121 /*@=mods@*/ 122 return POPT_ERROR_ERRNO; 123 } 124 if (close(fd) == -1) 125 return POPT_ERROR_ERRNO; 126 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 159 return 0; 160} 161 162int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv)) 163{ 164 char * fn, * home; 165 int rc; 166 167 /*@-type@*/ 168 if (!con->appName) return 0; 169 /*@=type@*/ 170 171 rc = poptReadConfigFile(con, "/etc/popt"); 172 if (rc) return rc; 173 if (getuid() != geteuid()) return 0; 174 175 if ((home = getenv("HOME"))) { 176 fn = alloca(strlen(home) + 20); 177 strcpy(fn, home); 178 strcat(fn, "/.popt"); 179 rc = poptReadConfigFile(con, fn); 180 if (rc) return rc; 181 } 182 183 return 0; 184} 185