Added a comment to the do_chmod() to mark it as a discouraged function.
[rsync/rsync.git] / popt / poptconfig.c
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. */
14 static 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 = (poptItem) 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
96 int 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
163 int poptReadDefaultConfig(poptContext con, /*@unused@*/ 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         size_t bufsize = strlen(home) + 20;
175         fn = alloca(bufsize);
176         if (fn == NULL) return 0;
177         snprintf(fn, bufsize, "%s/.popt", home);
178         rc = poptReadConfigFile(con, fn);
179         if (rc) return rc;
180     }
181
182     return 0;
183 }