xref: /openbsd-src/usr.bin/cvs/modules.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: modules.c,v 1.13 2008/03/08 21:58:34 tobias Exp $	*/
2 /*
3  * Copyright (c) 2008 Joris Vink <joris@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/dirent.h>
20 #include <sys/resource.h>
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "cvs.h"
27 #include "config.h"
28 
29 TAILQ_HEAD(, module_info)	modules;
30 
31 struct module_checkout *current_module = NULL;
32 char *module_repo_root = NULL;
33 
34 void
35 cvs_parse_modules(void)
36 {
37 	cvs_log(LP_TRACE, "cvs_parse_modules()");
38 
39 	TAILQ_INIT(&modules);
40 	cvs_read_config(CVS_PATH_MODULES, modules_parse_line);
41 }
42 
43 void
44 cvs_modules_list(void)
45 {
46 	struct module_info *mi;
47 
48 	TAILQ_FOREACH(mi, &modules, m_list)
49 		printf("%s\n", mi->mi_str);
50 }
51 
52 int
53 modules_parse_line(char *line, int lineno)
54 {
55 	int flags;
56 	struct module_info *mi;
57 	char *bline, *val, *p, *module, *sp, *dp;
58 	char *dirname, fpath[MAXPATHLEN], *prog;
59 
60 	prog = NULL;
61 	bline = xstrdup(line);
62 
63 	flags = 0;
64 	p = val = line;
65 	while (!isspace(*p) && *p != '\0')
66 		p++;
67 
68 	if (*p == '\0')
69 		goto bad;
70 
71 	*(p++) = '\0';
72 	module = val;
73 
74 	while (isspace(*p))
75 		p++;
76 
77 	if (*p == '\0')
78 		goto bad;
79 
80 	val = p;
81 	while (!isspace(*p) && *p != '\0')
82 		p++;
83 
84 	while (val[0] == '-') {
85 		p = val;
86 		while (!isspace(*p) && *p != '\0')
87 			p++;
88 
89 		if (*p == '\0')
90 			goto bad;
91 
92 		*(p++) = '\0';
93 
94 		switch (val[1]) {
95 		case 'a':
96 			if (flags & MODULE_TARGETDIR) {
97 				cvs_log(LP_NOTICE, "cannot use -a with -d");
98 				goto bad;
99 			}
100 			flags |= MODULE_ALIAS;
101 			break;
102 		case 'd':
103 			if (flags & MODULE_ALIAS) {
104 				cvs_log(LP_NOTICE, "cannot use -d with -a");
105 				goto bad;
106 			}
107 			flags |= MODULE_TARGETDIR;
108 			break;
109 		case 'l':
110 			flags |= MODULE_NORECURSE;
111 			break;
112 		case 'o':
113 			if (flags != 0 || prog != NULL) {
114 				cvs_log(LP_NOTICE,
115 				    "-o cannot be used with other flags");
116 				goto bad;
117 			}
118 
119 			val = p;
120 			while (!isspace(*val) && *val != '\0')
121 				val++;
122 			if (*val == '\0')
123 				goto bad;
124 
125 			*(val++) = '\0';
126 			prog = xstrdup(p);
127 			p = val;
128 			flags |= MODULE_RUN_ON_CHECKOUT;
129 			break;
130 		case 'i':
131 			if (flags != 0 || prog != NULL) {
132 				cvs_log(LP_NOTICE,
133 				    "-i cannot be used with other flags");
134 				goto bad;
135 			}
136 
137 			if ((val = strchr(p, ' ' )) == NULL)
138 				goto bad;
139 
140 			*(val++) = '\0';
141 			prog = xstrdup(p);
142 			p = val;
143 			flags |= MODULE_RUN_ON_COMMIT;
144 			break;
145 		default:
146 			goto bad;
147 		}
148 
149 		val = p;
150 	}
151 
152 	if (*val == '\0')
153 		goto bad;
154 
155 	mi = xmalloc(sizeof(*mi));
156 	mi->mi_name = xstrdup(module);
157 	mi->mi_flags = flags;
158 	mi->mi_prog = prog;
159 	mi->mi_str = bline;
160 
161 	dirname = NULL;
162 	TAILQ_INIT(&(mi->mi_modules));
163 	TAILQ_INIT(&(mi->mi_ignores));
164 	for (sp = val; *sp != '\0'; sp = dp) {
165 		dp = sp;
166 		while (!isspace(*dp) && *dp != '\0')
167 			dp++;
168 		if (*dp != '\0')
169 			*(dp++) = '\0';
170 
171 		if (mi->mi_flags & MODULE_ALIAS) {
172 			if (sp[0] == '!') {
173 				if (strlen(sp) < 2)
174 					fatal("invalid ! pattern");
175 				cvs_file_get((sp + 1), 0, &(mi->mi_ignores));
176 			} else {
177 				cvs_file_get(sp, 0, &(mi->mi_modules));
178 			}
179 		} else if (sp == val) {
180 			dirname = sp;
181 		} else {
182 			if (sp[0] == '!') {
183 				if (strlen(sp) < 2)
184 					fatal("invalid ! pattern");
185 
186 				sp++;
187 				(void)xsnprintf(fpath, sizeof(fpath), "%s/%s",
188 				    dirname, sp);
189 				cvs_file_get(fpath, 0, &(mi->mi_ignores));
190 			} else {
191 				(void)xsnprintf(fpath, sizeof(fpath), "%s/%s",
192 				    dirname, sp);
193 				cvs_file_get(fpath, 0, &(mi->mi_modules));
194 			}
195 		}
196 	}
197 
198 	if (!(mi->mi_flags & MODULE_ALIAS) && TAILQ_EMPTY(&(mi->mi_modules)))
199 		cvs_file_get(dirname, 0, &(mi->mi_modules));
200 
201 	TAILQ_INSERT_TAIL(&modules, mi, m_list);
202 	return (0);
203 
204 bad:
205 	if (prog != NULL)
206 		xfree(prog);
207 	xfree(bline);
208 	cvs_log(LP_NOTICE, "malformed line in CVSROOT/modules: %d", lineno);
209 	return (0);
210 }
211 
212 struct module_checkout *
213 cvs_module_lookup(char *name)
214 {
215 	struct module_checkout *mc;
216 	struct module_info *mi;
217 
218 	mc = xmalloc(sizeof(*mc));
219 
220 	TAILQ_FOREACH(mi, &modules, m_list) {
221 		if (!strcmp(name, mi->mi_name)) {
222 			mc->mc_modules = mi->mi_modules;
223 			mc->mc_ignores = mi->mi_ignores;
224 			mc->mc_canfree = 0;
225 			mc->mc_name = mi->mi_name;
226 			mc->mc_flags = mi->mi_flags;
227 			mc->mc_prog = mi->mi_prog;
228 			return (mc);
229 		}
230 	}
231 
232 	TAILQ_INIT(&(mc->mc_modules));
233 	TAILQ_INIT(&(mc->mc_ignores));
234 	cvs_file_get(name, 0, &(mc->mc_modules));
235 	mc->mc_canfree = 1;
236 	mc->mc_name = name;
237 	mc->mc_flags = MODULE_ALIAS;
238 	mc->mc_prog = NULL;
239 
240 	return (mc);
241 }
242