logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git

env.c (2366B)


  1. // Collection of Unix tools, comparable to coreutils
  2. // SPDX-FileCopyrightText: 2017-2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <assert.h> // assert
  6. #include <errno.h> // errno
  7. #include <stdbool.h> // bool, true, false
  8. #include <stdio.h> // puts, fprintf
  9. #include <stdlib.h> // putenv
  10. #include <string.h> // strchr, strerror
  11. #include <unistd.h> // getopt, opt*
  12. extern char **environ;
  13. char *envclear[1];
  14. int export()
  15. {
  16. int i = 0;
  17. for(; environ[i] != NULL; i++)
  18. {
  19. if(puts(environ[i]) < 0)
  20. {
  21. perror("env: puts(environ[i])");
  22. return 1;
  23. }
  24. }
  25. return 0;
  26. }
  27. void
  28. usage()
  29. {
  30. fprintf(stderr, "env [-i] [-u key | --unset=key] [key=value ...] [command [args]]\n");
  31. }
  32. int
  33. main(int argc, char *argv[])
  34. {
  35. int c;
  36. bool flag_i = false;
  37. char *val;
  38. /* flawfinder: ignore. Old implementations of getopt should fix themselves */
  39. while((c = getopt(argc, argv, ":iu:-:")) != -1)
  40. {
  41. switch(c)
  42. {
  43. case 'i':
  44. flag_i = true;
  45. break;
  46. case 'u':
  47. unsetenv(optarg);
  48. break;
  49. case '-':
  50. val = strchr(optarg, '=');
  51. if(val == NULL)
  52. {
  53. fprintf(stderr, "env: Error: Missing = in long option\n");
  54. return 1;
  55. }
  56. *val = 0;
  57. val++;
  58. if(strcmp(optarg, "unset") != 0)
  59. {
  60. fprintf(stderr, "env: Error: Unknown long option --%s\n", optarg);
  61. return 1;
  62. }
  63. unsetenv(val);
  64. break;
  65. case ':':
  66. fprintf(stderr, "env: Error: Missing operand for option: '-%c'\n", optopt);
  67. usage();
  68. return 1;
  69. case '?':
  70. fprintf(stderr, "env: Error: Unrecognised option: '-%c'\n", optopt);
  71. usage();
  72. return 1;
  73. default:
  74. assert(false);
  75. }
  76. }
  77. argc -= optind;
  78. argv += optind;
  79. if(flag_i)
  80. {
  81. environ = envclear;
  82. envclear[0] = NULL;
  83. }
  84. for(; argv[0]; argv++, argc--)
  85. {
  86. char *sep = strchr(argv[0], '=');
  87. if(sep == NULL)
  88. {
  89. break;
  90. }
  91. *sep = 0;
  92. sep++;
  93. if(setenv(argv[0], sep, 1))
  94. {
  95. fprintf(stderr, "env: setenv(%s, %s, 1): %s\n", argv[0], sep, strerror(errno));
  96. return 1;
  97. }
  98. }
  99. if(argc < 1)
  100. {
  101. return export();
  102. }
  103. assert(argv[0]);
  104. errno = 0;
  105. /* flawfinder: ignore. No restrictions on commands is intended */
  106. if(execvp(argv[0], argv) < 0)
  107. {
  108. fprintf(stderr, "env: execvp(\"%s\", ...): %s\n", argv[0], strerror(errno));
  109. return (errno == ENOENT) ? 127 : 126;
  110. }
  111. assert(false);
  112. }