Skip to content

Instantly share code, notes, and snippets.

@matthewdowney
Created August 1, 2022 00:14
Show Gist options
  • Save matthewdowney/79dd4bf99a7807f36cb0c2d2cba9e02d to your computer and use it in GitHub Desktop.
Save matthewdowney/79dd4bf99a7807f36cb0c2d2cba9e02d to your computer and use it in GitHub Desktop.
Clojure hack to overwrite the JVM's System/getenv map for environment variables without touching the actual environment. Definitely not safe.
(ns env
"Clojure hack to overwrite the JVM's System/getenv map for environment variables without touching the actual environment. Definitely not safe."
(:import (java.util Collections Map)))
(defn -unsafe-set-env [new-env]
(try
(let [clazz (Class/forName "java.lang.ProcessEnvironment")]
(doseq [field ["theEnvironment" "theCaseInsensitiveEnvironment"]]
(let [env-field (doto (.getDeclaredField clazz field) (.setAccessible true))]
(.putAll ^Map (.get env-field nil) new-env))))
(catch NoSuchFieldException e
(let [env (System/getenv)]
(doseq [clazz (.getDeclaredClasses Collections)]
(when (= (.getName clazz) "java.util.Collections$UnmodifiableMap")
(let [field (doto (.getDeclaredField clazz "m") (.setAccessible true))
obj (.get field env)]
(.clear ^Map obj)
(.putAll ^Map obj (into new-env env)))))))))
(defmacro with-unsafe-merge-env [new-env-vars & body]
`(let [env# (into {} (System/getenv))
_# (-unsafe-set-env (merge env# ~new-env-vars))
ret# (do ~@body)]
(-unsafe-set-env env#)
ret#))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment