Files
shadow/lib/shell.c
Alejandro Colomar 9858133cc6 lib/, src/: snprintf(3) already terminates strings with NUL
We don't need to terminate them manually after the call.  Remove all
that paranoid code, which in some cases was even wrong.  While at it,
let's do a few more things:

-  Use sizeof(buf) for the size of the buffer.  I found that a few cases
   were passing one less byte (probably because the last one was
   manually zeroed later).  This caused a double NUL.  snprintf(3) wants
   the size of the entire buffer to properly terminate it.  Passing the
   exact value hardcoded is brittle, so use sizeof().

-  Align and improve style of variable declarations.  This makes them
   appear in this diff, which will help review the patch.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
2023-12-13 12:34:30 +01:00

80 lines
1.9 KiB
C

/*
* SPDX-FileCopyrightText: 1989 - 1991, Julianne Frances Haugh
* SPDX-FileCopyrightText: 1996 - 1998, Marek Michałkiewicz
* SPDX-FileCopyrightText: 2003 - 2006, Tomasz Kłoczko
* SPDX-FileCopyrightText: 2009 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <errno.h>
#include "prototypes.h"
#include "defines.h"
extern char **newenvp;
extern size_t newenvc;
/*
* shell - execute the named program
*
* shell begins by trying to figure out what argv[0] is going to
* be for the named process. The user may pass in that argument,
* or it will be the last pathname component of the file with a
* '-' prepended.
* Then, it executes the named file.
*/
int shell (const char *file, /*@null@*/const char *arg, char *const envp[])
{
int err;
char arg0[1024];
if (file == NULL) {
errno = EINVAL;
return errno;
}
/*
* The argv[0]'th entry is usually the path name, but
* for various reasons the invoker may want to override
* that. So, we determine the 0'th entry only if they
* don't want to tell us what it is themselves.
*/
if (arg == NULL) {
snprintf(arg0, sizeof(arg0), "-%s", Basename(file));
arg = arg0;
}
/*
* First we try the direct approach. The system should be
* able to figure out what we are up to without too much
* grief.
*/
(void) execle (file, arg, (char *) NULL, envp);
err = errno;
if (access (file, R_OK|X_OK) == 0) {
/*
* Assume this is a shell script (with no shebang).
* Interpret it with /bin/sh
*/
(void) execle (SHELL, "sh", "-", file, (char *) NULL, envp);
err = errno;
}
/*
* Obviously something is really wrong - I can't figure out
* how to execute this stupid shell, so I might as well give
* up in disgust ...
*/
(void) snprintf (arg0, sizeof arg0, _("Cannot execute %s"), file);
errno = err;
perror (arg0);
return err;
}