#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnorba.h" extern CORBA_ORB _gnorba_gnome_orbit_orb; /* * get_name_server_ior_from_root_window: * * This gets the IOR for the name server in a reliable way. * The root window has a property set "CORBA_NAME_SERVICE" * which has a Window ID. We then fetch that Window's * CORBA_NAME_SERVICE property and if it points to itself, * we know we had a valid and running name service */ static char * get_name_server_ior_from_root_window (void) { GdkAtom name_server_atom, name_server_ior_atom; GdkAtom string_atom, window_atom; Atom type; char *ior = NULL, *result; Window *proxy_data; Window proxy; int format; unsigned long nitems, after; guint32 old_warnings; old_warnings = gdk_error_warnings; gdk_error_warnings =0; gdk_error_code = 0; type = None; proxy = None; name_server_atom = gdk_atom_intern("GNOME_NAME_SERVER", FALSE); name_server_ior_atom = gdk_atom_intern("GNOME_NAME_SERVER_IOR", FALSE); string_atom = gdk_atom_intern("STRING", FALSE); window_atom = gdk_atom_intern("WINDOW", FALSE); proxy_data = NULL; XGetWindowProperty ( GDK_DISPLAY (), GDK_ROOT_WINDOW(), name_server_atom, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, (guchar **) &proxy_data); if (type == None) goto error; if (type != None){ if ((format == 32) && (nitems == 1)) proxy = *proxy_data; XFree (proxy_data); } proxy_data = NULL; XGetWindowProperty ( GDK_DISPLAY (), proxy, name_server_atom, 0, 1, False, AnyPropertyType, &type, &format, &nitems, &after, (guchar **) &proxy_data); if (!gdk_error_code && type != None){ if ((format == 32) && (nitems == 1)) if (*proxy_data != proxy){ XFree (proxy_data); goto error; } } else proxy = GDK_NONE; XFree (proxy_data); if (proxy == GDK_NONE) goto error; XGetWindowProperty (GDK_DISPLAY(), proxy, name_server_ior_atom, 0, 9999, False, string_atom, &type, &format, &nitems, &after, (guchar **)&ior); if (type != string_atom){ if (type != None) XFree (ior); goto error; } result = g_strdup (ior); XFree(ior); gdk_flush (); gdk_error_code = 0; gdk_error_warnings = old_warnings; gdk_flush (); return result; error: gdk_flush (); gdk_error_code = 0; gdk_error_warnings = old_warnings; gdk_flush (); return NULL; } typedef struct { GMainLoop *mloop; char iorbuf[2048]; char *do_srv_output; FILE *fh; } EXEActivateInfo; /* copied from goad.c */ static gboolean handle_exepipe(GIOChannel *source, GIOCondition condition, EXEActivateInfo *data) { gboolean retval = TRUE; *data->iorbuf = '\0'; if(!(condition & G_IO_IN) || !fgets(data->iorbuf, sizeof(data->iorbuf), data->fh)) { retval = FALSE; } if(retval && !strncmp(data->iorbuf, "IOR:", 4)) retval = FALSE; if(data->do_srv_output) g_message("srv output: '%s'", data->iorbuf); if(!retval) g_main_quit(data->mloop); return retval; } static CORBA_Object name_server_by_forking (CORBA_Environment *ev) { CORBA_Object name_service = CORBA_OBJECT_NIL; int iopipes[2]; pid_t pid; /* * Since we're pretty sure no name server is running, * we start it ourself and tell the (GNOME session) * world about it */ /* fork & get the ior from orbit-name-service stdout */ pipe(iopipes); pid = fork (); if (pid == -1) return name_service; if (pid) { FILE *iorfh; int status; EXEActivateInfo ai; guint watchid; GIOChannel *gioc; /* Parent */ waitpid(pid, &status, 0); /* de-zombify */ close(iopipes[1]); ai.fh = iorfh = fdopen(iopipes[0], "r"); ai.do_srv_output = getenv("GOAD_DEBUG_EXERUN"); ai.mloop = g_main_new(FALSE); gioc = g_io_channel_unix_new(iopipes[0]); watchid = g_io_add_watch(gioc, G_IO_IN|G_IO_HUP|G_IO_NVAL|G_IO_ERR, (GIOFunc)&handle_exepipe, &ai); g_io_channel_unref(gioc); g_main_run(ai.mloop); g_main_destroy(ai.mloop); g_strstrip(ai.iorbuf); if (strncmp(ai.iorbuf, "IOR:", 4)) goto out; name_service = CORBA_ORB_string_to_object((CORBA_ORB)_gnorba_gnome_orbit_orb, ai.iorbuf, ev); out: fclose(iorfh); } else if (fork ()) { /* de-zombifier process, just exit */ _exit(0); } else { /* Child of a child. We run the naming service */ struct sigaction sa; int i, open_max; open_max = sysconf(_SC_OPEN_MAX); for (i = 3; i < open_max; i++) fcntl(i, F_SETFD, 1); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, 0); close(0); close(iopipes[0]); dup2(iopipes[1], 1); dup2(iopipes[1], 2); setsid(); execlp("gnome-name-service", "gnome-name-service", NULL); _exit(1); } return name_service; } /** * gnome_name_service_get: * * This routine returns an object reference to the name server * for this user/session pair. This launches the name server if * it is the first application running it. * * Returns: an object reference to the name service. * */ CORBA_Object gnome_name_service_get(void) { static CORBA_Object name_service = CORBA_OBJECT_NIL; CORBA_Object retval = CORBA_OBJECT_NIL; CORBA_Environment ev; char *ior; int attempts; g_return_val_if_fail(_gnorba_gnome_orbit_orb, CORBA_OBJECT_NIL); CORBA_exception_init(&ev); /* * Actually, only 2 attempts would be enough * * We need this as 2 gnome-name-servers might be started * at the same time, so the name_server_by_forking might * fail. */ for (attempts = 0; CORBA_Object_is_nil(name_service, &ev) && attempts < 3; attempts++) { ior = get_name_server_ior_from_root_window (); if (ior) { CosNaming_NameComponent nc[1] = {{"GNOME", "subcontext"}}; CosNaming_Name nom; CORBA_Object tmp; nom._length = 1; nom._buffer = nc; name_service = CORBA_ORB_string_to_object(_gnorba_gnome_orbit_orb, ior, &ev); g_free (ior); if (!CORBA_Object_is_nil (name_service, &ev)) { tmp = CosNaming_NamingContext_resolve(name_service, &nom, &ev); if(ev._major == CORBA_NO_EXCEPTION) { CORBA_Object_release(tmp, &ev); goto out; } } } name_service = name_server_by_forking (&ev); if (!CORBA_Object_is_nil (name_service, &ev)) goto out; } if(CORBA_Object_is_nil(name_service, &ev)) g_warning(_("Could not get name service!")); out: retval = CORBA_Object_duplicate(name_service, &ev); CORBA_exception_free(&ev); return retval; }