7a1a4c2bf9b002d826fea2736310f39b7e179919
[rsync/rsync.git] / popt / poptconfig.c
1 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
2    file accompanying popt source distributions, available from 
3    ftp://ftp.redhat.com/pub/code/popt */
4
5 #include "system.h"
6 #include "poptint.h"
7
8 static void configLine(poptContext con, char * line) {
9     int nameLength = strlen(con->appName);
10     char * opt;
11     struct poptAlias alias;
12     char * entryType;
13     char * longName = NULL;
14     char shortName = '\0';
15     
16     if (strncmp(line, con->appName, nameLength)) return;
17     line += nameLength;
18     if (!*line || !isspace(*line)) return;
19     while (*line && isspace(*line)) line++;
20     entryType = line;
21
22     while (!*line || !isspace(*line)) line++;
23     *line++ = '\0';
24     while (*line && isspace(*line)) line++;
25     if (!*line) return;
26     opt = line;
27
28     while (!*line || !isspace(*line)) line++;
29     *line++ = '\0';
30     while (*line && isspace(*line)) line++;
31     if (!*line) return;
32
33     if (opt[0] == '-' && opt[1] == '-')
34         longName = opt + 2;
35     else if (opt[0] == '-' && !opt[2])
36         shortName = opt[1];
37
38     if (!strcmp(entryType, "alias")) {
39         if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
40         alias.longName = longName, alias.shortName = shortName;
41         poptAddAlias(con, alias, 0);
42     } else if (!strcmp(entryType, "exec")) {
43         con->execs = realloc(con->execs,
44                                 sizeof(*con->execs) * (con->numExecs + 1));
45         if (longName)
46             con->execs[con->numExecs].longName = xstrdup(longName);
47         else
48             con->execs[con->numExecs].longName = NULL;
49
50         con->execs[con->numExecs].shortName = shortName;
51         con->execs[con->numExecs].script = xstrdup(line);
52         
53         con->numExecs++;
54     }
55 }
56
57 int poptReadConfigFile(poptContext con, const char * fn) {
58     char * file, * chptr, * end;
59     char * buf, * dst;
60     int fd, rc;
61     int fileLength;
62
63     fd = open(fn, O_RDONLY);
64     if (fd < 0) {
65         if (errno == ENOENT)
66             return 0;
67         else 
68             return POPT_ERROR_ERRNO;
69     }
70
71     fileLength = lseek(fd, 0, SEEK_END);
72     (void) lseek(fd, 0, 0);
73
74     file = alloca(fileLength + 1);
75     if (read(fd, file, fileLength) != fileLength) {
76         rc = errno;
77         close(fd);
78         errno = rc;
79         return POPT_ERROR_ERRNO;
80     }
81     close(fd);
82
83     dst = buf = alloca(fileLength + 1);
84
85     chptr = file;
86     end = (file + fileLength);
87     while (chptr < end) {
88         switch (*chptr) {
89           case '\n':
90             *dst = '\0';
91             dst = buf;
92             while (*dst && isspace(*dst)) dst++;
93             if (*dst && *dst != '#') {
94                 configLine(con, dst);
95             }
96             chptr++;
97             break;
98           case '\\':
99             *dst++ = *chptr++;
100             if (chptr < end) {
101                 if (*chptr == '\n') 
102                     dst--, chptr++;     
103                     /* \ at the end of a line does not insert a \n */
104                 else
105                     *dst++ = *chptr++;
106             }
107             break;
108           default:
109             *dst++ = *chptr++;
110             break;
111         }
112     }
113
114     return 0;
115 }
116
117 int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
118     char * fn, * home;
119     int rc;
120
121     if (!con->appName) return 0;
122
123     rc = poptReadConfigFile(con, "/etc/popt");
124     if (rc) return rc;
125     if (getuid() != geteuid()) return 0;
126
127     if ((home = getenv("HOME"))) {
128         fn = alloca(strlen(home) + 20);
129         strcpy(fn, home);
130         strcat(fn, "/.popt");
131         rc = poptReadConfigFile(con, fn);
132         if (rc) return rc;
133     }
134
135     return 0;
136 }
137