One idea is to write two functions. The first one is recursive and doesn't actually do the insert, it instead finds either a node with the same key, or the closest matching node, and it returns the node it found. (or null if the tree is empty)
Then your other function is responsible for calling the recursive one and then it uses the ndoe returned from that, to insert the new node both into the tree and the list simultaneously.

To do that, you:
Work out which side of the node function 1 found. Lets assume it has to go on the right. Find it's right neighbour by following that node's existing next link.
Okay, now insertion into the list is easy, allocate your new item and set up its prev an next links to those two nodes, and adjust those two nodes to point to the new one.
Then since in this case it goes on the right of the node you found you can set the right link of that node to point to your new node.
Your new node's left and right will be NULL of course.
Make sense?
You can work out the special case for when the root is NULL.

E.g.

Code:

4
/ \
2 6
/ \ \
1 3 7

Say you want to insert 5.
You go right of 4 because 5 is greater, then you look at 6 and see that 5 would be left of there but the left pointer is NULL, so you return that node. Now follow 6's prev pointer and that'll get you to node 4. Then adjust 4's next to point to 5, and adjust 6's prev to point to 5. Actually I'm sure you get the idea by now...

Actually, you can do the first part iteratively and then put the whole thing in one function. It should be more efficient that way.

The sentinel is needed for when you went to insert say 0 or 8 into this data structure. You'd follow 1's prev and that has to be a real node (not just a pointer) so you can set it's next pointer. You use the same sentinel node at BOTH ends of the list.

One idea is to write two functions. The first one is recursive and doesn't actually do the insert, it instead finds either a node with the same key, or the closest matching node that does not have two children, and it reuturns the node it found. (or null if the tree is empty)
Then your other function is responsible for calling the recursive one and then it uses the ndoe returned from that, to insert the new node both into the tree and the list simultaneously.

To do that, you:
Work out which side of the node function 1 found. Lets assume it has to go on the right. Find it's right neighbour by following that node's existing next link.
Okay, now insertion into the list is easy, allocate your new item and set up its prev an next links to those two nodes, and adjust those two nodes to point to the new one.
Then since in this case it goes on the right of the node you found you can set the right link of that node to point to your new node.
Your new node's left and right will be NULL of course.
Make sense?
You can work out the special case for when the root is NULL.

E.g.

Code:

4
/ \
2 6
/ \ \
1 3 7

Say you want to insert 5.
You go right of 4 because 5 is greater, then you look at 6 and see that one of its children is NULL, so you return that node. Now follow 6's prev pointer and that'll get you to node 4. Then adjust 4's next to point to 5, and adjust 6's prev to point to 5. Actually I'm sure you get the idea by now...

The sentinel is needed for when you went to insert say 0 or 8 into this data structure. You'd follow 1's prev and that has to be a real node (not just a pointer) so you can set it's next pointer. You use the same sentinel node at BOTH ends of the list.

doesnt my insert function do what you are describing in the second part?
what about this for the first part.. this is my find function:

doesnt my insert function do what you are describing in the second part?

No, it's more like the first part, but it wont do because it returns NULL when the item is not found and the tree is not empty. You'd need it to return the node that the new one will hang off instead. Thinking about it more, I'd now recommend writing the insert function to make it iterative instead of recursive. Recursion is useful when you're going down more than one branch, such as when you're printing out the whole tree, or when you need to do something on your way back up the tree. Neither of those are the case here. You simply find your way down through the tree and then when you reach the node that needs to have a child attached to it, you attach the node and then stop treating the tree as a tree and start treating it as a doubly-linked list, of which you have a node from, and can go forwards and backwards from, at will.

so do I call the find function in my insert function?
how do i set the sentinel node and the next/prev pointers???

You set up the sentinel node when you insert the first item. At that point, both prev and next from the sentinel point to the node you inserted, and the prev and next of the node you inserted both point to the sentinel. That's it! Once you do that, the rest of the list insertion just works, and doesn't even have to know the sentinel exists.

Your find function would be more efficient if it was iterative as well btw.

like in the actual program? do i send in the sentinel node? or should i send in the sent->next's node

Okay it wont be a self-balancing binary tree. Those are a lot harder anyway!

You don't need to pass in the sentinel node. It's something you access from your insert function as if it were a global. You could perhaps make it a static variable in the insert function later, but for now just access it like a global. If this were C++ it would be part of the class.
You can just set it up like this, and these are the only lines of code that know anything about sent besides where it is declared. Remember sent should be an actual BNODE, not just a pointer.

Ok im a little lost.. how is sent declared if its just a BNODE.. is it declared in the program or inside that particular function? how do i send it in?

A global variable is one that is not declared inside a function. You could do it that way, and then you don't need to pass it in.
However that does prevent you from constructing more than one tree easily, so if you really want to pass it in, you can pass in the address of it to a pointer parameter. It probably just makes things more cluttered like that though.
Either way, when it's declared you probably just want it to be "BNODE sent;" as dynamically allocating it doesn't really give you any advantage.