1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 7*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate */ 10*7c478bd9Sstevel@tonic-gate 11*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 12*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: match.c,v 1.8 2001/03/02 19:57:08 ca Exp $") 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #include <sm/string.h> 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate /* 17*7c478bd9Sstevel@tonic-gate ** SM_MATCH -- Match a character string against a glob pattern. 18*7c478bd9Sstevel@tonic-gate ** 19*7c478bd9Sstevel@tonic-gate ** Parameters: 20*7c478bd9Sstevel@tonic-gate ** str -- string. 21*7c478bd9Sstevel@tonic-gate ** par -- pattern to find in str. 22*7c478bd9Sstevel@tonic-gate ** 23*7c478bd9Sstevel@tonic-gate ** Returns: 24*7c478bd9Sstevel@tonic-gate ** true on match, false on non-match. 25*7c478bd9Sstevel@tonic-gate ** 26*7c478bd9Sstevel@tonic-gate ** A pattern consists of normal characters, which match themselves, 27*7c478bd9Sstevel@tonic-gate ** and meta-sequences. A * matches any sequence of characters. 28*7c478bd9Sstevel@tonic-gate ** A ? matches any single character. A [ introduces a character class. 29*7c478bd9Sstevel@tonic-gate ** A ] marks the end of a character class; if the ] is missing then 30*7c478bd9Sstevel@tonic-gate ** the [ matches itself rather than introducing a character class. 31*7c478bd9Sstevel@tonic-gate ** A character class matches any of the characters between the brackets. 32*7c478bd9Sstevel@tonic-gate ** The range of characters from X to Y inclusive is written X-Y. 33*7c478bd9Sstevel@tonic-gate ** If the first character after the [ is ! then the character class is 34*7c478bd9Sstevel@tonic-gate ** complemented. 35*7c478bd9Sstevel@tonic-gate ** 36*7c478bd9Sstevel@tonic-gate ** To include a ] in a character class, make it the first character 37*7c478bd9Sstevel@tonic-gate ** listed (after the !, if any). To include a -, make it the first 38*7c478bd9Sstevel@tonic-gate ** character listed (after the !, if any) or the last character. 39*7c478bd9Sstevel@tonic-gate ** It is impossible for a ] to be the final character in a range. 40*7c478bd9Sstevel@tonic-gate ** For glob patterns that literally match "*", "?" or "[", 41*7c478bd9Sstevel@tonic-gate ** use [*], [?] or [[]. 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate bool 45*7c478bd9Sstevel@tonic-gate sm_match(str, pat) 46*7c478bd9Sstevel@tonic-gate const char *str; 47*7c478bd9Sstevel@tonic-gate const char *pat; 48*7c478bd9Sstevel@tonic-gate { 49*7c478bd9Sstevel@tonic-gate bool ccnot, ccmatch, ccfirst; 50*7c478bd9Sstevel@tonic-gate const char *ccstart; 51*7c478bd9Sstevel@tonic-gate char c, c2; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate for (;;) 54*7c478bd9Sstevel@tonic-gate { 55*7c478bd9Sstevel@tonic-gate switch (*pat) 56*7c478bd9Sstevel@tonic-gate { 57*7c478bd9Sstevel@tonic-gate case '\0': 58*7c478bd9Sstevel@tonic-gate return *str == '\0'; 59*7c478bd9Sstevel@tonic-gate case '?': 60*7c478bd9Sstevel@tonic-gate if (*str == '\0') 61*7c478bd9Sstevel@tonic-gate return false; 62*7c478bd9Sstevel@tonic-gate ++pat; 63*7c478bd9Sstevel@tonic-gate ++str; 64*7c478bd9Sstevel@tonic-gate continue; 65*7c478bd9Sstevel@tonic-gate case '*': 66*7c478bd9Sstevel@tonic-gate ++pat; 67*7c478bd9Sstevel@tonic-gate if (*pat == '\0') 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate /* optimize case of trailing '*' */ 70*7c478bd9Sstevel@tonic-gate return true; 71*7c478bd9Sstevel@tonic-gate } 72*7c478bd9Sstevel@tonic-gate for (;;) 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate if (sm_match(pat, str)) 75*7c478bd9Sstevel@tonic-gate return true; 76*7c478bd9Sstevel@tonic-gate if (*str == '\0') 77*7c478bd9Sstevel@tonic-gate return false; 78*7c478bd9Sstevel@tonic-gate ++str; 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 81*7c478bd9Sstevel@tonic-gate case '[': 82*7c478bd9Sstevel@tonic-gate ccstart = pat++; 83*7c478bd9Sstevel@tonic-gate ccnot = false; 84*7c478bd9Sstevel@tonic-gate if (*pat == '!') 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate ccnot = true; 87*7c478bd9Sstevel@tonic-gate ++pat; 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate ccmatch = false; 90*7c478bd9Sstevel@tonic-gate ccfirst = true; 91*7c478bd9Sstevel@tonic-gate for (;;) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate if (*pat == '\0') 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate pat = ccstart; 96*7c478bd9Sstevel@tonic-gate goto defl; 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate if (*pat == ']' && !ccfirst) 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate c = *pat++; 101*7c478bd9Sstevel@tonic-gate ccfirst = false; 102*7c478bd9Sstevel@tonic-gate if (*pat == '-' && pat[1] != ']') 103*7c478bd9Sstevel@tonic-gate { 104*7c478bd9Sstevel@tonic-gate ++pat; 105*7c478bd9Sstevel@tonic-gate if (*pat == '\0') 106*7c478bd9Sstevel@tonic-gate { 107*7c478bd9Sstevel@tonic-gate pat = ccstart; 108*7c478bd9Sstevel@tonic-gate goto defl; 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate c2 = *pat++; 111*7c478bd9Sstevel@tonic-gate if (*str >= c && *str <= c2) 112*7c478bd9Sstevel@tonic-gate ccmatch = true; 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate else 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate if (*str == c) 117*7c478bd9Sstevel@tonic-gate ccmatch = true; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate if (ccmatch ^ ccnot) 121*7c478bd9Sstevel@tonic-gate { 122*7c478bd9Sstevel@tonic-gate ++pat; 123*7c478bd9Sstevel@tonic-gate ++str; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate else 126*7c478bd9Sstevel@tonic-gate return false; 127*7c478bd9Sstevel@tonic-gate continue; 128*7c478bd9Sstevel@tonic-gate default: 129*7c478bd9Sstevel@tonic-gate defl: 130*7c478bd9Sstevel@tonic-gate if (*pat != *str) 131*7c478bd9Sstevel@tonic-gate return false; 132*7c478bd9Sstevel@tonic-gate ++pat; 133*7c478bd9Sstevel@tonic-gate ++str; 134*7c478bd9Sstevel@tonic-gate continue; 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate } 138