libite 2.6.1
which.c
Go to the documentation of this file.
1/* C implementation of UNIX which(1)
2 *
3 * Copyright (c) 2017-2021 Joachim Wiberg <troglobit@gmail.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
24
25#include <ctype.h>
26#include <errno.h>
27#include <stdio.h> /* snprintf() */
28#include <stdlib.h> /* realloc(), free() */
29#include <string.h> /* strtok_r() */
30#include <unistd.h> /* access() */
31
32/* Strip any arguments in "/path/to/bin --some args", modifies input string */
33static char *strip_args(char *path)
34{
35 size_t i = 0;
36
37 if (!path)
38 return NULL;
39
40 /* Find first whitespace (space/tab/etc.) */
41 while (path[i] && !isspace(path[i]))
42 i++;
43 path[i] = 0;
44
45 return path;
46}
47
54char *which(const char *cmd)
55{
56 size_t pathlen = 0;
57 char *ptr, *tok, *env, *path = NULL;
58
59 if (!cmd) {
60 errno = EINVAL;
61 return NULL;
62 }
63
64 if (cmd[0] == '/') {
65 path = strip_args(strdup(cmd));
66 if (!path)
67 return NULL;
68
69 if (!access(path, X_OK))
70 return path;
71
72 if (path)
73 free(path);
74
75 return NULL;
76 }
77
78 ptr = getenv("PATH");
79 if (!ptr)
80 return NULL;
81
82 env = strdup(ptr);
83 if (!env)
84 return NULL;
85
86 tok = strtok_r(env, ":", &ptr);
87 while (tok) {
88 size_t len = strlen(tok) + strlen(cmd) + 2;
89
90 if (pathlen < len) {
91 path = realloc(path, len);
92 if (!path) {
93 free(env);
94 return NULL;
95 }
96 pathlen = len;
97 }
98
99 snprintf(path, pathlen, "%s/%s", tok, cmd);
100 path = strip_args(path);
101 if (!path || !access(path, X_OK)) {
102 free(env);
103 return path;
104 }
105
106 tok = strtok_r(NULL, ":", &ptr);
107 }
108
109 if (path)
110 free(path);
111 free(env);
112
113 return NULL;
114}
115
122int whichp(const char *cmd)
123{
124 char *path;
125
126 path = which(cmd);
127 if (path) {
128 free(path);
129 return 1;
130 }
131
132 return 0;
133}
134
char * which(const char *cmd)
Definition which.c:54
int whichp(const char *cmd)
Definition which.c:122