Import pkg_install-20090425:
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / lib / license.c
blob1516a85a1da198e20e6afb7efe5645c2b8c9fd63
1 /* $NetBSD: license.c,v 1.1 2009/04/25 21:31:14 joerg 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 "public-domain "
50 "gnu-gpl-v2 "
51 "gnu-lgpl-v2 gnu-lgpl-v2.1 "
52 "gnu-gpl-v3 gnu-lgpl-v3 "
53 "original-bsd modified-bsd x11 "
54 "apache-2.0 "
55 "artistic artistic-2.0 "
56 "cddl-1.0 "
57 "open-font-license ";
59 #ifdef DEBUG
60 static size_t hash_collisions;
61 #endif
63 static char **license_hash[HASH_SIZE];
64 static const char license_spaces[] = " \t\n";
65 static const char license_chars[] = "abcdefghijklmnopqrstuvwxyz0123456789_-.";
67 static size_t
68 hash_license(const char *license, size_t len)
70 size_t hash;
72 for (hash = 0; *license && len; ++license, --len)
73 hash = *license + hash * 32;
74 return hash % HASH_SIZE;
77 static void
78 add_license_internal(const char *license, size_t len)
80 char *new_license;
81 size_t slot, i;
83 slot = hash_license(license, len);
85 new_license = malloc(len + 1);
86 memcpy(new_license, license, len);
87 new_license[len] = '\0';
89 if (license_hash[slot] == NULL) {
90 license_hash[slot] = calloc(sizeof(char *), 2);
91 license_hash[slot][0] = new_license;
92 } else {
93 for (i = 0; license_hash[slot][i]; ++i) {
94 if (!memcmp(license_hash[slot][i], license, len) &&
95 license_hash[slot][i][len] == '\0') {
96 free(new_license);
97 return;
101 #ifdef DEBUG
102 ++hash_collisions;
103 #endif
105 license_hash[slot] = realloc(license_hash[slot],
106 sizeof(char *) * (i + 2));
107 license_hash[slot][i] = new_license;
108 license_hash[slot][i + 1] = NULL;
113 add_licenses(const char *line)
115 const char *next;
117 if (line == NULL)
118 return 0;
120 for (line += strspn(line, license_spaces); line; ) {
121 next = line + strspn(line, license_chars);
122 if (next == line)
123 return *line ? -1 : 0;
124 add_license_internal(line, next - line);
125 line = next + strspn(next, license_spaces);
126 if (next == line)
127 return *line ? -1 : 0;
129 return 0;
132 static int
133 acceptable_license_internal(const char *license, size_t len)
135 size_t slot, i;
137 slot = hash_license(license, len);
139 if (license_hash[slot] == NULL)
140 return 0;
142 for (i = 0; license_hash[slot][i]; ++i) {
143 if (strncmp(license_hash[slot][i], license, len) == 0 &&
144 license_hash[slot][i][len] == '\0')
145 return 1;
148 return 0;
152 acceptable_license(const char *license)
154 size_t len;
156 len = strlen(license);
157 if (strspn(license, license_chars) != len)
158 return -1;
160 return acceptable_license_internal(license, len);
163 static int
164 acceptable_pkg_license_internal(const char **licensep, int toplevel)
166 const char *license = *licensep;
167 int need_parenthesis, is_true = 0;
168 int expr_type = 0; /* 0: unset, 1: or, 2: and */
169 size_t len;
171 license += strspn(license, license_spaces);
173 if (*license == '(' && !toplevel) {
174 need_parenthesis = 1;
175 ++license;
176 license += strspn(license, license_spaces);
177 } else {
178 need_parenthesis = 0;
181 for (;;) {
182 if (*license == '(') {
183 switch (acceptable_pkg_license_internal(&license, 0)) {
184 case -1:
185 return -1;
186 case 0:
187 if (expr_type == 2)
188 is_true = 0;
189 break;
190 case 1:
191 is_true = 1;
192 break;
194 license += strspn(license, license_spaces);
195 } else {
196 len = strspn(license, license_chars);
197 if (len == 0)
198 return -1;
200 if (acceptable_license_internal(license, len)) {
201 if (expr_type != 2)
202 is_true = 1;
203 } else if (expr_type == 2) {
204 is_true = 0;
207 license += len;
209 len = strspn(license, license_spaces);
210 if (len == 0 && *license && *license != ')')
211 return -1;
212 license += len;
215 if (*license == ')') {
216 if (!need_parenthesis)
217 return -1;
218 *licensep = license + 1;
219 return is_true;
221 if (*license == '\0') {
222 if (need_parenthesis)
223 return -1;
224 *licensep = license;
225 return is_true;
228 if (strncmp(license, "AND", 3) == 0) {
229 if (expr_type == 1)
230 return -1;
231 expr_type = 2;
232 license += 3;
233 } else if (strncmp(license, "OR", 2) == 0) {
234 if (expr_type == 2)
235 return -1;
236 expr_type = 1;
237 license += 2;
238 } else {
239 return -1;
241 len = strspn(license, license_spaces);
242 if (len == 0 && *license != '(')
243 return -1;
244 license += len;
247 return is_true;
251 acceptable_pkg_license(const char *license)
253 int ret;
255 ret = acceptable_pkg_license_internal(&license, 1);
256 if (ret == -1)
257 return -1;
258 license += strspn(license, license_spaces);
259 if (*license)
260 return -1;
261 return ret;
264 void
265 load_license_lists(void)
267 if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES")))
268 errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES");
269 if (add_licenses(acceptable_licenses))
270 errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES");
271 if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES")))
272 errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES");
273 if (add_licenses(default_acceptable_licenses))
274 errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES");