static struct rmsgpack_dom_value q_glob(struct rmsgpack_dom_value input, unsigned argc, const struct argument * argv) { struct rmsgpack_dom_value res; unsigned i = 0; memset(&res, 0, sizeof(res)); res.type = RDT_BOOL; res.val.bool_ = 0; (void)i; if (argc != 1) return res; if (argv[0].type != AT_VALUE || argv[0].a.value.type != RDT_STRING) return res; if (input.type != RDT_STRING) return res; res.val.bool_ = rl_fnmatch( argv[0].a.value.val.string.buff, input.val.string.buff, 0 ) == 0; return res; }
static int read_launch_conf(struct RunInfo *info, const char *game_name) { int fd = open("./launch.conf", O_RDONLY); int rv; int bci = 0; char token[MAX_TOKEN_LEN]; if (fd < 0) { return -errno; } while (1) { if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } if (rl_fnmatch(token, game_name, 0) != 0) { if ((rv = find_token(fd, ";")) < 0) { goto clean; } continue; } LOG_DEBUG("Matched rule '%s'", token); break; } if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } while (strcmp(token, ";") != 0) { if (strcmp(token, "multitap") == 0) { info->multitap = 1; } else if (strcmp(token, "dualanalog") == 0) { info->dualanalog = 1; } else if (token[0] == '!') { strncpy(&info->broken_cores[bci], &token[1], PATH_MAX - bci); bci += strnlen(&token[1], PATH_MAX) + 1; } if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } } rv = 0; clean: close(fd); return rv; }
static int select_core(char *core_path, size_t max_len, const struct RunInfo *info) { int fd = open("./cores.conf", O_RDONLY); int rv; int bci = 0; char token[MAX_TOKEN_LEN]; int broken = 0; if (fd < 0) { return -errno; } LOG_INFO("Selecting core for system '%s'", info->system); while (1) { if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } if (rl_fnmatch(token, info->system, 0) != 0) { if ((rv = find_token(fd, ";")) < 0) { goto clean; } continue; } LOG_INFO("Matched system '%s'", token); break; } if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } while (strcmp(token, ";") != 0) { broken = 0; for (bci = 0; info->broken_cores[bci] != '\0'; bci += strlen(&info->broken_cores[bci]) + 1) { LOG_DEBUG("%s, %s", &info->broken_cores[bci], token); if (strcmp(&info->broken_cores[bci], token) == 0) { broken = 1; LOG_DEBUG("Not using core %s because it is " "marked broken for this game", &info->broken_cores[bci]); break; } } if (!broken) { goto success; } if ((rv = get_token(fd, token, MAX_TOKEN_LEN)) < 0) { goto clean; } } rv = -EINVAL; goto clean; success: snprintf(core_path, max_len, "./cores/%s.so", token); rv = 0; clean: close(fd); return rv; }
int rl_fnmatch(const char *pattern, const char *string, int flags) { const char *c; int rv; int charmatch = 0; for (c = pattern; *c != '\0'; c++) { /* String ended before pattern */ if ((*c != '*') && (*string == '\0')) return FNM_NOMATCH; switch (*c) { /* Match any number of unknown chars */ case '*': /* Find next node in the pattern * ignoring multiple asterixes */ do { c++; if (*c == '\0') return 0; } while (*c == '*'); /* Match the remaining pattern * ignoring more and more characters. */ do { /* We reached the end of the string without a * match. There is a way to optimize this by * calculating the minimum chars needed to * match the remaining pattern but I don't * think it is worth the work ATM. */ if (*string == '\0') return FNM_NOMATCH; rv = rl_fnmatch(c, string, flags); string++; } while (rv != 0); return 0; /* Match char from list */ case '[': charmatch = 0; for (c++; *c != ']'; c++) { /* Bad format */ if (*c == '\0') return FNM_NOMATCH; /* Match already found */ if (charmatch) continue; if (*c == *string) charmatch = 1; } /* No match in list */ if (!charmatch) return FNM_NOMATCH; string++; break; /* Has any character */ case '?': string++; break; /* Match following character verbatim */ case '\\': c++; /* Dangling escape at end of pattern. * FIXME: Was c == '\0' (makes no sense). * Not sure if c == NULL or *c == '\0' * is intended. Assuming *c due to c++ right before. */ if (*c == '\0') return FNM_NOMATCH; default: if (*c != *string) return FNM_NOMATCH; string++; } } /* End of string and end of pattend */ if (*string == '\0') return 0; return FNM_NOMATCH; }
int main(void) { assert(rl_fnmatch("TEST", "TEST", 0) == 0); assert(rl_fnmatch("TE?T", "TEST", 0) == 0); assert(rl_fnmatch("TE[Ssa]T", "TEST", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEsT", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEdT", 0) == 0); assert(rl_fnmatch("TE[Ssda]T", "TEaT", 0) == 0); assert(rl_fnmatch("TEST*", "TEST", 0) == 0); assert(rl_fnmatch("TEST**", "TEST", 0) == 0); assert(rl_fnmatch("TE*ST*", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST*", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST*", "TExST", 0) == 0); assert(rl_fnmatch("TE**ST", "TEST", 0) == 0); assert(rl_fnmatch("TE**ST", "TExST", 0) == 0); assert(rl_fnmatch("TE\\**ST", "TE*xST", 0) == 0); assert(rl_fnmatch("*.*", "test.jpg", 0) == 0); assert(rl_fnmatch("*.jpg", "test.jpg", 0) == 0); assert(rl_fnmatch("*.[Jj][Pp][Gg]", "test.jPg", 0) == 0); assert(rl_fnmatch("*.[Jj]*[Gg]", "test.jPg", 0) == 0); assert(rl_fnmatch("TEST?", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TES[asd", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST\\", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST*S", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE**ST", "TExT", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE\\*T", "TExT", 0) == FNM_NOMATCH); assert(rl_fnmatch("TES?", "TES", 0) == FNM_NOMATCH); assert(rl_fnmatch("TE", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("TEST!", "TEST", 0) == FNM_NOMATCH); assert(rl_fnmatch("DSAD", "TEST", 0) == FNM_NOMATCH); }