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