static void setStringListProperty(SmcConn connection, const char *name, const char **values, int nValues) { SmProp prop, *pProp; int i; prop.name = (char *)name; prop.type = SmLISTofARRAY8; prop.vals = malloc(nValues * sizeof (SmPropValue)); if (!prop.vals) return; for (i = 0; i < nValues; i++) { prop.vals[i].value = (char *)values[i]; prop.vals[i].length = strlen(values[i]); } prop.num_vals = nValues; pProp = ∝ SmcSetProperties(connection, 1, &pProp); free(prop.vals); }
static void sm_set_some_properties() { SmPropValue program_val, userid_val; SmProp program_prop, userid_prop, clone_prop; SmProp *props[3]; props[0]=&program_prop; props[1]=&userid_prop; props[2]=&clone_prop; program_val.value=ioncore_g.argv[0]; program_val.length=strlen(program_val.value); program_prop.name=SmProgram; program_prop.type=SmARRAY8; program_prop.num_vals=1; program_prop.vals=&program_val; userid_val.value=getenv("USER"); userid_val.length=strlen(userid_val.value); userid_prop.name=SmUserID; userid_prop.type=SmARRAY8; userid_prop.num_vals=1; userid_prop.vals=&userid_val; clone_prop.name=SmCloneCommand; clone_prop.type=SmLISTofARRAY8; clone_prop.num_vals=1; clone_prop.vals=&program_val; SmcSetProperties(sm_conn, sizeof(props)/sizeof(props[0]), (SmProp **)&props); }
void meta_session_shutdown (void) { /* Change our restart mode to IfRunning */ SmProp prop1; SmPropValue prop1val; SmProp *props[1]; char hint = SmRestartIfRunning; if (!meta_get_display ()) { meta_verbose ("Cannot close session because there is no display"); return; } warn_about_lame_clients_and_finish_interact (FALSE); if (session_connection == NULL) return; prop1.name = SmRestartStyleHint; prop1.type = SmCARD8; prop1.num_vals = 1; prop1.vals = &prop1val; prop1val.value = &hint; prop1val.length = 1; props[0] = &prop1; SmcSetProperties (session_connection, 1, props); }
KRequestShutdownHelper::KRequestShutdownHelper() { #if HAVE_X11 SmcCallbacks calls; calls.save_yourself.callback = save_yourself_callback; calls.die.callback = dummy_callback; calls.save_complete.callback = dummy_callback; calls.shutdown_cancelled.callback = dummy_callback; char* id = NULL; char err[ 11 ]; conn = SmcOpenConnection( NULL, NULL, 1, 0, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, &calls, NULL, &id, 10, err ); if( id != NULL ) free( id ); if( conn == NULL ) return; // no SM // set the required properties, mostly dummy values SmPropValue propvalue[ 5 ]; SmProp props[ 5 ]; propvalue[ 0 ].length = sizeof( unsigned char ); unsigned char value0 = SmRestartNever; // so that this extra SM connection doesn't interfere propvalue[ 0 ].value = &value0; props[ 0 ].name = const_cast< char* >( SmRestartStyleHint ); props[ 0 ].type = const_cast< char* >( SmCARD8 ); props[ 0 ].num_vals = 1; props[ 0 ].vals = &propvalue[ 0 ]; struct passwd* entry = getpwuid( geteuid() ); propvalue[ 1 ].length = entry != NULL ? strlen( entry->pw_name ) : 0; propvalue[ 1 ].value = (SmPointer)( entry != NULL ? entry->pw_name : "" ); props[ 1 ].name = const_cast< char* >( SmUserID ); props[ 1 ].type = const_cast< char* >( SmARRAY8 ); props[ 1 ].num_vals = 1; props[ 1 ].vals = &propvalue[ 1 ]; propvalue[ 2 ].length = 0; propvalue[ 2 ].value = (SmPointer)( "" ); props[ 2 ].name = const_cast< char* >( SmRestartCommand ); props[ 2 ].type = const_cast< char* >( SmLISTofARRAY8 ); props[ 2 ].num_vals = 1; props[ 2 ].vals = &propvalue[ 2 ]; propvalue[ 3 ].length = strlen( "requestshutdownhelper" ); propvalue[ 3 ].value = (SmPointer)"requestshutdownhelper"; props[ 3 ].name = const_cast< char* >( SmProgram ); props[ 3 ].type = const_cast< char* >( SmARRAY8 ); props[ 3 ].num_vals = 1; props[ 3 ].vals = &propvalue[ 3 ]; propvalue[ 4 ].length = 0; propvalue[ 4 ].value = (SmPointer)( "" ); props[ 4 ].name = const_cast< char* >( SmCloneCommand ); props[ 4 ].type = const_cast< char* >( SmLISTofARRAY8 ); props[ 4 ].num_vals = 1; props[ 4 ].vals = &propvalue[ 4 ]; SmProp* p[ 5 ] = { &props[ 0 ], &props[ 1 ], &props[ 2 ], &props[ 3 ], &props[ 4 ] }; SmcSetProperties( conn, 5, p ); notifier = new QSocketNotifier( IceConnectionNumber( SmcGetIceConnection( conn )), QSocketNotifier::Read, this ); connect( notifier, SIGNAL(activated(int)), SLOT(processData())); #endif }
static void sm_set_other_properties() { char *restore="-session"; char *clientid="-smclientid"; int nvals=0, i; const char *sdir=NULL, *cid=NULL; SmPropValue restart_hint_val, *restart_val=NULL; SmProp restart_hint_prop={ SmRestartStyleHint, SmCARD8, 1, NULL}; SmProp restart_prop={ SmRestartCommand, SmLISTofARRAY8, 0, NULL}; SmProp *props[2]; restart_hint_prop.vals=&restart_hint_val; props[0]=&restart_prop; props[1]=&restart_hint_prop; sdir=extl_sessiondir(); cid=mod_sm_get_ion_id(); if(sdir==NULL || cid==NULL) return; restart_hint_val.value=&restart_hint; restart_hint_val.length=1; restart_val=(SmPropValue *)malloc((ioncore_g.argc+4)*sizeof(SmPropValue)); for(i=0; i<ioncore_g.argc; i++){ if(strcmp(ioncore_g.argv[i], restore)==0 || strcmp(ioncore_g.argv[i], clientid)==0){ i++; }else{ restart_val[nvals].value=ioncore_g.argv[i]; restart_val[nvals++].length=strlen(ioncore_g.argv[i]); } } restart_val[nvals].value=restore; restart_val[nvals++].length=strlen(restore); restart_val[nvals].value=(char*)sdir; restart_val[nvals++].length=strlen(sdir); restart_val[nvals].value=clientid; restart_val[nvals++].length=strlen(clientid); restart_val[nvals].value=(char*)cid; restart_val[nvals++].length=strlen(cid); restart_prop.num_vals=nvals; restart_prop.vals=restart_val; SmcSetProperties(sm_conn, sizeof(props)/sizeof(props[0]), (SmProp **)&props); free(restart_val); }
static void setProgramInfo (SmcConn connection, pid_t pid, uid_t uid) { SmProp progProp, pidProp, userProp; SmPropValue progVal, pidVal, userVal; SmProp *props[3]; char pidBuffer[32]; unsigned int count = 0; struct passwd *pw; progProp.name = const_cast<char *> (SmProgram); progProp.type = const_cast<char *> (SmARRAY8); progProp.num_vals = 1; progProp.vals = &progVal; progVal.value = (SmPointer) "compiz"; progVal.length = strlen ((char *) progVal.value); props[count++] = &progProp; snprintf (pidBuffer, sizeof (pidBuffer), "%d", pid); pidProp.name = const_cast<char *> (SmProcessID); pidProp.type = const_cast<char *> (SmARRAY8); pidProp.num_vals = 1; pidProp.vals = &pidVal; pidVal.value = (SmPointer) pidBuffer; pidVal.length = strlen (pidBuffer); props[count++] = &pidProp; pw = getpwuid (uid); if (pw) { userProp.name = const_cast<char *> (SmUserID); userProp.type = const_cast<char *> (SmARRAY8); userProp.num_vals = 1; userProp.vals = &userVal; userVal.value = (SmPointer) pw->pw_name; userVal.length = strlen (pw->pw_name); props[count++] = &userProp; } SmcSetProperties (connection, count, props); }
static void setRestartStyle(SmcConn connection, char hint) { SmProp prop, *pProp; SmPropValue propVal; prop.name = SmRestartStyleHint; prop.type = SmCARD8; prop.num_vals = 1; prop.vals = &propVal; propVal.value = &hint; propVal.length = 1; pProp = ∝ SmcSetProperties(connection, 1, &pProp); }
void meta_session_shutdown (void) { /* Change our restart mode to IfRunning */ SmProp prop1; SmPropValue prop1val; SmProp *props[1]; char hint = SmRestartIfRunning; if (session_connection == NULL) return; prop1.name = SmRestartStyleHint; prop1.type = SmCARD8; prop1.num_vals = 1; prop1.vals = &prop1val; prop1val.value = &hint; prop1val.length = 1; props[0] = &prop1; SmcSetProperties (session_connection, 1, props); }
static void smc_save_yourself_CB (SmcConn smcConn, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast) { #define NR_PROPS 5 SmProp *props[NR_PROPS]; SmProp prop_ptr[NR_PROPS]; SmPropValue values[20], *vp; int val_idx = 0, vp_idx = 0; int props_idx = 0; int i; char *smid_opt, *chdir_opt = NULL; Lisp_Object user_login_name = Fuser_login_name (Qnil); /* Must have these. */ if (! STRINGP (Vinvocation_name) || ! STRINGP (user_login_name)) return; /* How to start a new instance of Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmCloneCommand); props[props_idx]->type = xstrdup (SmLISTofARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; ++props_idx; /* The name of the program. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmProgram); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = SBYTES (Vinvocation_name); props[props_idx]->vals[0].value = SDATA (Vinvocation_name); ++props_idx; /* User id. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmUserID); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = SBYTES (user_login_name); props[props_idx]->vals[0].value = SDATA (user_login_name); ++props_idx; char *cwd = get_current_dir_name (); if (cwd) { props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmCurrentDirectory); props[props_idx]->type = xstrdup (SmARRAY8); props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (cwd); props[props_idx]->vals[0].value = cwd; ++props_idx; } /* How to restart Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = xstrdup (SmRestartCommand); props[props_idx]->type = xstrdup (SmLISTofARRAY8); /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir ... */ if (INT_ADD_WRAPV (initial_argc, 3, &i)) memory_full (SIZE_MAX); props[props_idx]->num_vals = i; vp = xnmalloc (i, sizeof *vp); props[props_idx]->vals = vp; props[props_idx]->vals[vp_idx].length = strlen (emacs_program); props[props_idx]->vals[vp_idx++].value = emacs_program; smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); strcpy (stpcpy (smid_opt, SMID_OPT), client_id); props[props_idx]->vals[vp_idx].length = strlen (smid_opt); props[props_idx]->vals[vp_idx++].value = smid_opt; props[props_idx]->vals[vp_idx].length = strlen (NOSPLASH_OPT); props[props_idx]->vals[vp_idx++].value = NOSPLASH_OPT; if (cwd) { chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1); strcpy (stpcpy (chdir_opt, CHDIR_OPT), cwd); props[props_idx]->vals[vp_idx].length = strlen (chdir_opt); props[props_idx]->vals[vp_idx++].value = chdir_opt; } for (i = 1; i < initial_argc; ++i) { props[props_idx]->vals[vp_idx].length = strlen (initial_argv[i]); props[props_idx]->vals[vp_idx++].value = initial_argv[i]; } ++props_idx; SmcSetProperties (smcConn, props_idx, props); xfree (smid_opt); xfree (chdir_opt); xfree (cwd); xfree (vp); for (i = 0; i < props_idx; ++i) { xfree (props[i]->type); xfree (props[i]->name); } /* See if we maybe shall interact with the user. */ if (interactStyle != SmInteractStyleAny || ! shutdown || saveType == SmSaveLocal || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) { /* No interaction, we are done saving ourself. */ SmcSaveYourselfDone (smcConn, True); } }
static void smc_save_yourself_CB (SmcConn smcConn, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast) { #define NR_PROPS 5 SmProp *props[NR_PROPS]; SmProp prop_ptr[NR_PROPS]; SmPropValue values[20]; int val_idx = 0; int props_idx = 0; char *cwd = NULL; char *smid_opt, *chdir_opt = NULL; /* How to start a new instance of Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmCloneCommand; props[props_idx]->type = SmLISTofARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; ++props_idx; /* The name of the program. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmProgram; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (SSDATA (Vinvocation_name)); props[props_idx]->vals[0].value = SDATA (Vinvocation_name); ++props_idx; /* How to restart Emacs. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmRestartCommand; props[props_idx]->type = SmLISTofARRAY8; /* /path/to/emacs, --smid=xxx --no-splash --chdir=dir */ props[props_idx]->num_vals = 4; props[props_idx]->vals = &values[val_idx]; props[props_idx]->vals[0].length = strlen (emacs_program); props[props_idx]->vals[0].value = emacs_program; smid_opt = xmalloc (strlen (SMID_OPT) + strlen (client_id) + 1); strcpy (smid_opt, SMID_OPT); strcat (smid_opt, client_id); props[props_idx]->vals[1].length = strlen (smid_opt); props[props_idx]->vals[1].value = smid_opt; props[props_idx]->vals[2].length = strlen (NOSPLASH_OPT); props[props_idx]->vals[2].value = NOSPLASH_OPT; cwd = get_current_dir_name (); if (cwd) { chdir_opt = xmalloc (strlen (CHDIR_OPT) + strlen (cwd) + 1); strcpy (chdir_opt, CHDIR_OPT); strcat (chdir_opt, cwd); props[props_idx]->vals[3].length = strlen (chdir_opt); props[props_idx]->vals[3].value = chdir_opt; } val_idx += cwd ? 4 : 3; ++props_idx; /* User id. */ props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmUserID; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (SSDATA (Vuser_login_name)); props[props_idx]->vals[0].value = SDATA (Vuser_login_name); ++props_idx; if (cwd) { props[props_idx] = &prop_ptr[props_idx]; props[props_idx]->name = SmCurrentDirectory; props[props_idx]->type = SmARRAY8; props[props_idx]->num_vals = 1; props[props_idx]->vals = &values[val_idx++]; props[props_idx]->vals[0].length = strlen (cwd); props[props_idx]->vals[0].value = cwd; ++props_idx; } SmcSetProperties (smcConn, props_idx, props); xfree (smid_opt); xfree (chdir_opt); free (cwd); /* See if we maybe shall interact with the user. */ if (interactStyle != SmInteractStyleAny || ! shutdown || saveType == SmSaveLocal || ! SmcInteractRequest (smcConn, SmDialogNormal, smc_interact_CB, 0)) { /* No interaction, we are done saving ourself. */ SmcSaveYourselfDone (smcConn, True); } }
static void set_clone_restart_commands (void) { char *restartv[10]; char *clonev[10]; char *discardv[10]; int i; SmProp prop1, prop2, prop3, *props[3]; /* Restart (use same client ID) */ prop1.name = SmRestartCommand; prop1.type = SmLISTofARRAY8; g_return_if_fail (client_id); i = 0; restartv[i] = "consortium"; ++i; restartv[i] = "--sm-client-id"; ++i; restartv[i] = client_id; ++i; restartv[i] = NULL; prop1.vals = g_new (SmPropValue, i); i = 0; while (restartv[i]) { prop1.vals[i].value = restartv[i]; prop1.vals[i].length = strlen (restartv[i]); ++i; } prop1.num_vals = i; /* Clone (no client ID) */ i = 0; clonev[i] = "consortium"; ++i; clonev[i] = NULL; prop2.name = SmCloneCommand; prop2.type = SmLISTofARRAY8; prop2.vals = g_new (SmPropValue, i); i = 0; while (clonev[i]) { prop2.vals[i].value = clonev[i]; prop2.vals[i].length = strlen (clonev[i]); ++i; } prop2.num_vals = i; /* Discard */ i = 0; discardv[i] = "rm"; ++i; discardv[i] = "-f"; ++i; discardv[i] = (char*) full_save_file (); ++i; discardv[i] = NULL; prop3.name = SmDiscardCommand; prop3.type = SmLISTofARRAY8; prop3.vals = g_new (SmPropValue, i); i = 0; while (discardv[i]) { prop3.vals[i].value = discardv[i]; prop3.vals[i].length = strlen (discardv[i]); ++i; } prop3.num_vals = i; props[0] = &prop1; props[1] = &prop2; props[2] = &prop3; SmcSetProperties (session_connection, 3, props); g_free (prop1.vals); g_free (prop2.vals); g_free (prop3.vals); }
void meta_session_init (const char *previous_client_id, const char *previous_save_file) { /* Some code here from twm */ char buf[256]; unsigned long mask; SmcCallbacks callbacks; char *saved_client_id; meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'\n", previous_save_file ? previous_save_file : "(none)"); if (previous_save_file) { saved_client_id = load_state (previous_save_file); previous_client_id = saved_client_id; } else if (previous_client_id) { char *save_file = g_strconcat (previous_client_id, ".ms", NULL); saved_client_id = load_state (save_file); g_free (save_file); } else { saved_client_id = NULL; } ice_init (); mask = SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; callbacks.save_yourself.callback = save_yourself_callback; callbacks.save_yourself.client_data = NULL; callbacks.die.callback = die_callback; callbacks.die.client_data = NULL; callbacks.save_complete.callback = save_complete_callback; callbacks.save_complete.client_data = NULL; callbacks.shutdown_cancelled.callback = shutdown_cancelled_callback; callbacks.shutdown_cancelled.client_data = NULL; session_connection = SmcOpenConnection (NULL, /* use SESSION_MANAGER env */ NULL, /* means use existing ICE connection */ SmProtoMajor, SmProtoMinor, mask, &callbacks, (char*) previous_client_id, &client_id, 255, buf); if (session_connection == NULL) { meta_topic (META_DEBUG_SM, "Failed to a open connection to a session manager, so window positions will not be saved: %s\n", buf); goto out; } else { if (client_id == NULL) meta_bug ("Session manager gave us a NULL client ID?"); meta_topic (META_DEBUG_SM, "Obtained session ID '%s'\n", client_id); } if (previous_client_id && strcmp (previous_client_id, client_id) == 0) current_state = STATE_IDLE; else current_state = STATE_REGISTERING; { SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6]; SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val; char pid[32]; char hint = SmRestartImmediately; char priority = 20; /* low to run before other apps */ prop1.name = SmProgram; prop1.type = SmARRAY8; prop1.num_vals = 1; prop1.vals = &prop1val; prop1val.value = "consortium"; prop1val.length = strlen ("consortium"); /* twm sets getuid() for this, but the SM spec plainly * says pw_name, twm is on crack */ prop2.name = SmUserID; prop2.type = SmARRAY8; prop2.num_vals = 1; prop2.vals = &prop2val; prop2val.value = (char*) g_get_user_name (); prop2val.length = strlen (prop2val.value); prop3.name = SmRestartStyleHint; prop3.type = SmCARD8; prop3.num_vals = 1; prop3.vals = &prop3val; prop3val.value = &hint; prop3val.length = 1; sprintf (pid, "%d", getpid ()); prop4.name = SmProcessID; prop4.type = SmARRAY8; prop4.num_vals = 1; prop4.vals = &prop4val; prop4val.value = pid; prop4val.length = strlen (prop4val.value); /* Always start in home directory */ prop5.name = SmCurrentDirectory; prop5.type = SmARRAY8; prop5.num_vals = 1; prop5.vals = &prop5val; prop5val.value = (char*) g_get_home_dir (); prop5val.length = strlen (prop5val.value); prop6.name = "_GSM_Priority"; prop6.type = SmCARD8; prop6.num_vals = 1; prop6.vals = &prop6val; prop6val.value = &priority; prop6val.length = 1; props[0] = &prop1; props[1] = &prop2; props[2] = &prop3; props[3] = &prop4; props[4] = &prop5; props[5] = &prop6; SmcSetProperties (session_connection, 6, props); } out: g_free (saved_client_id); }
NS_IMETHODIMP nsNativeAppSupportUnix::Start(bool *aRetVal) { NS_ASSERTION(gAppData, "gAppData must not be null."); // The dbus library is used by both nsWifiScannerDBus and BluetoothDBusService, // from diffrent threads. This could lead to race conditions if the dbus is not // initialized before making any other library calls. #ifdef MOZ_ENABLE_DBUS dbus_threads_init_default(); #endif #if (MOZ_WIDGET_GTK == 2) if (gtk_major_version < MIN_GTK_MAJOR_VERSION || (gtk_major_version == MIN_GTK_MAJOR_VERSION && gtk_minor_version < MIN_GTK_MINOR_VERSION)) { GtkWidget* versionErrDialog = gtk_message_dialog_new(nullptr, GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, UNSUPPORTED_GTK_MSG, gtk_major_version, gtk_minor_version, MIN_GTK_MAJOR_VERSION, MIN_GTK_MINOR_VERSION); gtk_dialog_run(GTK_DIALOG(versionErrDialog)); gtk_widget_destroy(versionErrDialog); exit(0); } #endif *aRetVal = true; #ifdef MOZ_X11 gboolean sm_disable = FALSE; if (!getenv("SESSION_MANAGER")) { sm_disable = TRUE; } nsAutoCString prev_client_id; char **curarg = gArgv + 1; while (*curarg) { char *arg = *curarg; if (arg[0] == '-' && arg[1] == '-') { arg += 2; if (!strcmp(arg, "sm-disable")) { RemoveArg(curarg); sm_disable = TRUE; continue; } else if (!strcmp(arg, "sm-client-id")) { RemoveArg(curarg); if (*curarg[0] != '-') { prev_client_id = *curarg; RemoveArg(curarg); } continue; } } ++curarg; } if (prev_client_id.IsEmpty()) { prev_client_id = getenv("DESKTOP_AUTOSTART_ID"); } // We don't want child processes to use the same ID unsetenv("DESKTOP_AUTOSTART_ID"); char *client_id = nullptr; if (!sm_disable) { PRLibrary *iceLib = PR_LoadLibrary("libICE.so.6"); if (!iceLib) { return NS_OK; } PRLibrary *smLib = PR_LoadLibrary("libSM.so.6"); if (!smLib) { PR_UnloadLibrary(iceLib); return NS_OK; } IceSetIOErrorHandler = (IceSetIOErrorHandlerFn)PR_FindFunctionSymbol(iceLib, "IceSetIOErrorHandler"); IceAddConnectionWatch = (IceAddConnectionWatchFn)PR_FindFunctionSymbol(iceLib, "IceAddConnectionWatch"); IceConnectionNumber = (IceConnectionNumberFn)PR_FindFunctionSymbol(iceLib, "IceConnectionNumber"); IceProcessMessages = (IceProcessMessagesFn)PR_FindFunctionSymbol(iceLib, "IceProcessMessages"); IceGetConnectionContext = (IceGetConnectionContextFn)PR_FindFunctionSymbol(iceLib, "IceGetConnectionContext"); if (!IceSetIOErrorHandler || !IceAddConnectionWatch || !IceConnectionNumber || !IceProcessMessages || !IceGetConnectionContext) { PR_UnloadLibrary(iceLib); PR_UnloadLibrary(smLib); return NS_OK; } SmcInteractDone = (SmcInteractDoneFn)PR_FindFunctionSymbol(smLib, "SmcInteractDone"); SmcSaveYourselfDone = (SmcSaveYourselfDoneFn)PR_FindFunctionSymbol(smLib, "SmcSaveYourselfDone"); SmcInteractRequest = (SmcInteractRequestFn)PR_FindFunctionSymbol(smLib, "SmcInteractRequest"); SmcCloseConnection = (SmcCloseConnectionFn)PR_FindFunctionSymbol(smLib, "SmcCloseConnection"); SmcOpenConnection = (SmcOpenConnectionFn)PR_FindFunctionSymbol(smLib, "SmcOpenConnection"); SmcSetProperties = (SmcSetPropertiesFn)PR_FindFunctionSymbol(smLib, "SmcSetProperties"); if (!SmcInteractDone || !SmcSaveYourselfDone || !SmcInteractRequest || !SmcCloseConnection || !SmcOpenConnection || !SmcSetProperties) { PR_UnloadLibrary(iceLib); PR_UnloadLibrary(smLib); return NS_OK; } ice_init(); // all callbacks are mandatory in libSM 1.0, so listen even if we don't care. unsigned long mask = SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; SmcCallbacks callbacks; callbacks.save_yourself.callback = nsNativeAppSupportUnix::SaveYourselfCB; callbacks.save_yourself.client_data = static_cast<SmPointer>(this); callbacks.die.callback = nsNativeAppSupportUnix::DieCB; callbacks.die.client_data = static_cast<SmPointer>(this); callbacks.save_complete.callback = nsNativeAppSupportUnix::SaveCompleteCB; callbacks.save_complete.client_data = nullptr; callbacks.shutdown_cancelled.callback = nsNativeAppSupportUnix::ShutdownCancelledCB; callbacks.shutdown_cancelled.client_data = static_cast<SmPointer>(this); char errbuf[256]; mSessionConnection = SmcOpenConnection(nullptr, this, SmProtoMajor, SmProtoMinor, mask, &callbacks, prev_client_id.get(), &client_id, sizeof(errbuf), errbuf); } if (!mSessionConnection) { return NS_OK; } LogModule::Init(); // need to make sure initialized before SetClientState if (prev_client_id.IsEmpty() || (client_id && !prev_client_id.Equals(client_id))) { SetClientState(STATE_REGISTERING); } else { SetClientState(STATE_IDLE); } gdk_x11_set_sm_client_id(client_id); // Set SM Properties // SmCloneCommand, SmProgram, SmRestartCommand, SmUserID are required // properties so must be set, and must have a sensible fallback value. // Determine executable path to use for XSMP session restore // Is there a request to suppress default binary launcher? nsAutoCString path(getenv("MOZ_APP_LAUNCHER")); if (path.IsEmpty()) { NS_ASSERTION(gDirServiceProvider, "gDirServiceProvider is NULL! This shouldn't happen!"); nsCOMPtr<nsIFile> executablePath; nsresult rv; bool dummy; rv = gDirServiceProvider->GetFile(XRE_EXECUTABLE_FILE, &dummy, getter_AddRefs(executablePath)); if (NS_SUCCEEDED(rv)) { // Strip off the -bin suffix to get the shell script we should run; this is what Breakpad does nsAutoCString leafName; rv = executablePath->GetNativeLeafName(leafName); if (NS_SUCCEEDED(rv) && StringEndsWith(leafName, NS_LITERAL_CSTRING("-bin"))) { leafName.SetLength(leafName.Length() - strlen("-bin")); executablePath->SetNativeLeafName(leafName); } executablePath->GetNativePath(path); } } if (path.IsEmpty()) { // can't determine executable path. Best fallback is name from // application.ini but it might not resolve to the same executable at // launch time. path = gAppData->name; // will always be set ToLowerCase(path); MOZ_LOG(sMozSMLog, LogLevel::Warning, ("Could not determine executable path. Falling back to %s.", path.get())); } SmProp propRestart, propClone, propProgram, propUser, *props[4]; SmPropValue valsRestart[3], valsClone[1], valsProgram[1], valsUser[1]; int n = 0; NS_NAMED_LITERAL_CSTRING(kClientIDParam, "--sm-client-id"); SetSMValue(valsRestart[0], path); SetSMValue(valsRestart[1], kClientIDParam); SetSMValue(valsRestart[2], nsDependentCString(client_id)); SetSMProperty(propRestart, SmRestartCommand, SmLISTofARRAY8, 3, valsRestart); props[n++] = &propRestart; SetSMValue(valsClone[0], path); SetSMProperty(propClone, SmCloneCommand, SmLISTofARRAY8, 1, valsClone); props[n++] = &propClone; nsAutoCString appName(gAppData->name); // will always be set ToLowerCase(appName); SetSMValue(valsProgram[0], appName); SetSMProperty(propProgram, SmProgram, SmARRAY8, 1, valsProgram); props[n++] = &propProgram; nsAutoCString userName; // username that started the program struct passwd* pw = getpwuid(getuid()); if (pw && pw->pw_name) { userName = pw->pw_name; } else { userName = NS_LITERAL_CSTRING("nobody"); MOZ_LOG(sMozSMLog, LogLevel::Warning, ("Could not determine user-name. Falling back to %s.", userName.get())); } SetSMValue(valsUser[0], userName); SetSMProperty(propUser, SmUserID, SmARRAY8, 1, valsUser); props[n++] = &propUser; SmcSetProperties(mSessionConnection, n, props); g_free(client_id); #endif /* MOZ_X11 */ return NS_OK; }
static void set_save_props(SmcConn smc_conn, int master_flag) { const char *s; const char *user; const char *program; char priority = 10; char style; int i, n; SmPropValue programVal; SmPropValue userIDVal; #if USE_DISCARD_PROPERTY const char *sh = "sh"; const char *c = "-c"; const char *sm_file; SmPropValue discardVal[3]; SmProp discardProp; #endif #ifdef USE_EXT_INIT_WIN char bufx[32]; #endif SmPropValue restartVal[32]; SmPropValue styleVal; SmPropValue priorityVal; SmProp programProp; SmProp userIDProp; SmProp restartProp; SmProp cloneProp; SmProp styleProp; SmProp priorityProp; SmProp *props[7]; char bufs[32], bufm[32]; if (EDebug(EDBUG_TYPE_SESSION)) Eprintf("set_save_props\n"); programProp.name = (char *)SmProgram; programProp.type = (char *)SmARRAY8; programProp.num_vals = 1; programProp.vals = &programVal; userIDProp.name = (char *)SmUserID; userIDProp.type = (char *)SmARRAY8; userIDProp.num_vals = 1; userIDProp.vals = &userIDVal; #if USE_DISCARD_PROPERTY discardProp.name = (char *)SmDiscardCommand; discardProp.type = (char *)SmLISTofARRAY8; discardProp.num_vals = 3; discardProp.vals = discardVal; #endif restartProp.name = (char *)SmRestartCommand; restartProp.type = (char *)SmLISTofARRAY8; restartProp.vals = restartVal; cloneProp.name = (char *)SmCloneCommand; cloneProp.type = (char *)SmLISTofARRAY8; cloneProp.vals = restartVal; styleProp.name = (char *)SmRestartStyleHint; styleProp.type = (char *)SmCARD8; styleProp.num_vals = 1; styleProp.vals = &styleVal; priorityProp.name = (char *)"_GSM_Priority"; priorityProp.type = (char *)SmCARD8; priorityProp.num_vals = 1; priorityProp.vals = &priorityVal; if (master_flag) /* Master WM restarts immediately for a doExit("restart") */ style = restarting ? SmRestartImmediately : SmRestartIfRunning; else /* Slave WMs never restart */ style = SmRestartNever; user = username(); /* The SM specs state that the SmProgram should be the argument passed * to execve. Passing argv[0] is close enough. */ program = Mode.wm.exec_name; userIDVal.length = (user) ? strlen(user) : 0; userIDVal.value = (char *)user; programVal.length = strlen(program); programVal.value = (char *)program; styleVal.length = 1; styleVal.value = &style; priorityVal.length = 1; priorityVal.value = &priority; #if USE_DISCARD_PROPERTY /* Tell session manager how to clean up our old data */ sm_file = EGetSavePrefix(); Esnprintf(buf, sizeof(buf), "rm %s*.clients.*", sm_file); discardVal[0].length = strlen(sh); discardVal[0].value = sh; discardVal[1].length = strlen(c); discardVal[1].value = c; discardVal[2].length = strlen(buf); discardVal[2].value = buf; /* ??? Also used in restartVal ??? */ #endif n = 0; restartVal[n++].value = (char *)program; if (Mode.wm.single) { Esnprintf(bufs, sizeof(bufs), "%i", Mode.wm.master_screen); restartVal[n++].value = (char *)"-s"; restartVal[n++].value = (char *)bufs; } else if (restarting && !Mode.wm.master) { Esnprintf(bufm, sizeof(bufm), "%i", Mode.wm.master_screen); restartVal[n++].value = (char *)"-m"; restartVal[n++].value = bufm; } #ifdef USE_EXT_INIT_WIN if (restarting) { Esnprintf(bufx, sizeof(bufx), "%#lx", new_init_win_ext); restartVal[n++].value = (char *)"-X"; restartVal[n++].value = bufx; } #endif #if 0 restartVal[n++].value = (char *)smfile; restartVal[n++].value = (char *)sm_file; #endif s = Mode.conf.name; if (s) { restartVal[n++].value = (char *)"-p"; restartVal[n++].value = (char *)s; } s = Mode.conf.dir; if (s) { restartVal[n++].value = (char *)"-P"; restartVal[n++].value = (char *)s; } s = Mode.conf.cache_dir; if (s) { restartVal[n++].value = (char *)"-Q"; restartVal[n++].value = (char *)s; } s = sm_client_id; restartVal[n++].value = (char *)"-S"; restartVal[n++].value = (char *)s; for (i = 0; i < n; i++) restartVal[i].length = strlen((const char *)restartVal[i].value); restartProp.num_vals = n; /* SM specs require SmCloneCommand excludes "--sm-client-id" option */ cloneProp.num_vals = restartProp.num_vals - 2; if (EDebug(EDBUG_TYPE_SESSION)) for (i = 0; i < restartProp.num_vals; i++) Eprintf("restartVal[i]: %2d: %s\n", restartVal[i].length, (char *)restartVal[i].value); n = 0; props[n++] = &programProp; props[n++] = &userIDProp; #if USE_DISCARD_PROPERTY props[n++] = &discardProp; #endif props[n++] = &restartProp; props[n++] = &cloneProp; props[n++] = &styleProp; props[n++] = &priorityProp; SmcSetProperties(smc_conn, n, props); }
static void ice_init(void) { static SmPointer context; SmcCallbacks callbacks; char error_string_ret[4096]; char *client_id; char style[2]; SmPropValue styleVal; SmProp styleProp; SmProp *props[1]; int sm_fd; if (!getenv("SESSION_MANAGER")) return; IceSetIOErrorHandler(ice_io_error_handler); callbacks.save_yourself.callback = callback_save_yourself; callbacks.die.callback = callback_die; callbacks.save_complete.callback = callback_save_complete; callbacks.shutdown_cancelled.callback = callback_shutdown_cancelled; callbacks.save_yourself.client_data = callbacks.die.client_data = callbacks.save_complete.client_data = callbacks.shutdown_cancelled.client_data = (SmPointer) NULL; client_id = Estrdup(sm_client_id); error_string_ret[0] = '\0'; sm_conn = SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, &callbacks, client_id, &sm_client_id, 4096, error_string_ret); Efree(client_id); if (error_string_ret[0]) Eprintf("While connecting to session manager: %s.", error_string_ret); if (!sm_conn) return; style[0] = SmRestartIfRunning; style[1] = 0; styleVal.length = 1; styleVal.value = style; styleProp.name = (char *)SmRestartStyleHint; styleProp.type = (char *)SmCARD8; styleProp.num_vals = 1; styleProp.vals = &styleVal; props[0] = &styleProp; ice_conn = SmcGetIceConnection(sm_conn); sm_fd = IceConnectionNumber(ice_conn); /* Just in case we are a copy of E created by a doExit("restart") */ SmcSetProperties(sm_conn, 1, props); fcntl(sm_fd, F_SETFD, fcntl(sm_fd, F_GETFD, 0) | FD_CLOEXEC); sm_efd = EventFdRegister(sm_fd, ice_msgs_process); }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; char t[256], *vendor, *client_id; SmcCallbacks callbacks; SmProp prop_program, prop_user; SmProp *prop_list[2]; SmPropValue val_program, val_user; struct userdata *u; const char *e; pa_client_new_data data; pa_assert(m); if (ice_in_use) { pa_log("module-x11-xsmp may no be loaded twice."); return -1; } IceAddConnectionWatch(new_ice_connection, m->core); ice_in_use = TRUE; m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; u->module = m; u->client = NULL; u->connection = NULL; u->x11 = NULL; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL)))) goto fail; e = pa_modargs_get_value(ma, "session_manager", NULL); if (!e && !getenv("SESSION_MANAGER")) { pa_log("X11 session manager not running."); goto fail; } memset(&callbacks, 0, sizeof(callbacks)); callbacks.die.callback = die_cb; callbacks.die.client_data = u; callbacks.save_yourself.callback = save_yourself_cb; callbacks.save_yourself.client_data = m->core; callbacks.save_complete.callback = save_complete_cb; callbacks.save_complete.client_data = m->core; callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb; callbacks.shutdown_cancelled.client_data = m->core; if (!(u->connection = SmcOpenConnection( (char*) e, m->core, SmProtoMajor, SmProtoMinor, SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask, &callbacks, NULL, &client_id, sizeof(t), t))) { pa_log("Failed to open connection to session manager: %s", t); goto fail; } prop_program.name = (char*) SmProgram; prop_program.type = (char*) SmARRAY8; val_program.value = (char*) PACKAGE_NAME; val_program.length = (int) strlen(val_program.value); prop_program.num_vals = 1; prop_program.vals = &val_program; prop_list[0] = &prop_program; prop_user.name = (char*) SmUserID; prop_user.type = (char*) SmARRAY8; pa_get_user_name(t, sizeof(t)); val_user.value = t; val_user.length = (int) strlen(val_user.value); prop_user.num_vals = 1; prop_user.vals = &val_user; prop_list[1] = &prop_user; SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list); pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id); pa_client_new_data_init(&data); data.module = m; data.driver = __FILE__; pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "XSMP Session on %s as %s", vendor, client_id); pa_proplist_sets(data.proplist, "xsmp.vendor", vendor); pa_proplist_sets(data.proplist, "xsmp.client.id", client_id); u->client = pa_client_new(u->core, &data); pa_client_new_data_done(&data); free(vendor); free(client_id); if (!u->client) goto fail; pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }