You can modify the environment so that your program runs as if in that environment (and not the environment gdb was launched under). See info for details. Look at “Your Program’s Environment”. There are convenience commands for changing the path, for example. For example, path DIRECTORY adds the directory to the head of your path.
You can examine an environment variable with show environment VAR and you can use set to set it and unset to unset it.
You can set the working directory using set cwd. You can also change stdout and stdin. You can see the current working directory using show cwd. You can also just cd to another directory. Note that the gdb current working directory is not guaranteed to be the same one used by the process being debugged.
You can control which address the program starts in, to an extent. To look this up, search Info for disable-randomization. Some bugs appear only when the program is started at a certain address.
You can control which shell your program runs under (useful when processing command line arguments).
You can redirect output using run > outfile.
There’s a whole section on debugging threads. I did not read it.
There is some information on debugging forks.
gdb allows you to save the state as a checkpoint. This allows you to go back to the same state you were in (e.g. near the point of a crash). Use checkpoint to save a snapshot. Use info checkpoints to see all checkpoints. Use restart <checkpoint> to restore that particular state. And delete <checkpoint> to delete it. Note that the process ID will change when you restore.
One benefit of checkpoints vs breakpoints is that when you rerun a program, due to address randomization, you cannot set breakpoints/watchpoints on an absolute address. You do not need to worry about this with checkpoints.