/* t-spawn.c - Check the spawn functions.
* Copyright (C) 2024 g10 Code GmbH
*
* This file is part of libgpg-error.
*
* libgpg-error 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.1 of
* the License, or (at your option) any later version.
*
* libgpg-error 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 program; if not, see .
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#if HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#define PGM "t-spawn"
#include "t-common.h"
#define MAXLINE 1024
static void
run_test (const char *progname)
{
gpg_err_code_t rc;
int r;
gpgrt_spawn_actions_t act;
gpgrt_process_t process;
gpgrt_stream_t fp_out;
const char *const envchange[] = {
"ADD=0", /* Add */
"REPLACE=1", /* Replace */
"GNUPGHOME", /* Remove */
NULL,
};
const char *argv1[] = {
"--child",
NULL,
};
char line[MAXLINE];
int ok_add, ok_replace, ok_remove;
/* Make sure ADD is not defined in the parent process. */
rc = gpgrt_setenv ("ADD", NULL, 1);
if (rc)
fail ("gpgrt_setenv failed at %d: %s", __LINE__, gpg_strerror (rc));
/* Set REPLACE and GNUPGHOME in the parent process. */
rc = gpgrt_setenv ("REPLACE", "0", 1);
if (rc)
fail ("gpgrt_setenv failed at %d: %s", __LINE__, gpg_strerror (rc));
rc = gpgrt_setenv ("GNUPGHOME", "/tmp/test", 1);
if (rc)
fail ("gpgrt_setenv failed at %d: %s", __LINE__, gpg_strerror (rc));
rc = gpgrt_spawn_actions_new (&act);
if (rc)
fail ("gpgrt_spawn_actions_new failed at %d: %s",
__LINE__, gpg_strerror (rc));
gpgrt_spawn_actions_set_envchange (act, envchange);
rc = gpgrt_process_spawn (progname, argv1,
(GPGRT_PROCESS_STDIN_KEEP
| GPGRT_PROCESS_STDOUT_PIPE
| GPGRT_PROCESS_STDERR_KEEP),
act, &process);
if (rc)
fail ("gpgrt_process_spawn failed at %d: %s", __LINE__, gpg_strerror (rc));
gpgrt_spawn_actions_release (act);
rc = gpgrt_process_get_streams (process, 0, NULL, &fp_out, NULL);
if (rc)
fail ("gpgrt_process_get_streams failed at %d: %s",
__LINE__, gpg_strerror (rc));
ok_add = ok_replace = 0;
ok_remove = 1;
while (gpgrt_fgets (line, DIM (line), fp_out))
{
#ifdef HAVE_W32_SYSTEM
{ /* Take care of CRLF. */
char *p = strchr (line, '\r');
if (p)
*p = '\n';
}
#endif
if (!strncmp (line, "ADD=", 3))
{
if (!strncmp (line+4, "0\n", 2))
ok_add = 1;
}
if (!strncmp (line, "REPLACE=", 8))
{
if (!strncmp (line+8, "1\n", 2))
ok_replace = 1;
}
if (!strncmp (line, "GNUPGHOME=", 10))
ok_remove = 0;
}
r = gpgrt_fclose (fp_out);
if (r)
fail ("gpgrt_fclose failed at %d: %d", __LINE__, r);
rc = gpgrt_process_wait (process, 1);
if (rc)
fail ("gpgrt_process_wait failed at %d: %s", __LINE__, gpg_strerror (rc));
gpgrt_process_release (process);
if (verbose)
show ("Result: add=%s, replace=%s, remove=%s\n",
ok_add? "OK" : "FAIL", ok_replace? "OK" : "FAIL",
ok_remove? "OK" : "FAIL");
if (!ok_add)
fail ("ADD failed");
if (!ok_replace)
fail ("REPLACE failed");
if (!ok_remove)
fail ("GNUPGHOME failed");
}
int
main (int argc, char **argv)
{
int last_argc = -1;
int child = 0;
const char *progname = argv[0];
if (argc)
{
argc--; argv++;
}
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--help"))
{
puts (
"usage: ./t-spawn [options]\n"
"\n"
"Options:\n"
" --verbose Show what is going on\n"
" --debug Flyswatter\n"
" --child Internal use for the child process\n"
);
exit (0);
}
if (!strcmp (*argv, "--verbose"))
{
verbose = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose = debug = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--child"))
{
child = 1;
argc--; argv++;
}
}
if (!gpg_error_check_version (GPG_ERROR_VERSION))
{
die ("gpg_error_check_version returned an error");
errorcount++;
}
if (child)
{
char *e;
e = gpgrt_getenv ("ADD");
if (e)
{
printf ("ADD=%s\n", e);
gpgrt_free (e);
}
e = gpgrt_getenv ("REPLACE");
if (e)
{
printf ("REPLACE=%s\n", e);
gpgrt_free (e);
}
e = gpgrt_getenv ("GNUPGHOME");
if (e)
{
printf ("GNUPGHOME=%s\n", e);
gpgrt_free (e);
}
return 0;
}
run_test (progname);
return errorcount ? 1 : 0;
}