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