xref: /original-bsd/usr.sbin/mtree/spec.c (revision 51dd4909)
1 /*-
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)spec.c	5.14 (Berkeley) 03/02/91";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <pwd.h>
14 #include <grp.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <ctype.h>
18 #include "mtree.h"
19 
20 extern NODE *root;			/* root of the tree */
21 
22 static int lineno;			/* current spec line number */
23 
24 spec()
25 {
26 	register NODE *centry, *last;
27 	register char *p;
28 	NODE ginfo, *emalloc();
29 	char buf[2048];
30 
31 	bzero((void *)&ginfo, sizeof(ginfo));
32 	for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno) {
33 		if (!(p = index(buf, '\n'))) {
34 			(void)fprintf(stderr,
35 			    "mtree: line %d too long.\n", lineno);
36 			exit(1);
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" */
44 		if (!(p = strtok(p, "\n\t ")))
45 			specerr();
46 
47 		if (p[0] == '/')
48 			switch(p[1]) {
49 			case 's':
50 				if (strcmp(p + 1, "set"))
51 					break;
52 				set(&ginfo);
53 				continue;
54 			case 'u':
55 				if (strcmp(p + 1, "unset"))
56 					break;
57 				unset(&ginfo);
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 
67 		if (!strcmp(p, "..")) {
68 			/* don't go up, if haven't gone down */
69 			if (!root)
70 				noparent();
71 			if (last->type != F_DIR || last->flags & F_DONE) {
72 				if (last == root)
73 					noparent();
74 				last = last->parent;
75 			}
76 			last->flags |= F_DONE;
77 			continue;
78 		}
79 
80 		centry = emalloc(sizeof(NODE) + strlen(p));
81 		*centry = ginfo;
82 		(void)strcpy(centry->name, p);
83 #define	MAGIC	"?*["
84 		if (strpbrk(p, MAGIC))
85 			centry->flags |= F_MAGIC;
86 		set(centry);
87 
88 		if (!root) {
89 			last = root = centry;
90 			root->parent = root;
91 		} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
92 			centry->parent = last;
93 			last = last->child = centry;
94 		} else {
95 			centry->parent = last->parent;
96 			centry->prev = last;
97 			last = last->next = centry;
98 		}
99 	}
100 }
101 
102 set(ip)
103 	register NODE *ip;
104 {
105 	register int type;
106 	register char *kw, *val;
107 	gid_t getgroup();
108 	uid_t getowner();
109 	long atol(), strtol();
110 
111 	while (kw = strtok((char *)NULL, "= \t\n")) {
112 		ip->flags |= type = key(kw);
113 		val = strtok((char *)NULL, " \t\n");
114 		if (!val)
115 			specerr();
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;
126 		case F_MODE: {
127 			mode_t *m, *setmode();
128 
129 			if (!(m = setmode(val))) {
130 				(void)fprintf(stderr,
131 				    "mtree: invalid file mode %s.\n", val);
132 				specerr();
133 			}
134 			ip->st_mode = getmode(m, 0);
135 			break;
136 		}
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;
150 		case F_TIME:
151 			ip->st_mtime = atol(val);
152 			break;
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;
170 				if (!strcmp(val, "fifo"))
171 					ip->type = F_FIFO;
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;
187 		}
188 	}
189 }
190 
191 unset(ip)
192 	register NODE *ip;
193 {
194 	register char *p;
195 
196 	while (p = strtok((char *)NULL, "\n\t "))
197 		ip->flags &= ~key(p);
198 }
199 
200 key(p)
201 	char *p;
202 {
203 	switch(*p) {
204 	case 'c':
205 		if (!strcmp(p, "cksum"))
206 			return(F_CKSUM);
207 		break;
208 	case 'g':
209 		if (!strcmp(p, "group"))
210 			return(F_GROUP);
211 		break;
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;
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);
235 		break;
236 	case 't':
237 		if (!strcmp(p, "type"))
238 			return(F_TYPE);
239 		if (!strcmp(p, "time"))
240 			return(F_TIME);
241 		break;
242 	}
243 	(void)fprintf(stderr, "mtree: unknown keyword %s.\n", p);
244 	specerr();
245 	/* NOTREACHED */
246 }
247 
248 
249 uid_t
250 getowner(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 
268 gid_t
269 getgroup(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 
287 noparent()
288 {
289 	(void)fprintf(stderr, "mtree: no parent node.\n");
290 	specerr();
291 }
292 
293 specerr()
294 {
295 	(void)fprintf(stderr,
296 	    "mtree: line %d of the specification is incorrect.\n", lineno);
297 	exit(1);
298 }
299 
300 NODE *
301 emalloc(size)
302 	int size;
303 {
304 	void *p;
305 
306 	/* NOSTRICT */
307 	if (!(p = malloc((u_int)size)))
308 		nomem();
309 	bzero(p, size);
310 	return((NODE *)p);
311 }
312 
313 nomem()
314 {
315 	(void)fprintf(stderr, "mtree: %s.\n", strerror(ENOMEM));
316 	exit(1);
317 }
318