@@ -178,7 +178,12 @@ namespace TeeJee.ProcessHelper{
178178
179179 try {
180180
181- string scriptfile = save_bash_script_temp (script);
181+ string ? scriptfile = save_bash_script_temp (script);
182+
183+ if (scriptfile == null ) {
184+ log_error(" Failed to create temporary script" );
185+ return 1 ;
186+ }
182187
183188 string [] argv = new string [1 ];
184189 argv[0 ] = scriptfile;
@@ -202,6 +207,44 @@ namespace TeeJee.ProcessHelper{
202207 }
203208 }
204209
210+ public int notify_async (string script ){
211+ /**
212+ * Execute notify-send asynchronously.
213+ * Commands are written to a temporary bash script and executed.
214+ * Return value indicates if script was started successfully.
215+ */
216+
217+ try {
218+
219+ string ? scriptfile = save_bash_notify_temp (script);
220+
221+ if (scriptfile == null ) {
222+ log_error(" Failed to create temporary script for notify-send" );
223+ return 1 ;
224+ }
225+
226+ string [] argv = new string [1 ];
227+ argv[0 ] = scriptfile;
228+
229+ string [] env = Environ . get ();
230+
231+ Pid child_pid;
232+ Process . spawn_async_with_pipes(
233+ TEMP_DIR , // working dir
234+ argv, // argv
235+ env, // environment
236+ SpawnFlags . SEARCH_PATH ,
237+ null ,
238+ out child_pid);
239+
240+ return 0 ;
241+ }
242+ catch (Error e){
243+ log_error (e. message);
244+ return 1 ;
245+ }
246+ }
247+
205248 /**
206249 executes a command as the "normal" unprivileged user async
207250 may execute the command as root if the user could not be determined or the name could not be resolved
@@ -222,6 +265,26 @@ namespace TeeJee.ProcessHelper{
222265 return TeeJee . ProcessHelper . exec_script_async(cmd);
223266 }
224267
268+ /**
269+ Even if notify-send fails to execute or its exit code cannot be read, it does not pose a major problem.
270+ Therefore, writing to the status file is disabled.
271+ */
272+ public static int exec_notify_async (string command ) {
273+ // find correct user
274+ int uid = TeeJee . System . get_user_id();
275+ string cmd = command;
276+ if (uid > 0 ) {
277+ // non root
278+ string ? user = TeeJee . System . get_username_from_uid(uid);
279+ if (user != null ) {
280+ cmd = " pkexec --user %s env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS " . printf(user) + cmd;
281+ }
282+ }
283+
284+ log_debug(cmd);
285+ return TeeJee . ProcessHelper . notify_async(cmd);
286+ }
287+
225288 public string ? save_bash_script_temp (string commands , string ? script_path = null ,
226289 bool force_locale = true , bool supress_errors = false ){
227290
@@ -271,6 +334,53 @@ namespace TeeJee.ProcessHelper{
271334 return null ;
272335 }
273336
337+ public string ? save_bash_notify_temp (string commands , string ? script_path = null ,
338+ bool force_locale = true , bool supress_errors = false ){
339+
340+ string sh_path = script_path;
341+
342+ /* Creates a temporary bash script with given commands
343+ * Returns the script file path */
344+
345+ var script = new StringBuilder ();
346+ script. append (" #!/usr/bin/env bash\n " );
347+ script. append (" \n " );
348+ if (force_locale){
349+ script. append(" LANG=C\n " );
350+ script. append(" LC_ALL=C.UTF-8\n " );
351+ }
352+ script. append (" \n " );
353+ script. append (" %s\n " . printf(commands));
354+
355+ if ((sh_path == null ) || (sh_path. length == 0 )){
356+ sh_path = get_temp_file_path();
357+ }
358+
359+ try {
360+ // write script file
361+ var file = File . new_for_path (sh_path);
362+ if (file. query_exists ()) {
363+ file. delete ();
364+ }
365+ var file_stream = file. create (FileCreateFlags . REPLACE_DESTINATION );
366+ var data_stream = new DataOutputStream (file_stream);
367+ data_stream. put_string (script. str);
368+ data_stream. close();
369+
370+ // set execute permission
371+ Posix . chmod (sh_path, 0744 );
372+
373+ return sh_path;
374+ }
375+ catch (Error e) {
376+ if (! supress_errors){
377+ log_error (e. message);
378+ }
379+ }
380+
381+ return null ;
382+ }
383+
274384 public string get_temp_file_path (){
275385
276386 /* Generates temporary file path */
0 commit comments