140266059SGregory Neil Shapiro /* 25dd76dd0SGregory Neil Shapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers. 340266059SGregory Neil Shapiro * All rights reserved. 440266059SGregory Neil Shapiro * 540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 740266059SGregory Neil Shapiro * the sendmail distribution. 840266059SGregory Neil Shapiro * 940266059SGregory Neil Shapiro */ 1040266059SGregory Neil Shapiro 1140266059SGregory Neil Shapiro #include <sm/gen.h> 12*4313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: match.c,v 1.11 2013-11-22 20:51:43 ca Exp $") 1340266059SGregory Neil Shapiro 1440266059SGregory Neil Shapiro #include <sm/string.h> 1540266059SGregory Neil Shapiro 1640266059SGregory Neil Shapiro /* 1740266059SGregory Neil Shapiro ** SM_MATCH -- Match a character string against a glob pattern. 1840266059SGregory Neil Shapiro ** 1940266059SGregory Neil Shapiro ** Parameters: 2040266059SGregory Neil Shapiro ** str -- string. 2140266059SGregory Neil Shapiro ** par -- pattern to find in str. 2240266059SGregory Neil Shapiro ** 2340266059SGregory Neil Shapiro ** Returns: 2440266059SGregory Neil Shapiro ** true on match, false on non-match. 2540266059SGregory Neil Shapiro ** 2640266059SGregory Neil Shapiro ** A pattern consists of normal characters, which match themselves, 2740266059SGregory Neil Shapiro ** and meta-sequences. A * matches any sequence of characters. 2840266059SGregory Neil Shapiro ** A ? matches any single character. A [ introduces a character class. 2940266059SGregory Neil Shapiro ** A ] marks the end of a character class; if the ] is missing then 3040266059SGregory Neil Shapiro ** the [ matches itself rather than introducing a character class. 3140266059SGregory Neil Shapiro ** A character class matches any of the characters between the brackets. 3240266059SGregory Neil Shapiro ** The range of characters from X to Y inclusive is written X-Y. 3340266059SGregory Neil Shapiro ** If the first character after the [ is ! then the character class is 3440266059SGregory Neil Shapiro ** complemented. 3540266059SGregory Neil Shapiro ** 3640266059SGregory Neil Shapiro ** To include a ] in a character class, make it the first character 3740266059SGregory Neil Shapiro ** listed (after the !, if any). To include a -, make it the first 3840266059SGregory Neil Shapiro ** character listed (after the !, if any) or the last character. 3940266059SGregory Neil Shapiro ** It is impossible for a ] to be the final character in a range. 4040266059SGregory Neil Shapiro ** For glob patterns that literally match "*", "?" or "[", 4140266059SGregory Neil Shapiro ** use [*], [?] or [[]. 4240266059SGregory Neil Shapiro */ 4340266059SGregory Neil Shapiro 4440266059SGregory Neil Shapiro bool 4540266059SGregory Neil Shapiro sm_match(str, pat) 4640266059SGregory Neil Shapiro const char *str; 4740266059SGregory Neil Shapiro const char *pat; 4840266059SGregory Neil Shapiro { 4940266059SGregory Neil Shapiro bool ccnot, ccmatch, ccfirst; 5040266059SGregory Neil Shapiro const char *ccstart; 5140266059SGregory Neil Shapiro char c, c2; 5240266059SGregory Neil Shapiro 5340266059SGregory Neil Shapiro for (;;) 5440266059SGregory Neil Shapiro { 5540266059SGregory Neil Shapiro switch (*pat) 5640266059SGregory Neil Shapiro { 5740266059SGregory Neil Shapiro case '\0': 5840266059SGregory Neil Shapiro return *str == '\0'; 5940266059SGregory Neil Shapiro case '?': 6040266059SGregory Neil Shapiro if (*str == '\0') 6140266059SGregory Neil Shapiro return false; 6240266059SGregory Neil Shapiro ++pat; 6340266059SGregory Neil Shapiro ++str; 6440266059SGregory Neil Shapiro continue; 6540266059SGregory Neil Shapiro case '*': 6640266059SGregory Neil Shapiro ++pat; 6740266059SGregory Neil Shapiro if (*pat == '\0') 6840266059SGregory Neil Shapiro { 6940266059SGregory Neil Shapiro /* optimize case of trailing '*' */ 7040266059SGregory Neil Shapiro return true; 7140266059SGregory Neil Shapiro } 7240266059SGregory Neil Shapiro for (;;) 7340266059SGregory Neil Shapiro { 7440266059SGregory Neil Shapiro if (sm_match(pat, str)) 7540266059SGregory Neil Shapiro return true; 7640266059SGregory Neil Shapiro if (*str == '\0') 7740266059SGregory Neil Shapiro return false; 7840266059SGregory Neil Shapiro ++str; 7940266059SGregory Neil Shapiro } 8040266059SGregory Neil Shapiro /* NOTREACHED */ 8140266059SGregory Neil Shapiro case '[': 8240266059SGregory Neil Shapiro ccstart = pat++; 8340266059SGregory Neil Shapiro ccnot = false; 8440266059SGregory Neil Shapiro if (*pat == '!') 8540266059SGregory Neil Shapiro { 8640266059SGregory Neil Shapiro ccnot = true; 8740266059SGregory Neil Shapiro ++pat; 8840266059SGregory Neil Shapiro } 8940266059SGregory Neil Shapiro ccmatch = false; 9040266059SGregory Neil Shapiro ccfirst = true; 9140266059SGregory Neil Shapiro for (;;) 9240266059SGregory Neil Shapiro { 9340266059SGregory Neil Shapiro if (*pat == '\0') 9440266059SGregory Neil Shapiro { 9540266059SGregory Neil Shapiro pat = ccstart; 9640266059SGregory Neil Shapiro goto defl; 9740266059SGregory Neil Shapiro } 9840266059SGregory Neil Shapiro if (*pat == ']' && !ccfirst) 9940266059SGregory Neil Shapiro break; 10040266059SGregory Neil Shapiro c = *pat++; 10140266059SGregory Neil Shapiro ccfirst = false; 10240266059SGregory Neil Shapiro if (*pat == '-' && pat[1] != ']') 10340266059SGregory Neil Shapiro { 10440266059SGregory Neil Shapiro ++pat; 10540266059SGregory Neil Shapiro if (*pat == '\0') 10640266059SGregory Neil Shapiro { 10740266059SGregory Neil Shapiro pat = ccstart; 10840266059SGregory Neil Shapiro goto defl; 10940266059SGregory Neil Shapiro } 11040266059SGregory Neil Shapiro c2 = *pat++; 11140266059SGregory Neil Shapiro if (*str >= c && *str <= c2) 11240266059SGregory Neil Shapiro ccmatch = true; 11340266059SGregory Neil Shapiro } 11440266059SGregory Neil Shapiro else 11540266059SGregory Neil Shapiro { 11640266059SGregory Neil Shapiro if (*str == c) 11740266059SGregory Neil Shapiro ccmatch = true; 11840266059SGregory Neil Shapiro } 11940266059SGregory Neil Shapiro } 12040266059SGregory Neil Shapiro if (ccmatch ^ ccnot) 12140266059SGregory Neil Shapiro { 12240266059SGregory Neil Shapiro ++pat; 12340266059SGregory Neil Shapiro ++str; 12440266059SGregory Neil Shapiro } 12540266059SGregory Neil Shapiro else 12640266059SGregory Neil Shapiro return false; 12740266059SGregory Neil Shapiro continue; 12840266059SGregory Neil Shapiro default: 12940266059SGregory Neil Shapiro defl: 13040266059SGregory Neil Shapiro if (*pat != *str) 13140266059SGregory Neil Shapiro return false; 13240266059SGregory Neil Shapiro ++pat; 13340266059SGregory Neil Shapiro ++str; 13440266059SGregory Neil Shapiro continue; 13540266059SGregory Neil Shapiro } 13640266059SGregory Neil Shapiro } 13740266059SGregory Neil Shapiro } 138