/** \ingroup popt * \file popt/poptconfig.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "poptint.h" /*@access poptContext @*/ /*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ static void configLine(poptContext con, char * line) /*@modifies con @*/ { size_t nameLength; const char * entryType; const char * opt; poptItem item = alloca(sizeof(*item)); int i, j; if (con->appName == NULL) return; nameLength = strlen(con->appName); /*@-boundswrite@*/ memset(item, 0, sizeof(*item)); if (strncmp(line, con->appName, nameLength)) return; line += nameLength; if (*line == '\0' || !isspace(*line)) return; while (*line != '\0' && isspace(*line)) line++; entryType = line; while (*line == '\0' || !isspace(*line)) line++; *line++ = '\0'; while (*line != '\0' && isspace(*line)) line++; if (*line == '\0') return; opt = line; while (*line == '\0' || !isspace(*line)) line++; *line++ = '\0'; while (*line != '\0' && isspace(*line)) line++; if (*line == '\0') return; /*@-temptrans@*/ /* FIX: line alias is saved */ if (opt[0] == '-' && opt[1] == '-') item->option.longName = opt + 2; else if (opt[0] == '-' && opt[2] == '\0') item->option.shortName = opt[1]; /*@=temptrans@*/ if (poptParseArgvString(line, &item->argc, &item->argv)) return; /*@-modobserver@*/ item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; for (i = 0, j = 0; i < item->argc; i++, j++) { const char * f; if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { f = item->argv[i] + sizeof("--POPTdesc="); if (f[0] == '$' && f[1] == '"') f++; item->option.descrip = f; item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; j--; } else if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { f = item->argv[i] + sizeof("--POPTargs="); if (f[0] == '$' && f[1] == '"') f++; item->option.argDescrip = f; item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; item->option.argInfo |= POPT_ARG_STRING; j--; } else if (j != i) item->argv[j] = item->argv[i]; } if (j != i) { item->argv[j] = NULL; item->argc = j; } /*@=modobserver@*/ /*@=boundswrite@*/ /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ if (!strcmp(entryType, "alias")) (void) poptAddItem(con, item, 0); else if (!strcmp(entryType, "exec")) (void) poptAddItem(con, item, 1); /*@=nullstate@*/ } /*@=compmempass@*/ int poptReadConfigFile(poptContext con, const char * fn) { const char * file, * chptr, * end; char * buf; /*@dependent@*/ char * dst; int fd, rc; off_t fileLength; fd = open(fn, O_RDONLY); if (fd < 0) return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); fileLength = lseek(fd, 0, SEEK_END); if (fileLength == -1 || lseek(fd, 0, 0) == -1) { rc = errno; (void) close(fd); errno = rc; return POPT_ERROR_ERRNO; } file = alloca(fileLength + 1); if (read(fd, (char *)file, fileLength) != fileLength) { rc = errno; (void) close(fd); errno = rc; return POPT_ERROR_ERRNO; } if (close(fd) == -1) return POPT_ERROR_ERRNO; /*@-boundswrite@*/ dst = buf = alloca(fileLength + 1); chptr = file; end = (file + fileLength); /*@-infloops@*/ /* LCL: can't detect chptr++ */ while (chptr < end) { switch (*chptr) { case '\n': *dst = '\0'; dst = buf; while (*dst && isspace(*dst)) dst++; if (*dst && *dst != '#') configLine(con, dst); chptr++; /*@switchbreak@*/ break; case '\\': *dst++ = *chptr++; if (chptr < end) { if (*chptr == '\n') dst--, chptr++; /* \ at the end of a line does not insert a \n */ else *dst++ = *chptr++; } /*@switchbreak@*/ break; default: *dst++ = *chptr++; /*@switchbreak@*/ break; } } /*@=infloops@*/ /*@=boundswrite@*/ return 0; } int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { char * fn, * home; int rc; if (con->appName == NULL) return 0; rc = poptReadConfigFile(con, "/etc/popt"); if (rc) return rc; if ((home = getenv("HOME"))) { fn = alloca(strlen(home) + 20); strcpy(fn, home); strcat(fn, "/.popt"); rc = poptReadConfigFile(con, fn); if (rc) return rc; } return 0; }