1 /* $OpenBSD: modules.c,v 1.19 2015/11/05 09:48:21 nicm 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/types.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 cvs_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[PATH_MAX], *prog; 59 60 prog = NULL; 61 bline = xstrdup(line); 62 63 flags = 0; 64 p = val = line; 65 while (!isspace((unsigned char)*p) && *p != '\0') 66 p++; 67 68 if (*p == '\0') 69 goto bad; 70 71 *(p++) = '\0'; 72 module = val; 73 74 while (isspace((unsigned char)*p)) 75 p++; 76 77 if (*p == '\0') 78 goto bad; 79 80 val = p; 81 while (!isspace((unsigned char)*p) && *p != '\0') 82 p++; 83 84 while (val[0] == '-') { 85 p = val; 86 while (!isspace((unsigned char)*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((unsigned char)*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 RB_INIT(&(mi->mi_modules)); 163 RB_INIT(&(mi->mi_ignores)); 164 165 for (sp = val; *sp != '\0'; sp = dp) { 166 dp = sp; 167 while (!isspace((unsigned char)*dp) && *dp != '\0') 168 dp++; 169 if (*dp != '\0') 170 *(dp++) = '\0'; 171 172 if (mi->mi_flags & MODULE_ALIAS) { 173 if (sp[0] == '!') { 174 if (strlen(sp) < 2) 175 fatal("invalid ! pattern"); 176 cvs_file_get((sp + 1), 0, 177 &(mi->mi_ignores), 0); 178 } else { 179 cvs_file_get(sp, 0, 180 &(mi->mi_modules), 0); 181 } 182 } else if (sp == val) { 183 dirname = sp; 184 } else { 185 if (sp[0] == '!') { 186 if (strlen(sp) < 2) 187 fatal("invalid ! pattern"); 188 189 sp++; 190 (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", 191 dirname, sp); 192 cvs_file_get(fpath, 0, 193 &(mi->mi_ignores), 0); 194 } else { 195 (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", 196 dirname, sp); 197 cvs_file_get(fpath, 0, 198 &(mi->mi_modules), 0); 199 } 200 } 201 } 202 203 if (!(mi->mi_flags & MODULE_ALIAS) && RB_EMPTY(&(mi->mi_modules))) 204 cvs_file_get(dirname, 0, &(mi->mi_modules), 0); 205 206 TAILQ_INSERT_TAIL(&modules, mi, m_list); 207 return (0); 208 209 bad: 210 free(prog); 211 free(bline); 212 cvs_log(LP_NOTICE, "malformed line in CVSROOT/modules: %d", lineno); 213 return (0); 214 } 215 216 struct module_checkout * 217 cvs_module_lookup(char *name) 218 { 219 struct module_checkout *mc; 220 struct module_info *mi; 221 222 mc = xmalloc(sizeof(*mc)); 223 224 TAILQ_FOREACH(mi, &modules, m_list) { 225 if (!strcmp(name, mi->mi_name)) { 226 mc->mc_modules = mi->mi_modules; 227 mc->mc_ignores = mi->mi_ignores; 228 mc->mc_canfree = 0; 229 mc->mc_name = mi->mi_name; 230 mc->mc_flags = mi->mi_flags; 231 mc->mc_prog = mi->mi_prog; 232 return (mc); 233 } 234 } 235 236 RB_INIT(&(mc->mc_modules)); 237 RB_INIT(&(mc->mc_ignores)); 238 cvs_file_get(name, 0, &(mc->mc_modules), 0); 239 mc->mc_canfree = 1; 240 mc->mc_name = name; 241 mc->mc_flags = MODULE_ALIAS; 242 mc->mc_prog = NULL; 243 244 return (mc); 245 } 246