@@ -218,6 +218,7 @@ print_summary (void)
218218 " on, off]. A positive real number denotes the maximum time\n"
219219 " to wait for a response, in seconds. Defaults to "
220220 G_STRINGIFY (CHICLE_PROBE_DURATION_DEFAULT ) ".\n"
221+ " --probe-mode=ARG How to probe the terminal [any, ctty, stdio].\n"
221222 " --version Show version.\n"
222223 " -v, --verbose Be verbose.\n"
223224
@@ -431,6 +432,27 @@ parse_probe_arg (G_GNUC_UNUSED const gchar *option_name, const gchar *value, G_G
431432 return result ;
432433}
433434
435+ static gboolean
436+ parse_probe_mode_arg (G_GNUC_UNUSED const gchar * option_name , const gchar * value , G_GNUC_UNUSED gpointer data , GError * * error )
437+ {
438+ gboolean result = TRUE;
439+
440+ if (!g_ascii_strcasecmp (value , "any" ))
441+ options .probe_mode = CHICLE_PROBE_MODE_ANY ;
442+ else if (!g_ascii_strcasecmp (value , "ctty" ))
443+ options .probe_mode = CHICLE_PROBE_MODE_CTTY ;
444+ else if (!g_ascii_strcasecmp (value , "stdio" ))
445+ options .probe_mode = CHICLE_PROBE_MODE_STDIO ;
446+ else
447+ {
448+ g_set_error (error , G_OPTION_ERROR , G_OPTION_ERROR_BAD_VALUE ,
449+ "Probe mode must be one of [any, ctty, stdio]." );
450+ result = FALSE;
451+ }
452+
453+ return result ;
454+ }
455+
434456static gboolean
435457parse_colors_arg (G_GNUC_UNUSED const gchar * option_name , const gchar * value , G_GNUC_UNUSED gpointer data , GError * * error )
436458{
@@ -1756,6 +1778,59 @@ chicle_retire_passthrough_workarounds_tmux (void)
17561778 return result ;
17571779}
17581780
1781+ static ChafaTerm *
1782+ new_ctty_term (void )
1783+ {
1784+ ChafaTerm * ctty_term = NULL ;
1785+
1786+ #if defined(L_ctermid ) && !defined(G_OS_WIN32 )
1787+ gchar dev_name [L_ctermid ];
1788+ gint in_fd = -1 , out_fd = -1 ;
1789+ pid_t proc_group ;
1790+
1791+ ctermid (dev_name );
1792+
1793+ in_fd = open (dev_name , O_RDONLY );
1794+ out_fd = open (dev_name , O_WRONLY );
1795+
1796+ if (in_fd < 0 || out_fd < 0 )
1797+ goto out ;
1798+
1799+ /* Don't probe tty if we're definitely in the background. This mitigates
1800+ * issues with running under timeout(1) in CI and such, but does not
1801+ * guarantee that we won't be moved to background between now and
1802+ * ChafaTerm's call to tcsetattr(), causing it to block. Those cases are
1803+ * outside the scope of our handling.
1804+ *
1805+ * If the user explicitly requests ctty probing, we skip this check. */
1806+
1807+ if (options .probe_mode != CHICLE_PROBE_MODE_CTTY )
1808+ {
1809+ proc_group = getpgrp ();
1810+
1811+ if (tcgetpgrp (in_fd ) != proc_group
1812+ || tcgetpgrp (out_fd ) != proc_group )
1813+ goto out ;
1814+ }
1815+
1816+ ctty_term = chafa_term_new (NULL ,
1817+ in_fd ,
1818+ out_fd ,
1819+ out_fd );
1820+ #endif
1821+
1822+ out :
1823+ if (!ctty_term )
1824+ {
1825+ if (in_fd >= 0 )
1826+ close (in_fd );
1827+ if (out_fd >= 0 )
1828+ close (out_fd );
1829+ }
1830+
1831+ return ctty_term ;
1832+ }
1833+
17591834gboolean
17601835chicle_parse_options (int * argc , char * * argv [])
17611836{
@@ -1807,6 +1882,7 @@ chicle_parse_options (int *argc, char **argv [])
18071882 { "polite" , '\0' , 0 , G_OPTION_ARG_CALLBACK , parse_polite_arg , "Polite" , NULL },
18081883 { "preprocess" , 'p' , 0 , G_OPTION_ARG_CALLBACK , parse_preprocess_arg , "Preprocessing" , NULL },
18091884 { "probe" , '\0' , 0 , G_OPTION_ARG_CALLBACK , parse_probe_arg , "Terminal probing" , NULL },
1885+ { "probe-mode" , '\0' , 0 , G_OPTION_ARG_CALLBACK , parse_probe_mode_arg , "Probe mode" , NULL },
18101886 { "relative" , '\0' , 0 , G_OPTION_ARG_CALLBACK , parse_relative_arg , "Relative" , NULL },
18111887 { "scale" , '\0' , 0 , G_OPTION_ARG_CALLBACK , parse_scale_arg , "Scale" , NULL },
18121888 { "size" , 's' , 0 , G_OPTION_ARG_CALLBACK , parse_size_arg , "Output size" , NULL },
@@ -1946,41 +2022,60 @@ chicle_parse_options (int *argc, char **argv [])
19462022
19472023 /* Synchronous probe for sixels, default colors, etc. */
19482024
1949- if ((options .probe == CHICLE_TRISTATE_TRUE
1950- || options .probe == CHICLE_TRISTATE_AUTO )
1951- && options .probe_duration >= 0.0 )
19522025 {
1953- chafa_term_sync_probe (term , options .probe_duration * 1000 );
2026+ ChafaTerm * ctty_term = NULL ;
2027+ ChafaTerm * probe_term = NULL ;
19542028
1955- if (!options .pixel_mode_set )
1956- {
1957- options .pixel_mode = chafa_term_info_get_best_pixel_mode (
1958- chafa_term_get_term_info (term ));
1959- }
2029+ if (options .probe_mode == CHICLE_PROBE_MODE_CTTY
2030+ || (options .probe_mode == CHICLE_PROBE_MODE_ANY &&
2031+ (!isatty (STDIN_FILENO ) || !isatty (STDOUT_FILENO ))))
2032+ probe_term = ctty_term = new_ctty_term ();
19602033
1961- if (!options .fg_color_set )
1962- {
1963- gint32 color = chafa_term_get_default_fg_color (term );
1964- if (color >= 0 )
1965- options .fg_color = color ;
1966- }
2034+ if (!probe_term )
2035+ probe_term = term ;
19672036
1968- if (!options .bg_color_set )
2037+ if ((options .probe == CHICLE_TRISTATE_TRUE
2038+ || options .probe == CHICLE_TRISTATE_AUTO )
2039+ && options .probe_duration >= 0.0 )
19692040 {
1970- gint32 color = chafa_term_get_default_bg_color (term );
1971- if (color >= 0 )
1972- options .bg_color = color ;
2041+ chafa_term_sync_probe (probe_term , options .probe_duration * 1000 );
2042+
2043+ if (!options .pixel_mode_set )
2044+ {
2045+ options .pixel_mode = chafa_term_info_get_best_pixel_mode (
2046+ chafa_term_get_term_info (probe_term ));
2047+ }
2048+
2049+ if (!options .fg_color_set )
2050+ {
2051+ gint32 color = chafa_term_get_default_fg_color (probe_term );
2052+ if (color >= 0 )
2053+ options .fg_color = color ;
2054+ }
2055+
2056+ if (!options .bg_color_set )
2057+ {
2058+ gint32 color = chafa_term_get_default_bg_color (probe_term );
2059+ if (color >= 0 )
2060+ options .bg_color = color ;
2061+ }
19732062 }
1974- }
19752063
1976- /* Detect terminal geometry */
2064+ /* Detect terminal geometry */
2065+
2066+ chafa_term_get_size_px (probe_term ,
2067+ & detected_term_size .width_pixels ,
2068+ & detected_term_size .height_pixels );
2069+ chafa_term_get_size_cells (probe_term ,
2070+ & detected_term_size .width_cells ,
2071+ & detected_term_size .height_cells );
19772072
1978- chafa_term_get_size_px (term ,
1979- & detected_term_size . width_pixels ,
1980- & detected_term_size . height_pixels );
1981- chafa_term_get_size_cells ( term ,
1982- & detected_term_size . width_cells ,
1983- & detected_term_size . height_cells );
2073+ chafa_term_set_term_info (term ,
2074+ chafa_term_get_term_info ( probe_term ));
2075+
2076+ if ( ctty_term )
2077+ chafa_term_destroy ( ctty_term );
2078+ }
19842079
19852080 /* Fall back on COLUMNS. It's the best we can do in some environments (e.g. CI). */
19862081
0 commit comments