1 /* $NetBSD: license.c,v 1.2 2011/04/22 08:19:25 adam Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #if HAVE_CONFIG_H 33 #include "config.h" 34 #endif 35 36 #include <nbcompat.h> 37 38 #if HAVE_ERR_H 39 #include <err.h> 40 #endif 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include "lib.h" 45 46 #define HASH_SIZE 521 47 48 const char *default_acceptable_licenses = 49 "public-domain " 50 "gnu-fdl-v1.1 gnu-fdl-v1.2 gnu-fdl-v1.3 " 51 "gnu-gpl-v2 gnu-lgpl-v2 gnu-lgpl-v2.1 " 52 "gnu-gpl-v3 gnu-lgpl-v3 " 53 "original-bsd modified-bsd 2-clause-bsd " 54 "x11 mit miros " 55 "apache-1.1 apache-2.0 " 56 "artistic artistic-2.0 " 57 "cddl-1.0 " 58 "cpl-1.0 " 59 "open-font-license " 60 "mpl-1.0 mpl-1.1 " 61 "png-license " 62 "postgresql-license " 63 "zpl " 64 "python-software-foundation " 65 "ipafont " 66 "isc " 67 "info-zip " 68 "boost-license"; 69 70 #ifdef DEBUG 71 static size_t hash_collisions; 72 #endif 73 74 static char **license_hash[HASH_SIZE]; 75 static const char license_spaces[] = " \t\n"; 76 static const char license_chars[] = 77 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."; 78 79 static size_t 80 hash_license(const char *license, size_t len) 81 { 82 size_t hash; 83 84 for (hash = 0; *license && len; ++license, --len) 85 hash = *license + hash * 32; 86 return hash % HASH_SIZE; 87 } 88 89 static void 90 add_license_internal(const char *license, size_t len) 91 { 92 char *new_license; 93 size_t slot, i; 94 95 slot = hash_license(license, len); 96 97 new_license = malloc(len + 1); 98 memcpy(new_license, license, len); 99 new_license[len] = '\0'; 100 101 if (license_hash[slot] == NULL) { 102 license_hash[slot] = calloc(sizeof(char *), 2); 103 license_hash[slot][0] = new_license; 104 } else { 105 for (i = 0; license_hash[slot][i]; ++i) { 106 if (!memcmp(license_hash[slot][i], license, len) && 107 license_hash[slot][i][len] == '\0') { 108 free(new_license); 109 return; 110 } 111 } 112 113 #ifdef DEBUG 114 ++hash_collisions; 115 #endif 116 117 license_hash[slot] = realloc(license_hash[slot], 118 sizeof(char *) * (i + 2)); 119 license_hash[slot][i] = new_license; 120 license_hash[slot][i + 1] = NULL; 121 } 122 } 123 124 int 125 add_licenses(const char *line) 126 { 127 const char *next; 128 129 if (line == NULL) 130 return 0; 131 132 for (line += strspn(line, license_spaces); line; ) { 133 next = line + strspn(line, license_chars); 134 if (next == line) 135 return *line ? -1 : 0; 136 add_license_internal(line, next - line); 137 line = next + strspn(next, license_spaces); 138 if (next == line) 139 return *line ? -1 : 0; 140 } 141 return 0; 142 } 143 144 static int 145 acceptable_license_internal(const char *license, size_t len) 146 { 147 size_t slot, i; 148 149 slot = hash_license(license, len); 150 151 if (license_hash[slot] == NULL) 152 return 0; 153 154 for (i = 0; license_hash[slot][i]; ++i) { 155 if (strncmp(license_hash[slot][i], license, len) == 0 && 156 license_hash[slot][i][len] == '\0') 157 return 1; 158 } 159 160 return 0; 161 } 162 163 int 164 acceptable_license(const char *license) 165 { 166 size_t len; 167 168 len = strlen(license); 169 if (strspn(license, license_chars) != len) { 170 warnx("Invalid character in license name at position %" PRIzu, len); 171 return -1; 172 } 173 174 return acceptable_license_internal(license, len); 175 } 176 177 static int 178 acceptable_pkg_license_internal(const char **licensep, int toplevel, const char *start) 179 { 180 const char *license = *licensep; 181 int need_parenthesis, is_true = 0; 182 int expr_type = 0; /* 0: unset, 1: or, 2: and */ 183 size_t len; 184 185 license += strspn(license, license_spaces); 186 187 if (*license == '(' && !toplevel) { 188 need_parenthesis = 1; 189 ++license; 190 license += strspn(license, license_spaces); 191 } else { 192 need_parenthesis = 0; 193 } 194 195 for (;;) { 196 if (*license == '(') { 197 switch (acceptable_pkg_license_internal(&license, 0, start)) { 198 case -1: 199 return -1; 200 case 0: 201 if (expr_type == 2) 202 is_true = 0; 203 break; 204 case 1: 205 is_true = 1; 206 break; 207 } 208 license += strspn(license, license_spaces); 209 } else { 210 len = strspn(license, license_chars); 211 if (len == 0) { 212 warnx("Invalid character in license name at position %" PRIzu, license - start + 1); 213 return -1; 214 } 215 216 if (acceptable_license_internal(license, len)) { 217 if (expr_type != 2) 218 is_true = 1; 219 } else if (expr_type == 2) { 220 is_true = 0; 221 } 222 223 license += len; 224 225 len = strspn(license, license_spaces); 226 if (len == 0 && *license && *license != ')') { 227 warnx("Missing space at position %" PRIzu, license - start + 1); 228 return -1; 229 } 230 license += len; 231 } 232 233 if (*license == ')') { 234 if (!need_parenthesis) { 235 warnx("Missing open parenthesis at position %" PRIzu, license - start + 1); 236 return -1; 237 } 238 *licensep = license + 1; 239 return is_true; 240 } 241 if (*license == '\0') { 242 if (need_parenthesis) { 243 warnx("Unbalanced parenthesis at position %" PRIzu, license - start + 1); 244 return -1; 245 } 246 *licensep = license; 247 return is_true; 248 } 249 250 if (strncmp(license, "AND", 3) == 0) { 251 if (expr_type == 1) { 252 warnx("Invalid operator in OR expression at position %" PRIzu, license - start + 1); 253 return -1; 254 } 255 expr_type = 2; 256 license += 3; 257 } else if (strncmp(license, "OR", 2) == 0) { 258 if (expr_type == 2) { 259 warnx("Invalid operator in AND expression at position %" PRIzu, license - start + 1); 260 return -1; 261 } 262 expr_type = 1; 263 license += 2; 264 } else { 265 warnx("Invalid operator at position %" PRIzu, license - start + 1); 266 return -1; 267 } 268 len = strspn(license, license_spaces); 269 if (len == 0 && *license != '(') { 270 warnx("Missing space at position %" PRIzu, license - start + 1); 271 return -1; 272 } 273 license += len; 274 } 275 } 276 277 int 278 acceptable_pkg_license(const char *license) 279 { 280 int ret; 281 282 ret = acceptable_pkg_license_internal(&license, 1, license); 283 if (ret == -1) 284 return -1; 285 license += strspn(license, license_spaces); 286 if (*license) { 287 warnx("Trailing garbage in license specification"); 288 return -1; 289 } 290 return ret; 291 } 292 293 void 294 load_license_lists(void) 295 { 296 if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES"))) 297 errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES"); 298 if (add_licenses(acceptable_licenses)) 299 errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES"); 300 if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES"))) 301 errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES"); 302 if (add_licenses(default_acceptable_licenses)) 303 errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES"); 304 } 305