poptconfig.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /** \ingroup popt
  2. * \file popt/poptconfig.c
  3. */
  4. /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
  5. file accompanying popt source distributions, available from
  6. ftp://ftp.rpm.org/pub/rpm/dist. */
  7. #include "system.h"
  8. #include "poptint.h"
  9. /*@access poptContext @*/
  10. /*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
  11. static void configLine(poptContext con, char * line)
  12. /*@modifies con @*/
  13. {
  14. size_t nameLength;
  15. const char * entryType;
  16. const char * opt;
  17. poptItem item = (poptItem) alloca(sizeof(*item));
  18. int i, j;
  19. if (con->appName == NULL)
  20. return;
  21. nameLength = strlen(con->appName);
  22. /*@-boundswrite@*/
  23. memset(item, 0, sizeof(*item));
  24. if (strncmp(line, con->appName, nameLength)) return;
  25. line += nameLength;
  26. if (*line == '\0' || !isSpace(line)) return;
  27. while (*line != '\0' && isSpace(line)) line++;
  28. entryType = line;
  29. while (*line == '\0' || !isSpace(line)) line++;
  30. *line++ = '\0';
  31. while (*line != '\0' && isSpace(line)) line++;
  32. if (*line == '\0') return;
  33. opt = line;
  34. while (*line == '\0' || !isSpace(line)) line++;
  35. *line++ = '\0';
  36. while (*line != '\0' && isSpace(line)) line++;
  37. if (*line == '\0') return;
  38. /*@-temptrans@*/ /* FIX: line alias is saved */
  39. if (opt[0] == '-' && opt[1] == '-')
  40. item->option.longName = opt + 2;
  41. else if (opt[0] == '-' && opt[2] == '\0')
  42. item->option.shortName = opt[1];
  43. /*@=temptrans@*/
  44. if (poptParseArgvString(line, &item->argc, &item->argv)) return;
  45. /*@-modobserver@*/
  46. item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
  47. for (i = 0, j = 0; i < item->argc; i++, j++) {
  48. const char * f;
  49. if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
  50. f = item->argv[i] + sizeof("--POPTdesc=");
  51. if (f[0] == '$' && f[1] == '"') f++;
  52. item->option.descrip = f;
  53. item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
  54. j--;
  55. } else
  56. if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
  57. f = item->argv[i] + sizeof("--POPTargs=");
  58. if (f[0] == '$' && f[1] == '"') f++;
  59. item->option.argDescrip = f;
  60. item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
  61. item->option.argInfo |= POPT_ARG_STRING;
  62. j--;
  63. } else
  64. if (j != i)
  65. item->argv[j] = item->argv[i];
  66. }
  67. if (j != i) {
  68. item->argv[j] = NULL;
  69. item->argc = j;
  70. }
  71. /*@=modobserver@*/
  72. /*@=boundswrite@*/
  73. /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
  74. if (!strcmp(entryType, "alias"))
  75. (void) poptAddItem(con, item, 0);
  76. else if (!strcmp(entryType, "exec"))
  77. (void) poptAddItem(con, item, 1);
  78. /*@=nullstate@*/
  79. }
  80. /*@=compmempass@*/
  81. int poptReadConfigFile(poptContext con, const char * fn)
  82. {
  83. const char * file, * chptr, * end;
  84. char * buf;
  85. /*@dependent@*/ char * dst;
  86. int fd, rc;
  87. off_t fileLength;
  88. fd = open(fn, O_RDONLY);
  89. if (fd < 0)
  90. return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO);
  91. fileLength = lseek(fd, 0, SEEK_END);
  92. if (fileLength == -1 || lseek(fd, 0, 0) == -1) {
  93. rc = errno;
  94. (void) close(fd);
  95. errno = rc;
  96. return POPT_ERROR_ERRNO;
  97. }
  98. file = alloca(fileLength + 1);
  99. if (read(fd, (char *)file, fileLength) != fileLength) {
  100. rc = errno;
  101. (void) close(fd);
  102. errno = rc;
  103. return POPT_ERROR_ERRNO;
  104. }
  105. if (close(fd) == -1)
  106. return POPT_ERROR_ERRNO;
  107. /*@-boundswrite@*/
  108. dst = buf = alloca(fileLength + 1);
  109. chptr = file;
  110. end = (file + fileLength);
  111. /*@-infloops@*/ /* LCL: can't detect chptr++ */
  112. while (chptr < end) {
  113. switch (*chptr) {
  114. case '\n':
  115. *dst = '\0';
  116. dst = buf;
  117. while (*dst && isSpace(dst)) dst++;
  118. if (*dst && *dst != '#')
  119. configLine(con, dst);
  120. chptr++;
  121. /*@switchbreak@*/ break;
  122. case '\\':
  123. *dst++ = *chptr++;
  124. if (chptr < end) {
  125. if (*chptr == '\n')
  126. dst--, chptr++;
  127. /* \ at the end of a line does not insert a \n */
  128. else
  129. *dst++ = *chptr++;
  130. }
  131. /*@switchbreak@*/ break;
  132. default:
  133. *dst++ = *chptr++;
  134. /*@switchbreak@*/ break;
  135. }
  136. }
  137. /*@=infloops@*/
  138. /*@=boundswrite@*/
  139. return 0;
  140. }
  141. int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
  142. {
  143. char * fn, * home;
  144. int rc;
  145. if (con->appName == NULL) return 0;
  146. rc = poptReadConfigFile(con, "/etc/popt");
  147. if (rc) return rc;
  148. if ((home = getenv("HOME"))) {
  149. size_t bufsize = strlen(home) + 20;
  150. fn = alloca(bufsize);
  151. if (fn == NULL) return 0;
  152. snprintf(fn, bufsize, "%s/.popt", home);
  153. rc = poptReadConfigFile(con, fn);
  154. if (rc) return rc;
  155. }
  156. return 0;
  157. }