1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/src/cmd/ksh93/features/externs
Martijn Dekker 7b0e0776e2 cleanup: remove legacy code for systems without fork(2)
In 2021, it seems like it's about time to join the 21st century
and officially require fork(2). In practice this was already the
case as the legacy code was unmaintained and didn't compile.
2021-03-21 06:39:32 +00:00

121 lines
2.9 KiB
Text

set prototyped
hdr nc,exec_attr
mem exception.name,_exception.name math.h
lib setreuid,setregid,nice,fork,spawnveg,fchdir
lib pathnative,pathposix,uwin_path,uwin_unpath,fts_notify
lib memcntl sys/mman.h
lib getexecuser,free_execattr exec_attr.h -lsecdb
reference unistd.h
extern nice int (int)
extern setreuid int (uid_t,uid_t)
extern setregid int (gid_t,gid_t)
tst note{ determining extra bytes per argument for arguments list }end output{
/*
* Figure out if this OS requires extra bytes per argument
* in the arguments list of a process.
* Outputs an appropriate #define ARG_EXTRA_BYTES.
* Without this, 'command -x' failed with E2BIG on macOS, Linux and Solaris
* even if all the arguments should fit in ARG_MAX based on their length.
*/
/* AST includes */
#include <ast.h>
#include <error.h>
#include <sfio.h>
#include <stak.h>
#include <wait.h>
/* Standard includes */
#include <errno.h>
int main(int argc,char *argv[])
{
int extra_bytes = 0, envlen, argmax, i;
pid_t childpid;
error_info.id="ARG_EXTRA_BYTES test (parent)";
while(1)
{
envlen = 0;
for(i=0; argv[i]; i++)
envlen += strlen(argv[i]) + 1 + extra_bytes;
envlen += 1 + extra_bytes; /* final null element */
for(i=0; environ[i]; i++)
envlen += strlen(environ[i]) + 1 + extra_bytes;
envlen += 1 + extra_bytes; /* final null element */
argmax = strtoimax(astconf("ARG_MAX",NiL,NiL),NiL,0) - envlen;
if (argmax < 2048)
{
error(ERROR_ERROR|2, "argmax too small");
return 1;
}
if(!(childpid = fork()))
{
/* child */
int bytec;
error_info.id="ARG_EXTRA_BYTES test (child)";
argv = (char **)stakalloc((argmax / 2 + 1) * sizeof(char*));
argc = bytec = 0;
while(bytec < argmax)
{
if(argc==0)
argv[argc] = "/usr/bin/env";
else if(argc==1)
argv[argc] = "true";
else
argv[argc] = "x";
/* also add 1 for terminating zero byte */
bytec += strlen(argv[argc]) + 1 + extra_bytes;
argc++;
}
argv[argc] = (char*)0;
if(execve(argv[0], argv, environ) < 0)
{
if(errno == E2BIG)
return 1;
else
{
error(ERROR_SYSTEM|2, "execve failed");
return 2;
}
}
error(ERROR_SYSTEM|2, "[BUG] we should never get here!");
return 2;
}
else
{
/* parent */
int exitstatus;
if (waitpid(childpid,&i,0) < 0)
{
error(ERROR_SYSTEM|2, "waitpid failed");
return 1;
}
if (!WIFEXITED(i) || (exitstatus = WEXITSTATUS(i)) > 1)
{
error(ERROR_ERROR|2, "child process exited abnormally");
return 1;
}
if (exitstatus == 0)
break; /* yay :) */
extra_bytes++;
if (extra_bytes > 256)
{
error(ERROR_ERROR|2, "giving up");
return 1;
}
}
}
sfprintf(sfstdout,
"#define ARG_EXTRA_BYTES\t%d\t/* extra bytes per argument for arguments list */\n",
extra_bytes);
return 0;
}
}end fail{
echo "#define ARG_EXTRA_BYTES 16 /* BUG: test failed; assuming 16 */"
}end