Comment out PW_COMPACT, cause binary incompatibilities with *BSD
[unix-history] / usr.sbin / mtree / spec.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
4e97a0eb 35static char sccsid[] = "@(#)spec.c 5.17 (Berkeley) 4/17/92";
15637ed4
RG
36#endif /* not lint */
37
38#include <sys/types.h>
4e97a0eb
NW
39#include <sys/stat.h>
40#include <fts.h>
15637ed4
RG
41#include <pwd.h>
42#include <grp.h>
15637ed4 43#include <errno.h>
4e97a0eb
NW
44#include <unistd.h>
45#include <stdio.h>
15637ed4
RG
46#include <ctype.h>
47#include "mtree.h"
4e97a0eb 48#include "extern.h"
15637ed4 49
4e97a0eb 50int lineno; /* Current spec line number. */
15637ed4 51
4e97a0eb
NW
52static void set __P((char *, NODE *));
53static void unset __P((char *, NODE *));
15637ed4 54
4e97a0eb 55NODE *
15637ed4
RG
56spec()
57{
58 register NODE *centry, *last;
59 register char *p;
4e97a0eb
NW
60 NODE ginfo, *root;
61 int c_cur, c_next;
15637ed4
RG
62 char buf[2048];
63
4e97a0eb
NW
64 root = NULL;
65 bzero(&ginfo, sizeof(ginfo));
66 c_cur = c_next = 0;
67 for (lineno = 1; fgets(buf, sizeof(buf), stdin);
68 ++lineno, c_cur = c_next, c_next = 0) {
69 /* Skip empty lines. */
70 if (buf[0] == '\n')
71 continue;
72
73 /* Find end of line. */
74 if ((p = index(buf, '\n')) == NULL)
75 err("line %d too long", lineno);
76
77 /* See if next line is continuation line. */
78 if (p[-1] == '\\') {
79 --p;
80 c_next = 1;
15637ed4 81 }
4e97a0eb
NW
82
83 /* Null-terminate the line. */
15637ed4 84 *p = '\0';
4e97a0eb
NW
85
86 /* Skip leading whitespace. */
15637ed4 87 for (p = buf; *p && isspace(*p); ++p);
4e97a0eb
NW
88
89 /* If nothing but whitespace or comment char, continue. */
15637ed4
RG
90 if (!*p || *p == '#')
91 continue;
92
4e97a0eb
NW
93#ifdef DEBUG
94 (void)fprintf(stderr, "line %d: {%s}\n", lineno, p);
95#endif
96 if (c_cur) {
97 set(p, centry);
98 continue;
99 }
100
101 /* Grab file name, "$", "set", or "unset". */
102 if ((p = strtok(p, "\n\t ")) == NULL)
103 err("missing field");
15637ed4
RG
104
105 if (p[0] == '/')
106 switch(p[1]) {
107 case 's':
108 if (strcmp(p + 1, "set"))
109 break;
4e97a0eb 110 set(NULL, &ginfo);
15637ed4
RG
111 continue;
112 case 'u':
113 if (strcmp(p + 1, "unset"))
114 break;
4e97a0eb 115 unset(NULL, &ginfo);
15637ed4
RG
116 continue;
117 }
118
4e97a0eb
NW
119 if (index(p, '/'))
120 err("slash character in file name");
15637ed4
RG
121
122 if (!strcmp(p, "..")) {
4e97a0eb 123 /* Don't go up, if haven't gone down. */
15637ed4 124 if (!root)
4e97a0eb 125 goto noparent;
15637ed4
RG
126 if (last->type != F_DIR || last->flags & F_DONE) {
127 if (last == root)
4e97a0eb 128 goto noparent;
15637ed4
RG
129 last = last->parent;
130 }
131 last->flags |= F_DONE;
132 continue;
4e97a0eb
NW
133
134noparent: err("no parent node");
15637ed4
RG
135 }
136
4e97a0eb
NW
137 if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
138 err("%s", strerror(errno));
15637ed4
RG
139 *centry = ginfo;
140 (void)strcpy(centry->name, p);
141#define MAGIC "?*["
142 if (strpbrk(p, MAGIC))
143 centry->flags |= F_MAGIC;
4e97a0eb 144 set(NULL, centry);
15637ed4
RG
145
146 if (!root) {
147 last = root = centry;
148 root->parent = root;
149 } else if (last->type == F_DIR && !(last->flags & F_DONE)) {
150 centry->parent = last;
151 last = last->child = centry;
152 } else {
153 centry->parent = last->parent;
154 centry->prev = last;
155 last = last->next = centry;
156 }
157 }
4e97a0eb 158 return (root);
15637ed4
RG
159}
160
4e97a0eb
NW
161static void
162set(t, ip)
163 char *t;
15637ed4
RG
164 register NODE *ip;
165{
166 register int type;
167 register char *kw, *val;
4e97a0eb
NW
168 struct group *gr;
169 struct passwd *pw;
170 mode_t *m;
171 int value;
172 char *ep;
15637ed4 173
4e97a0eb
NW
174 for (; kw = strtok(t, "= \t\n"); t = NULL) {
175 ip->flags |= type = parsekey(kw, &value);
176 if (value && (val = strtok(NULL, " \t\n")) == NULL)
177 err("missing value");
15637ed4
RG
178 switch(type) {
179 case F_CKSUM:
4e97a0eb
NW
180 ip->cksum = strtoul(val, &ep, 10);
181 if (*ep)
182 err("invalid checksum %s", val);
183 break;
184 case F_GID:
185 ip->st_gid = strtoul(val, &ep, 10);
186 if (*ep)
187 err("invalid gid %s", val);
15637ed4 188 break;
4e97a0eb
NW
189 case F_GNAME:
190 if ((gr = getgrnam(val)) == NULL)
191 err("unknown group %s", val);
192 ip->st_gid = gr->gr_gid;
15637ed4
RG
193 break;
194 case F_IGN:
195 /* just set flag bit */
196 break;
4e97a0eb
NW
197 case F_MODE:
198 if ((m = setmode(val)) == NULL)
199 err("invalid file mode %s", val);
15637ed4
RG
200 ip->st_mode = getmode(m, 0);
201 break;
15637ed4 202 case F_NLINK:
4e97a0eb
NW
203 ip->st_nlink = strtoul(val, &ep, 10);
204 if (*ep)
205 err("invalid link count %s", val);
15637ed4
RG
206 break;
207 case F_SIZE:
4e97a0eb
NW
208 ip->st_size = strtoul(val, &ep, 10);
209 if (*ep)
210 err("invalid size %s", val);
15637ed4
RG
211 break;
212 case F_SLINK:
4e97a0eb
NW
213 if ((ip->slink = strdup(val)) == NULL)
214 err("%s", strerror(errno));
15637ed4
RG
215 break;
216 case F_TIME:
4e97a0eb
NW
217 ip->st_mtime = strtoul(val, &ep, 10);
218 if (*ep)
219 err("invalid time %s", val);
15637ed4
RG
220 break;
221 case F_TYPE:
222 switch(*val) {
223 case 'b':
224 if (!strcmp(val, "block"))
225 ip->type = F_BLOCK;
226 break;
227 case 'c':
228 if (!strcmp(val, "char"))
229 ip->type = F_CHAR;
230 break;
231 case 'd':
232 if (!strcmp(val, "dir"))
233 ip->type = F_DIR;
234 break;
235 case 'f':
236 if (!strcmp(val, "file"))
237 ip->type = F_FILE;
238 if (!strcmp(val, "fifo"))
239 ip->type = F_FIFO;
240 break;
241 case 'l':
242 if (!strcmp(val, "link"))
243 ip->type = F_LINK;
244 break;
245 case 's':
246 if (!strcmp(val, "socket"))
247 ip->type = F_SOCK;
248 break;
249 default:
4e97a0eb 250 err("unknown file type %s", val);
15637ed4
RG
251 }
252 break;
4e97a0eb
NW
253 case F_UID:
254 ip->st_uid = strtoul(val, &ep, 10);
255 if (*ep)
256 err("invalid uid %s", val);
257 break;
258 case F_UNAME:
259 if ((pw = getpwnam(val)) == NULL)
260 err("unknown user %s", val);
261 ip->st_uid = pw->pw_uid;
262 break;
15637ed4
RG
263 }
264 }
265}
266
4e97a0eb
NW
267static void
268unset(t, ip)
269 char *t;
15637ed4
RG
270 register NODE *ip;
271{
272 register char *p;
273
4e97a0eb
NW
274 while (p = strtok(t, "\n\t "))
275 ip->flags &= ~parsekey(p, NULL);
15637ed4 276}