Search code examples
bashshellenvironment

How, or in which pattern, are environment variables listed in a shell (bash)?


I have a task to implement my own shell in C from scratch for my school.

As a reference, I must take bash.

My question is, how are the environ variables listed when either env or printenv are called?

I've noticed it's neither by creation date nor by alphabetical order.

My shell has its own environment as a char **, and I'm wondering how should I shuffle it after a new variable declared so that it imitates bash correctly.

I tried running export a=aaaa in bash and it appeared in the middle of the list.


Solution

  • how are the environ variables listed when either env or printenv are called?

    Both these programs are open source. From coreutlis/env.c:

      char *const *e = environ;
      while (*e)
        printf ("%s%c", *e++, opt_nul_terminate_output ? '\0' : '\n');
    

    From coreutils/printenv:

      for (env = environ; *env != NULL; ++env)
        printf ("%s%c", *env, opt_nul_terminate_output ? '\0' : '\n');
    

    I've noticed it's neither by creation date nor by alphabetical order.

    Inspecting glibc/setenv.c I think it appends the values on the end, and keeps a separate binary search tree (#include <search.h>) with variable names for fast searching.

    Posix states from https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html :

    There is no meaning associated with the order of strings in the environment.

    and I think this is enough to give implementations freedom to use any order they want.

    in bash and it appeared in the middle of the list.

    There is no reason for Bash to use environ. Bash has its own export_env 2d array, and it keeps variables using its own HASH_TABLE implementation - hashlib.c and also VAR_CONTEXT.