mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
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.
121 lines
2.9 KiB
Text
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
|