@@ -68,6 +68,7 @@ uint16_t alt_launcher_fb_terminal_key(uint32_t mask, bool osd_button)
6868static pid_t s_pid = 0 ;
6969static int s_crash_count = 0 ;
7070static unsigned long s_respawn_timer = 0 ;
71+ static unsigned long s_tty_deadline = 0 ;
7172static unsigned long s_native_status_timer = 0 ;
7273static unsigned long s_native_fb_mode_timer = 0 ;
7374static bool s_gave_up = false ;
@@ -254,16 +255,6 @@ static void enable_native_crt_path(void)
254255 if (!s_native_fb_mode_timer) s_native_fb_mode_timer = 1 ;
255256}
256257
257- static void wait_launcher_tty_ready (pid_t pid)
258- {
259- for (int i = 0 ; i < 100 ; i++)
260- {
261- if (launcher_tty_ready (pid))
262- return ;
263- usleep (10000 );
264- }
265- }
266-
267258static void return_to_normal_mode (void )
268259{
269260 user_io_osd_key_enable (1 );
@@ -282,6 +273,7 @@ static void reset_launcher_state(void)
282273{
283274 s_pid = 0 ;
284275 s_respawn_timer = 0 ;
276+ s_tty_deadline = 0 ;
285277 s_crash_count = 0 ;
286278 s_gave_up = false ;
287279 s_init_pending = false ;
@@ -337,26 +329,63 @@ static void release_launcher_video(void)
337329 }
338330}
339331
332+ static void exec_launcher_child (const char *path)
333+ {
334+ setenv (" LC_ALL" , " en_US.UTF-8" , 1 );
335+ setenv (" HOME" , " /root" , 1 );
336+
337+ cpu_set_t set;
338+ CPU_ZERO (&set);
339+ CPU_SET (0 , &set);
340+ sched_setaffinity (0 , sizeof (set), &set);
341+
342+ setsid ();
343+
344+ int tty_fd = open (s_tty_path, O_RDWR );
345+ if (tty_fd >= 0 )
346+ {
347+ ioctl (tty_fd, TIOCSCTTY , 0 );
348+ dup2 (tty_fd, STDIN_FILENO );
349+ dup2 (tty_fd, STDOUT_FILENO );
350+ dup2 (tty_fd, STDERR_FILENO );
351+ if (tty_fd > STDERR_FILENO )
352+ close (tty_fd);
353+ }
354+
355+ static const char clear[] = " \033 [0m\033 [?25l\033 [37m\033 [40m\033 [2J\033 [H" ;
356+ if (write (STDOUT_FILENO , clear, sizeof (clear) - 1 ) < 0 ) {}
357+
358+ if (s_native_crt)
359+ execl (path, path, " --crt" , NULL );
360+ else
361+ execl (path, path, NULL );
362+ _exit (1 );
363+ }
364+
365+ static void finalize_spawn (void )
366+ {
367+ s_tty_deadline = 0 ;
368+ video_chvt (s_vt);
369+ if (!s_native_crt)
370+ video_fb_enable (1 );
371+ else
372+ {
373+ input_switch (0 );
374+ user_io_status_set (" [9]" , 1 );
375+ }
376+
377+ // The frontend grabs input as soon as it starts. If the OSD is still
378+ // up (e.g. user toggled CRT mode or hit Reboot from System Settings),
379+ // it would trap input with no way to dismiss it — drop it now.
380+ if (menu_present ()) MenuHide ();
381+ }
382+
340383static void spawn (void )
341384{
342385 char path[2100 ];
343386 strncpy (path, getFullPath (s_launcher_path), sizeof (path) - 1 );
344387 path[sizeof (path) - 1 ] = ' \0 ' ;
345388
346- static const char cmd[] =
347- " #!/bin/bash\n "
348- " export LC_ALL=en_US.UTF-8\n "
349- " export HOME=/root\n "
350- " printf '\\ 033[0m\\ 033[?25l\\ 033[37m\\ 033[40m\\ 033[2J\\ 033[H'\n "
351- " if [ \" $ALT_LAUNCHER_CRT\" = \" 1\" ]; then\n "
352- " exec \" $ALT_LAUNCHER_PATH\" --crt\n "
353- " fi\n "
354- " exec \" $ALT_LAUNCHER_PATH\"\n " ;
355-
356- unlink (" /tmp/alt_launcher" );
357- if (!FileSave (" /tmp/alt_launcher" , (void *)cmd, strlen (cmd)))
358- return ;
359-
360389 user_io_osd_key_enable (0 );
361390 clear_launcher_tty ();
362391
@@ -384,32 +413,11 @@ static void spawn(void)
384413 printf (" alt_launcher: spawned pid=%d path=%s\n " , s_pid, path);
385414 if (!s_pid)
386415 {
387- setenv (" ALT_LAUNCHER_PATH" , path, 1 );
388- setenv (" ALT_LAUNCHER_CRT" , s_native_crt ? " 1" : " 0" , 1 );
389- cpu_set_t set;
390- CPU_ZERO (&set);
391- CPU_SET (0 , &set);
392- sched_setaffinity (0 , sizeof (set), &set);
393- setsid ();
394- execl (" /sbin/agetty" , " /sbin/agetty" , " -a" , " root" , " -l" ,
395- " /tmp/alt_launcher" , " -i" , " --nohostname" , " -L" , s_tty, " linux" , NULL );
396- _exit (1 );
397- }
398-
399- wait_launcher_tty_ready (s_pid);
400- video_chvt (s_vt);
401- if (!s_native_crt)
402- video_fb_enable (1 );
403- else
404- {
405- input_switch (0 );
406- user_io_status_set (" [9]" , 1 );
416+ exec_launcher_child (path);
407417 }
408418
409- // The frontend grabs input as soon as it starts. If the OSD is still
410- // up (e.g. user toggled CRT mode or hit Reboot from System Settings),
411- // it would trap input with no way to dismiss it — drop it now.
412- if (menu_present ()) MenuHide ();
419+ s_tty_deadline = GetTimer (1000 );
420+ if (!s_tty_deadline) s_tty_deadline = 1 ;
413421}
414422
415423bool alt_launcher_active (void )
@@ -419,7 +427,7 @@ bool alt_launcher_active(void)
419427
420428bool alt_launcher_scheduler_sleep_enabled (void )
421429{
422- return s_pid || s_init_pending || s_respawn_timer;
430+ return s_pid || s_init_pending || s_respawn_timer || s_tty_deadline ;
423431}
424432
425433bool alt_launcher_native_crt (void )
@@ -474,6 +482,7 @@ void alt_launcher_init(bool native_crt)
474482 return ;
475483 s_crash_count = 0 ;
476484 s_respawn_timer = 0 ;
485+ s_tty_deadline = 0 ;
477486 s_native_crt = native_crt;
478487 s_init_pending = true ;
479488}
@@ -491,6 +500,7 @@ void alt_launcher_prepare_for_script(void)
491500 wait_launcher_stopped (pid);
492501 user_io_osd_key_enable (1 );
493502 s_respawn_timer = 0 ;
503+ s_tty_deadline = 0 ;
494504 s_crash_count = 0 ;
495505 s_init_pending = false ;
496506 s_gave_up = false ;
@@ -536,6 +546,7 @@ void alt_launcher_poll(void)
536546 if (waitpid (s_pid, &status, WNOHANG ) == s_pid)
537547 {
538548 s_pid = 0 ;
549+ s_tty_deadline = 0 ;
539550 user_io_osd_key_enable (1 );
540551 bool exited = WIFEXITED (status);
541552 int exit_status = exited ? WEXITSTATUS (status) : 0 ;
@@ -570,7 +581,11 @@ void alt_launcher_poll(void)
570581 s_crash_count = 0 ;
571582 s_respawn_timer = GetTimer (1000 );
572583 if (!s_respawn_timer) s_respawn_timer = 1 ;
584+ return ;
573585 }
586+
587+ if (s_tty_deadline && (launcher_tty_ready (s_pid) || CheckTimer (s_tty_deadline)))
588+ finalize_spawn ();
574589 return ;
575590 }
576591
0 commit comments