Merge pull request #35 from DevManu-de/dev-redirect-handle
[psh.git] / lib / path_searcher.c
blob99f2138f7272ab4385a077a1dc02c85c8cf93928
1 /*
2 libpsh/path_searcher.c - path searcher
3 Copyright 2020 Zhang Maiyun.
5 This file is part of Psh, P shell.
7 Psh is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Psh is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
21 #include <stddef.h>
22 #include <string.h>
24 #include "libpsh/xmalloc.h"
26 /* Call CHK_FUNC on each (substr + TARGET) concatenated string in PATH
27 * separated by SEPARATOR.
28 * Returns the first concatenated string for which CHK_FUNC returns non-zero;
29 * or NULL if none succeeded. Result should be free()d */
30 char *psh_search_path(const char *path, int separator, const char *target,
31 int (*chk_func)(const char *))
33 /* +1 for '\0' */
34 size_t len_substr, len_target = strlen(target) + 1,
35 size_allocated = 2 * len_target;
36 char *concatenated = xmalloc(size_allocated), *occur = (char *)1;
38 while (occur)
40 occur = strchr(path, separator);
41 len_substr = occur ? (size_t)(occur - path) : strlen(path);
43 /* Realloc concatenated if it's too small */
44 if (len_substr + len_target > size_allocated)
46 size_allocated = len_target + len_substr;
47 concatenated = xrealloc(concatenated, size_allocated);
50 /* Copy substr */
51 memcpy(concatenated, path, len_substr);
52 /* Copy target str */
53 memcpy(concatenated + len_substr, target, len_target);
54 /* End string */
55 *(concatenated + len_target + len_substr - 1) = 0;
56 if (chk_func(concatenated))
57 return concatenated;
58 /* Jump over the substr */
59 path += len_substr + 1; /* +1 for separator */
61 xfree(concatenated);
62 return NULL;