mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-26 06:07:56 +00:00
Add our own polkit listener implementation
This lets us respect the fancy output setting, and it lets us do some other things that make it better integrated. Closes: #2379 Approved by: alexlarsson
This commit is contained in:
parent
6d95383050
commit
b8cad064eb
@ -20,6 +20,8 @@ app/%-dbus-generated.h: app/%-dbus-generated.c
|
||||
|
||||
flatpak_SOURCES = \
|
||||
app/flatpak-main.c \
|
||||
app/flatpak-polkit-agent-text-listener.h \
|
||||
app/flatpak-polkit-agent-text-listener.c \
|
||||
app/flatpak-builtins.h \
|
||||
app/flatpak-builtins-utils.h \
|
||||
app/flatpak-builtins-utils.c \
|
||||
|
||||
@ -32,8 +32,7 @@
|
||||
|
||||
#ifdef USE_SYSTEM_HELPER
|
||||
#include <polkit/polkit.h>
|
||||
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <polkitagent/polkitagent.h>
|
||||
#include "flatpak-polkit-agent-text-listener.h"
|
||||
#endif
|
||||
|
||||
#include "flatpak-builtins.h"
|
||||
@ -638,7 +637,7 @@ main (int argc,
|
||||
|
||||
#ifdef USE_SYSTEM_HELPER
|
||||
/* Install a polkit agent as fallback, in case we're running on a console */
|
||||
listener = polkit_agent_text_listener_new (NULL, &error);
|
||||
listener = flatpak_polkit_agent_text_listener_new (NULL, &error);
|
||||
if (listener == NULL)
|
||||
{
|
||||
g_debug ("Failed to create polkit agent listener: %s", error->message);
|
||||
@ -653,7 +652,8 @@ main (int argc,
|
||||
subject = polkit_unix_process_new_for_owner (getpid (), 0, -1);
|
||||
|
||||
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&opt_builder, "{sv}", "fallback", g_variant_new_boolean (TRUE));
|
||||
if (g_strcmp0 (g_getenv ("FLATPAK_FORCE_TEXT_AUTH"), "1") != 0)
|
||||
g_variant_builder_add (&opt_builder, "{sv}", "fallback", g_variant_new_boolean (TRUE));
|
||||
options = g_variant_ref_sink (g_variant_builder_end (&opt_builder));
|
||||
|
||||
agent = polkit_agent_listener_register_with_options (listener,
|
||||
|
||||
495
app/flatpak-polkit-agent-text-listener.c
Normal file
495
app/flatpak-polkit-agent-text-listener.c
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: David Zeuthen <davidz@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "flatpak-polkit-agent-text-listener.h"
|
||||
|
||||
#include "flatpak-utils-private.h"
|
||||
|
||||
struct _FlatpakPolkitAgentTextListener
|
||||
{
|
||||
PolkitAgentListener parent_instance;
|
||||
|
||||
GSimpleAsyncResult *simple;
|
||||
PolkitAgentSession *active_session;
|
||||
gulong cancel_id;
|
||||
GCancellable *cancellable;
|
||||
|
||||
FILE *tty;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PolkitAgentListenerClass parent_class;
|
||||
} FlatpakPolkitAgentTextListenerClass;
|
||||
|
||||
static void flatpak_polkit_agent_text_listener_initiate_authentication (PolkitAgentListener *_listener,
|
||||
const gchar *action_id,
|
||||
const gchar *message,
|
||||
const gchar *icon_name,
|
||||
PolkitDetails *details,
|
||||
const gchar *cookie,
|
||||
GList *identities,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
static gboolean flatpak_polkit_agent_text_listener_initiate_authentication_finish (PolkitAgentListener *_listener,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
static void initable_iface_init (GInitableIface *initable_iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (FlatpakPolkitAgentTextListener, flatpak_polkit_agent_text_listener, POLKIT_AGENT_TYPE_LISTENER,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));
|
||||
|
||||
static void
|
||||
flatpak_polkit_agent_text_listener_init (FlatpakPolkitAgentTextListener *listener)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_polkit_agent_text_listener_finalize (GObject *object)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (object);
|
||||
|
||||
if (listener->tty != NULL)
|
||||
fclose (listener->tty);
|
||||
|
||||
if (listener->active_session != NULL)
|
||||
g_object_unref (listener->active_session);
|
||||
|
||||
if (G_OBJECT_CLASS (flatpak_polkit_agent_text_listener_parent_class)->finalize != NULL)
|
||||
G_OBJECT_CLASS (flatpak_polkit_agent_text_listener_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
flatpak_polkit_agent_text_listener_class_init (FlatpakPolkitAgentTextListenerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
PolkitAgentListenerClass *listener_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (klass);
|
||||
gobject_class->finalize = flatpak_polkit_agent_text_listener_finalize;
|
||||
|
||||
listener_class = POLKIT_AGENT_LISTENER_CLASS (klass);
|
||||
listener_class->initiate_authentication = flatpak_polkit_agent_text_listener_initiate_authentication;
|
||||
listener_class->initiate_authentication_finish = flatpak_polkit_agent_text_listener_initiate_authentication_finish;
|
||||
}
|
||||
|
||||
PolkitAgentListener *
|
||||
flatpak_polkit_agent_text_listener_new (GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
return POLKIT_AGENT_LISTENER (g_initable_new (FLATPAK_POLKIT_AGENT_TYPE_TEXT_LISTENER,
|
||||
cancellable,
|
||||
error,
|
||||
NULL));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (initable);
|
||||
gboolean ret;
|
||||
const gchar *tty_name;
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
tty_name = ctermid (NULL);
|
||||
if (tty_name == NULL)
|
||||
{
|
||||
g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED,
|
||||
"Cannot determine pathname for current controlling terminal for the process: %s",
|
||||
strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
listener->tty = fopen (tty_name, "r+");
|
||||
if (listener->tty == NULL)
|
||||
{
|
||||
g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED,
|
||||
"Error opening current controlling terminal for the process (`%s'): %s",
|
||||
tty_name, strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
initable_iface_init (GInitableIface *initable_iface)
|
||||
{
|
||||
initable_iface->init = initable_init;
|
||||
}
|
||||
|
||||
static void
|
||||
on_completed (PolkitAgentSession *session,
|
||||
gboolean gained_authorization,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (user_data);
|
||||
|
||||
if (flatpak_fancy_output ())
|
||||
fprintf (listener->tty, FLATPAK_ANSI_RED);
|
||||
if (gained_authorization)
|
||||
fprintf (listener->tty, "==== AUTHENTICATION COMPLETE ====\n");
|
||||
else
|
||||
fprintf (listener->tty, "==== AUTHENTICATION FAILED ====\n");
|
||||
if (flatpak_fancy_output ())
|
||||
{
|
||||
sleep (1); /* show the message for a bit */
|
||||
fprintf (listener->tty, FLATPAK_ANSI_COLOR_RESET FLATPAK_ANSI_ALT_SCREEN_OFF);
|
||||
}
|
||||
fflush (listener->tty);
|
||||
|
||||
g_simple_async_result_complete_in_idle (listener->simple);
|
||||
|
||||
g_object_unref (listener->simple);
|
||||
g_object_unref (listener->active_session);
|
||||
g_cancellable_disconnect (listener->cancellable, listener->cancel_id);
|
||||
g_object_unref (listener->cancellable);
|
||||
|
||||
listener->simple = NULL;
|
||||
listener->active_session = NULL;
|
||||
listener->cancel_id = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
on_request (PolkitAgentSession *session,
|
||||
const gchar *request,
|
||||
gboolean echo_on,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (user_data);
|
||||
struct termios ts, ots;
|
||||
GString *str;
|
||||
|
||||
fprintf (listener->tty, "%s", request);
|
||||
fflush (listener->tty);
|
||||
|
||||
setbuf (listener->tty, NULL);
|
||||
|
||||
tcgetattr (fileno (listener->tty), &ts);
|
||||
ots = ts;
|
||||
ts.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||
tcsetattr (fileno (listener->tty), TCSAFLUSH, &ts);
|
||||
|
||||
str = g_string_new (NULL);
|
||||
while (TRUE)
|
||||
{
|
||||
gint c;
|
||||
c = getc (listener->tty);
|
||||
if (c == '\n')
|
||||
{
|
||||
/* ok, done */
|
||||
break;
|
||||
}
|
||||
else if (c == EOF)
|
||||
{
|
||||
tcsetattr (fileno (listener->tty), TCSAFLUSH, &ots);
|
||||
g_error ("Got unexpected EOF while reading from controlling terminal.");
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (str, c);
|
||||
}
|
||||
}
|
||||
tcsetattr (fileno (listener->tty), TCSAFLUSH, &ots);
|
||||
putc ('\n', listener->tty);
|
||||
|
||||
polkit_agent_session_response (session, str->str);
|
||||
memset (str->str, '\0', str->len);
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_show_error (PolkitAgentSession *session,
|
||||
const gchar *text,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (user_data);
|
||||
fprintf (listener->tty, "Error: %s\n", text);
|
||||
fflush (listener->tty);
|
||||
}
|
||||
|
||||
static void
|
||||
on_show_info (PolkitAgentSession *session,
|
||||
const gchar *text,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (user_data);
|
||||
fprintf (listener->tty, "Info: %s\n", text);
|
||||
fflush (listener->tty);
|
||||
}
|
||||
|
||||
static void
|
||||
on_cancelled (GCancellable *cancellable,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (user_data);
|
||||
fprintf (listener->tty, "Cancelled\n");
|
||||
fflush (listener->tty);
|
||||
polkit_agent_session_cancel (listener->active_session);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
identity_to_human_readable_string (PolkitIdentity *identity)
|
||||
{
|
||||
gchar *ret;
|
||||
|
||||
g_return_val_if_fail (POLKIT_IS_IDENTITY (identity), NULL);
|
||||
|
||||
ret = NULL;
|
||||
if (POLKIT_IS_UNIX_USER (identity))
|
||||
{
|
||||
struct passwd pw;
|
||||
struct passwd *ppw;
|
||||
char buf[2048];
|
||||
int res;
|
||||
|
||||
res = getpwuid_r (polkit_unix_user_get_uid (POLKIT_UNIX_USER (identity)),
|
||||
&pw,
|
||||
buf,
|
||||
sizeof buf,
|
||||
&ppw);
|
||||
if (res != 0)
|
||||
{
|
||||
g_warning ("Error calling getpwuid_r: %s", strerror (res));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ppw->pw_gecos == NULL || strlen (ppw->pw_gecos) == 0 || strcmp (ppw->pw_gecos, ppw->pw_name) == 0)
|
||||
{
|
||||
ret = g_strdup_printf ("%s", ppw->pw_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = g_strdup_printf ("%s (%s)", ppw->pw_gecos, ppw->pw_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == NULL)
|
||||
ret = polkit_identity_to_string (identity);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PolkitIdentity *
|
||||
choose_identity (FlatpakPolkitAgentTextListener *listener,
|
||||
GList *identities)
|
||||
{
|
||||
GList *l;
|
||||
guint n;
|
||||
guint num_identities;
|
||||
GString *str;
|
||||
PolkitIdentity *ret;
|
||||
guint num;
|
||||
gchar *endp;
|
||||
|
||||
ret = NULL;
|
||||
|
||||
fprintf (listener->tty, "Multiple identities can be used for authentication:\n");
|
||||
for (l = identities, n = 0; l != NULL; l = l->next, n++)
|
||||
{
|
||||
PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
|
||||
gchar *s;
|
||||
s = identity_to_human_readable_string (identity);
|
||||
fprintf (listener->tty, " %d. %s\n", n + 1, s);
|
||||
g_free (s);
|
||||
}
|
||||
num_identities = n;
|
||||
fprintf (listener->tty, "Choose identity to authenticate as (1-%d): ", num_identities);
|
||||
fflush (listener->tty);
|
||||
|
||||
str = g_string_new (NULL);
|
||||
while (TRUE)
|
||||
{
|
||||
gint c;
|
||||
c = getc (listener->tty);
|
||||
if (c == '\n')
|
||||
{
|
||||
/* ok, done */
|
||||
break;
|
||||
}
|
||||
else if (c == EOF)
|
||||
{
|
||||
g_error ("Got unexpected EOF while reading from controlling terminal.");
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (str, c);
|
||||
}
|
||||
}
|
||||
|
||||
num = strtol (str->str, &endp, 10);
|
||||
if (str->len == 0 || *endp != '\0' || (num < 1 || num > num_identities))
|
||||
{
|
||||
fprintf (listener->tty, "Invalid response `%s'.\n", str->str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = g_list_nth_data (identities, num-1);
|
||||
|
||||
out:
|
||||
g_string_free (str, TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
flatpak_polkit_agent_text_listener_initiate_authentication (PolkitAgentListener *_listener,
|
||||
const gchar *action_id,
|
||||
const gchar *message,
|
||||
const gchar *icon_name,
|
||||
PolkitDetails *details,
|
||||
const gchar *cookie,
|
||||
GList *identities,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
FlatpakPolkitAgentTextListener *listener = FLATPAK_POLKIT_AGENT_TEXT_LISTENER (_listener);
|
||||
GSimpleAsyncResult *simple;
|
||||
PolkitIdentity *identity;
|
||||
|
||||
simple = g_simple_async_result_new (G_OBJECT (listener),
|
||||
callback,
|
||||
user_data,
|
||||
flatpak_polkit_agent_text_listener_initiate_authentication);
|
||||
if (listener->active_session != NULL)
|
||||
{
|
||||
g_simple_async_result_set_error (simple, POLKIT_ERROR, POLKIT_ERROR_FAILED,
|
||||
"An authentication session is already underway.");
|
||||
g_simple_async_result_complete_in_idle (simple);
|
||||
g_object_unref (simple);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_assert (g_list_length (identities) >= 1);
|
||||
|
||||
if (flatpak_fancy_output ())
|
||||
{
|
||||
fprintf (listener->tty, FLATPAK_ANSI_ALT_SCREEN_ON FLATPAK_ANSI_RED);
|
||||
}
|
||||
|
||||
fprintf (listener->tty, "==== AUTHENTICATING FOR %s ====\n", action_id);
|
||||
|
||||
if (flatpak_fancy_output ())
|
||||
fprintf (listener->tty, FLATPAK_ANSI_COLOR_RESET);
|
||||
|
||||
fprintf (listener->tty, "%s\n", message);
|
||||
|
||||
/* handle multiple identies by asking which one to use */
|
||||
if (g_list_length (identities) > 1)
|
||||
{
|
||||
identity = choose_identity (listener, identities);
|
||||
if (identity == NULL)
|
||||
{
|
||||
fprintf (listener->tty, "\x1B[1;31m");
|
||||
fprintf (listener->tty, "==== AUTHENTICATION CANCELED ====\n");
|
||||
fprintf (listener->tty, "\x1B[0m");
|
||||
fflush (listener->tty);
|
||||
g_simple_async_result_set_error (simple,
|
||||
POLKIT_ERROR,
|
||||
POLKIT_ERROR_FAILED,
|
||||
"Authentication was canceled.");
|
||||
g_simple_async_result_complete_in_idle (simple);
|
||||
g_object_unref (simple);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *s;
|
||||
identity = identities->data;
|
||||
s = identity_to_human_readable_string (identity);
|
||||
fprintf (listener->tty,
|
||||
"Authenticating as: %s\n",
|
||||
s);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
listener->active_session = polkit_agent_session_new (identity, cookie);
|
||||
g_signal_connect (listener->active_session,
|
||||
"completed",
|
||||
G_CALLBACK (on_completed),
|
||||
listener);
|
||||
g_signal_connect (listener->active_session,
|
||||
"request",
|
||||
G_CALLBACK (on_request),
|
||||
listener);
|
||||
g_signal_connect (listener->active_session,
|
||||
"show-info",
|
||||
G_CALLBACK (on_show_info),
|
||||
listener);
|
||||
g_signal_connect (listener->active_session,
|
||||
"show-error",
|
||||
G_CALLBACK (on_show_error),
|
||||
listener);
|
||||
|
||||
listener->simple = simple;
|
||||
listener->cancellable = g_object_ref (cancellable);
|
||||
listener->cancel_id = g_cancellable_connect (cancellable,
|
||||
G_CALLBACK (on_cancelled),
|
||||
listener,
|
||||
NULL);
|
||||
|
||||
polkit_agent_session_initiate (listener->active_session);
|
||||
|
||||
out:
|
||||
;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
flatpak_polkit_agent_text_listener_initiate_authentication_finish (PolkitAgentListener *_listener,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
g_warn_if_fail (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (res)) ==
|
||||
flatpak_polkit_agent_text_listener_initiate_authentication);
|
||||
|
||||
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
24
app/flatpak-polkit-agent-text-listener.h
Normal file
24
app/flatpak-polkit-agent-text-listener.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __FLATPAK_POLKIT_AGENT_TEXT_LISTENER_H
|
||||
#define __FLATPAK_POLKIT_AGENT_TEXT_LISTENER_H
|
||||
|
||||
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
|
||||
#include <polkit/polkit.h>
|
||||
#include <polkitagent/polkitagent.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _FlatpakPolkitAgentTextListener FlatpakPolkitAgentTextListener;
|
||||
|
||||
#define FLATPAK_POLKIT_AGENT_TYPE_TEXT_LISTENER (flatpak_polkit_agent_text_listener_get_type())
|
||||
#define FLATPAK_POLKIT_AGENT_TEXT_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FLATPAK_POLKIT_AGENT_TYPE_TEXT_LISTENER, FlatpakPolkitAgentTextListener))
|
||||
#define FLATPAK_POLKIT_AGENT_IS_TEXT_LISTENER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FLATPAK_POLKIT_AGENT_TYPE_TEXT_LISTENER))
|
||||
|
||||
GType flatpak_polkit_agent_text_listener_get_type (void) G_GNUC_CONST;
|
||||
PolkitAgentListener *flatpak_polkit_agent_text_listener_new (GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FLATPAK_POLKIT_AGENT_TEXT_LISTENER_H */
|
||||
|
||||
@ -42,7 +42,8 @@ typedef enum {
|
||||
FLATPAK_HOST_COMMAND_FLAGS_WATCH_BUS = 1 << 1,
|
||||
} FlatpakHostCommandFlags;
|
||||
|
||||
|
||||
#define FLATPAK_ANSI_ALT_SCREEN_ON "\x1B[?1049h"
|
||||
#define FLATPAK_ANSI_ALT_SCREEN_OFF "\x1B[?1049l"
|
||||
#define FLATPAK_ANSI_BOLD_ON "\x1b[1m"
|
||||
#define FLATPAK_ANSI_BOLD_OFF "\x1b[22m"
|
||||
#define FLATPAK_ANSI_RED "\x1b[31m"
|
||||
|
||||
@ -592,6 +592,9 @@ flatpak_get_gtk_theme (void)
|
||||
gboolean
|
||||
flatpak_fancy_output (void)
|
||||
{
|
||||
if (g_strcmp0 (g_getenv ("FLATPAK_FANCY_OUTPUT"), "0") == 0)
|
||||
return FALSE;
|
||||
|
||||
return isatty (STDOUT_FILENO);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user