What you need to study is llDialog().
http://wiki.secondlife.com/wiki/LlDialogHere is a sketchy so-called framework...
key Owner;
key Avatar;
string AvatarName;
integer Handle;
integer Cyclic = 0;
integer Channel;
integer kbCyclicChannel()
{
Cyclic = (Cyclic + 1) & 0xFFFF;
Channel = -200000 - Cyclic;
return Channel;
}
default
{
on_rez(integer param) { llResetScript(); }
state_entry()
{
Owner = llGetOwner();
state waiting;
}
}
state waiting
{
on_rez(integer param) { llResetScript(); }
touch_start(integer num)
{
Avatar = llDetectedKey(0);
if (Avatar == Owner) { return; } // Eventually
AvatarName = llDetectedName(0);
Handle = llListen(kbCyclicChannel(), "", Owner, ""

;
llSetTimerEvent(30.0); // 30s timeout;
llDialog(Owner, AvatarName + " would like to...", ["Allow", "Deny"], Channel);
}
listen(integer channel, string name, key id, string msg)
{
llSetTimerEvent(0.0); // Disable the timeout
llListenRemove(Handle); // No need to listen any more
if (msg == "Allow"

{
state action;
}
else if (msg == "Deny"

{
llDialog(Avatar, llKey2Name(Owner) + " refused to...", ["OK"], -9999); // Eventually
}
}
timer()
{
llSetTimerEvent(0.0); // Timeout!
llListenRemove(Handle); // Ignore the dialog
llOwnerSay("Time out. Dialog disabled."

;
llDialog(Avatar, llKey2Name(Owner) + " didn't react in a timely fashion.", ["OK"], -9999); // Eventually
}
} // End of wainting state
state action
{
on_rez(integer param) { llResetScript(); }
state_entry()
{
Handle = llListen(kbCyclicChannel(), "", Avatar, ""

;
llSetTimerEvent(30.0); // 30s timeout;
llDialog(Avatar, "What would you like to do?, ["Action1", "Action2", "Action3"], Channel);
}
listen(integer channel, string name, key id, string msg)
{
llSetTimerEvent(0.0); // Deactivate the timeout
llListenRemove(Handle); // No need to listen any more
if (msg == "Action1"

{
// Do something...
llOwnerSay(AvatarName + " selected 'Action 1'"

;
}
else if (msg == "Action2"

{
// Do something...
llOwnerSay(AvatarName + " selected 'Action 2'"

;
}
else if (msg == "Action3"

{
// Do something...
llOwnerSay(AvatarName + " selected 'Action 3'"

;
}
}
timer()
{
llSetTimerEvent(0.0);
llListenRemove(Handle);
llOwnerSay("Time out. " + AvatarName + " didn't react in a timely fashion."

;
llInstantMessage(Avatar, "Time out. Dialog disabled."

;
}
} // End of action state
Untested but that should work... once you'll remove the (eventual) typos.
Note that I didn't worry about if the object is attached or not so it will work also if it's on the ground.