fix silly indirect-through-zero bug
[unix-history] / usr / src / usr.sbin / mtree / spec.c
CommitLineData
cbe4b98c 1/*-
87b199a9
KB
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
cbe4b98c 5 * %sccs.include.redist.c%
87b199a9
KB
6 */
7
8#ifndef lint
4c7f2dd1 9static char sccsid[] = "@(#)spec.c 5.14 (Berkeley) %G%";
87b199a9
KB
10#endif /* not lint */
11
12#include <sys/types.h>
cbe4b98c
KB
13#include <pwd.h>
14#include <grp.h>
87b199a9 15#include <stdio.h>
f06151dd
KB
16#include <errno.h>
17#include <ctype.h>
87b199a9
KB
18#include "mtree.h"
19
6e4c29b1 20extern NODE *root; /* root of the tree */
87b199a9 21
cbe4b98c
KB
22static int lineno; /* current spec line number */
23
87b199a9
KB
24spec()
25{
6e4c29b1 26 register NODE *centry, *last;
87b199a9 27 register char *p;
6e4c29b1 28 NODE ginfo, *emalloc();
f06151dd 29 char buf[2048];
87b199a9 30
6e4c29b1 31 bzero((void *)&ginfo, sizeof(ginfo));
87b199a9
KB
32 for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno) {
33 if (!(p = index(buf, '\n'))) {
34 (void)fprintf(stderr,
7fe47549 35 "mtree: line %d too long.\n", lineno);
f06151dd 36 exit(1);
87b199a9
KB
37 }
38 *p = '\0';
39 for (p = buf; *p && isspace(*p); ++p);
40 if (!*p || *p == '#')
41 continue;
42
43 /* grab file name, "$", "set", or "unset" */
78f31dbc 44 if (!(p = strtok(p, "\n\t ")))
87b199a9
KB
45 specerr();
46
87b199a9
KB
47 if (p[0] == '/')
48 switch(p[1]) {
87b199a9
KB
49 case 's':
50 if (strcmp(p + 1, "set"))
51 break;
f06151dd 52 set(&ginfo);
87b199a9
KB
53 continue;
54 case 'u':
4c7f2dd1 55 if (strcmp(p + 1, "unset"))
87b199a9 56 break;
f06151dd 57 unset(&ginfo);
87b199a9
KB
58 continue;
59 }
60
61 if (index(p, '/')) {
62 (void)fprintf(stderr,
63 "mtree: file names may not contain slashes.\n");
64 specerr();
65 }
66
87b199a9
KB
67 if (!strcmp(p, "..")) {
68 /* don't go up, if haven't gone down */
03f682fb
KB
69 if (!root)
70 noparent();
6e4c29b1 71 if (last->type != F_DIR || last->flags & F_DONE) {
03f682fb
KB
72 if (last == root)
73 noparent();
74 last = last->parent;
87b199a9 75 }
03f682fb
KB
76 last->flags |= F_DONE;
77 continue;
87b199a9
KB
78 }
79
6e4c29b1
KB
80 centry = emalloc(sizeof(NODE) + strlen(p));
81 *centry = ginfo;
7e5e86d9
KB
82 (void)strcpy(centry->name, p);
83#define MAGIC "?*["
84 if (strpbrk(p, MAGIC))
85 centry->flags |= F_MAGIC;
6e4c29b1 86 set(centry);
87b199a9
KB
87
88 if (!root) {
89 last = root = centry;
90 root->parent = root;
6e4c29b1 91 } else if (last->type == F_DIR && !(last->flags & F_DONE)) {
87b199a9
KB
92 centry->parent = last;
93 last = last->child = centry;
94 } else {
95 centry->parent = last->parent;
f06151dd 96 centry->prev = last;
87b199a9
KB
97 last = last->next = centry;
98 }
99 }
100}
03f682fb 101
f06151dd 102set(ip)
6e4c29b1 103 register NODE *ip;
cbe4b98c 104{
6e4c29b1
KB
105 register int type;
106 register char *kw, *val;
cbe4b98c
KB
107 gid_t getgroup();
108 uid_t getowner();
109 long atol(), strtol();
110
78f31dbc 111 while (kw = strtok((char *)NULL, "= \t\n")) {
f06151dd 112 ip->flags |= type = key(kw);
78f31dbc 113 val = strtok((char *)NULL, " \t\n");
f06151dd 114 if (!val)
cbe4b98c 115 specerr();
f06151dd
KB
116 switch(type) {
117 case F_CKSUM:
118 ip->cksum = atol(val);
119 break;
120 case F_GROUP:
121 ip->st_gid = getgroup(val);
122 break;
123 case F_IGN:
124 /* just set flag bit */
125 break;
78f31dbc 126 case F_MODE: {
1978bf80 127 mode_t *m, *setmode();
78f31dbc 128
1978bf80 129 if (!(m = setmode(val))) {
78f31dbc
KB
130 (void)fprintf(stderr,
131 "mtree: invalid file mode %s.\n", val);
132 specerr();
133 }
1978bf80 134 ip->st_mode = getmode(m, 0);
f06151dd 135 break;
78f31dbc 136 }
f06151dd
KB
137 case F_NLINK:
138 ip->st_nlink = atoi(val);
139 break;
140 case F_OWNER:
141 ip->st_uid = getowner(val);
142 break;
143 case F_SIZE:
144 ip->st_size = atol(val);
145 break;
146 case F_SLINK:
147 if (!(ip->slink = strdup(val)))
148 nomem();
149 break;
0af6fb71
KB
150 case F_TIME:
151 ip->st_mtime = atol(val);
152 break;
f06151dd
KB
153 case F_TYPE:
154 switch(*val) {
155 case 'b':
156 if (!strcmp(val, "block"))
157 ip->type = F_BLOCK;
158 break;
159 case 'c':
160 if (!strcmp(val, "char"))
161 ip->type = F_CHAR;
162 break;
163 case 'd':
164 if (!strcmp(val, "dir"))
165 ip->type = F_DIR;
166 break;
167 case 'f':
168 if (!strcmp(val, "file"))
169 ip->type = F_FILE;
c85e0d87
KB
170 if (!strcmp(val, "fifo"))
171 ip->type = F_FIFO;
f06151dd
KB
172 break;
173 case 'l':
174 if (!strcmp(val, "link"))
175 ip->type = F_LINK;
176 break;
177 case 's':
178 if (!strcmp(val, "socket"))
179 ip->type = F_SOCK;
180 break;
181 default:
182 (void)fprintf(stderr,
183 "mtree: unknown file type %s.\n", val);
184 specerr();
185 }
186 break;
cbe4b98c 187 }
cbe4b98c
KB
188 }
189}
190
f06151dd 191unset(ip)
6e4c29b1 192 register NODE *ip;
cbe4b98c 193{
f06151dd
KB
194 register char *p;
195
78f31dbc 196 while (p = strtok((char *)NULL, "\n\t "))
f06151dd 197 ip->flags &= ~key(p);
cbe4b98c
KB
198}
199
cbe4b98c
KB
200key(p)
201 char *p;
202{
203 switch(*p) {
204 case 'c':
205 if (!strcmp(p, "cksum"))
206 return(F_CKSUM);
207 break;
cbe4b98c
KB
208 case 'g':
209 if (!strcmp(p, "group"))
210 return(F_GROUP);
211 break;
f06151dd
KB
212 case 'i':
213 if (!strcmp(p, "ignore"))
214 return(F_IGN);
215 break;
216 case 'l':
217 if (!strcmp(p, "link"))
218 return(F_SLINK);
219 break;
cbe4b98c
KB
220 case 'm':
221 if (!strcmp(p, "mode"))
222 return(F_MODE);
223 break;
224 case 'n':
225 if (!strcmp(p, "nlink"))
226 return(F_NLINK);
227 break;
228 case 'o':
229 if (!strcmp(p, "owner"))
230 return(F_OWNER);
231 break;
232 case 's':
233 if (!strcmp(p, "size"))
234 return(F_SIZE);
cbe4b98c
KB
235 break;
236 case 't':
237 if (!strcmp(p, "type"))
238 return(F_TYPE);
0af6fb71
KB
239 if (!strcmp(p, "time"))
240 return(F_TIME);
cbe4b98c
KB
241 break;
242 }
f06151dd 243 (void)fprintf(stderr, "mtree: unknown keyword %s.\n", p);
cbe4b98c
KB
244 specerr();
245 /* NOTREACHED */
246}
247
cbe4b98c 248
70db696e 249uid_t
cbe4b98c
KB
250getowner(p)
251 register char *p;
252{
253 struct passwd *pw;
254 int val;
255
256 if (isdigit(*p)) {
257 if ((val = atoi(p)) >= 0)
258 return((uid_t)val);
259 (void)fprintf(stderr, "mtree: illegal uid value %s.\n", p);
260 } else if (pw = getpwnam(p))
261 return(pw->pw_uid);
262 else
263 (void)fprintf(stderr, "mtree: unknown user %s.\n", p);
264 specerr();
265 /* NOTREACHED */
266}
267
70db696e 268gid_t
cbe4b98c
KB
269getgroup(p)
270 register char *p;
271{
272 struct group *gr;
273 int val;
274
275 if (isdigit(*p)) {
276 if ((val = atoi(p)) >= 0)
277 return((gid_t)val);
278 (void)fprintf(stderr, "mtree: illegal gid value %s.\n", p);
279 } else if (gr = getgrnam(p))
280 return(gr->gr_gid);
281 else
282 (void)fprintf(stderr, "mtree: unknown group %s.\n", p);
283 specerr();
284 /* NOTREACHED */
285}
286
03f682fb
KB
287noparent()
288{
289 (void)fprintf(stderr, "mtree: no parent node.\n");
290 specerr();
291}
cbe4b98c 292
cbe4b98c
KB
293specerr()
294{
295 (void)fprintf(stderr,
296 "mtree: line %d of the specification is incorrect.\n", lineno);
297 exit(1);
298}
f06151dd 299
70db696e 300NODE *
f06151dd
KB
301emalloc(size)
302 int size;
303{
304 void *p;
305
306 /* NOSTRICT */
307 if (!(p = malloc((u_int)size)))
308 nomem();
309 bzero(p, size);
6e4c29b1 310 return((NODE *)p);
f06151dd
KB
311}
312
f06151dd
KB
313nomem()
314{
315 (void)fprintf(stderr, "mtree: %s.\n", strerror(ENOMEM));
316 exit(1);
317}