Fixed some bugs/behavioral differences to the R5 implementation.

* Run() was returning fTaskID, which was invalidated by Quit().
* assert_app_signature() -> check_app_signature(). InitData() now quits
  when an error occured and no error variable has been supplied. That seems
  to be what R5 does.
* When args are present B_ARGV_RECEIVED is always sent to the own team,
  even if the app flags include B_ARGV_ONLY. But it is sent to a remote
  application (already running instance), only if that app has NOT
  B_ARGV_ONLY set.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@564 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2002-08-03 16:19:31 +00:00
parent be5af1baf8
commit 9986313c0c
+54 -36
View File
@@ -170,7 +170,7 @@ enum {
// prototypes of helper functions // prototypes of helper functions
static const char* looper_name_for(const char *signature); static const char* looper_name_for(const char *signature);
static void assert_app_signature(const char *signature); static status_t check_app_signature(const char *signature);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
BApplication::BApplication(const char* signature) BApplication::BApplication(const char* signature)
@@ -261,7 +261,9 @@ thread_id BApplication::Run()
debugger(""); debugger("");
} }
fTaskID = find_thread(NULL); // Note: We need a local variable too (for the return value), since
// fTaskID is cleared by Quit().
thread_id thread = fTaskID = find_thread(NULL);
if (fMsgPort == B_NO_MORE_PORTS || fMsgPort == B_BAD_VALUE) if (fMsgPort == B_NO_MORE_PORTS || fMsgPort == B_BAD_VALUE)
{ {
@@ -272,7 +274,7 @@ thread_id BApplication::Run()
run_task(); run_task();
return fTaskID; return thread;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void BApplication::Quit() void BApplication::Quit()
@@ -569,7 +571,7 @@ void BApplication::InitData(const char* signature, status_t* error)
if (be_app) if (be_app)
debugger("2 BApplication objects were created. Only one is allowed."); debugger("2 BApplication objects were created. Only one is allowed.");
// check signature // check signature
assert_app_signature(signature); fInitError = check_app_signature(signature);
fAppName = signature; fAppName = signature;
bool isRegistrar = (signature && !strcmp(signature, kRegistrarSignature)); bool isRegistrar = (signature && !strcmp(signature, kRegistrarSignature));
// get team and thread // get team and thread
@@ -577,7 +579,8 @@ void BApplication::InitData(const char* signature, status_t* error)
thread_id thread = main_thread_for(team); thread_id thread = main_thread_for(team);
// get app executable ref // get app executable ref
entry_ref ref; entry_ref ref;
fInitError = get_app_ref(&ref); if (fInitError == B_OK)
fInitError = get_app_ref(&ref);
// get the BAppFileInfo and extract the information we need // get the BAppFileInfo and extract the information we need
uint32 appFlags = B_REG_DEFAULT_APP_FLAGS; uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
if (fInitError == B_OK) { if (fInitError == B_OK) {
@@ -611,9 +614,10 @@ void BApplication::InitData(const char* signature, status_t* error)
} else } else
appInfo.port = fMsgPort; appInfo.port = fMsgPort;
// Create a B_ARGV_RECEIVED message and send it to ourselves. // Create a B_ARGV_RECEIVED message and send it to ourselves.
// Do that even, if we are B_ARGV_ONLY.
// TODO: When BLooper::AddMessage() is done, use that instead of // TODO: When BLooper::AddMessage() is done, use that instead of
// PostMessage(). // PostMessage().
if (!(appFlags & B_ARGV_ONLY) && __libc_argc > 1) { if (__libc_argc > 1) {
BMessage argvMessage(B_ARGV_RECEIVED); BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage); do_argv(&argvMessage);
PostMessage(&argvMessage, this); PostMessage(&argvMessage, this);
@@ -624,47 +628,48 @@ void BApplication::InitData(const char* signature, status_t* error)
} else if (fInitError == B_OK) { } else if (fInitError == B_OK) {
// not pre-registered -- try to register the application // not pre-registered -- try to register the application
team_id otherTeam = -1; team_id otherTeam = -1;
status_t regError = B_OK;
// the registrar must not register // the registrar must not register
if (!isRegistrar) { if (!isRegistrar) {
regError = be_roster->AddApplication(signature, &ref, appFlags, fInitError = be_roster->AddApplication(signature, &ref, appFlags,
team, thread, fMsgPort, true, NULL, &otherTeam); team, thread, fMsgPort, true, NULL, &otherTeam);
} }
if (regError == B_ALREADY_RUNNING) { if (fInitError == B_ALREADY_RUNNING) {
// An instance is already running and we asked for // An instance is already running and we asked for
// single/exclusive launch. Send our argv to the running app and // single/exclusive launch. Send our argv to the running app.
// exit. // Do that only, if the app is NOT B_ARGV_ONLY.
if (!(appFlags & B_ARGV_ONLY) && otherTeam >= 0 if (otherTeam >= 0 && __libc_argc > 1) {
&& __libc_argc > 1) {
BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage);
// We need to replace the first argv string with the path
// of the respective application.
app_info otherAppInfo; app_info otherAppInfo;
if (be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo) if (be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo)
== B_OK) { == B_OK && !(otherAppInfo.flags & B_ARGV_ONLY)) {
// create an B_ARGV_RECEIVED message
BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage);
// replace the first argv string with the path of the
// other application
BPath path; BPath path;
if (path.SetTo(&otherAppInfo.ref) == B_OK) if (path.SetTo(&otherAppInfo.ref) == B_OK)
argvMessage.ReplaceString("argv", 0, path.Path()); argvMessage.ReplaceString("argv", 0, path.Path());
// send the message
BMessenger(NULL, otherTeam).SendMessage(&argvMessage);
} }
BMessenger(NULL, otherTeam).SendMessage(&argvMessage);
} }
exit(0); } else if (fInitError == B_OK) {
}
if (regError == B_OK) {
// the registrations was successful // the registrations was successful
// Create a B_ARGV_RECEIVED message and send it to ourselves. // Create a B_ARGV_RECEIVED message and send it to ourselves.
// Do that even, if we are B_ARGV_ONLY.
// TODO: When BLooper::AddMessage() is done, use that instead of // TODO: When BLooper::AddMessage() is done, use that instead of
// PostMessage(). // PostMessage().
if (!(appFlags & B_ARGV_ONLY) && __libc_argc > 1) { if (__libc_argc > 1) {
BMessage argvMessage(B_ARGV_RECEIVED); BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage); do_argv(&argvMessage);
PostMessage(&argvMessage, this); PostMessage(&argvMessage, this);
} }
// send a B_READY_TO_RUN message as well // send a B_READY_TO_RUN message as well
PostMessage(B_READY_TO_RUN, this); PostMessage(B_READY_TO_RUN, this);
} else } else if (fInitError > B_ERRORS_END) {
fInitError = regError; // Registrar internal errors shouldn't fall into the user's hands.
fInitError = B_ERROR;
}
} }
// init be_app and be_app_messenger // init be_app and be_app_messenger
if (fInitError == B_OK) { if (fInitError == B_OK) {
@@ -673,9 +678,12 @@ void BApplication::InitData(const char* signature, status_t* error)
} }
// TODO: SetName() // TODO: SetName()
// TODO: create_app_meta_mime() // TODO: create_app_meta_mime()
// return the error // Return the error or exit, if there was an error and no error variable
// has been supplied.
if (error) if (error)
*error = fInitError; *error = fInitError;
else if (fInitError != B_OK)
exit(0);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void BApplication::BeginRectTracking(BRect r, bool trackWhole) void BApplication::BeginRectTracking(BRect r, bool trackWhole)
@@ -778,13 +786,19 @@ int32 BApplication::async_quit_entry(void* data)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// assert_app_signature // check_app_signature
// /*! \brief Checks whether the supplied string is a valid application signature.
// Terminates with and error message, when the supplied signature is not a
// valid application signature. An error message is printed, if the string is no valid app signature.
\param signature The string to be checked.
\return
- \c B_OK: \a signature is a valid app signature.
- \c B_BAD_VALUE: \a signature is \c NULL or no valid app signature.
*/
static static
void status_t
assert_app_signature(const char *signature) check_app_signature(const char *signature)
{ {
bool isValid = false; bool isValid = false;
BMimeType type(signature); BMimeType type(signature);
@@ -796,14 +810,18 @@ assert_app_signature(const char *signature)
printf("bad signature (%s), must begin with \"application/\" and " printf("bad signature (%s), must begin with \"application/\" and "
"can't conflict with existing registered mime types inside " "can't conflict with existing registered mime types inside "
"the \"application\" media type.\n", signature); "the \"application\" media type.\n", signature);
exit(1);
} }
return (isValid ? B_OK : B_BAD_VALUE);
} }
// looper_name_for // looper_name_for
// /*! \brief Returns the looper name for a given signature.
// Returns the looper name for a given signature: Normally "AppLooperPort",
// but in case of the registrar a special name. Normally this is "AppLooperPort", but in case of the registrar a
special name.
\return The looper name.
*/
static static
const char* const char*
looper_name_for(const char *signature) looper_name_for(const char *signature)