@@ -202,6 +202,39 @@ namespace TeeJee.ProcessHelper{
202202 }
203203 }
204204
205+ public int notify_async (string script ){
206+ /**
207+ * Execute notify-send asynchronously.
208+ * Commands are written to a temporary bash script and executed.
209+ * Return value indicates if script was started successfully.
210+ */
211+
212+ try {
213+
214+ string scriptfile = save_bash_notify_temp (script);
215+
216+ string [] argv = new string [1 ];
217+ argv[0 ] = scriptfile;
218+
219+ string [] env = Environ . get ();
220+
221+ Pid child_pid;
222+ Process . spawn_async_with_pipes(
223+ TEMP_DIR , // working dir
224+ argv, // argv
225+ env, // environment
226+ SpawnFlags . SEARCH_PATH ,
227+ null ,
228+ out child_pid);
229+
230+ return 0 ;
231+ }
232+ catch (Error e){
233+ log_error (e. message);
234+ return 1 ;
235+ }
236+ }
237+
205238 /**
206239 executes a command as the "normal" unprivileged user async
207240 may execute the command as root if the user could not be determined or the name could not be resolved
@@ -222,6 +255,26 @@ namespace TeeJee.ProcessHelper{
222255 return TeeJee . ProcessHelper . exec_script_async(cmd);
223256 }
224257
258+ /**
259+ Even if notify-send fails to execute or its exit code cannot be read, it does not pose a major problem.
260+ Therefore, writing to the status file is disabled.
261+ */
262+ public static int exec_notify_async (string command ) {
263+ // find correct user
264+ int uid = TeeJee . System . get_user_id();
265+ string cmd = command;
266+ if (uid > 0 ) {
267+ // non root
268+ string ? user = TeeJee . System . get_username_from_uid(uid);
269+ if (user != null ) {
270+ cmd = " pkexec --user %s env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS " . printf(user) + cmd;
271+ }
272+ }
273+
274+ log_debug(cmd);
275+ return TeeJee . ProcessHelper . notify_async(cmd);
276+ }
277+
225278 public string ? save_bash_script_temp (string commands , string ? script_path = null ,
226279 bool force_locale = true , bool supress_errors = false ){
227280
@@ -271,6 +324,54 @@ namespace TeeJee.ProcessHelper{
271324 return null ;
272325 }
273326
327+ public string ? save_bash_notify_temp (string commands , string ? script_path = null ,
328+ bool force_locale = true , bool supress_errors = false ){
329+
330+ string sh_path = script_path;
331+
332+ /* Creates a temporary bash script with given commands
333+ * Returns the script file path */
334+
335+ var script = new StringBuilder ();
336+ script. append (" #!/usr/bin/env bash\n " );
337+ script. append (" \n " );
338+ if (force_locale){
339+ script. append(" LANG=C\n " );
340+ script. append(" LC_ALL=C.UTF-8\n " );
341+ }
342+ script. append (" \n " );
343+ script. append (" %s\n " . printf(commands));
344+ script. append (" \n\n exitCode=$?\n " );
345+
346+ if ((sh_path == null ) || (sh_path. length == 0 )){
347+ sh_path = get_temp_file_path();
348+ }
349+
350+ try {
351+ // write script file
352+ var file = File . new_for_path (sh_path);
353+ if (file. query_exists ()) {
354+ file. delete ();
355+ }
356+ var file_stream = file. create (FileCreateFlags . REPLACE_DESTINATION );
357+ var data_stream = new DataOutputStream (file_stream);
358+ data_stream. put_string (script. str);
359+ data_stream. close();
360+
361+ // set execute permission
362+ Posix . chmod (sh_path, 0744 );
363+
364+ return sh_path;
365+ }
366+ catch (Error e) {
367+ if (! supress_errors){
368+ log_error (e. message);
369+ }
370+ }
371+
372+ return null ;
373+ }
374+
274375 public string get_temp_file_path (){
275376
276377 /* Generates temporary file path */
0 commit comments