xref: /openbsd-src/usr.bin/cvs/modules.c (revision 397ddb8a3f80a7c0fc96b9834bf9a6841845ed3c)
1*397ddb8aSnicm /*	$OpenBSD: modules.c,v 1.19 2015/11/05 09:48:21 nicm Exp $	*/
275bebbccSjoris /*
375bebbccSjoris  * Copyright (c) 2008 Joris Vink <joris@openbsd.org>
475bebbccSjoris  *
575bebbccSjoris  * Permission to use, copy, modify, and distribute this software for any
675bebbccSjoris  * purpose with or without fee is hereby granted, provided that the above
775bebbccSjoris  * copyright notice and this permission notice appear in all copies.
875bebbccSjoris  *
975bebbccSjoris  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1075bebbccSjoris  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1175bebbccSjoris  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1275bebbccSjoris  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1375bebbccSjoris  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1475bebbccSjoris  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1575bebbccSjoris  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1675bebbccSjoris  */
1775bebbccSjoris 
18b9fc9a72Sderaadt #include <sys/types.h>
1975bebbccSjoris #include <sys/dirent.h>
2075bebbccSjoris #include <sys/resource.h>
2175bebbccSjoris 
22e24106fdStobias #include <ctype.h>
2375bebbccSjoris #include <stdlib.h>
2475bebbccSjoris #include <string.h>
2575bebbccSjoris 
2675bebbccSjoris #include "cvs.h"
2775bebbccSjoris #include "config.h"
2875bebbccSjoris 
2975bebbccSjoris TAILQ_HEAD(, module_info)	modules;
3075bebbccSjoris 
31bf6291b7Sjoris struct module_checkout *current_module = NULL;
32bf6291b7Sjoris char *module_repo_root = NULL;
33bf6291b7Sjoris 
3475bebbccSjoris void
cvs_parse_modules(void)3575bebbccSjoris cvs_parse_modules(void)
3675bebbccSjoris {
3775bebbccSjoris 	cvs_log(LP_TRACE, "cvs_parse_modules()");
3875bebbccSjoris 
3975bebbccSjoris 	TAILQ_INIT(&modules);
4075bebbccSjoris 	cvs_read_config(CVS_PATH_MODULES, modules_parse_line);
4175bebbccSjoris }
4275bebbccSjoris 
4375bebbccSjoris void
cvs_modules_list(void)44dee76bdfSjoris cvs_modules_list(void)
45dee76bdfSjoris {
46dee76bdfSjoris 	struct module_info *mi;
47dee76bdfSjoris 
48dee76bdfSjoris 	TAILQ_FOREACH(mi, &modules, m_list)
49c9cdde6aSjoris 		cvs_printf("%s\n", mi->mi_str);
50dee76bdfSjoris }
51dee76bdfSjoris 
528868bb21Sjoris int
modules_parse_line(char * line,int lineno)53ba6315b4Sjoris modules_parse_line(char *line, int lineno)
5475bebbccSjoris {
5575bebbccSjoris 	int flags;
5675bebbccSjoris 	struct module_info *mi;
57dee76bdfSjoris 	char *bline, *val, *p, *module, *sp, *dp;
58b9fc9a72Sderaadt 	char *dirname, fpath[PATH_MAX], *prog;
5975bebbccSjoris 
600486e6bfSjoris 	prog = NULL;
61dee76bdfSjoris 	bline = xstrdup(line);
62dee76bdfSjoris 
6375bebbccSjoris 	flags = 0;
6475bebbccSjoris 	p = val = line;
65f6ac027fSokan 	while (!isspace((unsigned char)*p) && *p != '\0')
6675bebbccSjoris 		p++;
6775bebbccSjoris 
68ba6315b4Sjoris 	if (*p == '\0')
69ba6315b4Sjoris 		goto bad;
70ba6315b4Sjoris 
7175bebbccSjoris 	*(p++) = '\0';
7275bebbccSjoris 	module = val;
7375bebbccSjoris 
74f6ac027fSokan 	while (isspace((unsigned char)*p))
7575bebbccSjoris 		p++;
7675bebbccSjoris 
77ba6315b4Sjoris 	if (*p == '\0')
78ba6315b4Sjoris 		goto bad;
7975bebbccSjoris 
8075bebbccSjoris 	val = p;
81f6ac027fSokan 	while (!isspace((unsigned char)*p) && *p != '\0')
8275bebbccSjoris 		p++;
8375bebbccSjoris 
8475bebbccSjoris 	while (val[0] == '-') {
8575bebbccSjoris 		p = val;
86f6ac027fSokan 		while (!isspace((unsigned char)*p) && *p != '\0')
8775bebbccSjoris 			p++;
8875bebbccSjoris 
89ba6315b4Sjoris 		if (*p == '\0')
90ba6315b4Sjoris 			goto bad;
9175bebbccSjoris 
9275bebbccSjoris 		*(p++) = '\0';
9375bebbccSjoris 
9475bebbccSjoris 		switch (val[1]) {
9575bebbccSjoris 		case 'a':
96bf6291b7Sjoris 			if (flags & MODULE_TARGETDIR) {
97bf6291b7Sjoris 				cvs_log(LP_NOTICE, "cannot use -a with -d");
980486e6bfSjoris 				goto bad;
99bf6291b7Sjoris 			}
100bf6291b7Sjoris 			flags |= MODULE_ALIAS;
101bf6291b7Sjoris 			break;
102bf6291b7Sjoris 		case 'd':
103bf6291b7Sjoris 			if (flags & MODULE_ALIAS) {
104bf6291b7Sjoris 				cvs_log(LP_NOTICE, "cannot use -d with -a");
1050486e6bfSjoris 				goto bad;
106bf6291b7Sjoris 			}
107bf6291b7Sjoris 			flags |= MODULE_TARGETDIR;
108bf6291b7Sjoris 			break;
109bf6291b7Sjoris 		case 'l':
110bf6291b7Sjoris 			flags |= MODULE_NORECURSE;
11175bebbccSjoris 			break;
112ea48eba6Sjoris 		case 'o':
113ea48eba6Sjoris 			if (flags != 0 || prog != NULL) {
114ea48eba6Sjoris 				cvs_log(LP_NOTICE,
115ea48eba6Sjoris 				    "-o cannot be used with other flags");
1160486e6bfSjoris 				goto bad;
117ea48eba6Sjoris 			}
118ea48eba6Sjoris 
119e24106fdStobias 			val = p;
120f6ac027fSokan 			while (!isspace((unsigned char)*val) && *val != '\0')
121e24106fdStobias 				val++;
122e24106fdStobias 			if (*val == '\0')
123ea48eba6Sjoris 				goto bad;
124ea48eba6Sjoris 
125ea48eba6Sjoris 			*(val++) = '\0';
126ea48eba6Sjoris 			prog = xstrdup(p);
127ea48eba6Sjoris 			p = val;
128ea48eba6Sjoris 			flags |= MODULE_RUN_ON_CHECKOUT;
129ea48eba6Sjoris 			break;
1307fca5395Sjoris 		case 'i':
131ba6315b4Sjoris 			if (flags != 0 || prog != NULL) {
1327fca5395Sjoris 				cvs_log(LP_NOTICE,
1337fca5395Sjoris 				    "-i cannot be used with other flags");
1340486e6bfSjoris 				goto bad;
1357fca5395Sjoris 			}
136ba6315b4Sjoris 
137ba6315b4Sjoris 			if ((val = strchr(p, ' ' )) == NULL)
138ba6315b4Sjoris 				goto bad;
139ba6315b4Sjoris 
140ba6315b4Sjoris 			*(val++) = '\0';
141ba6315b4Sjoris 			prog = xstrdup(p);
142ba6315b4Sjoris 			p = val;
1437fca5395Sjoris 			flags |= MODULE_RUN_ON_COMMIT;
1447fca5395Sjoris 			break;
145dee76bdfSjoris 		default:
146dee76bdfSjoris 			goto bad;
14775bebbccSjoris 		}
14875bebbccSjoris 
14975bebbccSjoris 		val = p;
15075bebbccSjoris 	}
15175bebbccSjoris 
152ba6315b4Sjoris 	if (*val == '\0')
153ba6315b4Sjoris 		goto bad;
1547fca5395Sjoris 
15575bebbccSjoris 	mi = xmalloc(sizeof(*mi));
15675bebbccSjoris 	mi->mi_name = xstrdup(module);
157bf6291b7Sjoris 	mi->mi_flags = flags;
158ba6315b4Sjoris 	mi->mi_prog = prog;
159dee76bdfSjoris 	mi->mi_str = bline;
1607fca5395Sjoris 
1617fca5395Sjoris 	dirname = NULL;
162f106b389Sjoris 	RB_INIT(&(mi->mi_modules));
163f106b389Sjoris 	RB_INIT(&(mi->mi_ignores));
164f106b389Sjoris 
165e24106fdStobias 	for (sp = val; *sp != '\0'; sp = dp) {
166e24106fdStobias 		dp = sp;
167f6ac027fSokan 		while (!isspace((unsigned char)*dp) && *dp != '\0')
168e24106fdStobias 			dp++;
169e24106fdStobias 		if (*dp != '\0')
1707fca5395Sjoris 			*(dp++) = '\0';
1717fca5395Sjoris 
1727fca5395Sjoris 		if (mi->mi_flags & MODULE_ALIAS) {
173cc6e7cceSjoris 			if (sp[0] == '!') {
174cc6e7cceSjoris 				if (strlen(sp) < 2)
175cc6e7cceSjoris 					fatal("invalid ! pattern");
1764cb553bbSjoris 				cvs_file_get((sp + 1), 0,
1774cb553bbSjoris 				    &(mi->mi_ignores), 0);
178cc6e7cceSjoris 			} else {
1794cb553bbSjoris 				cvs_file_get(sp, 0,
1804cb553bbSjoris 				    &(mi->mi_modules), 0);
181cc6e7cceSjoris 			}
1827fca5395Sjoris 		} else if (sp == val) {
1837fca5395Sjoris 			dirname = sp;
1847fca5395Sjoris 		} else {
1857fca5395Sjoris 			if (sp[0] == '!') {
186cc6e7cceSjoris 				if (strlen(sp) < 2)
187cc6e7cceSjoris 					fatal("invalid ! pattern");
188cc6e7cceSjoris 
1897fca5395Sjoris 				sp++;
1907fca5395Sjoris 				(void)xsnprintf(fpath, sizeof(fpath), "%s/%s",
1917fca5395Sjoris 				    dirname, sp);
1924cb553bbSjoris 				cvs_file_get(fpath, 0,
1934cb553bbSjoris 				    &(mi->mi_ignores), 0);
1947fca5395Sjoris 			} else {
1957fca5395Sjoris 				(void)xsnprintf(fpath, sizeof(fpath), "%s/%s",
1967fca5395Sjoris 				    dirname, sp);
1974cb553bbSjoris 				cvs_file_get(fpath, 0,
1984cb553bbSjoris 				    &(mi->mi_modules), 0);
1997fca5395Sjoris 			}
2007fca5395Sjoris 		}
2017fca5395Sjoris 	}
2027fca5395Sjoris 
203f106b389Sjoris 	if (!(mi->mi_flags & MODULE_ALIAS) && RB_EMPTY(&(mi->mi_modules)))
2044cb553bbSjoris 		cvs_file_get(dirname, 0, &(mi->mi_modules), 0);
2057fca5395Sjoris 
20675bebbccSjoris 	TAILQ_INSERT_TAIL(&modules, mi, m_list);
2078868bb21Sjoris 	return (0);
208ba6315b4Sjoris 
209ba6315b4Sjoris bad:
210*397ddb8aSnicm 	free(prog);
211*397ddb8aSnicm 	free(bline);
212ba6315b4Sjoris 	cvs_log(LP_NOTICE, "malformed line in CVSROOT/modules: %d", lineno);
2138868bb21Sjoris 	return (0);
21475bebbccSjoris }
21575bebbccSjoris 
216bf6291b7Sjoris struct module_checkout *
cvs_module_lookup(char * name)21775bebbccSjoris cvs_module_lookup(char *name)
21875bebbccSjoris {
219bf6291b7Sjoris 	struct module_checkout *mc;
22075bebbccSjoris 	struct module_info *mi;
22175bebbccSjoris 
222bf6291b7Sjoris 	mc = xmalloc(sizeof(*mc));
223bf6291b7Sjoris 
22475bebbccSjoris 	TAILQ_FOREACH(mi, &modules, m_list) {
225bf6291b7Sjoris 		if (!strcmp(name, mi->mi_name)) {
2267fca5395Sjoris 			mc->mc_modules = mi->mi_modules;
2277fca5395Sjoris 			mc->mc_ignores = mi->mi_ignores;
2287fca5395Sjoris 			mc->mc_canfree = 0;
229ba6315b4Sjoris 			mc->mc_name = mi->mi_name;
230bf6291b7Sjoris 			mc->mc_flags = mi->mi_flags;
231ba6315b4Sjoris 			mc->mc_prog = mi->mi_prog;
232bf6291b7Sjoris 			return (mc);
233bf6291b7Sjoris 		}
23475bebbccSjoris 	}
23575bebbccSjoris 
236f106b389Sjoris 	RB_INIT(&(mc->mc_modules));
237f106b389Sjoris 	RB_INIT(&(mc->mc_ignores));
2384cb553bbSjoris 	cvs_file_get(name, 0, &(mc->mc_modules), 0);
2397fca5395Sjoris 	mc->mc_canfree = 1;
240ba6315b4Sjoris 	mc->mc_name = name;
24151ed3220Stobias 	mc->mc_flags = MODULE_ALIAS;
242ba6315b4Sjoris 	mc->mc_prog = NULL;
243bf6291b7Sjoris 
244bf6291b7Sjoris 	return (mc);
24575bebbccSjoris }
246