move environ handling to stdcio, and add the missing perror for stdcio so that it doesn't recursively try to open itself.

This commit is contained in:
Kalamatee 2023-04-24 00:01:32 +01:00 committed by deadwood
parent ff86935809
commit cf01fc779a
20 changed files with 619 additions and 23 deletions

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2021, The AROS Development Team. All rights reserved.
Copyright (C) 2008-2023, The AROS Development Team. All rights reserved.
Support functions for POSIX exec*() functions.
*/
@ -24,6 +24,7 @@
#include "__posixc_intbase.h"
#include "__exec.h"
#include "__posixc_env.h"
#include "__upath.h"
#include "__fdesc.h"
#include "__vfork.h"

View File

@ -0,0 +1,33 @@
/*
Copyright (C) 2023, The AROS Development Team. All rights reserved.
Desc: AROS specific function for environ emulation handling
*/
#include <aros/debug.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/stdcio.h>
#include "__env.h"
char ***__posixc_get_environptr (void)
{
return __stdcio_get_environptr();
}
int __posixc_set_envlistptr (char ***envlistptr)
{
return __stdcio_set_envlistptr(envlistptr);
}
char ***__posixc_get_envlistptr (void)
{
return __stdcio_get_envlistptr();
}
__env_item *__posixc_env_getvar(const char *varname, int valuesize)
{
return (__env_item *)__stdcio_env_getvar(varname, valuesize);
}

View File

@ -0,0 +1,13 @@
/*
Copyright (C) 2023, The AROS Development Team. All rights reserved.
Desc: AROS specific function for environ emulation handling
*/
#include "__env.h"
char ***__posixc_get_environptr (void);
int __posixc_set_envlistptr (char ***envlistptr);
char ***__posixc_get_envlistptr (void);
__env_item *__posixc_env_getvar(const char *varname, int valuesize);

View File

@ -52,12 +52,6 @@ struct PosixCIntBase
sigset_t signals;
#endif
/* __posixc_environ.c; don't use this field outside that file */
char ***environptr;
/* __env.c */
struct __env_item *env_list;
/* __exec.c */
BPTR exec_seglist;
char *exec_args;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2021, The AROS Development Team. All rights reserved.
Copyright (C) 2008-2023, The AROS Development Team. All rights reserved.
*/
#include <aros/debug.h>
@ -23,6 +23,7 @@
#include <stdio.h>
#include "__posixc_intbase.h"
#include "__posixc_env.h"
#include "__fdesc.h"
#include "__vfork.h"
#include "__exec.h"
@ -506,9 +507,11 @@ static void parent_enterpretendchild(struct vfork_data *udata)
*/
__stdc_program_startup(udata->parent_newexitjmp, &udata->child_error);
#if (0)
/* Remember and switch env var list */
udata->parent_env_list = PosixCBase->env_list;
PosixCBase->env_list = udata->child_posixcbase->env_list;
udata->parent_env_list = __posixc_get_envlistptr();
__posixc_set_envlistptr(udata->child_posixcbase->PosixCBase.StdCIOBase->env_list);
#endif
/* Remember and switch fd descriptor table */
udata->parent_internalpool = PosixCBase->internalpool;
@ -557,8 +560,10 @@ static void parent_leavepretendchild(struct vfork_data *udata)
/* Restore parent's StdCBase */
PosixCBase->PosixCBase.StdCBase = udata->parent_stdcbase;
#if (0)
/* Restore parent's env var list */
PosixCBase->env_list = udata->parent_env_list;
__posixc_set_envlistptr(udata->parent_env_list);
#endif
/* Restore parent's old fd_array */
PosixCBase->internalpool = udata->parent_internalpool;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 1995-2020, The AROS Development Team. All rights reserved.
Copyright (C) 1995-2023, The AROS Development Team. All rights reserved.
POSIX.1-2008 function execl().
*/

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2020, The AROS Development Team. All rights reserved.
Copyright (C) 2008-2023, The AROS Development Team. All rights reserved.
POSIX.1-2008 function execlp().
*/

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2008-2013, The AROS Development Team. All rights reserved.
Copyright (C) 2008-2023, The AROS Development Team. All rights reserved.
POSIX.1-2008 function execv().
*/

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 1995-2013, The AROS Development Team. All rights reserved.
Copyright (C) 1995-2023, The AROS Development Team. All rights reserved.
POSIX.1-2008 function execvp().
*/

View File

@ -238,7 +238,6 @@ POSIXC_LINKLIB := \
gcvt \
getopt \
getopt_long \
posixc_environ \
setlinebuf
# Both in linklib and shared library
@ -249,6 +248,7 @@ POSIXC_COMMON := \
NOWARN_FLAGS := $(NOWARN_NONNULL_COMPARE)
USER_CFLAGS += $(NOWARN_FLAGS) $(CFLAGS_MERGE_CONSTANTS)
USER_INCLUDES += -iquote $(SRCDIR)/compiler/stdc
USER_CPPFLAGS := \
-D__TIMER_NOLIBBASE__ \

View File

@ -1188,11 +1188,8 @@ int flock(int fd, int operation)
# * sys/mount.h: BSD
int getfsstat(struct statfs *buf, long bufsize, int flags)
int statfs(const char *path, struct statfs *buf)
.skip 3
#
# * unistd.h: Legacy support, amiga/AROS extension
int __posixc_set_environptr(char ***environptr)
char ***__posixc_get_environptr(void)
.skip 1
#useconds_t ualarm(useconds_t, useconds_t)
int usleep(useconds_t microseconds)
pid_t vfork(void)

232
compiler/stdc/__env.c Normal file
View File

@ -0,0 +1,232 @@
/*
Copyright (C) 1995-2023, The AROS Development Team. All rights reserved.
Internal functions for environment variables handling.
*/
#include "__stdcio_intbase.h"
#include <stdlib.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>
#include <dos/var.h>
#include "__env.h"
#if AROS_AMIGAOS_COMPLIANCE && (AROS_AMIGAOS_COMPLIANCE >= 30)
/* ScanVars is a Morphos addition in dos.library v50, so we
* have this stub here for posixc.library compatability with
* dos.library v30..v39.
*/
static LONG v30_ScanVars(struct Hook *hook, ULONG flags, APTR userdata)
{
/* We scan through the process->pr_LocalVars list */
struct Process *pr;
struct LocalVar *var;
struct ScanVarsMsg msg;
LONG res = 0;
APTR UtilityBase;
UtilityBase = OpenLibrary("utility.library", 0);
if (UtilityBase == NULL)
return 0;
msg.sv_SVMSize = sizeof(struct ScanVarsMsg);
msg.sv_Flags = flags;
pr = (struct Process *)FindTask(NULL);
/* We know that the callers of this routine
* will be asking for GVF_LOCAL_ONLY
*/
var = (struct LocalVar *)pr->pr_LocalVars.mlh_Head;
ForeachNode(&pr->pr_LocalVars, var)
{
if (var->lv_Node.ln_Type == LV_VAR)
{
msg.sv_Name = var->lv_Node.ln_Name;
msg.sv_Var = var->lv_Value;
msg.sv_VarLen = var->lv_Len;
msg.sv_GDir = "";
res = CallHookPkt(hook, userdata, &msg);
if(res != 0)
break;
}
}
CloseLibrary(UtilityBase);
return res;
}
#undef ScanVars
#define ScanVars(a,b,c) v30_ScanVars(a,b,c)
#endif
static __env_item *__env_newvar(const char *name, int valuesize)
{
__env_item *item;
item = malloc(sizeof(__env_item));
if (!item) goto err1;
item->name = strdup(name);
if (!item->name) goto err2;
item->value = malloc(valuesize);
if (!item->value) goto err3;
item->next = NULL;
return item;
err3:
free(item->name);
err2:
free(item);
err1:
return NULL;
}
static __env_item **internal_findvar(register const char *name)
{
struct StdCIOIntBase *StdCIOBase =
(struct StdCIOIntBase *)__aros_getbase_StdCIOBase();
__env_item **curr;
for (
curr = &StdCIOBase->env_list;
*curr && strcmp((*curr)->name, name);
curr = &((*curr)->next)
);
return curr;
}
/*
Allocates space for a variable with name 'name' returning a pointer to it.
If a variable with this name already exists then returns a pointer to that
variable.
Returns NULL on error.
*/
__env_item *__stdcio_env_getvar(const char *name, int valuesize)
{
register __env_item **curr;
curr = internal_findvar(name);
if (*curr)
{
if (strlen((*curr)->value) < valuesize)
{
free((*curr)->value);
(*curr)->value = malloc(valuesize);
if (!(*curr)->value)
{
__env_item *tmp = (*curr)->next;
free(*curr);
*curr = tmp;
}
}
}
else
{
*curr = __env_newvar(name, valuesize);
}
return *curr;
}
void __env_delvar(const char *name)
{
register __env_item **curr;
curr = internal_findvar(name);
if (*curr)
{
register __env_item *tmp = *curr;
*curr = (*curr)->next;
free(tmp->name);
free(tmp->value);
free(tmp);
}
}
struct EnvData
{
int envcount;
int varbufsize;
char * varbufptr;
};
/* Hook function counting the number of variables and computing the buffer size
needed for name=value character buffer. */
LONG get_var_len(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
{
struct EnvData *data = (struct EnvData *) userdata;
data->envcount++;
data->varbufsize +=
(ptrdiff_t) strlen((char*)message->sv_Name) +
message->sv_VarLen + 2;
return 0;
}
/* Hook function storing name=value strings in buffer */
LONG get_var(struct Hook *hook, APTR userdata, struct ScanVarsMsg *message)
{
struct EnvData *data = userdata;
data->varbufptr[0] = '\0';
strcat(data->varbufptr, (char*) message->sv_Name);
strcat(data->varbufptr, "=");
strncat(data->varbufptr, (char*) message->sv_Var, message->sv_VarLen);
data->varbufptr = data->varbufptr + strlen(data->varbufptr) + 1;
return 0;
}
/* Function storing name=value strings in given environ buffer. When buffer is
null, it returns minimal necessary size of the buffer needed to store all
name=value strings. */
int __env_get_environ(char **environ, int size)
{
int i;
struct Hook hook;
struct EnvData u;
char *varbuf;
u.envcount = 0;
u.varbufsize = 0;
memset(&hook, 0, sizeof(struct Hook));
hook.h_Entry = (HOOKFUNC) get_var_len;
ScanVars(&hook, GVF_LOCAL_ONLY, &u);
if(environ == NULL)
return sizeof(char*) * (u.envcount + 1) + u.varbufsize;
else if(size < sizeof(char*) *(u.envcount + 1) + u.varbufsize)
return -1;
/* store name=value strings after table of pointers */
varbuf = (char*) (environ + (u.envcount + 1));
/* time to fill in the buffers */
u.varbufptr = varbuf;
u.varbufptr[0] = '\0';
hook.h_Entry = (HOOKFUNC) get_var;
ScanVars(&hook, GVF_LOCAL_ONLY, &u);
for(i = 0; i < u.envcount; i++)
{
environ[i] = varbuf;
varbuf = strchr(varbuf, '\0') + 1;
}
environ[u.envcount] = NULL;
return 0;
}

23
compiler/stdc/__env.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef ___ENV_H
#define ___ENV_H
/*
Copyright © 1995-2023, The AROS Development Team. All rights reserved.
$Id$
Desc: internal header file for environment variables handling
Lang: english
*/
typedef struct __env_item
{
struct __env_item *next;
char *name;
char *value;
} __env_item;
void __env_delvar(const char *varname);
int __env_get_environ(char **environ, int size);
#endif /* ___ENV_H */

View File

@ -0,0 +1,93 @@
/*
Copyright (C) 2023, The AROS Development Team. All rights reserved.
Desc:
*/
#include <aros/debug.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <dos/dos.h>
#include "__stdcio_intbase.h"
#include "__env.h"
#include <stdio.h>
/*****************************************************************************
NAME */
#include <stdlib.h>
int __stdcio_set_envlistptr (
/* SYNOPSIS */
char ***envlistptr)
/* FUNCTION
INPUTS
RESULT
NOTES
Private - do not use!
EXAMPLE
BUGS
SEE ALSO
__stdcio_get_envlistptr()
INTERNALS
******************************************************************************/
{
struct StdCIOIntBase *StdCIOBase =
(struct StdCIOIntBase *)__aros_getbase_StdCIOBase();
D(bug("[stdcio] %s(0x%p)\n", __func__, envlistptr);)
StdCIOBase->env_list = (struct __env_item *)envlistptr;
return (1);
}
/*****************************************************************************
NAME */
#include <stdlib.h>
char ***__stdcio_get_envlistptr (
/* SYNOPSIS */
void)
/* FUNCTION
INPUTS
-
RESULT
NOTES
Private - do not use!
EXAMPLE
BUGS
SEE ALSO
__stdcio_set_envlistptr()
INTERNALS
******************************************************************************/
{
struct StdCIOIntBase *StdCIOBase =
(struct StdCIOIntBase *)__aros_getbase_StdCIOBase();
return (char ***)StdCIOBase->env_list;
}

View File

@ -0,0 +1,111 @@
/*
Copyright (C) 2012-2023, The AROS Development Team. All rights reserved.
Desc: AROS specific function for environ emulation handling
*/
#include <aros/debug.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <dos/dos.h>
#include "__stdcio_intbase.h"
#include "__env.h"
#include <stdio.h>
/*****************************************************************************
NAME */
#include <stdlib.h>
int __stdcio_set_environptr (
/* SYNOPSIS */
char ***environptr)
/* FUNCTION
This function is called to enable environ emulation mode.
INPUTS
environptr - ptr to the child environ variable (== &environ).
RESULT
0 on fail, other value on success
NOTES
This function will enable environ emulation. This means that
all current DOS local variables are converted to the 'var=value'
format and be accessible through char **environ.
EXAMPLE
BUGS
At the moment only a static list is supported. getenv() and setenv()
don't use this yet so changes done with these functions are not
reflected in environ.
This is still TODO.
SEE ALSO
__stdcio_get_environptr(), __stdcio_getenv(), setenv()
INTERNALS
******************************************************************************/
{
struct StdCIOIntBase *StdCIOBase =
(struct StdCIOIntBase *)__aros_getbase_StdCIOBase();
int len;
D(
bug("[stdcio] %s(0x%p)\n", __func__, environptr);
bug("[stdcio] %s: Initializing environ emulation\n", __func__);
)
StdCIOBase->environptr = environptr;
len = __env_get_environ(NULL, 0);
*environptr = malloc(len);
return (__env_get_environ(*environptr, len) >= 0);
}
/*****************************************************************************
NAME */
#include <stdlib.h>
char ***__stdcio_get_environptr (
/* SYNOPSIS */
void)
/* FUNCTION
This function the get pointer to the child environ global variable
currently used by posixc.library.
INPUTS
-
RESULT
environptr - ptr to the child environ variable (== &environ).
NULL is return if envirion emulation is disabled.
NOTES
EXAMPLE
BUGS
SEE ALSO
__stdcio_set_environptr()
INTERNALS
******************************************************************************/
{
struct StdCIOIntBase *StdCIOBase =
(struct StdCIOIntBase *)__aros_getbase_StdCIOBase();
return StdCIOBase->environptr;
}

View File

@ -17,6 +17,12 @@ struct StdCIOIntBase
{
struct StdCIOBase StdCIOBase;
/* __stdcio_environ.c; don't use this field outside that file */
char ***environptr;
/* __env.c */
struct __env_item *env_list;
/* getenv.c */
LONG varsize;
char *envvar;

View File

@ -479,8 +479,11 @@ STDC_COMMON := \
math/infinity
STDCIO := \
__env \
__stdcio_assert \
__stdcio_init \
__stdcio_env \
__stdcio_environ \
__stdio \
clearerr \
fclose \
@ -504,6 +507,7 @@ STDCIO := \
getchar \
getenv \
gets \
perror \
printf \
putchar \
puts \
@ -526,6 +530,9 @@ STDCIO := \
STDCIO_COMMON := \
__stdcio_stdstreams
STDCIO_LINKLIB := \
stdcio_environ
##MM- core-linklibs : linklibs-stdc linklibs-stdcio linklibs-libm
STDC_LINKOBJS := $(addsuffix .o,$(addprefix $(GENDIR)/$(CURDIR)/stdc/,$(notdir $(STDC_COMMON))))
@ -555,7 +562,7 @@ USER_CPPFLAGS := \
#%build_module mmake=compiler-stdcio \
# modname=stdcio modtype=library \
# files="$(STDCIO) $(STDCIO_COMMON)" \
# linklibobjs=$(STDCIO_LINKOBJS) \
# linklibfiles=$(STDCIO_LINKLIB) linklibobjs=$(STDCIO_LINKOBJS) \
# uselibs="stdc_rel" usesdks="rel"
STDC_MATH_STATIC := \

53
compiler/stdc/perror.c Normal file
View File

@ -0,0 +1,53 @@
/*
Copyright (C) 1995-2013, The AROS Development Team. All rights reserved.
C99 function perror().
*/
#include <errno.h>
#include <string.h>
/*****************************************************************************
NAME */
#include <stdio.h>
void perror (
/* SYNOPSIS */
const char *string
)
/* FUNCTION
looks up the language-dependent error message string affiliated with an error
number and writes it, followed by a newline, to the standard error stream.
INPUTS
string - the string to prepend the error message. If NULL only the error
message will be printed, otherwise the error message will be
separated from string by a colon.
RESULT
NOTES
EXAMPLE
BUGS
SEE ALSO
INTERNALS
******************************************************************************/
{
if (string)
{
fputs(string, stderr);
fputs(": ", stderr);
}
fputs(__stdc_strerror(errno), stderr);
fputs("\n", stderr);
} /* perror */

View File

@ -1,5 +1,5 @@
##begin config
version 0.3
version 0.4
basename StdCIO
libbasetypeextern struct StdCIOBase
libbasetype struct StdCIOIntBase
@ -23,7 +23,13 @@ options peropenerbase,rellinklib
##begin functionlist
# == Internal functions ==
.skip 20
# * unistd.h: Legacy support, amiga/AROS extension
int __stdcio_set_environptr(char ***environptr)
char ***__stdcio_get_environptr(void)
int __stdcio_set_envlistptr(char ***envlisttr)
char ***__stdcio_get_envlistptr(void)
char *__stdcio_env_getvar(const char *varname, int valuesize)
.skip 15
#
# == C99 functions that need dos.library ==
# * assert.h

View File

@ -0,0 +1,22 @@
/*
Copyright (C) 2012-2023, The AROS Development Team. All rights reserved.
Desc: Code enabling environ emulation mode for user programs.
This code is part of the static link library of stdcio.
When programs do not access this variable environ emulation
won't be enable.
See __stdcio_set_environptr() autodoc for more information.
*/
#include <aros/symbolsets.h>
extern int __stdcio_set_environptr (char ***environptr);
char **environ;
static int __environ_init(struct ExecBase *SysBase)
{
return __stdcio_set_environptr(&environ);
}
ADD2INIT(__environ_init, 0)