1*2f9c47fbSgutteridge /* $NetBSD: pmatch.c,v 1.9 2024/10/09 23:16:03 gutteridge Exp $ */ 216a9632eSchristos 316a9632eSchristos /*- 416a9632eSchristos * Copyright (c) 1980, 1991 The Regents of the University of California. 516a9632eSchristos * All rights reserved. 616a9632eSchristos * 716a9632eSchristos * Redistribution and use in source and binary forms, with or without 816a9632eSchristos * modification, are permitted provided that the following conditions 916a9632eSchristos * are met: 1016a9632eSchristos * 1. Redistributions of source code must retain the above copyright 1116a9632eSchristos * notice, this list of conditions and the following disclaimer. 1216a9632eSchristos * 2. Redistributions in binary form must reproduce the above copyright 1316a9632eSchristos * notice, this list of conditions and the following disclaimer in the 1416a9632eSchristos * documentation and/or other materials provided with the distribution. 15aad01611Sagc * 3. Neither the name of the University nor the names of its contributors 1616a9632eSchristos * may be used to endorse or promote products derived from this software 1716a9632eSchristos * without specific prior written permission. 1816a9632eSchristos * 1916a9632eSchristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2016a9632eSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2116a9632eSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2216a9632eSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2316a9632eSchristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2416a9632eSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2516a9632eSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2616a9632eSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2716a9632eSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2816a9632eSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2916a9632eSchristos * SUCH DAMAGE. 3016a9632eSchristos */ 3116a9632eSchristos 3216a9632eSchristos #include <sys/param.h> 332be6059bSthorpej 342be6059bSthorpej /* So we can build this in userland for the tests in strlist.c */ 352be6059bSthorpej #if defined(_KERNEL) || defined(_STANDALONE) 3616a9632eSchristos #include <lib/libkern/libkern.h> 372be6059bSthorpej #else 382be6059bSthorpej int pmatch(const char *, const char *, const char **); 392be6059bSthorpej #endif 402be6059bSthorpej 4116a9632eSchristos /* 4216a9632eSchristos * pmatch(): 4316a9632eSchristos * Return 2 on exact match. 4416a9632eSchristos * Return 1 on substring match. 4516a9632eSchristos * Return 0 on no match. 4616a9632eSchristos * Return -1 on error. 4716a9632eSchristos * *estr will point to the end of the longest exact or substring match. 4816a9632eSchristos */ 4916a9632eSchristos int 5082357f6dSdsl pmatch(const char *string, const char *pattern, const char **estr) 5116a9632eSchristos { 5216a9632eSchristos u_char stringc, patternc, rangec; 5316a9632eSchristos int match, negate_range; 54fe82005eSchristos const char *oestr, *pestr, *testr = NULL; 5516a9632eSchristos 5616a9632eSchristos if (estr == NULL) 5716a9632eSchristos estr = &testr; 5816a9632eSchristos 5916a9632eSchristos for (;; ++string) { 6016a9632eSchristos stringc = *string; 6116a9632eSchristos switch (patternc = *pattern++) { 6216a9632eSchristos case 0: 6316a9632eSchristos *estr = string; 6416a9632eSchristos return stringc == '\0' ? 2 : 1; 6516a9632eSchristos case '?': 6616a9632eSchristos if (stringc == '\0') 6716a9632eSchristos return 0; 6816a9632eSchristos *estr = string; 6916a9632eSchristos break; 7016a9632eSchristos case '*': 7116a9632eSchristos if (!*pattern) { 7216a9632eSchristos while (*string) 7316a9632eSchristos string++; 7416a9632eSchristos *estr = string; 7516a9632eSchristos return 2; 7616a9632eSchristos } 7716a9632eSchristos oestr = *estr; 7816a9632eSchristos pestr = NULL; 7916a9632eSchristos 8016a9632eSchristos do { 8116a9632eSchristos switch (pmatch(string, pattern, estr)) { 8216a9632eSchristos case -1: 8316a9632eSchristos return -1; 8416a9632eSchristos case 0: 8516a9632eSchristos break; 8616a9632eSchristos case 1: 8716a9632eSchristos pestr = *estr; 8816a9632eSchristos break; 8916a9632eSchristos case 2: 9016a9632eSchristos return 2; 9116a9632eSchristos default: 9216a9632eSchristos return -1; 9316a9632eSchristos } 9416a9632eSchristos *estr = string; 9516a9632eSchristos } 9616a9632eSchristos while (*string++); 9716a9632eSchristos 9816a9632eSchristos if (pestr) { 9916a9632eSchristos *estr = pestr; 10016a9632eSchristos return 1; 10116a9632eSchristos } else { 10216a9632eSchristos *estr = oestr; 10316a9632eSchristos return 0; 10416a9632eSchristos } 10516a9632eSchristos 10616a9632eSchristos case '[': 10716a9632eSchristos match = 0; 10816a9632eSchristos if ((negate_range = (*pattern == '^')) != 0) 10916a9632eSchristos pattern++; 11016a9632eSchristos while ((rangec = *pattern++) != '\0') { 11116a9632eSchristos if (rangec == ']') 11216a9632eSchristos break; 11316a9632eSchristos if (match) 11416a9632eSchristos continue; 11516a9632eSchristos if (rangec == '-' && *(pattern - 2) != '[' && 11616a9632eSchristos *pattern != ']') { 11716a9632eSchristos match = 11816a9632eSchristos stringc <= (u_char)*pattern && 11916a9632eSchristos (u_char)*(pattern - 2) <= stringc; 12016a9632eSchristos pattern++; 12116a9632eSchristos } else 12216a9632eSchristos match = (stringc == rangec); 12316a9632eSchristos } 12416a9632eSchristos if (rangec == 0) 12516a9632eSchristos return -1; 12616a9632eSchristos if (match == negate_range) 12716a9632eSchristos return 0; 12816a9632eSchristos *estr = string; 12916a9632eSchristos break; 13016a9632eSchristos default: 13116a9632eSchristos if (patternc != stringc) 13216a9632eSchristos return 0; 13316a9632eSchristos *estr = string; 13416a9632eSchristos break; 13516a9632eSchristos } 13616a9632eSchristos } 13716a9632eSchristos } 138