xref: /original-bsd/usr.sbin/mtree/spec.c (revision 40cc2ab7)
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 are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)spec.c	5.3 (Berkeley) 05/15/90";
20 #endif /* not lint */
21 
22 #include <sys/types.h>
23 #include <ctype.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "mtree.h"
27 
28 extern ENTRY *root;			/* root of the tree */
29 int lineno;				/* current spec line number */
30 mode_t dmode;
31 mode_t fmode;
32 
33 spec()
34 {
35 	register char *p;
36 	ENTRY *centry, *last;
37 	INFO info;
38 	int ch, ignore;
39 	char buf[2048], *emalloc();
40 
41 	info.flags = 0;
42 	last = NULL;
43 	for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno) {
44 		if (!(p = index(buf, '\n'))) {
45 			(void)fprintf(stderr,
46 			    "mtree: line %d too long.\n", lineno);
47 			while ((ch = getchar()) != '\n' && ch != EOF);
48 			continue;
49 		}
50 		*p = '\0';
51 		for (p = buf; *p && isspace(*p); ++p);
52 		if (!*p || *p == '#')
53 			continue;
54 
55 		/* grab file name, "$", "set", or "unset" */
56 		if (!(p = strtok(buf, "\n\t ")))
57 			specerr();
58 
59 		ignore = 0;
60 		if (p[0] == '/')
61 			switch(p[1]) {
62 			case 'i':
63 				ignore = 1;
64 				if (!(p = strtok((char *)NULL, "\t ")))
65 					specerr();
66 				break;
67 			case 's':
68 				if (strcmp(p + 1, "set"))
69 					break;
70 				if (!(p = strtok((char *)NULL, "\t ")))
71 					specerr();
72 				set(p, &info, 1);
73 				continue;
74 			case 'u':
75 				if (strcmp(p + 1, "unset"))
76 					break;
77 				if (!(p = strtok((char *)NULL, "\t ")))
78 					specerr();
79 				unset(p, &info);
80 				continue;
81 			}
82 
83 		if (index(p, '/')) {
84 			(void)fprintf(stderr,
85 			    "mtree: file names may not contain slashes.\n");
86 			specerr();
87 		}
88 
89 		if (!(info.flags&F_TYPE)) {
90 			(void)fprintf(stderr, "mtree: no type set.\n");
91 			specerr();
92 		}
93 
94 		if (!strcmp(p, "..")) {
95 			/* don't go up, if haven't gone down */
96 			if (!root)
97 				noparent();
98 			if (last->info.type != F_DIR || last->flags&F_DONE) {
99 				if (last == root)
100 					noparent();
101 				last = last->parent;
102 			}
103 			last->flags |= F_DONE;
104 			continue;
105 		}
106 
107 		centry = (ENTRY *)emalloc(sizeof(ENTRY));
108 		if (!(centry->name = strdup(p)))
109 			nomem();
110 		centry->info = info;
111 		centry->info.st_mode = info.type == F_DIR ? dmode : fmode;
112 		centry->flags = ignore;
113 		while (p = strtok((char *)NULL, "\t "))
114 			set(p, &centry->info, 0);
115 
116 		if (!root) {
117 			last = root = centry;
118 			root->parent = root;
119 		} else if (last->info.type == F_DIR && !(last->flags&F_DONE)) {
120 			centry->parent = last;
121 			last = last->child = centry;
122 		} else {
123 			centry->parent = last->parent;
124 			last = last->next = centry;
125 		}
126 	}
127 }
128 
129 noparent()
130 {
131 	(void)fprintf(stderr, "mtree: no parent node.\n");
132 	specerr();
133 }
134