I think that what confuses you is that a decreasing exponential ($e^{-x}$) does never reach 0, so an ADSR generator with truly exponential segments would stay stuck ; because it would never reach the target value. For example, if the generator is at the height of the attack phase (say $y = 1$) and has to land to a sustain value at $y = 0.5$, it can't go there with a true exponential, because the true exponential won't decay to 0.5, it'll only asymptotically go to 0.5!
If you look at an analog envelope generator (for example the 7555 based circuit everybody seems to use), you can see that during the attack phase, when the capacitor is charging, it is "aiming higher" than the threshold used to indicate the end of the attack phase. On a (7)555 based circuit powered by +15V, During the attack stage, the capacitor is charged with a +15V step, but the attack stage ends when a threshold of +10V has been reached. This is a design choice, though 2/3 is the "magic number" found in many classic envelope generator, and this might be the one musicians are familiar with.

Thus, the functions you might want to deal with are not exponentials, but shifted/truncated/scales versions of it, and you'll have to make some choices as to how "squashed" you want them to be.
I am curious anyway as to why you are trying to get such formulas - maybe it's because of the limits of the tool you are using for synthesis ; but if you are trying to implement those using a general purpose programming language (C, java, python) with some code running for each sample of the envelope, and a notion of "state", read on... Because it's always easier to express things as "such segment will go from whatever value it has just reached to 0".
My two pieces of advice on implementing envelopes.
The first one is not to try to scale all the slopes/increments so that the envelope exactly reach start and end values. For example you want an envelope that goes from 0.8 to 0.2 in 2 seconds, so you might be tempted to compute an increment of -0.3 / second. Don't do that. Instead, break it down into two steps: getting a ramp that goes from 0 to 1.0 in 2 seconds ; and then applying a linear transform that maps 0 to 0.8 and 1.0 to 0.2. There are two advantages to work this way - the first is that it simplifies any computation you'll have relative to envelope times to a ramp from 0 to 1 ; the second is that if you change the envelope parameters (increments and start/end times) midway everything will remain well-behaved. Good if you're working on a synth, since people will ask to have envelope time parameters as modulation destinations.
The second is to use pre-computed lookup table with envelope shapes. It is computationally lighter, it takes out many dirty details (for example you don't have to bother with an exponential not reaching 0 exactly - truncate it at your whim and rescale it so that it is mapped to [0, 1]), and it's dead easy to provide an option to alter envelope shapes, for each stage.
Here is the pseudo-code for the approach I describe.
render:
counter += increment[stage]
if counter > 1.0:
stage = stage + 1
start_value = value
counter = 0
position = interpolated_lookup(envelope_shape[stage], counter)
value = start_value + (target_level[stage] - start_value) * position
trigger(state):
if state = ON:
stage = ATTACK
value = 0 # for mono-style envelopes that are reset to 0 on new notes
counter = 0
else:
counter = 0
stage = RELEASE
initialization:
target_level[ATTACK] = 1.0
target_level[RELEASE] = 0.0
target_level[END_OF_RELEASE] = 0.0
increment[SUSTAIN] = 0.0
increment[END_OF_RELEASE] = 0.0
configuration:
increment[ATTACK] = ...
increment[DECAY] = ...
target_level[DECAY] = target_level[SUSTAIN] = ...
increment[RELEASE] = ...
envelope_shape[ATTACK] = lookup_table_exponential
envelope_shape[DECAY] = lookup_table_exponential
envelope_shape[RELEASE] = lookup_table_exponential