@@ -298,19 +298,48 @@ impl Error for VarError {
298298 }
299299}
300300
301+ #[ unstable( feature = "unsafe_env" , issue = "none" ) ]
301302/// Sets the environment variable `key` to the value `value` for the currently running
302303/// process.
303304///
304- /// Note that while concurrent access to environment variables is safe in Rust,
305- /// some platforms only expose inherently unsafe non-threadsafe APIs for
306- /// inspecting the environment. As a result, extra care needs to be taken when
307- /// auditing calls to unsafe external FFI functions to ensure that any external
308- /// environment accesses are properly synchronized with accesses in Rust.
305+ /// # Safety
309306///
310- /// Discussion of this unsafety on Unix may be found in:
307+ /// This function must not be called in the presence of concurrent threads that
308+ /// may simultaneously read or write the environment. Also, it's not allowed
309+ /// to use this function in functions marked with `#[test]` attribute because
310+ /// test harness uses threads internally.
311311///
312- /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
313- /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
312+ /// # Panics
313+ ///
314+ /// This function may panic if `key` is empty, contains an ASCII equals sign `'='`
315+ /// or the NUL character `'\0'`, or when `value` contains the NUL character.
316+ ///
317+ /// # Examples
318+ ///
319+ /// ```
320+ /// #![feature(unsafe_env)]
321+ ///
322+ /// use std::env;
323+ ///
324+ /// let key = "KEY";
325+ /// unsafe {
326+ /// env::set(key, "VALUE");
327+ /// }
328+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
329+ /// ```
330+ pub unsafe fn set < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
331+ _set_var ( key. as_ref ( ) , value. as_ref ( ) , |k, v| os_imp:: setenv ( k, v) )
332+ }
333+
334+ /// Sets the environment variable `key` to the value `value` for the currently running
335+ /// process.
336+ ///
337+ /// # Safety
338+ ///
339+ /// This function must not be called in the presence of concurrent threads that
340+ /// may simultaneously read or write the environment. Also, it's not allowed
341+ /// to use this function in functions marked with `#[test]` attribute because
342+ /// test harness uses threads internally.
314343///
315344/// # Panics
316345///
@@ -328,27 +357,59 @@ impl Error for VarError {
328357/// ```
329358#[ stable( feature = "env" , since = "1.0.0" ) ]
330359pub fn set_var < K : AsRef < OsStr > , V : AsRef < OsStr > > ( key : K , value : V ) {
331- _set_var ( key. as_ref ( ) , value. as_ref ( ) )
360+ _set_var ( key. as_ref ( ) , value. as_ref ( ) , |k , v| unsafe { os_imp :: setenv_locking ( k , v ) } )
332361}
333362
334- fn _set_var ( key : & OsStr , value : & OsStr ) {
335- os_imp :: setenv ( key, value) . unwrap_or_else ( |e| {
363+ fn _set_var < F : Fn ( & OsStr , & OsStr ) -> io :: Result < ( ) > > ( key : & OsStr , value : & OsStr , f : F ) {
364+ f ( key, value) . unwrap_or_else ( |e| {
336365 panic ! ( "failed to set environment variable `{:?}` to `{:?}`: {}" , key, value, e)
337366 } )
338367}
339368
369+ #[ unstable( feature = "unsafe_env" , issue = "none" ) ]
340370/// Removes an environment variable from the environment of the currently running process.
341371///
342- /// Note that while concurrent access to environment variables is safe in Rust,
343- /// some platforms only expose inherently unsafe non-threadsafe APIs for
344- /// inspecting the environment. As a result extra care needs to be taken when
345- /// auditing calls to unsafe external FFI functions to ensure that any external
346- /// environment accesses are properly synchronized with accesses in Rust.
372+ /// # Safety
373+ ///
374+ /// This function must not be called in the presence of concurrent threads that
375+ /// may simultaneously read or write the environment. Also, it's not allowed
376+ /// to use this function in functions marked with `#[test]` attribute because
377+ /// test harness uses threads internally.
378+ ///
379+ /// # Panics
380+ ///
381+ /// This function may panic if `key` is empty, contains an ASCII equals sign
382+ /// `'='` or the NUL character `'\0'`, or when the value contains the NUL
383+ /// character.
384+ ///
385+ /// # Examples
386+ ///
387+ /// ```
388+ /// #![feature(unsafe_env)]
389+ ///
390+ /// use std::env;
391+ ///
392+ /// let key = "KEY";
393+ /// env::set_var(key, "VALUE");
394+ /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
395+ ///
396+ /// unsafe {
397+ /// env::remove(key);
398+ /// }
399+ /// assert!(env::var(key).is_err());
400+ /// ```
401+ pub unsafe fn remove < K : AsRef < OsStr > > ( key : K ) {
402+ _remove_var ( key. as_ref ( ) , |n| os_imp:: unsetenv ( n) )
403+ }
404+
405+ /// Removes an environment variable from the environment of the currently running process.
347406///
348- /// Discussion of this unsafety on Unix may be found in:
407+ /// # Safety
349408///
350- /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188)
351- /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
409+ /// This function must not be called in the presence of concurrent threads that
410+ /// may simultaneously read or write the environment. Also, it's not allowed
411+ /// to use this function in functions marked with `#[test]` attribute because
412+ /// test harness uses threads internally.
352413///
353414/// # Panics
354415///
@@ -370,12 +431,11 @@ fn _set_var(key: &OsStr, value: &OsStr) {
370431/// ```
371432#[ stable( feature = "env" , since = "1.0.0" ) ]
372433pub fn remove_var < K : AsRef < OsStr > > ( key : K ) {
373- _remove_var ( key. as_ref ( ) )
434+ _remove_var ( key. as_ref ( ) , |n| unsafe { os_imp :: unsetenv_locking ( n ) } )
374435}
375436
376- fn _remove_var ( key : & OsStr ) {
377- os_imp:: unsetenv ( key)
378- . unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{:?}`: {}" , key, e) )
437+ fn _remove_var < F : Fn ( & OsStr ) -> io:: Result < ( ) > > ( key : & OsStr , f : F ) {
438+ f ( key) . unwrap_or_else ( |e| panic ! ( "failed to remove environment variable `{:?}`: {}" , key, e) )
379439}
380440
381441/// An iterator that splits an environment variable into paths according to
0 commit comments