DRAFT lib: Implement popen, pclose.

* lib/stub/pclose.c: Move to...
* lib/stdio/pclose.c: ...here.  Implement.
* lib/stub/popen.c: Move to...
* lib/stdio/popen.c: ...here.  Implement.
* build-aux/configure-lib.sh (libc_gnu_SOURCES): Update file locations.
This commit is contained in:
Jan (janneke) Nieuwenhuizen 2022-11-01 19:48:31 +01:00
parent e0b239b45d
commit 0e13782f0e
No known key found for this signature in database
GPG Key ID: F3C1A0D9C1D65273
4 changed files with 141 additions and 43 deletions

View File

@ -339,7 +339,9 @@ lib/stdio/feof.c
lib/stdio/fgets.c
lib/stdio/freopen.c
lib/stdio/fscanf.c
lib/stdio/pclose.c
lib/stdio/perror.c
lib/stdio/popen.c
lib/stdio/rewind.c
lib/stdio/vfscanf.c
lib/stdlib/__exit.c
@ -385,8 +387,6 @@ lib/stub/gmtime.c
lib/stub/log.c
lib/stub/mktime.c
lib/stub/modf.c
lib/stub/pclose.c
lib/stub/popen.c
lib/stub/pow.c
lib/stub/rand.c
lib/stub/setbuf.c

View File

@ -1,6 +1,6 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
* Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
* Copyright © 2022 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of GNU Mes.
*
@ -20,14 +20,31 @@
#include <mes/lib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int
pclose (int x)
pclose (FILE *stream)
{
static int stub = 0;
if (__mes_debug () && !stub)
eputs ("pclose stub\n");
stub = 1;
errno = 0;
return 0;
int filedes = fileno (stream);
__ungetc_init ();
pid_t pid = __ungetc_buf[filedes];
if (!pid)
{
errno = EINVAL;
return -1;
}
if (fclose (stream))
return -1;
int status;
pid_t child_pid = waitpid (pid, &status, 0);
if (child_pid != pid)
return -1;
return status;
}

114
lib/stdio/popen.c Normal file
View File

@ -0,0 +1,114 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
* Copyright © 2022 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of GNU Mes.
*
* GNU Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* GNU Mes 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mes/lib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef SHELL_FILE_NAME
#define SHELL_FILE_NAME "/bin/sh"
#endif
#ifndef SHELL_COMMAND_NAME
#define SHELL_COMMAND_NAME "sh"
#endif
extern int *__ungetc_buf;
FILE *
popen (char const *command, char const *mode)
{
if (!command || !mode || (*mode != 'r' && *mode != 'w'))
{
errno = EINVAL;
return 0;
}
int pipedes[2];
if (pipe (pipedes) < 0)
return NULL;
pid_t pid = fork ();
if (pid == -1)
{
close (pipedes[0]);
close (pipedes[1]);
return 0;
}
else if (pid == 0)
{
// child
int dup = (*mode == 'w'
? dup2 (pipedes[STDIN], STDIN)
: dup2 (pipedes[STDOUT], STDOUT))
if (dup < 0)
_exit (127);
close (pipedes[STDIN]);
close (pipedes[STDOUT]);
char const *argv[4];
argv[0] = SHELL_COMMAND_NAME;
argv[1] = "-c";
argv[2] = command;
argv[3] = 0;
execve (SHELL_FILE_NAME, (char *const *) argv, environ);
_exit (127);
}
FILE *stream;
// parent
if (*mode == 'r')
{
close (pipedes[STDOUT]);
fcntl (pipedes[STDIN], F_SETFD, FD_CLOEXEC);
stream = fdopen (pipedes[STDIN], mode);
}
else
{
close (pipedes[STDIN]);
fcntl (pipedes[STDOUT], F_SETFD, FD_CLOEXEC);
stream = fdopen (pipedes[STDOUT], mode);
}
if (!stream)
{
int save_errno = errno;
kill (pid, SIGKILL);
if (!stream)
close (pipedes[*mode == 'r' ? STDOUT : STDIN]);
else
fclose (stream);
waitpid (pid, (int *)0, 0);
errno = save_errno;
return 0;
}
int filedes = fileno (stream);
// XXX misuse ungetc buffer for PID
// XXX TODO: make proper FILE struct
__ungetc_init ();
__ungetc_set (filedes, pidchild);
return stream;
}

View File

@ -1,33 +0,0 @@
/* -*-comment-start: "//";comment-end:""-*-
* GNU Mes --- Maxwell Equations of Software
* Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
*
* This file is part of GNU Mes.
*
* GNU Mes is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* GNU Mes 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mes/lib.h>
#include <errno.h>
int
popen (int x)
{
static int stub = 0;
if (__mes_debug () && !stub)
eputs ("popen stub\n");
stub = 1;
errno = 0;
return 0;
}