which.c (1531B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <limits.h> // PATH_MAX
- #include <stdbool.h>
- #include <stdio.h> // fprintf
- #include <stdlib.h> // getenv
- #include <string.h> // strtok
- #include <unistd.h> // access, getopt
- int
- main(int argc, char *argv[])
- {
- bool opt_a = false, opt_s = false;
- int missing = 0;
- char *path = getenv("PATH");
- if(path == NULL)
- {
- fputs("which: error: $PATH environment unset", stderr);
- return 1;
- }
- int c = -1;
- while((c = getopt(argc, argv, "as")) != -1)
- {
- switch(c)
- {
- case 'a':
- opt_a = true;
- break;
- case 's':
- opt_s = true;
- break;
- case '?':
- fprintf(stderr, "which: error: Unrecognised option: '-%c'\n", optopt);
- return 1;
- default:
- abort();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc <= 0) return 1;
- for(int i = 0; i < argc; i++)
- {
- char *cmd = argv[i];
- bool found = false;
- char *state = NULL;
- char *hay = strdup(path);
- if(hay == NULL)
- {
- perror("which: error: Failed duplicating $PATH");
- return 1;
- }
- for(char *tok = strtok_r(hay, ":", &state); tok != NULL; tok = strtok_r(NULL, ":", &state))
- {
- char buf[PATH_MAX] = "";
- snprintf(buf, PATH_MAX, "%s/%s", tok, cmd);
- if(access(buf, X_OK) == 0)
- {
- if(!opt_s) puts(buf);
- found = true;
- if(!opt_a) break;
- }
- }
- if(!found) missing++;
- free(hay);
- }
- return missing;
- }