How can I compile my C program with the polkit library? - c

Today, I tried to use polkit - an application-level toolkit for defining and handling the policy that allows unprivileged processes to speak to privileged processes. In order to understand it better, I tried to download this code:
#include <polkit/polkit.h>
static gboolean
on_tensec_timeout (gpointer user_data)
{
GMainLoop *loop = user_data;
g_print ("Ten seconds has passed. Now exiting.\n");
g_main_loop_quit (loop);
return FALSE;
}
static void
check_authorization_cb (PolkitAuthority *authority,
GAsyncResult *res,
gpointer user_data)
{
GMainLoop *loop = user_data;
PolkitAuthorizationResult *result;
GError *error;
error = NULL;
result = polkit_authority_check_authorization_finish (authority, res, &error);
if (error != NULL)
{
g_print ("Error checking authorization: %s\n", error->message);
g_error_free (error);
}
else
{
const gchar *result_str;
if (polkit_authorization_result_get_is_authorized (result))
{
result_str = "authorized";
}
else if (polkit_authorization_result_get_is_challenge (result))
{
result_str = "challenge";
}
else
{
result_str = "not authorized";
}
g_print ("Authorization result: %s\n", result_str);
}
g_print ("Authorization check has been cancelled and the dialog should now be hidden.\n"
"This process will exit in ten seconds.\n");
g_timeout_add (10000, on_tensec_timeout, loop);
}
static gboolean
do_cancel (GCancellable *cancellable)
{
g_print ("Timer has expired; cancelling authorization check\n");
g_cancellable_cancel (cancellable);
return FALSE;
}
int
main (int argc, char *argv[])
{
pid_t parent_pid;
const gchar *action_id;
GMainLoop *loop;
PolkitSubject *subject;
PolkitAuthority *authority;
GCancellable *cancellable;
g_type_init ();
if (argc != 2)
{
g_printerr ("usage: %s <action_id>\n", argv[0]);
return 1;
}
action_id = argv[1];
loop = g_main_loop_new (NULL, FALSE);
authority = polkit_authority_get_sync (NULL, NULL);
/* Typically mechanisms will use a PolkitSystemBusName since most
* clients communicate with the mechanism via D-Bus. However for
* this simple example we use the process id of the calling process.
*
* Note that if the parent was reaped we have to be careful not to
* check if init(1) is authorized (it always is).
*/
parent_pid = getppid ();
if (parent_pid == 1)
{
g_printerr ("Parent process was reaped by init(1)\n");
return 1;
}
subject = polkit_unix_process_new (parent_pid);
cancellable = g_cancellable_new ();
g_print ("Will cancel authorization check in 10 seconds\n");
/* Set up a 10 second timer to cancel the check */
g_timeout_add (10 * 1000,
(GSourceFunc) do_cancel,
cancellable);
polkit_authority_check_authorization (authority,
subject,
action_id,
NULL, /* PolkitDetails */
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
cancellable,
(GAsyncReadyCallback) check_authorization_cb,
loop);
g_main_loop_run (loop);
g_object_unref (authority);
g_object_unref (subject);
g_object_unref (cancellable);
g_main_loop_unref (loop);
return 0;
}
But when I tried to compile it with gcc, I received this output:
ciao.c:35:27: fatal error: polkit/polkit.h: File o directory non esistente
compilation terminated.

The path polkit/polkit.h is not in the system include path. Make sure you've downloaded and installed PolKit so that the headers and libraries are available.

I solved my problem adding this
pkg-config --cflags glib-2.0 polkit-gobject-1
and this
pkg-config --libs glib-2.0 polkit-gobject-1
to gcc compilation's command in this way
gcc `pkg-config --cflags glib-2.0 polkit-gobject-1` -o polkit PolicyKit/example.c `pkg-config --libs glib-2.0`

Related

The name is not activable on g_dbus_proxy_call_sync

On a GNOME Xorg session, to get the return value of method GetIdletime exposed on DBus, you can either use
$ dbus-send --print-reply --dest=org.gnome.Mutter.IdleMonitor /org/gnome/Mutter/IdleMonitor/Core org.gnome.Mutter.IdleMonitor.GetIdletime
or
$ gdbus call --session --dest org.gnome.Mutter.IdleMonitor --object-path /org/gnome/Mutter/IdleMonitor/Core --method org.gnome.Mutter.IdleMonitor.GetIdletime
I need to retrieve this value by using GDBus API, so I wrote the following code
/*
* Compile with:
* gcc -Wall print_user_idle_time-gnome.c -o print_user_idle_time-gnome `pkg-config --libs gio-2.0 --cflags`
*/
#include <gio/gio.h>
static void
print_user_idle_time (GDBusProxy *proxy)
{
guint64 user_idle_time;
gchar *method = "GetIdletime";
GError *error = NULL;
GVariant *ret = NULL;
ret = g_dbus_proxy_call_sync(proxy,
method,
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL, &error);
if (!ret) {
g_dbus_error_strip_remote_error (error);
g_print ("GetIdletime failed: %s\n", error->message);
g_error_free (error);
return;
}
user_idle_time = g_variant_get_uint64 (ret);
g_print("%lu\n", user_idle_time);
g_variant_unref (ret);
}
int
main (int argc, char *argv[])
{
GDBusProxy *proxy = NULL;
gchar *name = "org.gnome.Mutter.IdleMonitor";
gchar *object_path = "/org/gnome/Mutter/IdleMonitor/Core";
gchar *interface_name = "org.gnome.Mutter.IdleMonitor";
/* Create a D-Bus proxy */
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
name,
object_path,
interface_name,
NULL, NULL);
g_assert (proxy != NULL);
print_user_idle_time (proxy);
g_object_unref (proxy);
return 0;
}
But when I run it I get error GetIdletime failed: The name is not activable. What is wrong? Thank you
org.gnome.Mutter.IdleMonitor is on the session bus, not the system bus; so you need to use G_BUS_TYPE_SESSION.

Non-standard device event input for GTK

I am using GTK as the user interface to a piece of hardware (a 3D printer). The hardware can create events as a result of user interactions with the machine (not the GUI). For example, they can remove the build plate which trips a switch thus sending a signal to my program that this has happened, but how do I get gtk_main() to recognize that this event has happened?
In other words, how do I get gtk_main() to watch for non-standard device input events?
You can use custom actions provided by GtkApplication.
In any case you must implement by yourself the monitoring code, either by polling your hardware status or by leveraging more advanced techniques (if possible).
/* gcc -o monitor monitor.c $(pkg-config --cflags --libs gtk+-3.0) */
#include <gtk/gtk.h>
static void
startup(GtkApplication *application)
{
GAction *action;
/* plate-removed is a custom action */
action = G_ACTION(g_simple_action_new("plate-removed", NULL));
g_action_map_add_action(G_ACTION_MAP(application), action);
g_object_unref(action);
/* You can connect your callbacks to the GAction::activate signal */
action = g_action_map_lookup_action(G_ACTION_MAP(application), "plate-removed");
g_signal_connect_swapped(action, "activate",
G_CALLBACK(g_print), "Plate has been removed\n");
}
static gpointer
worker_thread(gpointer user_data)
{
GApplication *application = G_APPLICATION(user_data);
for (;;) {
g_usleep(g_random_int_range(500000, 5000000));
/* Event occurred: emit the signal */
g_action_group_activate_action(G_ACTION_GROUP(application),
"plate-removed", NULL);
}
return NULL;
}
static gboolean
polling_loop(gpointer user_data)
{
GApplication *application = G_APPLICATION(user_data);
if (g_random_int_range(1, 20) == 8) {
/* Event occurred: emit the signal */
g_action_group_activate_action(G_ACTION_GROUP(application),
"plate-removed", NULL);
}
return G_SOURCE_CONTINUE;
}
static void
activate(GtkApplication *application)
{
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_application_add_window(application, GTK_WINDOW(window));
gtk_widget_show_all(window);
/* You can use whatever you want to monitor your hardware, in particular
* a polling loop or a worker thread */
g_timeout_add(50, polling_loop, application);
/* g_thread_new("WorkerThread", worker_thread, application); */
}
int
main(int argc, char *argv[])
{
GtkApplication *application;
int retval;
application = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
g_signal_connect(application, "startup", G_CALLBACK(startup), NULL);
g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
retval = g_application_run(G_APPLICATION(application), argc, argv);
g_object_unref(application);
return retval;
}

glib critical error (gthread) and gtk spinner not showing up

I've a weird problem with distros which are !(Arch Linux).Actually I'm using Arch Linux with GNOME 3.16 and I've tried my software software with Fedora 22 alpha (GNOME 3.16), Ubuntu and Xubuntu 14.10/15.04 but I always receive the same error:GLib-CRITICAL **: Source ID XXX was not found when attempting to remove it
I know that the problem is with g_thread but I'm not able to understand why I'm not receiving that warning with Arch but only with other distros.Moreover, the gtk_spinner widgets are showing up only on Arch. On Fedora they aren't showing up and I'm not getting any errors...
gpointer (*hash_func[NUM_OF_HASH_ENTRY])(gpointer) = {compute_md5, compute_gost94, compute_sha1, compute_sha2, compute_sha3, compute_sha2, compute_sha3, compute_sha2, compute_sha3, compute_whirlpool};
struct hash_vars
{
gint n_bit; //number of hash bit (256, 384, 512)
gboolean gth_created[NUM_OF_HASH_ENTRY];
gchar *filename;
GHashTable *hash_table;
GtkWidget *hash_entry[NUM_OF_HASH_ENTRY]; //md5, gost, sha1, sha256, sha3-256, sha384, sha3_384, sha512, sha3-512, whir
GtkWidget *hash_check[NUM_OF_HASH_ENTRY]; //md5, gost, sha1, sha256, sha3-256, sha384, sha3_384, sha512, sha3-512, whir
GtkWidget *hash_spinner[NUM_OF_HASH_ENTRY];
gchar *key[NUM_OF_HASH_ENTRY];
struct threads_list
{
GThread *gth[NUM_OF_HASH_ENTRY];
} threads;
};
struct hash_vars hash_var;
/* other things */
for (i = 0; i < NUM_OF_HASH_ENTRY; i++)
{
gtk_widget_set_name (GTK_WIDGET (hash_var.hash_check[i]), bt_names[i]);
hash_var.gth_created[i] = FALSE;
g_signal_connect (hash_var.hash_check[i], "clicked", G_CALLBACK (create_thread), &hash_var);
}
result = gtk_dialog_run (GTK_DIALOG (dialog));
switch (result)
{
case GTK_RESPONSE_REJECT:
for (i = 0; i < NUM_OF_HASH_ENTRY; i++)
{
if(hash_var.gth_created[i])
g_thread_join (hash_var.threads.gth[i]);
}
g_free (hash_var.filename);
g_hash_table_destroy (hash_var.hash_table);
gtk_widget_destroy (dialog);
break;
}
}
gpointer
create_thread ( GtkWidget *bt,
gpointer user_data)
{
gint i;
struct hash_vars *hash_var = user_data;
const gchar *name = gtk_widget_get_name (bt);
for (i = 0; i < NUM_OF_HASH_ENTRY; i++)
{
if (g_strcmp0 (name, bt_names[i]) == 0)
{ hash_var->gth_created[i] = TRUE;
hash_var->threads.gth[i] = g_thread_new (NULL, (GThreadFunc)hash_func[i], hash_var);
}
}
}
and this is one of the hash functions:
gpointer
compute_md5 (gpointer user_data)
{
struct hash_vars *hash_var = user_data;
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (hash_var->hash_check[0])))
{
gtk_entry_set_text (GTK_ENTRY (hash_var->hash_entry[0]), "");
goto fine;
}
else if (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (hash_var->hash_entry[0])), -1) == 32)
goto fine;
gpointer ptr = g_hash_table_lookup (hash_var->hash_table, hash_var->key[0]);
if (ptr != NULL)
{
gtk_entry_set_text (GTK_ENTRY (hash_var->hash_entry[0]), (gchar *)g_hash_table_lookup (hash_var->hash_table, hash_var->key[0]));
goto fine;
}
gtk_spinner_start (GTK_SPINNER (hash_var->hash_spinner[0]));
/* computing md5 */
fine:
gtk_spinner_stop (GTK_SPINNER (hash_var->hash_spinner[0]));
g_thread_exit(NULL);
}
So, to summarize, my problems are:
I receive a GLib-Critical error only on distro !(Arch Linux)
gtk_spinner are showing up only on Arch
All suggestions are welcome :)
"GTK+, however, is not thread safe. You should only use GTK+ and GDK from the thread gtk_init() and gtk_main() were called on. This is usually referred to as the “main thread”."
— https://developer.gnome.org/gdk3/stable/gdk3-Threads.html#gdk3-Threads.description
Basically, any time you want to interact with GTK+ you should do it using an idle callback. That link explains how.
As for why it works on some platforms but not others, it's probably a race condition.

Gstreamer HLS pipeline creation error

I am trying to stream a HLS Stream using gstreamer 1.0. I have a filter which works
gst-launch-1.0 -v souphttpsrc location="http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8" ! hlsdemux ! tsdemux ! h264parse ! avdec_h264 ! autovideosink
But when I try to convert this into c code, it fails.
int main(int argc, char* argv[])
{
GMainLoop *loop;
GstElement *pipeline, *source, *demuxer, *tsdemux, *h264parse, *vdecoder, *vsink;
GstElement *aacparse, *adecoder, *aconvert, *asink;
GstBus *bus;
int bus_watch_id;
gst_debug_set_default_threshold(3);
gst_init(&argc, &argv);
loop = g_main_loop_new(NULL, FALSE);
if (argc != 2)
{
g_printerr("Usage: %s <http stream source>\n", argv[0]);
return -1;
}
pipeline = gst_pipeline_new("myApp");
source = gst_element_factory_make("souphttpsrc", "http-src");
demuxer = gst_element_factory_make("hlsdemux", "hls-demuxer");
tsdemux = gst_element_factory_make("tsdemux", "ts-demuxer");
h264parse = gst_element_factory_make("h264parse", "h264parse");
vdecoder = gst_element_factory_make("avdec_h264", "h264decoder");
vsink = gst_element_factory_make("autovideosink", "videosink");
/* set the input url to the source element */
g_object_set(G_OBJECT(source), "location", argv[1], NULL);
bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref(bus);
/* add elements into the pipeline */ //next aacparse
gst_bin_add_many(GST_BIN (pipeline), source, demuxer, tsdemux, h264parse, vdecoder,vsink, NULL);
gst_element_link(source, demuxer);
// this was wrong
/*gst_element_link_many(tsdemux, h264parse, vdecoder, vsink, NULL);*/
/* connect demuxer and decoder on pad added */
/*g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), vdecoder);*/
// Correct Implementation
gst_element_link_many(h264parse, vdecoder, vsink, NULL);
g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), tsdemux);
g_signal_connect(tsdemux, "pad-added", G_CALLBACK(on_pad_added), h264parse);
g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), vdecoder);
// Correct Implementation
g_print ("Starting play: %s\n", argv[1]);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_print ("Running\n");
g_main_loop_run(loop);
/* Clean up after execution of main loop */
g_print ("Stopping Playback: %s\n", argv[1]);
gst_element_set_state(pipeline, GST_STATE_NULL);
g_print ("Quitting\n");
g_object_unref(G_OBJECT(pipeline));
g_source_remove(bus_watch_id);
g_main_loop_unref(loop);
return 0;
}
I compile the code using:
cc my_app.c -o my_app $(pkg-config --cflags --libs gstreamer-1.0)
And launch the application using:
./my_app http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8
I always get the following error:
hlsdemux gsthlsdemux.c:792:gst_hls_demux_stream_loop:<hls-demuxer> error: stream stopped, reason not-negotiated
Do I have to do anything differently?
// this was wrong
gst_element_link(source, demuxer);
// Correct Implementation
gst_element_link(source, demuxer,NULL);
where is your void
on_pad_added (GstElement *element,
GstPad *pad,
gpointer data); function?and take a look at here.
I was able to get it working. The problem was "tsdemux" and "demuxer" have to connect at run time in "on_pad_added" method.

Gstreamer 1.2.4.1 windows build. Gstreamer Editing Services Examples on Windows Visual Studio 2012

I have dowloaded and installed http://gstreamer.freedesktop.org/data/pkg/windows/1.2.4.1/ gstreamer. Then I set up Visual Studio 2012 C++ project, add all *.props files. I want to try out Gstreamer Editing Services (GES) example project test4.c:
#include <ges/ges.h>
#include <gst/pbutils/encoding-profile.h>
GstEncodingProfile *make_encoding_profile (gchar * audio, gchar * container);
/* This example will take a series of files and create a audio-only timeline
* containing the first second of each file and render it to the output uri
* using ogg/vorbis */
/* make_encoding_profile
* simple method creating an encoding profile. This is here in
* order not to clutter the main function. */
GstEncodingProfile *
make_encoding_profile (gchar * audio, gchar * container)
{
GstEncodingContainerProfile *profile;
GstEncodingProfile *stream;
GstCaps *caps;
caps = gst_caps_from_string (container);
profile =
gst_encoding_container_profile_new ((gchar *) "ges-test4", NULL, caps,
NULL);
gst_caps_unref (caps);
caps = gst_caps_from_string (audio);
stream = (GstEncodingProfile *)
gst_encoding_audio_profile_new (caps, NULL, NULL, 0);
gst_encoding_container_profile_add_profile (profile, stream);
gst_caps_unref (caps);
return (GstEncodingProfile *) profile;
}
int
main (int argc, gchar ** argv)
{
GESPipeline *pipeline;
GESTimeline *timeline;
GESTrack *tracka;
GESLayer *layer;
GMainLoop *mainloop;
GstEncodingProfile *profile;
gchar *container = (gchar *) "application/ogg";
gchar *audio = (gchar *) "audio/x-vorbis";
gchar *output_uri;
guint i;
GError *err = NULL;
GOptionEntry options[] = {
{"format", 'f', 0, G_OPTION_ARG_STRING, &container,
"Container format", "<GstCaps>"},
{"aformat", 'a', 0, G_OPTION_ARG_STRING, &audio,
"Audio format", "<GstCaps>"},
{NULL}
};
GOptionContext *ctx;
ctx = g_option_context_new ("- renders a sequence of audio files.");
g_option_context_add_main_entries (ctx, options, NULL);
g_option_context_add_group (ctx, gst_init_get_option_group ());
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
g_printerr ("Error initializing: %s\n", err->message);
g_option_context_free (ctx);
return -1;
}
if (argc < 3) {
g_print ("Usage: %s <output uri> <list of audio files>\n", argv[0]);
return -1;
}
/* Initialize GStreamer (this will parse environment variables and commandline
* arguments. */
gst_init (&argc, &argv);
/* Initialize the GStreamer Editing Services */
ges_init ();
/* Setup of an audio timeline */
/* This is our main GESTimeline */
timeline = ges_timeline_new ();
tracka = GES_TRACK (ges_audio_track_new ());
/* We are only going to be doing one layer of clips */
layer = ges_layer_new ();
/* Add the tracks and the layer to the timeline */
if (!ges_timeline_add_layer (timeline, layer))
return -1;
if (!ges_timeline_add_track (timeline, tracka))
return -1;
/* Here we've finished initializing our timeline, we're
* ready to start using it... by solely working with the layer ! */
for (i = 2; i < argc; i++) {
gchar *uri = gst_filename_to_uri (argv[i], NULL);
GESUriClip *src = ges_uri_clip_new (uri);
g_assert (src);
g_free (uri);
g_object_set (src, "start", ges_layer_get_duration (layer),
"duration", GST_SECOND, NULL);
/* Since we're using a GESSimpleLayer, objects will be automatically
* appended to the end of the layer */
ges_layer_add_clip (layer, (GESClip *) src);
}
/* In order to view our timeline, let's grab a convenience pipeline to put
* our timeline in. */
pipeline = ges_pipeline_new ();
/* Add the timeline to that pipeline */
if (!ges_pipeline_set_timeline (pipeline, timeline))
return -1;
/* RENDER SETTINGS ! */
/* We set our output URI and rendering setting on the pipeline */
if (gst_uri_is_valid (argv[1])) {
output_uri = g_strdup (argv[1]);
} else {
output_uri = gst_filename_to_uri (argv[1], NULL);
}
profile = make_encoding_profile (audio, container);
if (!ges_pipeline_set_render_settings (pipeline, output_uri, profile))
return -1;
/* We want the pipeline to render (without any preview) */
if (!ges_pipeline_set_mode (pipeline, GES_PIPELINE_MODE_SMART_RENDER))
return -1;
/* The following is standard usage of a GStreamer pipeline (note how you haven't
* had to care about GStreamer so far ?).
*
* We set the pipeline to playing ... */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
/* ... and we start a GMainLoop. GES **REQUIRES** a GMainLoop to be running in
* order to function properly ! */
mainloop = g_main_loop_new (NULL, FALSE);
/* Simple code to have the mainloop shutdown after 4s */
/* FIXME : We should wait for EOS ! */
g_timeout_add_seconds (argc - 1, (GSourceFunc) g_main_loop_quit, mainloop);
g_main_loop_run (mainloop);
return 0;
}
The program runs from the begining to the end without any errors, however
I can't get the music files playing. I think the problem lurks in this piece of code:
if (gst_uri_is_valid (argv[1])) {
output_uri = g_strdup (argv[1]);
} else {
output_uri = gst_filename_to_uri (argv[1], NULL);
}
I don't really know what to type as the first command line argument (the output dir is expected). When I provide any directory and launch program, it waits for a few seconds and then prints out "Press any key to continue...", however I can't hear the music playing neither I find any files in the provided output directory. What is more I was unable to hear any sounds then trying out test1.c, test2.c and test3.c test examples too. Maybe there is special way to provide arguments? My arguments looked like this: D:/output D:/mp3/1.mp3 D:/mp3/2.mp3 .

Resources