(root)/
glib-2.79.0/
gio/
tests/
gsubprocess-testprog.c
       1  #include <gio/gio.h>
       2  #include <string.h>
       3  #include <stdio.h>
       4  #include <stdlib.h>
       5  #include <errno.h>
       6  #ifdef G_OS_UNIX
       7  #include <unistd.h>
       8  #else
       9  #include <io.h>
      10  #endif
      11  
      12  static GOptionEntry options[] = {
      13    G_OPTION_ENTRY_NULL
      14  };
      15  
      16  static void
      17  write_all (int           fd,
      18  	   const guint8* buf,
      19  	   gsize         len)
      20  {
      21    while (len > 0)
      22      {
      23        gssize bytes_written = write (fd, buf, len);
      24        int errsv = errno;
      25        if (bytes_written < 0)
      26  	g_error ("Failed to write to fd %d: %s",
      27  		 fd, g_strerror (errsv));
      28        buf += bytes_written;
      29        len -= bytes_written;
      30      }
      31  }
      32  
      33  static int
      34  echo_mode (int argc,
      35  	   char **argv)
      36  {
      37    int i;
      38  
      39    for (i = 2; i < argc; i++)
      40      {
      41        write_all (1, (guint8*)argv[i], strlen (argv[i]));
      42        write_all (1, (guint8*)"\n", 1);
      43      }
      44  
      45    return 0;
      46  }
      47  
      48  static int
      49  echo_stdout_and_stderr_mode (int argc,
      50  			     char **argv)
      51  {
      52    int i;
      53  
      54    for (i = 2; i < argc; i++)
      55      {
      56        write_all (1, (guint8*)argv[i], strlen (argv[i]));
      57        write_all (1, (guint8*)"\n", 1);
      58        write_all (2, (guint8*)argv[i], strlen (argv[i]));
      59        write_all (2, (guint8*)"\n", 1);
      60      }
      61  
      62    return 0;
      63  }
      64  
      65  static int
      66  cat_mode (int argc,
      67  	  char **argv)
      68  {
      69    GIOChannel *chan_stdin;
      70    GIOChannel *chan_stdout;
      71    GIOStatus status;
      72    char buf[1024];
      73    gsize bytes_read, bytes_written;
      74    GError *local_error = NULL;
      75    GError **error = &local_error;
      76  
      77    chan_stdin = g_io_channel_unix_new (0);
      78    g_io_channel_set_encoding (chan_stdin, NULL, error);
      79    g_assert_no_error (local_error);
      80    chan_stdout = g_io_channel_unix_new (1);
      81    g_io_channel_set_encoding (chan_stdout, NULL, error);
      82    g_assert_no_error (local_error);
      83  
      84    while (TRUE)
      85      {
      86        do
      87  	status = g_io_channel_read_chars (chan_stdin, buf, sizeof (buf),
      88  					  &bytes_read, error);
      89        while (status == G_IO_STATUS_AGAIN);
      90  
      91        if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
      92  	break;
      93  
      94        do
      95  	status = g_io_channel_write_chars (chan_stdout, buf, bytes_read,
      96  					   &bytes_written, error);
      97        while (status == G_IO_STATUS_AGAIN);
      98  
      99        if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
     100  	break;
     101      }
     102  
     103    g_io_channel_unref (chan_stdin);
     104    g_io_channel_unref (chan_stdout);
     105  
     106    if (local_error)
     107      {
     108        g_printerr ("I/O error: %s\n", local_error->message);
     109        g_clear_error (&local_error);
     110        return 1;
     111      }
     112    return 0;
     113  }
     114  
     115  static gint
     116  sleep_forever_mode (int argc,
     117  		    char **argv)
     118  {
     119    GMainLoop *loop;
     120    
     121    loop = g_main_loop_new (NULL, TRUE);
     122    g_main_loop_run (loop);
     123  
     124    return 0;
     125  }
     126  
     127  static int
     128  write_to_fds (int argc, char **argv)
     129  {
     130    int i;
     131  
     132    for (i = 2; i < argc; i++)
     133      {
     134        int fd = atoi (argv[i]);
     135        FILE *f = fdopen (fd, "w");
     136        const char buf[] = "hello world\n";
     137        size_t bytes_written;
     138        
     139        g_assert (f != NULL);
     140        
     141        bytes_written = fwrite (buf, 1, sizeof (buf), f);
     142        g_assert (bytes_written == sizeof (buf));
     143        
     144        if (fclose (f) == -1)
     145          g_assert_not_reached ();
     146      }
     147  
     148    return 0;
     149  }
     150  
     151  static int
     152  read_from_fd (int argc, char **argv)
     153  {
     154    int fd;
     155    const char expected_result[] = "Yay success!";
     156    guint8 buf[sizeof (expected_result) + 1];
     157    gsize bytes_read;
     158    FILE *f;
     159  
     160    if (argc != 3)
     161      {
     162        g_print ("Usage: %s read-from-fd FD\n", argv[0]);
     163        return 1;
     164      }
     165  
     166    fd = atoi (argv[2]);
     167    if (fd == 0)
     168      {
     169        g_warning ("Argument \"%s\" does not look like a valid nonzero file descriptor", argv[2]);
     170        return 1;
     171      }
     172  
     173    f = fdopen (fd, "r");
     174    if (f == NULL)
     175      {
     176        g_warning ("Failed to open fd %d: %s", fd, g_strerror (errno));
     177        return 1;
     178      }
     179  
     180    bytes_read = fread (buf, 1, sizeof (buf), f);
     181    if (bytes_read != sizeof (expected_result))
     182      {
     183        g_warning ("Read %zu bytes, but expected %zu", bytes_read, sizeof (expected_result));
     184        return 1;
     185      }
     186  
     187    if (memcmp (expected_result, buf, sizeof (expected_result)) != 0)
     188      {
     189        buf[sizeof (expected_result)] = '\0';
     190        g_warning ("Expected \"%s\" but read  \"%s\"", expected_result, (char *)buf);
     191        return 1;
     192      }
     193  
     194    if (fclose (f) == -1)
     195      g_assert_not_reached ();
     196  
     197    return 0;
     198  }
     199  
     200  static int
     201  env_mode (int argc, char **argv)
     202  {
     203    char **env;
     204    int i;
     205  
     206    env = g_get_environ ();
     207  
     208    for (i = 0; env[i]; i++)
     209      g_print ("%s\n", env[i]);
     210  
     211    g_strfreev (env);
     212  
     213    return 0;
     214  }
     215  
     216  static int
     217  cwd_mode (int argc, char **argv)
     218  {
     219    char *cwd;
     220  
     221    cwd = g_get_current_dir ();
     222    g_print ("%s\n", cwd);
     223    g_free (cwd);
     224  
     225    return 0;
     226  }
     227  
     228  static int
     229  printenv_mode (int argc, char **argv)
     230  {
     231    gint i;
     232  
     233    for (i = 2; i < argc; i++)
     234      {
     235        const gchar *value = g_getenv (argv[i]);
     236  
     237        if (value != NULL)
     238          g_print ("%s=%s\n", argv[i], value);
     239      }
     240  
     241    return 0;
     242  }
     243  
     244  #ifdef G_OS_UNIX
     245  static void
     246  on_sleep_exited (GObject         *object,
     247                   GAsyncResult    *result,
     248                   gpointer         user_data)
     249  {
     250    GSubprocess *subprocess = G_SUBPROCESS (object);
     251    gboolean *done = user_data;
     252    GError *local_error = NULL;
     253    gboolean ret;
     254  
     255    ret = g_subprocess_wait_finish (subprocess, result, &local_error);
     256    g_assert_no_error (local_error);
     257    g_assert_true (ret);
     258  
     259    *done = TRUE;
     260    g_main_context_wakeup (NULL);
     261  }
     262  
     263  static int
     264  sleep_and_kill (int argc, char **argv)
     265  {
     266    GPtrArray *args = NULL;
     267    GSubprocessLauncher *launcher = NULL;
     268    GSubprocess *proc = NULL;
     269    GError *local_error = NULL;
     270    pid_t sleep_pid;
     271    gboolean done = FALSE;
     272  
     273    args = g_ptr_array_new_with_free_func (g_free);
     274  
     275    /* Run sleep "forever" in a shell; this will trigger PTRACE_EVENT_EXEC */
     276    g_ptr_array_add (args, g_strdup ("sh"));
     277    g_ptr_array_add (args, g_strdup ("-c"));
     278    g_ptr_array_add (args, g_strdup ("exec sleep infinity"));
     279    g_ptr_array_add (args, NULL);
     280    launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
     281    proc = g_subprocess_launcher_spawnv (launcher, (const gchar **) args->pdata, &local_error);
     282    g_assert_no_error (local_error);
     283    g_assert_nonnull (proc);
     284  
     285    sleep_pid = atoi (g_subprocess_get_identifier (proc));
     286  
     287    g_subprocess_wait_async (proc, NULL, on_sleep_exited, &done);
     288  
     289    kill (sleep_pid, SIGKILL);
     290  
     291    while (!done)
     292      g_main_context_iteration (NULL, TRUE);
     293  
     294    g_assert_false (g_subprocess_get_successful (proc));
     295  
     296    g_clear_pointer (&args, g_ptr_array_unref);
     297    g_clear_object (&launcher);
     298    g_clear_object (&proc);
     299  
     300    return EXIT_SUCCESS;
     301  }
     302  #endif
     303  
     304  int
     305  main (int argc, char **argv)
     306  {
     307    GOptionContext *context;
     308    GError *error = NULL;
     309    const char *mode;
     310    gboolean ret;
     311  
     312    context = g_option_context_new ("MODE - Test GSubprocess stuff");
     313    g_option_context_add_main_entries (context, options, NULL);
     314    ret = g_option_context_parse (context, &argc, &argv, &error);
     315    g_option_context_free (context);
     316  
     317    if (!ret)
     318      {
     319        g_printerr ("%s: %s\n", argv[0], error->message);
     320        g_error_free (error);
     321        return 1;
     322      }
     323  
     324    if (argc < 2)
     325      {
     326        g_printerr ("MODE argument required\n");
     327        return 1;
     328      }
     329  
     330    g_log_writer_default_set_use_stderr (TRUE);
     331  
     332    mode = argv[1];
     333    if (strcmp (mode, "noop") == 0)
     334      return 0;
     335    else if (strcmp (mode, "exit1") == 0)
     336      return 1;
     337    else if (strcmp (mode, "assert-argv0") == 0)
     338      {
     339        if (strcmp (argv[0], "moocow") == 0)
     340  	return 0;
     341        g_printerr ("argv0=%s != moocow\n", argv[0]);
     342        return 1;
     343      }
     344    else if (strcmp (mode, "echo") == 0)
     345      return echo_mode (argc, argv);
     346    else if (strcmp (mode, "echo-stdout-and-stderr") == 0)
     347      return echo_stdout_and_stderr_mode (argc, argv);
     348    else if (strcmp (mode, "cat") == 0)
     349      return cat_mode (argc, argv);
     350    else if (strcmp (mode, "sleep-forever") == 0)
     351      return sleep_forever_mode (argc, argv);
     352    else if (strcmp (mode, "write-to-fds") == 0)
     353      return write_to_fds (argc, argv);
     354    else if (strcmp (mode, "read-from-fd") == 0)
     355      return read_from_fd (argc, argv);
     356    else if (strcmp (mode, "env") == 0)
     357      return env_mode (argc, argv);
     358    else if (strcmp (mode, "cwd") == 0)
     359      return cwd_mode (argc, argv);
     360    else if (strcmp (mode, "printenv") == 0)
     361      return printenv_mode (argc, argv);
     362  #ifdef G_OS_UNIX
     363    else if (strcmp (mode, "sleep-and-kill") == 0)
     364      return sleep_and_kill (argc, argv);
     365  #endif
     366    else
     367      {
     368        g_printerr ("Unknown MODE %s\n", argv[1]);
     369        return 1;
     370      }
     371  
     372    return TRUE;
     373  }