Jonathan Nieder <jrnie...@gmail.com> writes: > Hi Krzysztof, > > Sorry for the long delay in responding. > > Krzysztof A. Sobiecki wrote: > > [...] >> +++ dash-0.5.6.1/src/input.c 2010-06-25 00:45:19.000000000 +0200 >> @@ -400,15 +402,28 @@ popstring(void) >> */ >> >> int >> +isdir(const char *name) >> +{ >> + struct stat64 st; >> + if (stat64(name, &st) < 0) >> + return -1; >> + if (S_ISDIR(st.st_mode)) { >> + return -1; >> + } >> + return 0; >> +} > > This function does not distinguish between failures where errno is set > and where it is not... > >> + >> +int >> setinputfile(const char *fname, int flags) >> { >> int fd; >> >> INTOFF; >> - if ((fd = open(fname, O_RDONLY)) < 0) { >> + if ((isdir(fname) < 0) || ((fd = open(fname, O_RDONLY)) < 0)) { >> if (flags & INPUT_NOFILE_OK) >> goto out; >> - sh_error("Can't open %s", fname); >> + exitstatus = 127; >> + exerror(EXIFILE, "Can't open %s", fname); > > ... so the caller unconditionally suppresses errno. When I will have some time, I will think about it.
> The isdir() check happens before the open(), leading to unpleasant > behavior if a file is replaced by a directory between them. After 5 minutes, I hacked something to work around this problem(I hope). I have absolutely no faith about it. > The patch fixes two issues at once: changing the exit status to 127 > and catching attempts to redirect from a directory. I have tried to split it in two parts, but I didn't have time to do it properly. I'm sending what I have. > That said, do you think this could be made into two patches against > upstream to be sent to <d...@vger.kernel.org>? I don't think that this patches are good enough to send them to upstream. d.diff depends on c.diff
diff -rup ~dash-0.5.6.1/src/error.h tdash-0.5.6.1/src/error.h --- ~dash-0.5.6.1/src/error.h 2010-08-02 03:05:09.000000000 +0200 +++ tdash-0.5.6.1/src/error.h 2010-08-02 03:22:21.000000000 +0200 @@ -69,7 +69,7 @@ extern int exception; #define EXSHELLPROC 2 /* execute a shell procedure */ #define EXEXEC 3 /* command execution failed */ #define EXEXIT 4 /* exit the shell */ - +#define EXIFILE 5 /* inputfile cannot be opened or is a directory */ /* * These macros allow the user to suspend the handling of interrupt signals diff -rup ~dash-0.5.6.1/src/options.c tdash-0.5.6.1/src/options.c --- ~dash-0.5.6.1/src/options.c 2010-08-02 03:05:09.000000000 +0200 +++ tdash-0.5.6.1/src/options.c 2010-08-02 03:26:06.000000000 +0200 @@ -35,6 +35,9 @@ #include <signal.h> #include <unistd.h> #include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> #include "shell.h" #define DEFINE_OPTIONS @@ -117,6 +120,23 @@ STATIC int getopts(char *, char *, char */ int +isdir(const char *name) +{ + int fd; + struct stat64 st; + + if ((fd = open(name, O_RDONLY))<0) + return -1; + if (fstat64(fd, &st) < 0) + return -1; + if (S_ISDIR(st.st_mode)) { + return -1; + errno = EISDIR; + } + return 0; +} + +int procargs(int argc, char **argv) { int i; @@ -156,10 +176,16 @@ procargs(int argc, char **argv) if (*xargv) goto setarg0; } else if (!sflag) { - setinputfile(*xargv, 0); + if(!isdir(*xargv)) { + setinputfile(*xargv, 0); + } + else { + exerror(EXIFILE, "Can't open %s", *xargv); + } setarg0: - arg0 = *xargv++; - commandname = arg0; + arg0 = *xargv++; + commandname = arg0; + } shellparam.p = xargv;
diff -rup tdash-0.5.6.1/src/options.c dash-0.5.6.1/src/options.c --- tdash-0.5.6.1/src/options.c 2010-08-02 03:26:06.000000000 +0200 +++ dash-0.5.6.1/src/options.c 2010-08-02 03:26:31.000000000 +0200 @@ -180,6 +180,7 @@ procargs(int argc, char **argv) setinputfile(*xargv, 0); } else { + exitstatus = 127; exerror(EXIFILE, "Can't open %s", *xargv); } setarg0:
-- X was an interactive protocol: alpha blending a full-screen image looked like slugs racing down the monitor. http://www.keithp.com/~keithp/talks/usenix2000/render.html