chan.c (chan_open): Actually initialize the error indicator.
[fwd] / fattr.c
CommitLineData
3b7defab 1/* -*-c-*-
2 *
3b7defab 3 * Handling of file attributes
4 *
5 * (c) 1999 Straylight/Edgeware
6 */
7
206212ca 8/*----- Licensing notice --------------------------------------------------*
3b7defab 9 *
9155ea97 10 * This file is part of the `fwd' port forwarder.
3b7defab 11 *
9155ea97 12 * `fwd' is free software; you can redistribute it and/or modify
3b7defab 13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
206212ca 16 *
9155ea97 17 * `fwd' is distributed in the hope that it will be useful,
3b7defab 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
206212ca 21 *
3b7defab 22 * You should have received a copy of the GNU General Public License
9155ea97 23 * along with `fwd'; if not, write to the Free Software Foundation,
3b7defab 24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
9155ea97 27#include "fwd.h"
3b7defab 28
29/*----- Global variables --------------------------------------------------*/
30
31fattr fattr_global;
32
33/*----- Main code ---------------------------------------------------------*/
34
35/* --- @fattr_init@ --- *
36 *
37 * Arguments: @fattr *f@ = pointer to file attributes
38 *
39 * Returns: ---
40 *
41 * Use: Initializes a set of file attributes to default values.
42 */
43
44void fattr_init(fattr *f)
45{
46 unsigned um = umask(0);
47 umask(um);
48 f->mode = 0666 & ~um;
49 f->uid = -1;
50 f->gid = -1;
51}
52
53/* --- @fattr_option@ --- *
54 *
55 * Arguments: @scanner *sc@ = pointer to scanner to read
56 * @fattr *f@ = pointer to file attributes to set
57 *
58 * Returns: Whether the option was claimed.
59 *
60 * Use: Reads file attributes from a scanner.
61 */
62
63int fattr_option(scanner *sc, fattr *f)
64{
65 CONF_BEGIN(sc, "fattr", "file attribute")
66
67 /* --- Read a file mode specification --- */
68
69 if (strcmp(sc->d.buf, "mode") == 0) {
70 unsigned mode = 0;
71
72 /* --- Gobble an optional `=' sign --- */
73
9b699b28 74 conf_undelim(sc, 0, ",=+-");
3b7defab 75 token(sc);
76 if (sc->t == '=')
77 token(sc);
78
79 if (sc->t != CTOK_WORD)
80 error(sc, "parse error, expected file mode");
9b699b28 81 conf_undelim(sc, 0, 0);
3b7defab 82
83 /* --- If it looks digitlike, read as octal --- */
84
85 if (isdigit((unsigned char)*sc->d.buf))
86 mode = strtoul(sc->d.buf, 0, 8) & 07777;
87
88 /* --- Otherise read as chmod-like characters --- */
89
90 else {
91 const char *p;
e73034b0 92 unsigned mask = 04700;
93 unsigned state = 0;
3b7defab 94 unsigned or = 1;
95
96 /* --- Set the default from the umask --- */
97
98 {
99 unsigned um = umask(0);
100 umask(um);
101 mode = 0666 & ~um;
102 }
103
104 /* --- Parse the characters --- *
105 *
106 * This is a particularly lenient implementation of the usual chmod-
107 * style mode language.
108 */
109
110 for (p = sc->d.buf; *p; p++) {
111 switch (*p) {
112 case ',': break;
113
e73034b0 114 case 'a': mask = (mask & state) | 07777; state = 07777; break;
115 case 'u': mask = (mask & state) | 04700; state = 07777; break;
116 case 'g': mask = (mask & state) | 02070; state = 07777; break;
117 case 'o': mask = (mask & state) | 01007; state = 07777; break;
3b7defab 118
e73034b0 119 case '=': mode &= ~mask; /* Drop through */
120 case '+': state = 0; or = 1; break;
121 case '-': state = 0; or = 0; break;
3b7defab 122
123#define APPLY(m) if (or) mode |= ((m) & mask); else mode &= ~((m) & mask);
e73034b0 124 case 'r': state = 0; APPLY(00444); break;
125 case 'w': state = 0; APPLY(00222); break;
126 case 'x': state = 0; APPLY(00111); break;
127 case 's': state = 0; APPLY(06000); break;
128 case 't': state = 0; APPLY(01000); break;
3b7defab 129#undef APPLY
130
131 default: error(sc, "unknown mode character `%c'", *p);
132 }
133 }
134 }
135
136 token(sc);
137 f->mode = mode;
138 CONF_ACCEPT;
139 }
140
141 /* --- Read a file uid specification --- */
142
143 if (strcmp(sc->d.buf, "uid") == 0 ||
144 strcmp(sc->d.buf, "user") == 0 ||
145 strcmp(sc->d.buf, "owner") == 0) {
146 token(sc);
147 if (sc->t == '=')
148 token(sc);
149 if (sc->t != CTOK_WORD)
150 error(sc, "parse error, expected user name or uid");
151 if (isdigit((unsigned char)*sc->d.buf))
152 f->uid = atoi(sc->d.buf);
153 else {
154 struct passwd *pw = getpwnam(sc->d.buf);
155 if (!pw)
156 error(sc, "unknown user name `%s'", sc->d.buf);
157 f->uid = pw->pw_uid;
158 }
159 token(sc);
160 CONF_ACCEPT;
161 }
162
163 /* --- Read a file gid specification --- */
164
165 if (strcmp(sc->d.buf, "gid") == 0 ||
166 strcmp(sc->d.buf, "group") == 0) {
167 token(sc);
168 if (sc->t == '=')
169 token(sc);
170 if (sc->t != CTOK_WORD)
171 error(sc, "parse error, expected group name or gid");
172 if (isdigit((unsigned char)*sc->d.buf))
173 f->gid = atoi(sc->d.buf);
174 else {
175 struct group *gr = getgrnam(sc->d.buf);
176 if (!gr)
177 error(sc, "unknown user name `%s'", sc->d.buf);
178 f->gid = gr->gr_gid;
179 }
180 token(sc);
181 CONF_ACCEPT;
182 }
183
184 /* --- Nothing here for me --- */
185
186 CONF_END;
187}
188
189/* --- @fattr_apply@ --- *
190 *
191 * Arguments: @const char *file@ = pointer to filename
192 * @fattr *f@ = pointer to attribute set
193 *
194 * Returns: @-1@ if it failed.
195 *
196 * Use: Applies file attributes to a file. For best results, try to
197 * create the file with the right permissions and so on. This
198 * call will fix everything up, but there are potential races
199 * which might catch you out if you're not careful.
200 */
201
202int fattr_apply(const char *file, fattr *f)
203{
204 if (chown(file, f->uid, f->gid) == -1 ||
205 chmod(file, f->mode) == -1)
206 return (-1);
207 return (0);
208}
209
210/*----- That's all, folks -------------------------------------------------*/