mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-06-17 18:04:13 +02:00
goption: [linux] Look in /proc/self/cmdline for argv0 if not specified
We really shouldn't use <unknown> when we can perfectly easily get argv0 out of /proc. This avoids people having to pass argv down into gtk_init/g_option_context_parse etc., which is important because GTK+ uses it to initialize the WM_CLASS, which in turn GNOME Shell consumes for application tracking. https://bugzilla.gnome.org/show_bug.cgi?id=644309
This commit is contained in:
parent
131b9f98ea
commit
14bb138d58
@ -1657,6 +1657,39 @@ free_pending_nulls (GOptionContext *context,
|
|||||||
context->pending_nulls = NULL;
|
context->pending_nulls = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use a platform-specific mechanism to look up the first argument to
|
||||||
|
* the current process.
|
||||||
|
* Note if you implement this for other platforms, also add it to
|
||||||
|
* tests/option-argv0.c
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
platform_get_argv0 (void)
|
||||||
|
{
|
||||||
|
#ifdef __linux
|
||||||
|
char *cmdline;
|
||||||
|
char *base_arg0;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
if (!g_file_get_contents ("/proc/self/cmdline",
|
||||||
|
&cmdline,
|
||||||
|
&len,
|
||||||
|
NULL))
|
||||||
|
return NULL;
|
||||||
|
/* Sanity check for a NUL terminator. */
|
||||||
|
if (!memchr (cmdline, 0, len))
|
||||||
|
return NULL;
|
||||||
|
/* We could just return cmdline, but I think it's better
|
||||||
|
* to hold on to a smaller malloc block; the arguments
|
||||||
|
* could be large.
|
||||||
|
*/
|
||||||
|
base_arg0 = g_path_get_basename (cmdline);
|
||||||
|
g_free (cmdline);
|
||||||
|
return base_arg0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_option_context_parse:
|
* g_option_context_parse:
|
||||||
* @context: a #GOptionContext
|
* @context: a #GOptionContext
|
||||||
@ -1704,16 +1737,19 @@ g_option_context_parse (GOptionContext *context,
|
|||||||
/* Set program name */
|
/* Set program name */
|
||||||
if (!g_get_prgname())
|
if (!g_get_prgname())
|
||||||
{
|
{
|
||||||
if (argc && argv && *argc)
|
gchar *prgname;
|
||||||
{
|
|
||||||
gchar *prgname;
|
|
||||||
|
|
||||||
prgname = g_path_get_basename ((*argv)[0]);
|
if (argc && argv && *argc)
|
||||||
g_set_prgname (prgname);
|
prgname = g_path_get_basename ((*argv)[0]);
|
||||||
g_free (prgname);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
g_set_prgname ("<unknown>");
|
prgname = platform_get_argv0 ();
|
||||||
|
|
||||||
|
if (prgname)
|
||||||
|
g_set_prgname (prgname);
|
||||||
|
else
|
||||||
|
g_set_prgname ("<unknown>");
|
||||||
|
|
||||||
|
g_free (prgname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call pre-parse hooks */
|
/* Call pre-parse hooks */
|
||||||
|
@ -17,6 +17,10 @@ TEST_PROGS += option-context
|
|||||||
option_context_SOURCES = option-context.c
|
option_context_SOURCES = option-context.c
|
||||||
option_context_LDADD = $(progs_ldadd)
|
option_context_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
|
TEST_PROGS += option-argv0
|
||||||
|
option_argv0_SOURCES = option-argv0.c
|
||||||
|
option_argv0_LDADD = $(progs_ldadd)
|
||||||
|
|
||||||
TEST_PROGS += keyfile
|
TEST_PROGS += keyfile
|
||||||
keyfile_SOURCES = keyfile.c
|
keyfile_SOURCES = keyfile.c
|
||||||
keyfile_LDADD = $(progs_ldadd)
|
keyfile_LDADD = $(progs_ldadd)
|
||||||
|
63
glib/tests/option-argv0.c
Normal file
63
glib/tests/option-argv0.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This work is provided "as is"; redistribution and modification
|
||||||
|
* in whole or in part, in any medium, physical or electronic is
|
||||||
|
* permitted without restriction.
|
||||||
|
*
|
||||||
|
* This work 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.
|
||||||
|
*
|
||||||
|
* In no event shall the authors or contributors be liable for any
|
||||||
|
* direct, indirect, incidental, special, exemplary, or consequential
|
||||||
|
* damages (including, but not limited to, procurement of substitute
|
||||||
|
* goods or services; loss of use, data, or profits; or business
|
||||||
|
* interruption) however caused and on any theory of liability, whether
|
||||||
|
* in contract, strict liability, or tort (including negligence or
|
||||||
|
* otherwise) arising in any way out of the use of this software, even
|
||||||
|
* if advised of the possibility of such damage.
|
||||||
|
*
|
||||||
|
* Authors: Colin Walters <walters@verbum.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_platform_argv0 (void)
|
||||||
|
{
|
||||||
|
GOptionContext *context;
|
||||||
|
gboolean arg;
|
||||||
|
GOptionEntry entries [] =
|
||||||
|
{ { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL },
|
||||||
|
{ NULL } };
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
context = g_option_context_new (NULL);
|
||||||
|
g_option_context_add_main_entries (context, entries, NULL);
|
||||||
|
|
||||||
|
retval = g_option_context_parse (context, NULL, NULL, NULL);
|
||||||
|
g_assert (retval == TRUE);
|
||||||
|
g_assert (strcmp (g_get_prgname(), "option-argv0") == 0
|
||||||
|
|| strcmp (g_get_prgname (), "lt-option-argv0") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
/* Note - we can't actually use g_test_* because g_test_init mutates
|
||||||
|
* g_get_prgname() which is exactly what we wanted to test =/
|
||||||
|
*/
|
||||||
|
#ifdef __linux
|
||||||
|
g_print ("/option/argv0: ");
|
||||||
|
test_platform_argv0 ();
|
||||||
|
g_print ("OK\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1307,27 +1307,6 @@ add_test1 (void)
|
|||||||
g_option_context_free (context);
|
g_option_context_free (context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
empty_test1 (void)
|
|
||||||
{
|
|
||||||
GOptionContext *context;
|
|
||||||
GOptionEntry entries [] =
|
|
||||||
{ { NULL } };
|
|
||||||
char *prgname;
|
|
||||||
|
|
||||||
g_set_prgname (NULL);
|
|
||||||
context = g_option_context_new (NULL);
|
|
||||||
|
|
||||||
g_option_context_add_main_entries (context, entries, NULL);
|
|
||||||
|
|
||||||
g_option_context_parse (context, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
prgname = g_get_prgname ();
|
|
||||||
g_assert (prgname && strcmp (prgname, "<unknown>") == 0);
|
|
||||||
|
|
||||||
g_option_context_free (context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
empty_test2 (void)
|
empty_test2 (void)
|
||||||
{
|
{
|
||||||
@ -2031,7 +2010,9 @@ main (int argc,
|
|||||||
g_test_add_func ("/option/context/add", add_test1);
|
g_test_add_func ("/option/context/add", add_test1);
|
||||||
|
|
||||||
/* Test parsing empty args */
|
/* Test parsing empty args */
|
||||||
g_test_add_func ("/option/context/empty1", empty_test1);
|
/* Note there used to be an empty1 here, but it effectively moved
|
||||||
|
* to option-argv0.c.
|
||||||
|
*/
|
||||||
g_test_add_func ("/option/context/empty2", empty_test2);
|
g_test_add_func ("/option/context/empty2", empty_test2);
|
||||||
g_test_add_func ("/option/context/empty3", empty_test3);
|
g_test_add_func ("/option/context/empty3", empty_test3);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user