Blob Blame History Raw
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 <elf.h> header file. */
+#undef HAVE_ELF_H
+
 /* Define to 1 if you have the <features.h> header file. */
 #undef HAVE_FEATURES_H
 
@@ -96,6 +99,9 @@
 /* Define to 1 if you have the <paths.h> 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 <nt.const.h>
 #endif /*WINNT_NATIVE*/
 
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#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 <fpokorny@redhat.com>
+	 */
+	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: