fix issue with redirections to bash input file descriptor; new minimal chmod builtin; posix mode change for kill builtin return status; perform additional validation on brace expansion sequence expressions

This commit is contained in:
Chet Ramey
2025-02-12 11:18:16 -05:00
parent 3cfc255efe
commit c3ca11424d
13 changed files with 403 additions and 44 deletions
+7 -3
View File
@@ -103,8 +103,8 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins -I${srcdir} \
ALLPROG = print truefalse sleep finfo logname basename dirname fdflags \
tty pathchk tee head mkdir rmdir mkfifo mktemp printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid seq rm \
accept csv dsv cut stat getconf kv strptime
OTHERPROG = necho hello cat pushd asort fltexpr
accept csv dsv cut stat getconf kv strptime chmod
OTHERPROG = necho hello cat pushd asort fltexpr
SUBDIRS = perl
@@ -238,6 +238,9 @@ strftime: strftime.o
strptime: strptime.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strptime.o $(SHOBJ_LIBS)
chmod: chmod.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ chmod.o $(SHOBJ_LIBS)
mypid: mypid.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mypid.o $(SHOBJ_LIBS)
@@ -319,7 +322,7 @@ OBJS = print.o truefalse.o accept.o sleep.o finfo.o getconf.o logname.o \
basename.o dirname.o tty.o pathchk.o tee.o head.o rmdir.o necho.o \
hello.o cat.o csv.o dsv.o kv.o cut.o printenv.o id.o whoami.o uname.o \
sync.o push.o mkdir.o mktemp.o realpath.o strftime.o setpgid.o stat.o \
fdflags.o seq.o asort.o strptime.o
fdflags.o seq.o asort.o strptime.o chmod.o
${OBJS}: ${BUILD_DIR}/config.h
@@ -340,6 +343,7 @@ rmdir.o: rmdir.c
necho.o: necho.c
hello.o: hello.c
cat.o: cat.c
chmod.o: chmod.c
csv.o: csv.c
dsv.o: dsv.c
kv.o: kv.c
+156
View File
@@ -0,0 +1,156 @@
/* chmod - change file mode bits */
/* See Makefile for compilation details. */
/*
Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "bashtypes.h"
#include "posixstat.h"
#include <errno.h>
#include <stdio.h>
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "builtins.h"
#include "shell.h"
#include "bashgetopt.h"
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
extern int parse_symbolic_mode (char *, mode_t);
#define STANDARD_BITS (S_IRWXU | S_IRWXG | S_IRWXO)
#define ALLBITS (STANDARD_BITS | S_ISUID| S_ISGID | S_ISVTX)
int
chmod_builtin (WORD_LIST *list)
{
int opt, nmode, lmode, rval;
char *mode;
struct stat st;
WORD_LIST *l;
reset_internal_getopt ();
mode = (char *)NULL;
while ((opt = internal_getopt(list, "fhvRHLP")) != -1)
switch (opt)
{
CASE_HELPOPT;
default:
return (EX_DISKFALLBACK);
}
list = loptend;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
mode = list->word->word;
list = list->next;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
nmode = -1;
if (ISOCTAL (*mode)) /* octal number */
{
nmode = read_octal (mode);
if (nmode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
}
else /* test for valid symbolic mode */
{
/* initial bits are a=rwx; the mode argument modifies them */
lmode = parse_symbolic_mode (mode, ALLBITS);
if (lmode < 0)
{
builtin_error ("invalid file mode: %s", mode);
return (EXECUTION_FAILURE);
}
}
for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
{
lmode = nmode;
if (stat (l->word->word, &st) < 0)
{
builtin_error ("`%s': cannot stat: %s", l->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
continue;
}
if (lmode == -1)
{
lmode = parse_symbolic_mode (mode, st.st_mode & ALLBITS);
if (lmode < 0)
{
builtin_error ("`%s': invalid file mode: %s", l->word->word, mode);
rval = EXECUTION_FAILURE;
continue;
}
}
if (chmod (l->word->word, lmode))
{
builtin_error ("`%s': cannot change mode: %s", l->word->word, strerror (errno));
rval = EXECUTION_FAILURE;
continue;
}
}
return rval;
}
char *chmod_doc[] = {
"Change file mode bits.",
"",
"Change file mode bits. Change the mode bits of files named as",
"arguments, in the order specified, as specified by MODE."
"The MODE argument may be an octal number or a symbolic mode like",
"that described in chmod(1). If a symbolic mode is used, the",
"operations are interpreted relative to an initial mode of \"a=rwx\".",
"",
"The return value is 0 unless an error occurs.",
(char *)NULL
};
struct builtin chmod_struct = {
"chmod",
chmod_builtin,
BUILTIN_ENABLED,
chmod_doc,
"chmod [-R] mode file [file...]",
0
};