[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/msdos/is_exec.c [lexbind]
From: |
Miles Bader |
Subject: |
[Emacs-diffs] Changes to emacs/msdos/is_exec.c [lexbind] |
Date: |
Tue, 14 Oct 2003 18:51:26 -0400 |
Index: emacs/msdos/is_exec.c
diff -c /dev/null emacs/msdos/is_exec.c:1.1.18.1
*** /dev/null Tue Oct 14 18:51:26 2003
--- emacs/msdos/is_exec.c Tue Oct 14 18:51:23 2003
***************
*** 0 ****
--- 1,225 ----
+ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+ /* IS_EXEC.C
+ *
+ * Given a filename or a file handle, and the extension of the file,
+ * determine if the file is executable.
+ * First, the file extension is checked in case it uniquely identifies
+ * the file as either an executable or not. Failing this, the first
+ * two bytes of the file are tested for known signatures of executable
+ * files.
+ *
+ * Copyright (c) 1994 Eli Zaretskii <address@hidden>
+ *
+ * This software may be used freely so long as this copyright notice is
+ * left intact. There is no warranty on this software.
+ *
+ */
+
+ #include <libc/stubs.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <dpmi.h>
+ #include <go32.h>
+ #include <io.h>
+ #include <libc/farptrgs.h>
+ #include <libc/dosio.h>
+
+ extern unsigned short _djstat_flags;
+ unsigned short _get_magic(const char *, int);
+ int _is_executable(const char *, int, const char *);
+
+ /*
+ * Read a MAGIC NUMBER from a given file. These are the first
+ * two bytes of the file, if we look at them as an unsigned short. */
+
+ #define _STAT_EXEC_EXT 2 /* get execute bits from file extension? */
+ #define _STAT_EXEC_MAGIC 4 /* get execute bits from magic signature? */
+
+ unsigned short
+ _get_magic(const char *s, int fh)
+ {
+ __dpmi_regs regs;
+ unsigned short retval;
+ unsigned short fpos_high = 0, fpos_low = 0;
+ int read_fail = 0;
+
+ /* If given a pathname, open the file. */
+ if (s)
+ {
+ int handle;
+ if((handle = _open(s,0)) == -1)
+ return 0;
+ regs.x.bx = handle;
+ }
+ /* Else file already open. Remember its current file position
+ and move to beginning of file. */
+ else
+ {
+ regs.x.ax = 0x4201; /* set pointer from current position */
+ regs.x.bx = fh;
+ regs.x.cx = regs.x.dx = 0; /* move 0 bytes (i.e., stay put) */
+ __dpmi_int(0x21, ®s);
+ if (regs.x.flags & 1)
+ {
+ errno = __doserr_to_errno(regs.x.ax);
+ return 0;
+ }
+ fpos_high = regs.x.dx; /* got current position */
+ fpos_low = regs.x.ax;
+
+ regs.x.ax = 0x4200; /* set pointer from the beginning of
file */
+ regs.x.cx = regs.x.dx = 0; /* move to beginning of file */
+ __dpmi_int(0x21, ®s);
+ if (regs.x.flags & 1)
+ {
+ errno = __doserr_to_errno(regs.x.ax);
+ return 0;
+ }
+ }
+ regs.x.ds = __tb_segment;
+ regs.x.dx = __tb_offset;
+
+ /* Read 2 bytes from the file. */
+ regs.x.ax = 0x3f00;
+ regs.x.cx = 2;
+ __dpmi_int(0x21, ®s);
+
+ /* We can either (1) succeed, (2) read less than 2 bytes,
+ or (3) fail to read at all. */
+ if (regs.x.ax != 2)
+ read_fail = (regs.x.flags & 1) ? regs.x.ax : -1;
+
+ /* If called with filename, close the file. */
+ if (s)
+ {
+ regs.x.ax = 0x3e00;
+ __dpmi_int(0x21, ®s);
+ if (regs.x.flags & 1)
+ errno = __doserr_to_errno(regs.x.ax);
+ }
+ /* Else leave file pointer where we found it. */
+ else
+ {
+ regs.x.ax = 0x4200; /* set pointer from the beginning of
file */
+ regs.x.bx = fh;
+ regs.x.cx = fpos_high;
+ regs.x.dx = fpos_low;
+ __dpmi_int(0x21, ®s);
+ if (regs.x.flags & 1)
+ {
+ errno = __doserr_to_errno(regs.x.ax);
+ return 0;
+ }
+ }
+
+ if (read_fail == 0)
+ retval = _farpeekw(_dos_ds, __tb);
+ else
+ {
+ /* The file couldn't be read: assume non-executable. If the file
+ *is* executable, but was passed as a file-handle, and the user
+ opened it in write-only mode, they lose... */
+ retval = 0;
+ if (read_fail != -1)
+ errno = __doserr_to_errno(read_fail);
+ }
+
+ return retval;
+ }
+
+ /* A list of extensions which designate executable files. These
+ are NOT tested for the magic number. */
+ static char executables[] = "|EXE|COM|BAT|BTM|DLL|VXD|";
+
+ /* A list of extensions which belong to files known to NEVER be
+ executables. These exist to minimize read()'ing files while
+ detecting executables by magic number. You are welcome to
+ add to this list, but remember: only extensions which could
+ NEVER be present in executables should go here. */
+ static char non_executables[] = "\
+ |A|A01|A02|A03|A04|A05|ADL|ARC|ARJ|ASC|ASM|AUX|AWK\
+ |BAS|BIB|BGI|BMP\
+ |C|CC|CFG|CGZ|CH3|CHR|CI|CLP|CMF|CPI|CPP|CXX\
+ |DAT|DBF|DIZ|DOC|DVI\
+ |E|EL|ELC\
+ |F77|FN3\
+ |GIF|GZ\
+ |H|HLP|HPP|HXX\
+ |ICO|IN|INC|INF|INI\
+ |JPG\
+ |L|LEX|LF|LIB|LOG|LST|LZH\
+ |M|MAK|MAP|MF|MID|MPG\
+ |O|OBJ\
+ |PAK|PAS|PBM|PCD|PCX|PDS|PIC|PIF|PN3|PRJ|PS\
+ |RAS|RGB|RLE\
+ |S|SND|SY3\
+ |TAR|TAZ|TEX|TGA|TGZ|TIF|TXH|TXI|TXT\
+ |VOC\
+ |WAV|WK1|WK3|WKB|WQ1|WQ3|WQ4|WQ5|WQ6|WQ!\
+ |XBM\
+ |Y\
+ |ZIP|ZOO|";
+
+ int
+ _is_executable(const char *filename, int fhandle, const char *extension)
+ {
+ if (!extension && filename)
+ {
+ const char *cp, *ep=0;
+ for (cp=filename; *cp; cp++)
+ {
+ if (*cp == '.')
+ ep = cp;
+ if (*cp == '/' || *cp == '\\' || *cp == ':')
+ ep = 0;
+ }
+ extension = ep;
+ }
+ if ((_djstat_flags & _STAT_EXEC_EXT) == 0
+ && extension
+ && *extension
+ && strlen(extension) <= ((extension[0]=='.') ? 4 : 3))
+ {
+ /* Search the list of extensions in executables[]. */
+ char tmp_buf[6], *tp = tmp_buf;
+
+ *tp++ = '|';
+ if (*extension == '.')
+ extension++;
+ while (*extension)
+ *tp++ = toupper (*extension++);
+ *tp++ = '|';
+ *tp = '\0';
+ if (strstr(non_executables, tmp_buf))
+ return 0;
+ else if (strstr(executables, tmp_buf))
+ return 1;
+ }
+
+ /* No extension, or extension doesn't define execute
+ bits unambiguously. We are in for some dirty work.
+ Read the first two bytes of the file and see if they
+ are any of the known magic numbers which designate
+ executable files.
+ Unix-like shells, which have executable shell scripts
+ without extensions and DON'T have "#!" as their FIRST
+ TWO CHARACTERS, lose here. Sorry, folks. */
+ if ( (_djstat_flags & _STAT_EXEC_MAGIC) == 0 )
+ {
+ switch (_get_magic(filename, fhandle))
+ {
+ case 0x5a4d: /* "MZ" */
+ case 0x010b:
+ case 0x014c:
+ case 0x2123: /* "#!" */
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /* arch-tag: b0965811-8c3e-4bc4-8d81-4447a3594785
+ (do not change this comment) */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] Changes to emacs/msdos/is_exec.c [lexbind],
Miles Bader <=