setenv(3)

✨ setenv β€” change or add an environment variable ✨

okay bestie so we're in the section 3 of the manual (that's the Library Functions Manual babe, C library stuff πŸ’…) and today's main character is setenv, plus its lil sibling unsetenv. they literally control the environment variables. the whole vibe of your process. iconic behavior tbh 🌸


🫢 LIBRARY

Standard C library (libc, -lc) β€” yeah she lives in libc, no cap.


πŸ“œ SYNOPSIS

#include <stdlib.h>

int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);

πŸŽ€ Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

setenv(), unsetenv():
    _POSIX_C_SOURCE >= 200112L
        || /* glibc <= 2.19: */ _BSD_SOURCE

like, if you want these to even show up you gotta define the right macro first. glibc said boundaries πŸ’…


πŸ’– DESCRIPTION

so setenv() adds the variable name to the environment with the value value, but ONLY if name doesn't already exist. if name does already exist in the environment, then its value gets changed to value when overwrite is nonzero. if overwrite is zero, then the value of name is left alone (and setenv() still returns a success status, she's unbothered πŸ’…). also important: this function makes copies of the strings pointed to by name and value β€” which is the whole difference from putenv(3), who does NOT copy. no cap.

and unsetenv()? she deletes the variable name from the environment. if name doesn't exist in the environment, the function still succeeds and the environment is just... unchanged. no drama, no error, she just says "k whatever" πŸ¦‹


πŸ₯° RETURN VALUE

setenv() and unsetenv() both return zero on success, or -1 on error, with errno set to tell you which error. simple as that bestie.


😭 ERRORS

  • EINVAL β€” name is NULL, points to a string of length 0, or contains an '=' character. like girl, that's not a valid name, what are you doing πŸ’€
  • ENOMEM β€” insufficient memory to add a new variable to the environment. she ran out of room. tragic.

πŸ’… ATTRIBUTES

for the full explanation of what these terms even mean, check attributes(7). but here's the tea:

  • Interface: setenv(), unsetenv()
  • Attribute: Thread safety
  • Value: MT-Unsafe const:env

so yeah, MT-Unsafe with const:env β€” not thread safe bestie, be careful out there πŸ™ˆ


πŸ‘‘ STANDARDS

POSIX.1-2008. periodt.


🌈 HISTORY

POSIX.1-2001, 4.3BSD. she's got lore.

and the glow-up: prior to glibc 2.2.2, unsetenv() was prototyped as returning void; more recent glibc versions follow the POSIX.1-compliant prototype shown in the SYNOPSIS. she grew up πŸ₯Ή


πŸ’€ CAVEATS

POSIX.1 does not require setenv() or unsetenv() to be reentrant. so like, don't expect them to play nice in every reentrant situation, okay? just so you know 🫢


πŸ“ BUGS

POSIX.1 specifies that if name contains an '=' character, then setenv() should fail with the error EINVAL; however, versions of glibc before glibc 2.3.4 allowed an '=' sign in name. so depending on your glibc age, behavior varies. not me finding ancient glibc bugs 😭


🧚 SEE ALSO


okay that's the whole page bestie, go forth and set your environment variables responsibly πŸ’œ slay ✨

source/version + date check: this one's from Linux man-pages 6.20, dated 2026-02-08 β€” so if you're reading this, it was ✨destined✨. bye pookie πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms