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