(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
test-posix_spawn-open2.c
       1  /* Test of posix_spawn() function with 'open' action and O_APPEND flag.
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2020.  */
      18  
      19  /* Test whether posix_spawn_file_actions_addopen supports the O_APPEND flag.  */
      20  
      21  #include <config.h>
      22  
      23  #include <spawn.h>
      24  
      25  #include <errno.h>
      26  #include <fcntl.h>
      27  #include <signal.h>
      28  #include <stdio.h>
      29  #include <string.h>
      30  #include <unistd.h>
      31  #include <sys/types.h>
      32  #include <sys/wait.h>
      33  
      34  #define CHILD_PROGRAM_FILENAME "test-posix_spawn-open2" EXEEXT
      35  #define DATA_FILENAME "test-posix_spawn-open2-data.tmp"
      36  
      37  static int
      38  parent_main (void)
      39  {
      40    FILE *fp;
      41    char *argv[3] = { CHILD_PROGRAM_FILENAME, "-child", NULL };
      42    posix_spawn_file_actions_t actions;
      43    bool actions_allocated;
      44    int err;
      45    pid_t child;
      46    int status;
      47    int exitstatus;
      48  
      49    /* Create a data file with specific contents.  */
      50    fp = fopen (DATA_FILENAME, "wb");
      51    if (fp == NULL)
      52      {
      53        perror ("cannot create data file");
      54        return 1;
      55      }
      56    fwrite ("Halle ", 1, 6, fp);
      57    if (fflush (fp) || fclose (fp))
      58      {
      59        perror ("cannot prepare data file");
      60        return 1;
      61      }
      62  
      63    /* Test whether posix_spawn_file_actions_addopen with O_APPEND flag causes
      64       the child to append to this file.  */
      65    actions_allocated = false;
      66    if ((err = posix_spawn_file_actions_init (&actions)) != 0
      67        || (actions_allocated = true,
      68            (err = posix_spawn_file_actions_addopen (&actions, STDOUT_FILENO, DATA_FILENAME, O_RDWR | O_APPEND, 0600)) != 0
      69            || (err = posix_spawn (&child, CHILD_PROGRAM_FILENAME, &actions, NULL, argv, environ)) != 0))
      70      {
      71        if (actions_allocated)
      72          posix_spawn_file_actions_destroy (&actions);
      73        errno = err;
      74        perror ("subprocess failed");
      75        return 1;
      76      }
      77    posix_spawn_file_actions_destroy (&actions);
      78    status = 0;
      79    while (waitpid (child, &status, 0) != child)
      80      ;
      81    if (!WIFEXITED (status))
      82      {
      83        fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
      84        return 1;
      85      }
      86    exitstatus = WEXITSTATUS (status);
      87    if (exitstatus != 0)
      88      {
      89        fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
      90        return 1;
      91      }
      92  
      93    /* Check the contents of the data file.  */
      94    fp = fopen (DATA_FILENAME, "rb");
      95    if (fp == NULL)
      96      {
      97        perror ("cannot open data file");
      98        return 1;
      99      }
     100    char buf[1024];
     101    int nread = fread (buf, 1, sizeof (buf), fp);
     102    if (!(nread == 11 && memcmp (buf, "Halle Potta", 11) == 0))
     103      {
     104        fprintf (stderr, "data file wrong: has %d bytes, expected %d bytes\n", nread, 11);
     105        return 1;
     106      }
     107    if (fclose (fp))
     108      {
     109        perror ("cannot close data file");
     110        return 1;
     111      }
     112  
     113    /* Clean up data file.  */
     114    unlink (DATA_FILENAME);
     115  
     116    return 0;
     117  }
     118  
     119  static int
     120  child_main (void)
     121  {
     122    /* Write to STDOUT_FILENO.  */
     123    fwrite ("Potta", 1, 5, stdout);
     124    /* No 'fflush (stdout);' is needed.  It is implicit when the child process
     125       exits.  */
     126  
     127    return 0;
     128  }
     129  
     130  static void
     131  cleanup_then_die (int sig)
     132  {
     133    /* Clean up data file.  */
     134    unlink (DATA_FILENAME);
     135  
     136    /* Re-raise the signal and die from it.  */
     137    signal (sig, SIG_DFL);
     138    raise (sig);
     139  }
     140  
     141  int
     142  main (int argc, char *argv[])
     143  {
     144    int exitstatus;
     145  
     146    if (!(argc > 1 && strcmp (argv[1], "-child") == 0))
     147      {
     148        /* This is the parent process.  */
     149        signal (SIGINT, cleanup_then_die);
     150        signal (SIGTERM, cleanup_then_die);
     151        #ifdef SIGHUP
     152        signal (SIGHUP, cleanup_then_die);
     153        #endif
     154  
     155        exitstatus = parent_main ();
     156      }
     157    else
     158      {
     159        /* This is the child process.  */
     160        exitstatus = child_main ();
     161      }
     162    return exitstatus;
     163  }