env.c (2366B)
- // Collection of Unix tools, comparable to coreutils
- // SPDX-FileCopyrightText: 2017-2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <assert.h> // assert
- #include <errno.h> // errno
- #include <stdbool.h> // bool, true, false
- #include <stdio.h> // puts, fprintf
- #include <stdlib.h> // putenv
- #include <string.h> // strchr, strerror
- #include <unistd.h> // getopt, opt*
- extern char **environ;
- char *envclear[1];
- int export()
- {
- int i = 0;
- for(; environ[i] != NULL; i++)
- {
- if(puts(environ[i]) < 0)
- {
- perror("env: puts(environ[i])");
- return 1;
- }
- }
- return 0;
- }
- void
- usage()
- {
- fprintf(stderr, "env [-i] [-u key | --unset=key] [key=value ...] [command [args]]\n");
- }
- int
- main(int argc, char *argv[])
- {
- int c;
- bool flag_i = false;
- char *val;
- /* flawfinder: ignore. Old implementations of getopt should fix themselves */
- while((c = getopt(argc, argv, ":iu:-:")) != -1)
- {
- switch(c)
- {
- case 'i':
- flag_i = true;
- break;
- case 'u':
- unsetenv(optarg);
- break;
- case '-':
- val = strchr(optarg, '=');
- if(val == NULL)
- {
- fprintf(stderr, "env: Error: Missing = in long option\n");
- return 1;
- }
- *val = 0;
- val++;
- if(strcmp(optarg, "unset") != 0)
- {
- fprintf(stderr, "env: Error: Unknown long option --%s\n", optarg);
- return 1;
- }
- unsetenv(val);
- break;
- case ':':
- fprintf(stderr, "env: Error: Missing operand for option: '-%c'\n", optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "env: Error: Unrecognised option: '-%c'\n", optopt);
- usage();
- return 1;
- default:
- assert(false);
- }
- }
- argc -= optind;
- argv += optind;
- if(flag_i)
- {
- environ = envclear;
- envclear[0] = NULL;
- }
- for(; argv[0]; argv++, argc--)
- {
- char *sep = strchr(argv[0], '=');
- if(sep == NULL)
- {
- break;
- }
- *sep = 0;
- sep++;
- if(setenv(argv[0], sep, 1))
- {
- fprintf(stderr, "env: setenv(%s, %s, 1): %s\n", argv[0], sep, strerror(errno));
- return 1;
- }
- }
- if(argc < 1)
- {
- return export();
- }
- assert(argv[0]);
- errno = 0;
- /* flawfinder: ignore. No restrictions on commands is intended */
- if(execvp(argv[0], argv) < 0)
- {
- fprintf(stderr, "env: execvp(\"%s\", ...): %s\n", argv[0], strerror(errno));
- return (errno == ENOENT) ? 127 : 126;
- }
- assert(false);
- }