etc/protocols - sync with NetBSD-8
[minix.git] / external / bsd / pkg_install / dist / lib / license.c
blob6af3b1040461eb21fea3776e3eccd0835f129888
1 /* $NetBSD: license.c,v 1.4 2013/04/20 15:29:23 wiz Exp $ */
3 /*-
4 * Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
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.
32 #if HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <nbcompat.h>
38 #if HAVE_ERR_H
39 #include <err.h>
40 #endif
41 #include <stdlib.h>
42 #include <string.h>
44 #include "lib.h"
46 #define HASH_SIZE 521
48 const char *default_acceptable_licenses =
49 "apache-1.1 apache-2.0 "
50 "arphic-public "
51 "artistic artistic-2.0 "
52 "boost-license "
53 "cc-by-sa-v3.0 "
54 "cddl-1.0 "
55 "cpl-1.0 "
56 "epl-v1.0 "
57 "gnu-fdl-v1.1 gnu-fdl-v1.2 gnu-fdl-v1.3 "
58 "gnu-gpl-v1 "
59 "gnu-gpl-v2 gnu-lgpl-v2 gnu-lgpl-v2.1 "
60 "gnu-gpl-v3 gnu-lgpl-v3 "
61 "ibm-public-license-1.0 "
62 "ipafont "
63 "isc "
64 "lppl-1.3c "
65 "lucent "
66 "miros "
67 "mit "
68 "mpl-1.0 mpl-1.1 mpl-2.0 "
69 "mplusfont "
70 "ofl-v1.0 ofl-v1.1 "
71 "original-bsd modified-bsd 2-clause-bsd "
72 "php "
73 "png-license "
74 "postgresql-license "
75 "public-domain "
76 "python-software-foundation "
77 "qpl-v1.0 "
78 "sleepycat-public "
79 "unlicense "
80 "x11 "
81 "zlib "
82 "zpl";
84 #ifdef DEBUG
85 static size_t hash_collisions;
86 #endif
88 static char **license_hash[HASH_SIZE];
89 static const char license_spaces[] = " \t\n";
90 static const char license_chars[] =
91 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.";
93 static size_t
94 hash_license(const char *license, size_t len)
96 size_t hash;
98 for (hash = 0; *license && len; ++license, --len)
99 hash = *license + hash * 32;
100 return hash % HASH_SIZE;
103 static void
104 add_license_internal(const char *license, size_t len)
106 char *new_license;
107 size_t slot, i;
109 slot = hash_license(license, len);
111 new_license = malloc(len + 1);
112 memcpy(new_license, license, len);
113 new_license[len] = '\0';
115 if (license_hash[slot] == NULL) {
116 license_hash[slot] = calloc(sizeof(char *), 2);
117 license_hash[slot][0] = new_license;
118 } else {
119 for (i = 0; license_hash[slot][i]; ++i) {
120 if (!memcmp(license_hash[slot][i], license, len) &&
121 license_hash[slot][i][len] == '\0') {
122 free(new_license);
123 return;
127 #ifdef DEBUG
128 ++hash_collisions;
129 #endif
131 license_hash[slot] = realloc(license_hash[slot],
132 sizeof(char *) * (i + 2));
133 license_hash[slot][i] = new_license;
134 license_hash[slot][i + 1] = NULL;
139 add_licenses(const char *line)
141 const char *next;
143 if (line == NULL)
144 return 0;
146 for (line += strspn(line, license_spaces); line; ) {
147 next = line + strspn(line, license_chars);
148 if (next == line)
149 return *line ? -1 : 0;
150 add_license_internal(line, next - line);
151 line = next + strspn(next, license_spaces);
152 if (next == line)
153 return *line ? -1 : 0;
155 return 0;
158 static int
159 acceptable_license_internal(const char *license, size_t len)
161 size_t slot, i;
163 slot = hash_license(license, len);
165 if (license_hash[slot] == NULL)
166 return 0;
168 for (i = 0; license_hash[slot][i]; ++i) {
169 if (strncmp(license_hash[slot][i], license, len) == 0 &&
170 license_hash[slot][i][len] == '\0')
171 return 1;
174 return 0;
178 acceptable_license(const char *license)
180 size_t len;
182 len = strlen(license);
183 if (strspn(license, license_chars) != len) {
184 warnx("Invalid character in license name at position %" PRIzu, len);
185 return -1;
188 return acceptable_license_internal(license, len);
191 static int
192 acceptable_pkg_license_internal(const char **licensep, int toplevel, const char *start)
194 const char *license = *licensep;
195 int need_parenthesis, is_true = 0;
196 int expr_type = 0; /* 0: unset, 1: or, 2: and */
197 size_t len;
199 license += strspn(license, license_spaces);
201 if (*license == '(' && !toplevel) {
202 need_parenthesis = 1;
203 ++license;
204 license += strspn(license, license_spaces);
205 } else {
206 need_parenthesis = 0;
209 for (;;) {
210 if (*license == '(') {
211 switch (acceptable_pkg_license_internal(&license, 0, start)) {
212 case -1:
213 return -1;
214 case 0:
215 if (expr_type == 2)
216 is_true = 0;
217 break;
218 case 1:
219 is_true = 1;
220 break;
222 license += strspn(license, license_spaces);
223 } else {
224 len = strspn(license, license_chars);
225 if (len == 0) {
226 warnx("Invalid character in license name at position %" PRIzu, license - start + 1);
227 return -1;
230 if (acceptable_license_internal(license, len)) {
231 if (expr_type != 2)
232 is_true = 1;
233 } else if (expr_type == 2) {
234 is_true = 0;
237 license += len;
239 len = strspn(license, license_spaces);
240 if (len == 0 && *license && *license != ')') {
241 warnx("Missing space at position %" PRIzu, license - start + 1);
242 return -1;
244 license += len;
247 if (*license == ')') {
248 if (!need_parenthesis) {
249 warnx("Missing open parenthesis at position %" PRIzu, license - start + 1);
250 return -1;
252 *licensep = license + 1;
253 return is_true;
255 if (*license == '\0') {
256 if (need_parenthesis) {
257 warnx("Unbalanced parenthesis at position %" PRIzu, license - start + 1);
258 return -1;
260 *licensep = license;
261 return is_true;
264 if (strncmp(license, "AND", 3) == 0) {
265 if (expr_type == 1) {
266 warnx("Invalid operator in OR expression at position %" PRIzu, license - start + 1);
267 return -1;
269 expr_type = 2;
270 license += 3;
271 } else if (strncmp(license, "OR", 2) == 0) {
272 if (expr_type == 2) {
273 warnx("Invalid operator in AND expression at position %" PRIzu, license - start + 1);
274 return -1;
276 expr_type = 1;
277 license += 2;
278 } else {
279 warnx("Invalid operator at position %" PRIzu, license - start + 1);
280 return -1;
282 len = strspn(license, license_spaces);
283 if (len == 0 && *license != '(') {
284 warnx("Missing space at position %" PRIzu, license - start + 1);
285 return -1;
287 license += len;
292 acceptable_pkg_license(const char *license)
294 int ret;
296 ret = acceptable_pkg_license_internal(&license, 1, license);
297 if (ret == -1)
298 return -1;
299 license += strspn(license, license_spaces);
300 if (*license) {
301 warnx("Trailing garbage in license specification");
302 return -1;
304 return ret;
307 void
308 load_license_lists(void)
310 if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES")))
311 errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES");
312 if (add_licenses(acceptable_licenses))
313 errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES");
314 if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES")))
315 errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES");
316 if (add_licenses(default_acceptable_licenses))
317 errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES");