diff -upr tcsh-6.18.01_orig/config.h.in tcsh-6.18.01_work/config.h.in --- tcsh-6.18.01_orig/config.h.in 2013-04-23 14:10:52.181655679 +0200 +++ tcsh-6.18.01_work/config.h.in 2013-04-23 14:14:33.715035808 +0200 @@ -36,6 +36,9 @@ /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 +/* Define to 1 if you have the header file. */ +#undef HAVE_ELF_H + /* Define to 1 if you have the header file. */ #undef HAVE_FEATURES_H @@ -96,6 +99,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + /* Define to 1 if you have the `sbrk' function. */ #undef HAVE_SBRK diff -upr tcsh-6.18.01_orig/configure.in tcsh-6.18.01_work/configure.in --- tcsh-6.18.01_orig/configure.in 2013-04-23 14:10:52.157655645 +0200 +++ tcsh-6.18.01_work/configure.in 2013-04-23 14:13:53.226958044 +0200 @@ -306,7 +306,7 @@ AC_SEARCH_LIBS(catgets, catgets) AM_ICONV dnl Checks for header files -AC_CHECK_HEADERS([auth.h crypt.h features.h inttypes.h paths.h] dnl +AC_CHECK_HEADERS([auth.h crypt.h elf.h features.h inttypes.h paths.h] dnl [shadow.h stdint.h utmp.h utmpx.h]) AC_CHECK_HEADERS([wchar.h], [AC_CHECK_SIZEOF([wchar_t], [], [dnl @@ -388,7 +388,8 @@ AC_CHECK_FUNC([setlocale], [have_setloca AC_CHECK_FUNC([catgets], [have_catgets=yes], [have_catgets=no]) AC_CHECK_FUNCS([dup2 getauthid getcwd gethostname getpwent] dnl [getutent getutxent mallinfo memmove memset mkstemp nice] dnl - [nl_langinfo sbrk setpgid setpriority strerror strstr sysconf wcwidth]) + [nl_langinfo pread sbrk setpgid setpriority strerror strstr] dnl + [sysconf wcwidth]) AC_FUNC_GETPGRP AC_FUNC_MBRTOWC if test "x${cross_compiling}" != xyes ; then diff -upr tcsh-6.18.01_orig/sh.err.c tcsh-6.18.01_work/sh.err.c --- tcsh-6.18.01_orig/sh.err.c 2013-04-23 14:10:52.160655649 +0200 +++ tcsh-6.18.01_work/sh.err.c 2013-04-23 14:15:33.347155943 +0200 @@ -189,7 +189,8 @@ char *seterr = NULL; /* Holds last err #define ERR_INVALID 133 #define ERR_BADCOLORVAR 134 #define ERR_EOF 135 -#define NO_ERRORS 136 +#define ERR_ELFINTERP 136 +#define NO_ERRORS 137 static const char *elst[NO_ERRORS] INIT_ZERO_STRUCT; @@ -367,6 +368,7 @@ errinit(void) elst[ERR_BADJOB] = CSAVS(1, 136, "No such job (badjob)"); elst[ERR_BADCOLORVAR] = CSAVS(1, 137, "Unknown colorls variable `%c%c'"); elst[ERR_EOF] = CSAVS(1, 138, "Unexpected end of file"); + elst[ERR_ELFINTERP] = CSAVS(1, 139, "No such ELF interpreter"); } /* Cleanup data. */ diff -upr tcsh-6.18.01_orig/sh.exec.c tcsh-6.18.01_work/sh.exec.c --- tcsh-6.18.01_orig/sh.exec.c 2013-04-23 14:10:52.156655643 +0200 +++ tcsh-6.18.01_work/sh.exec.c 2013-04-23 14:35:43.561578622 +0200 @@ -40,6 +40,10 @@ RCSID("$tcsh: sh.exec.c,v 3.79 2011/02/2 #include #endif /*WINNT_NATIVE*/ +#ifdef HAVE_ELF_H +#include +#endif /*HAVE_ELF_H*/ + /* * C shell */ @@ -509,6 +513,142 @@ texec(Char *sf, Char **st) case 0: /* execv fails and returns 0! */ #endif /* _IBMR2 */ case ENOENT: +#ifdef HAVE_ELF_H + /* + * If dynamically linked ELF binary is not executed and exists, + * the real reason ENOENT is that ELF interpreter is missing. + * + * Written by Ulrich Drepper for bash + * adopted by Fridolin Pokorny + */ + if ((fd = xopen(f, O_RDONLY|O_LARGEFILE)) != -1) { + int nread; + char *sample; + int offset = -1; + int sample_size; + + /* Inspect 32 and 64 ELF */ + if (sizeof(Elf64_Ehdr) > sizeof(Elf32_Ehdr)) + sample_size = sizeof(Elf64_Ehdr); + else + sample_size = sizeof(Elf32_Ehdr); + + sample = xmalloc(sample_size); + + if (sample != 0 && + (nread = xread(fd, sample, sample_size)) == sample_size) { + if (memcmp(sample, ELFMAG, SELFMAG) == 0) { + if (sample[EI_CLASS] == ELFCLASS32 && + sample_size >= sizeof(Elf32_Ehdr)) { + Elf32_Ehdr ehdr; + Elf32_Phdr *phdr; + int nphdr; + + /* + * We have to copy the data since the sample buffer + * might not be aligned correctly to be accessed as + * an Elf32_Ehdr struct. + */ + memcpy(&ehdr, sample, sizeof(Elf32_Ehdr)); + + nphdr = ehdr.e_phnum; + phdr = xmalloc(nphdr * ehdr.e_phentsize); + if(phdr != NULL) { +#ifdef HAVE_PREAD + nread = pread(fd, phdr, nphdr * ehdr.e_phentsize, + ehdr.e_phoff); +#else /* !HAVE_PREAD */ + if (lseek(fd, ehdr.e_phoff, SEEK_SET) != -1) + nread = read(fd, phdr, + nphdr * ehdr.e_phentsize); + else + nread = -1; +#endif /* HAVE_PREAD */ + if (nread == nphdr * ehdr.e_phentsize) { + while (nphdr-- > 0) { + if (phdr[nphdr].p_type == PT_INTERP) { + offset = phdr[nphdr].p_offset; + break; + } + } + } + xfree(phdr); + } + } else if (sample[EI_CLASS] == ELFCLASS64 && + sample_size >= sizeof(Elf64_Ehdr)) { + Elf64_Ehdr ehdr; + Elf64_Phdr *phdr; + int nphdr; + + /* + * We have to copy the data since the sample buffer + * might not be aligned correctly to be accessed as + * an Elf64_Ehdr struct. + */ + memcpy(&ehdr, sample, sizeof(Elf64_Ehdr)); + + nphdr = ehdr.e_phnum; + phdr = xmalloc(nphdr * ehdr.e_phentsize); + if (phdr != NULL) { +#ifdef HAVE_PREAD + nread = pread (fd, phdr, nphdr * ehdr.e_phentsize, + ehdr.e_phoff); +#else /* !HAVE_PREAD */ + if (lseek(fd, ehdr.e_phoff, SEEK_SET) != -1) + nread = read (fd, phdr, + nphdr * ehdr.e_phentsize); + else + nread = -1; +#endif /* HAVE_PREAD */ + if (nread == nphdr * ehdr.e_phentsize) { + while (nphdr-- > 0) { + if (phdr[nphdr].p_type == PT_INTERP) { + offset = phdr[nphdr].p_offset; + break; + } + } + } + xfree (phdr); + } + } + + if (offset != -1) { + size_t maxlen = 0; + size_t actlen = 0; + char *interp = NULL; + + do { + if (actlen == maxlen) { + char *newinterp = xrealloc(interp, maxlen += 200); + if (newinterp == NULL) { + actlen = 0; + break; + } + interp = newinterp; +#ifdef HAVE_PREAD + actlen = pread (fd, interp, maxlen, offset); +#else /* !HAVE_PREAD */ + if (lseek (fd, offset, SEEK_SET) != -1) + actlen = read (fd, interp, maxlen); + else + actlen = -1; +#endif /* HAVE_PREAD */ + } + } while (actlen > 0 && + memchr (interp, '\0', actlen) == NULL); + + if (actlen > 0) { + xclose (fd); + xfree (interp); + setname(f); + stderror(ERR_NAME | ERR_ELFINTERP); + } + } + } + } + xfree(sample); + } +#endif /* HAVE_ELF_H */ break; default: