Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / lib / license.c
blob31ff6056b4431027174c6acf4e9d67645bdf0894
1 /* $NetBSD: license.c,v 1.10 2009/10/25 21:32:48 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 "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 "zpl";
63 #ifdef DEBUG
64 static size_t hash_collisions;
65 #endif
67 static char **license_hash[HASH_SIZE];
68 static const char license_spaces[] = " \t\n";
69 static const char license_chars[] =
70 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.";
72 static size_t
73 hash_license(const char *license, size_t len)
75 size_t hash;
77 for (hash = 0; *license && len; ++license, --len)
78 hash = *license + hash * 32;
79 return hash % HASH_SIZE;
82 static void
83 add_license_internal(const char *license, size_t len)
85 char *new_license;
86 size_t slot, i;
88 slot = hash_license(license, len);
90 new_license = malloc(len + 1);
91 memcpy(new_license, license, len);
92 new_license[len] = '\0';
94 if (license_hash[slot] == NULL) {
95 license_hash[slot] = calloc(sizeof(char *), 2);
96 license_hash[slot][0] = new_license;
97 } else {
98 for (i = 0; license_hash[slot][i]; ++i) {
99 if (!memcmp(license_hash[slot][i], license, len) &&
100 license_hash[slot][i][len] == '\0') {
101 free(new_license);
102 return;
106 #ifdef DEBUG
107 ++hash_collisions;
108 #endif
110 license_hash[slot] = realloc(license_hash[slot],
111 sizeof(char *) * (i + 2));
112 license_hash[slot][i] = new_license;
113 license_hash[slot][i + 1] = NULL;
118 add_licenses(const char *line)
120 const char *next;
122 if (line == NULL)
123 return 0;
125 for (line += strspn(line, license_spaces); line; ) {
126 next = line + strspn(line, license_chars);
127 if (next == line)
128 return *line ? -1 : 0;
129 add_license_internal(line, next - line);
130 line = next + strspn(next, license_spaces);
131 if (next == line)
132 return *line ? -1 : 0;
134 return 0;
137 static int
138 acceptable_license_internal(const char *license, size_t len)
140 size_t slot, i;
142 slot = hash_license(license, len);
144 if (license_hash[slot] == NULL)
145 return 0;
147 for (i = 0; license_hash[slot][i]; ++i) {
148 if (strncmp(license_hash[slot][i], license, len) == 0 &&
149 license_hash[slot][i][len] == '\0')
150 return 1;
153 return 0;
157 acceptable_license(const char *license)
159 size_t len;
161 len = strlen(license);
162 if (strspn(license, license_chars) != len) {
163 warnx("Invalid character in license name at position %zu", len);
164 return -1;
167 return acceptable_license_internal(license, len);
170 static int
171 acceptable_pkg_license_internal(const char **licensep, int toplevel, const char *start)
173 const char *license = *licensep;
174 int need_parenthesis, is_true = 0;
175 int expr_type = 0; /* 0: unset, 1: or, 2: and */
176 size_t len;
178 license += strspn(license, license_spaces);
180 if (*license == '(' && !toplevel) {
181 need_parenthesis = 1;
182 ++license;
183 license += strspn(license, license_spaces);
184 } else {
185 need_parenthesis = 0;
188 for (;;) {
189 if (*license == '(') {
190 switch (acceptable_pkg_license_internal(&license, 0, start)) {
191 case -1:
192 return -1;
193 case 0:
194 if (expr_type == 2)
195 is_true = 0;
196 break;
197 case 1:
198 is_true = 1;
199 break;
201 license += strspn(license, license_spaces);
202 } else {
203 len = strspn(license, license_chars);
204 if (len == 0) {
205 warnx("Invalid character in license name at position %zu", license - start + 1);
206 return -1;
209 if (acceptable_license_internal(license, len)) {
210 if (expr_type != 2)
211 is_true = 1;
212 } else if (expr_type == 2) {
213 is_true = 0;
216 license += len;
218 len = strspn(license, license_spaces);
219 if (len == 0 && *license && *license != ')') {
220 warnx("Missing space at position %zu", license - start + 1);
221 return -1;
223 license += len;
226 if (*license == ')') {
227 if (!need_parenthesis) {
228 warnx("Missing open parenthesis at position %zu", license - start + 1);
229 return -1;
231 *licensep = license + 1;
232 return is_true;
234 if (*license == '\0') {
235 if (need_parenthesis) {
236 warnx("Unbalanced parenthesis at position %zu", license - start + 1);
237 return -1;
239 *licensep = license;
240 return is_true;
243 if (strncmp(license, "AND", 3) == 0) {
244 if (expr_type == 1) {
245 warnx("Invalid operator in OR expression at position %zu", license - start + 1);
246 return -1;
248 expr_type = 2;
249 license += 3;
250 } else if (strncmp(license, "OR", 2) == 0) {
251 if (expr_type == 2) {
252 warnx("Invalid operator in AND expression at position %zu", license - start + 1);
253 return -1;
255 expr_type = 1;
256 license += 2;
257 } else {
258 warnx("Invalid operator at position %zu", license - start + 1);
259 return -1;
261 len = strspn(license, license_spaces);
262 if (len == 0 && *license != '(') {
263 warnx("Missing space at position %zu", license - start + 1);
264 return -1;
266 license += len;
271 acceptable_pkg_license(const char *license)
273 int ret;
275 ret = acceptable_pkg_license_internal(&license, 1, license);
276 if (ret == -1)
277 return -1;
278 license += strspn(license, license_spaces);
279 if (*license) {
280 warnx("Trailing garbage in license specification");
281 return -1;
283 return ret;
286 void
287 load_license_lists(void)
289 if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES")))
290 errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES");
291 if (add_licenses(acceptable_licenses))
292 errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES");
293 if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES")))
294 errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES");
295 if (add_licenses(default_acceptable_licenses))
296 errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES");