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