1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix 'ps' output for hashbangless scripts on Linux/macOS

When invoking a script without an interpreter (#!hashbang) path,
ksh forks, but there is no exec syscall in the child. The existing
command line is overwritten in fixargs() with the name of the new
script and associated arguments. In the generic/fallback version of
fixargs() which is used on Linux and macOS, if the new command line
is longer than the existing one, it is truncated. This works well
when calling a script with a shorter name.

However, it generates a misleading name in the common scenario
where a script is invoked from an interactive shell, which
typically has a short command line. For instance, if "/tmp/script"
is invoked, "ksh" gets replaced with "/tm" in "ps" output.

A solution is found in the fact that, on these systems, the
environment is stored immediately after the command line arguments.
This space can be made available for use by a longer command line
by moving the environment strings out of the way.

src/cmd/ksh93/sh/main.c: fixargs():
- Refactor BSD setproctitle(3) version to be more self-contained.
- In the generic (Linux/macOS) version, on init (i.e. mode==0), if
  the command line is smaller than 128 bytes and the environment
  strings have not yet been moved (i.e. if they still immediately
  follow the command line arguments in memory), then strdup the
  environment strings, pointing the *environment[] members to the
  new strings and adding the length of the strings to the maximum
  command line buffer size.

Reported-by: @gkamat
Resolves: https://github.com/ksh93/ksh/pull/300
This commit is contained in:
Martijn Dekker 2021-09-12 05:16:51 +02:00
parent c3f7cf0314
commit bdc3069bfd
3 changed files with 62 additions and 23 deletions

View file

@ -56,6 +56,7 @@ static void exfile(Shell_t*, Sfio_t*,int);
static void chkmail(Shell_t *shp, char*);
#if !defined(_NEXT_SOURCE) && !defined(__sun)
static void fixargs(char**,int);
# undef fixargs_disabled
#else
# define fixargs(a,b)
# define fixargs_disabled 1
@ -715,12 +716,13 @@ static void chkmail(Shell_t *shp, char *files)
*/
static void fixargs(char **argv, int mode)
{
#if EXECARGS
# if EXECARGS
if(mode==0)
return;
*execargs=(char *)argv;
#else
register char *cp;
# elif PSTAT
char *cp;
int offset=0,size;
# ifdef PSTAT
static int command_len;
char *buff;
union pstun un;
@ -735,21 +737,6 @@ static void fixargs(char **argv, int mode)
}
stakseek(command_len+2);
buff = stakseek(0);
# elif _lib_setproctitle
# define command_len 255
char buff[command_len + 1];
if(mode==0)
return;
# else
static int command_len;
static char *buff;
if(mode==0)
{
buff = argv[0];
command_len = environ[0] - buff - 1;
return;
}
# endif /* PSTAT */
if(command_len==0)
return;
while((cp = *argv++) && offset < command_len)
@ -762,12 +749,59 @@ static void fixargs(char **argv, int mode)
}
offset--;
memset(&buff[offset], 0, command_len - offset + 1);
# ifdef PSTAT
un.pst_command = stakptr(0);
pstat(PSTAT_SETCMD,un,0,0,0);
# elif _lib_setproctitle
# define CMDMAXLEN 255
char *cp;
int offset=0,size;
char buff[CMDMAXLEN + 1];
if(mode==0)
return;
while((cp = *argv++) && offset < CMDMAXLEN)
{
if(offset + (size=strlen(cp)) >= CMDMAXLEN)
size = CMDMAXLEN - offset;
memcpy(buff+offset,cp,size);
offset += size;
buff[offset++] = ' ';
}
buff[--offset] = '\0';
setproctitle("%s",buff);
# endif /* PSTAT */
#endif /* EXECARGS */
# undef CMDMAXLEN
# else
/* Generic version, works on at least Linux and macOS */
char *cp;
int offset=0,size;
static int buffsize;
static char *buff;
if(mode==0)
{
int i;
buff = argv[0];
for(i=0; argv[i]; i++)
buffsize += strlen(argv[i]) + 1;
if(buffsize < 128 && buff + buffsize == *environ)
{
/* Move the environment to make space for a larger command line buffer */
for(i=0; environ[i]; i++)
{
buffsize += strlen(environ[i]) + 1;;
environ[i] = sh_strdup(environ[i]);
}
}
return;
}
while((cp = *argv++) && offset < buffsize)
{
if(offset + (size=strlen(cp)) >= buffsize)
size = buffsize - offset;
memcpy(buff+offset,cp,size);
offset += size;
buff[offset++] = ' ';
}
offset--;
memset(&buff[offset], 0, buffsize - offset + 1);
# endif
}
#endif /* !fixargs_disabled */