Every object that has a 'Copy' option implements the 'make_<fac>_copy' method - for Contacts it's make_cnt_copy. You can override the make_cnt_copy function in a custom .spl file and define your own. You have to remember that this method runs in the context of the copied object and it receives a Group Leader as a parameter, so you don't actually need to save anything, the system will save it for you.
Example:
cnt::make_cnt_copy(...)
{
string func_name; func_name = "cnt::make_cnt_copy";
object gl; gl=argv[0];
// Get a new Object
send_wait(0, top_object(), "call_attr", "cnt", "get_new_dob", NULL, NULL, gl);
if (msg_error()) {
logf(ERROR, "%s cannot create a new Object: %s", func_name, msg[0]);
return;
};
object new_dob;
// Copy the fields from an existing object to the new Object
new_dob = msg[0];
new_dob.first_name = first_name;
new_dob.notes = notes;
// TODO: add your specific fields here.
// Return the new object
set_return_data( new_dob );
}