diff options
Diffstat (limited to 'Build/source/libs/libgnuw32')
22 files changed, 4580 insertions, 0 deletions
diff --git a/Build/source/libs/libgnuw32/Makefile.in b/Build/source/libs/libgnuw32/Makefile.in new file mode 100644 index 00000000000..38c02f34596 --- /dev/null +++ b/Build/source/libs/libgnuw32/Makefile.in @@ -0,0 +1,88 @@ +# Main Makefile for Gnu-win32 library +# Copyright (C) 1999-2000 Fabrice Popineau + +# This program 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 2, or (at your option) +# any later version. + +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +ac_include ../make/paths.mk +ac_include ../make/makevars.mk +ac_include ../make/common.mk +ac_include ../make/library.mk +ac_include ../make/programs.mk +ac_include ../make/texi.mk + +# ??? replace these with your own list of files +SOURCES=getopt.c \ + getopt1.c \ + popen.c \ + stat.c \ + system.c \ + string.c \ + filename.c \ + dirent.c \ + time.c \ + user.c \ + home.c \ + volume.c \ + lookcmd.c \ + ghostscr.c + +# DOCS= +MISC=configure mkinstalldirs install-sh aclocal.m4 +LIB_OBJS=$(SOURCES:.c=.o) + +# ??? replace with your targets +all: libgnuw32.a + +# ??? here I make the bindir, libdir and infodir directories; you +# might not need all of these. also, I assumed the names PROG and +# libMYPROG.a for the program and library. +install: all + $(top_srcdir)/mkinstalldirs $(bindir) + $(top_srcdir)/mkinstalldirs $(libdir) + $(top_srcdir)/mkinstalldirs $(infodir) + $(INSTALL) libgnuw32.a $(libdir)/libgnuw32.a + +uninstall: + /bin/rm -f $(libdir)/libgnuw32.a + +libgnuw32.a: $(LIB_OBJS) + /bin/rm -f libgnuw32.a + $(AR) $(AR_FLAGS) libgnuw32.a $(LIB_OBJS) + $(RANLIB) libgnuw32.a + +clean: + /bin/rm -f core *.o $(LIB_OBJS) libgnuw32.a + +distclean: clean + /bin/rm -f Makefile config.h config.status config.cache config.log \ + marklib.dvi + +mostlyclean: clean + +maintainer-clean: clean + +# automatic re-running of configure if the ocnfigure.in file has changed +${srcdir}/configure: configure.in + cd ${srcdir} && autoconf + +# autoheader might not change config.h.in, so touch a stamp file +Makefile: Makefile.in config.status + ./config.status +config.status: configure + ./config.status --recheck + +ac_include ../../make/rdepend.mk +ac_include depend.mk diff --git a/Build/source/libs/libgnuw32/configure.in b/Build/source/libs/libgnuw32/configure.in new file mode 100644 index 00000000000..db5deebbf4b --- /dev/null +++ b/Build/source/libs/libgnuw32/configure.in @@ -0,0 +1,26 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(dirent.c) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_RANLIB +AC_PROG_INSTALL + +dnl Checks for libraries. + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_DIRENT +AC_CHECK_HEADERS(fcntl.h malloc.h unistd.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_STRUCT_ST_RDEV + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_SETVBUF_REVERSED +AC_CHECK_FUNCS(putenv strdup strtol) + +AC_OUTPUT(Makefile) diff --git a/Build/source/libs/libgnuw32/depend.mak b/Build/source/libs/libgnuw32/depend.mak new file mode 100644 index 00000000000..5d05226a364 --- /dev/null +++ b/Build/source/libs/libgnuw32/depend.mak @@ -0,0 +1,39 @@ +$(objdir)/popen.obj: \ + win32lib.h + +$(objdir)/user.obj: \ + win32lib.h + +$(objdir)/home.obj: \ + win32lib.h + +$(objdir)/string.obj: \ + win32lib.h + +$(objdir)/system_popen_check.obj: \ + win32lib.h + +$(objdir)/stat.obj: \ + win32lib.h + +$(objdir)/filename.obj: \ + win32lib.h + +$(objdir)/error.obj: \ + win32lib.h + +$(objdir)/dirent.obj: \ + win32lib.h + +$(objdir)/volume.obj: \ + win32lib.h + +$(objdir)/lookcmd.obj: \ + win32lib.h + +$(objdir)/time.obj: \ + win32lib.h + +$(objdir)/system.obj: \ + win32lib.h + diff --git a/Build/source/libs/libgnuw32/dirent.c b/Build/source/libs/libgnuw32/dirent.c new file mode 100644 index 00000000000..f47dfb14d2d --- /dev/null +++ b/Build/source/libs/libgnuw32/dirent.c @@ -0,0 +1,129 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +#include <sys/dir.h> +#include <win32lib.h> + +/* Emulate the Unix directory procedures opendir, closedir, + and readdir. We can't use the procedures supplied in sysdep.c, + so we provide them here. */ + +struct direct dir_static; /* simulated directory contents */ +HANDLE dir_find_handle = INVALID_HANDLE_VALUE; +static int dir_is_fat; +char dir_pathname[MAXPATHLEN+1]; +WIN32_FIND_DATA dir_find_data; + +DIR * +opendir (const char *filename) +{ + DIR *dirp; + + /* Opening is done by FindFirstFile. However, a read is inherent to + this operation, so we defer the open until read time. */ + + if (!(dirp = (DIR *)xmalloc(sizeof(DIR)))) + return NULL; + ZeroMemory(dirp, sizeof(DIR)); + if (dir_find_handle != INVALID_HANDLE_VALUE) + return NULL; + + dirp->dd_fd = 0; + dirp->dd_loc = 0; + dirp->dd_size = 0; + + strncpy (dir_pathname, map_win32_filename (filename, NULL), MAXPATHLEN); + dir_pathname[MAXPATHLEN] = '\0'; + dir_is_fat = is_fat_volume (filename, NULL); + + return dirp; +} + +void +closedir (DIR *dirp) +{ + /* If we have a find-handle open, close it. */ + if (dir_find_handle != INVALID_HANDLE_VALUE) + { + FindClose (dir_find_handle); + dir_find_handle = INVALID_HANDLE_VALUE; + } + free (dirp); +} + +struct direct * +readdir (DIR *dirp) +{ + /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ + if (dir_find_handle == INVALID_HANDLE_VALUE) + { + char filename[MAXNAMLEN + 3]; + int ln; + + strcpy (filename, dir_pathname); + ln = strlen (filename) - 1; + if (!IS_DIR_SEP (filename[ln])) + strcat (filename, "\\"); + strcat (filename, "*"); + + dir_find_handle = FindFirstFile (filename, &dir_find_data); + + if (dir_find_handle == INVALID_HANDLE_VALUE) + return NULL; + } + else + { + if (!FindNextFile (dir_find_handle, &dir_find_data)) + return NULL; + } + + /* Emacs never uses this value, so don't bother making it match + value returned by stat(). */ + dir_static.d_ino = 1; + + dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + + dir_static.d_namlen - dir_static.d_namlen % 4; + + dir_static.d_namlen = strlen (dir_find_data.cFileName); + strcpy (dir_static.d_name, dir_find_data.cFileName); + if (dir_is_fat) + _strlwr (dir_static.d_name); + else +#if 0 + if (!NILP (Vmswindows_downcase_file_names)) +#endif + { + char *p; + for (p = dir_static.d_name; *p; p++) + if (*p >= 'a' && *p <= 'z') + break; + if (!*p) + _strlwr (dir_static.d_name); + } + + return &dir_static; +} diff --git a/Build/source/libs/libgnuw32/error.c b/Build/source/libs/libgnuw32/error.c new file mode 100644 index 00000000000..90315c89ccc --- /dev/null +++ b/Build/source/libs/libgnuw32/error.c @@ -0,0 +1,87 @@ +/* + +Error messages for fpTeX. + +Copyright (C) 1998-2000 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <win32lib.h> + +#ifdef MAKE_KPSE_DLL +#include <kpathsea/progname.h> + +extern KPSEDLL char *kpathsea_version_string; /* from kpathsea/version.c */ +#endif + +/* + Various messages to display error messages, either from Windows + or on the console. +*/ + +/* Last error message in a MessageBox. */ +void Win32Error(char *caller) +{ + LPVOID lpMsgBuf; + DWORD errCode; + if (errCode = GetLastError()) { + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + )) { + /* Display the string. */ + MessageBox( NULL, lpMsgBuf, caller, MB_OK|MB_ICONINFORMATION ); + /* Free the buffer. */ + LocalFree( lpMsgBuf ); + } + else { + char szBuf[24]; + wsprintf(szBuf, "%d", errCode); + MessageBox( NULL, szBuf, caller, MB_OK|MB_ICONINFORMATION ); + } + } +} + +void Win32Msg(char *msg) +{ +#ifdef MAKE_KPSE_DLL + char *program = "(unknown)"; + char *caller = NULL; + + if (kpse_program_name && *kpse_program_name) { + program = kpse_program_name; + } + + caller = concat3(program, "\r\n", kpathsea_version_string); +#else + char *caller = xmalloc(4096); + + if (caller && GetModuleFileName(NULL, caller, sizeof(caller)) == 0) { + strcpy(caller, "(unknown)"); + } +#endif + + MessageBox(NULL, msg, caller, MB_OK|MB_ICONINFORMATION); + + free(caller); +} + diff --git a/Build/source/libs/libgnuw32/filename.c b/Build/source/libs/libgnuw32/filename.c new file mode 100644 index 00000000000..5aede5152f3 --- /dev/null +++ b/Build/source/libs/libgnuw32/filename.c @@ -0,0 +1,392 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +#include <win32lib.h> + +/* Normalize filename by converting all path separators to + the specified separator. Also conditionally convert upper + case path name components to lower case. + Returns the index of the first meaningful char in the path + past any drive specifier of unc name specifier. + Remove any multiple path separators after a leading + drive specifier or double path separator. +*/ + +int +normalize_filename (char *fp, char path_sep) +{ + char *p; + int ret, i; + + if (fp == NULL || *fp == '\0') + return 0; + + /* Always lower-case drive letters a-z, even if the filesystem + preserves case in filenames. + This is so filenames can be compared by string comparison + functions that are case-sensitive. Even case-preserving filesystems + do not distinguish case in drive letters. */ + if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') { + *fp += 'a' - 'A'; + } + + /* Remove unneeded double slashes */ + ret = (IS_UNC_NAME(fp) ? 2 : + NAME_BEGINS_WITH_DEVICE(fp) ? + (IS_DIR_SEP(*(fp+2)) ? 3 : 2) : IS_DIR_SEP(*fp) ? 1 : 0); + for (i = ret, p = fp+i; + IS_DIR_SEP(*p); + i++, p++); + if (i > ret) { + int len = strlen(fp+i); + /* remove unneeded slashes, for the sake of win95 */ +#if 0 + fprintf(stderr, "moving %s to %s\n", fp+ret, fp+i); +#endif + memcpy(fp+ret, fp+i, len); + *(char *)(fp+ret+len) = '\0'; + } + + /* conditionnally rewrite to same path_sep, slash preferably */ + if (path_sep) { + for (p = fp; *p; p++) + if (IS_DIR_SEP(*p)) + *p = path_sep; + } + +#if 0 + fprintf(stderr, "normalize_filename returned (%d) %s\n", ret, fp); +#endif + + return ret; +} + + +/* Destructively turn backslashes into slashes. */ +void +dostounix_filename (char *p) +{ + normalize_filename (p, '/'); +} + +/* Destructively turn slashes into backslashes. */ +void +unixtodos_filename (char *p) +{ + normalize_filename (p, '\\'); +} + +/* Quote file name. */ +char * +quote_filename(char *name) +{ + int len = strlen(name); + char *quoted_name; + if (strchr(name, ' ') && *name != '"') { + quoted_name = xmalloc(len+3); + memcpy(quoted_name+1, name, len); + *quoted_name = '"'; + *(quoted_name+len+1) = '"'; + *(quoted_name+len+2) = '\0'; + } + else { + quoted_name = xstrdup(name); + } + return quoted_name; +} + +/* Unquote file name */ +char * +unquote_filename(char *name) +{ + int len = strlen(name); + if (*name == '"' && *(name + len - 1) == '"') { + memmove(name, name+1, len-2); + *(name + len - 2) = '\0'; + } + return name; +} + + +/* Remove all CR's that are followed by a LF. + (From msdos.c...probably should figure out a way to share it, + although this code isn't going to ever change.) */ +int +crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count) +{ + unsigned char *np = buf; + unsigned char *startp = buf; + unsigned char *endp = buf + n; + + if (n == 0) + return n; + while (buf < endp - 1) + { + if (*buf == 0x0a) + (*lf_count)++; + if (*buf == 0x0d) + { + if (*(++buf) != 0x0a) + *np++ = 0x0d; + } + else + *np++ = *buf++; + } + if (buf < endp) + { + if (*buf == 0x0a) + (*lf_count)++; + *np++ = *buf++; + } + return np - startp; +} + +/* Parse the root part of file name, if present. Return length and + optionally store pointer to char after root. */ +int +_parse_root (char * name, char ** pPath) +{ + char * start = name; + + if (name == NULL) + return 0; + + /* find the root name of the volume if given */ + if (isalpha (name[0]) && name[1] == ':') + { + /* skip past drive specifier */ + name += 2; + if (IS_DIR_SEP (name[0])) + name++; + } + else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1])) + { + int slashes = 2; + name += 2; + do + { + if (IS_DIR_SEP (*name) && --slashes == 0) + break; + name++; + } + while ( *name ); + if (IS_DIR_SEP (name[0])) + name++; + } + + if (pPath) + *pPath = name; + + return name - start; +} + +/* Get long base name for name; name is assumed to be absolute. */ +static int +get_long_basename (char * name, char * buf, int size) +{ + WIN32_FIND_DATA find_data; + HANDLE dir_handle; + int len = 0; +#ifdef PIGSFLY + char *p; + + /* If the last component of NAME has a wildcard character, + return it as the basename. */ + p = name + strlen (name); + while (*p != '\\' && *p != ':' && p > name) p--; + if (p > name) p++; + if (strchr (p, '*') || strchr (p, '?')) + { + if ((len = strlen (p)) < size) + memcpy (buf, p, len + 1); + else + len = 0; + return len; + } +#endif + + dir_handle = FindFirstFile (name, &find_data); + if (dir_handle != INVALID_HANDLE_VALUE) + { + if ((len = strlen (find_data.cFileName)) < size) + memcpy (buf, find_data.cFileName, len + 1); + else + len = 0; + FindClose (dir_handle); + } + return len; +} + +/* Get long name for file, if possible (assumed to be absolute). */ +BOOL +win32_get_long_filename (char * name, char * buf, int size) +{ + char * o = buf; + char * p; + char * q; + char full[ MAX_PATH ]; + int len; + + len = strlen (name); + if (len >= MAX_PATH) + return FALSE; + + /* Use local copy for destructive modification. */ + memcpy (full, name, len+1); + unixtodos_filename (full); + + /* Copy root part verbatim. */ + len = _parse_root (full, &p); + memcpy (o, full, len); + o += len; + size -= len; + + do + { + q = p; + p = strchr (q, '\\'); + if (p) *p = '\0'; + len = get_long_basename (full, o, size); + if (len > 0) + { + o += len; + size -= len; + if (p != NULL) + { + *p++ = '\\'; + if (size < 2) + return FALSE; + *o++ = '\\'; + size--; + *o = '\0'; + } + } + else + return FALSE; + } + while (p != NULL && *p); + + return TRUE; +} + +/* Map filename to a legal 8.3 name if necessary. */ +const char * +map_win32_filename (const char * name, const char ** pPath) +{ + static char shortname[MAX_PATH]; + char * str = shortname; + char c; + const char * path; + const char * save_name = name; + + if (is_fat_volume (name, &path)) /* truncate to 8.3 */ + { + register int left = 8; /* maximum number of chars in part */ + register int extn = 0; /* extension added? */ + register int dots = 2; /* maximum number of dots allowed */ + + while (name < path) + *str++ = *name++; /* skip past UNC header */ + + while ((c = *name++)) + { + switch ( c ) + { + case '\\': + case '/': + *str++ = '\\'; + extn = 0; /* reset extension flags */ + dots = 2; /* max 2 dots */ + left = 8; /* max length 8 for main part */ + break; + case ':': + *str++ = ':'; + extn = 0; /* reset extension flags */ + dots = 2; /* max 2 dots */ + left = 8; /* max length 8 for main part */ + break; + case '.': + if ( dots ) + { + /* Convert path components of the form .xxx to _xxx, + but leave . and .. as they are. This allows .emacs + to be read as _emacs, for example. */ + + if (! *name || + *name == '.' || + IS_DIR_SEP (*name)) + { + *str++ = '.'; + dots--; + } + else + { + *str++ = '_'; + left--; + dots = 0; + } + } + else if ( !extn ) + { + *str++ = '.'; + extn = 1; /* we've got an extension */ + left = 3; /* 3 chars in extension */ + } + else + { + /* any embedded dots after the first are converted to _ */ + *str++ = '_'; + } + break; + case '~': + case '#': /* don't lose these, they're important */ + if ( ! left ) + str[-1] = c; /* replace last character of part */ + /* FALLTHRU */ + default: + if ( left ) + { + *str++ = tolower (c); /* map to lower case (looks nicer) */ + left--; + dots = 0; /* started a path component */ + } + break; + } + } + *str = '\0'; + } + else + { + strcpy (shortname, name); + unixtodos_filename (shortname); + } + + if (pPath) + *pPath = shortname + (path - save_name); + + return shortname; +} diff --git a/Build/source/libs/libgnuw32/gnuw32.c b/Build/source/libs/libgnuw32/gnuw32.c new file mode 100644 index 00000000000..abbc1c43db3 --- /dev/null +++ b/Build/source/libs/libgnuw32/gnuw32.c @@ -0,0 +1,523 @@ +/* Libc replacement functions for win32. + +Copyright (C) 1998, 99 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + This does make sense only under WIN32. + Functions: + - popen() rewritten + - pclose() rewritten + - stat() wrapper for _stat(), removing trailing slashes + */ + +#ifdef 0 + +#include <fcntl.h> +#include <io.h> +#include <sys/stat.h> +#include <direct.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <gnuw32.h> + + + + +#if 0 +#endif + + +#if 0 + + +Thanks. DJGPP startup code has a full-blown wildcard globber in its +startup code as well, and it expands wildcards Unix style (i.e., it +supports [a-z] etc.). So I don't think we need any more functionality... + +Here's the relevant parts from DJGPP's system.c module. I omitted some +functions with obvious names like `emiterror', to avoid cluttering the +code with too many irrelevant details. `system1' (also omitted) is the +place where the command line, after being stripped from redirection and +pipe parts, is actually broken into separate argv[] parts and passed to +the child (via `spawnve' in the case of DJGPP); I assume that you already +have something like that. I did include the two functions which are used +to support quoting of command-line arguments, in case you are interested, +but note that some of their subtleties know how the startup code on the +child side will process quoted arguments (e.g., the case of 'foo bar' +with single quotes), so caveat emptor. + +The only part that is really relevant to processing pipes and redirection +is the loop which begins with the following lines: + + tmp = alloca(L_tmpnam); + prog = alloca (L_tmpnam); + + s = strcpy (alloca (strlen (cmdline) + 1), cmdline); + while (!done && result >= 0) + { + +Have fun! + +------------------------------------------------------------------ +/* Return a copy of a word between BEG and (excluding) END with all + quoting characters removed from it. */ + +static char * +__unquote (char *to, const char *beg, const char *end) +{ + const char *s = beg; + char *d = to; + int quote = 0; + + while (s < end) + { + switch (*s) + { + case '"': + case '\'': + if (!quote) + quote = *s; + else if (quote == *s) + quote = 0; + s++; + break; + case '\\': + if (s[1] == '"' || s[1] == '\'' + || (s[1] == ';' + && (__system_flags & __system_allow_multiple_cmds))) + s++; + /* Fall-through. */ + default: + *d++ = *s++; + break; + } + } + + *d = 0; + return to; +} + +/* A poor-man's lexical analyzer for simplified command processing. + + It only knows about these: + + redirection and pipe symbols + semi-colon `;' (that possibly ends a command) + argument quoting rules with quotes and `\' + whitespace delimiters of words (except in quoted args) + + Returns the type of next symbol and pointers to its first and (one + after) the last characters. + + Only `get_sym' and `unquote' should know about quoting rules. */ + +static cmd_sym_t +get_sym (char *s, char **beg, char **end) +{ + int in_a_word = 0; + + while (isspace (*s)) + s++; + + *beg = s; + + do { + *end = s + 1; + + if (in_a_word + && (!*s || strchr ("<>| \t\n", *s) + || ((sys_flags & __system_allow_multiple_cmds) && *s == ';'))) + { + --*end; + return WORD; + } + + switch (*s) + { + case '<': + return REDIR_INPUT; + case '>': + if (**end == '>') + { + ++*end; + return REDIR_APPEND; + } + return REDIR_OUTPUT; + case '|': + return PIPE; + case ';': + if (sys_flags & __system_allow_multiple_cmds) + return SEMICOLON; + else + in_a_word = 1; + break; + case '\0': + --*end; + return EOL; + case '\\': + if (s[1] == '"' || s[1] == '\'' + || (s[1] == ';' && (sys_flags & __system_allow_multiple_cmds))) + s++; + in_a_word = 1; + break; + case '\'': + case '"': + { + char quote = *s++; + + while (*s && *s != quote) + { + if (*s++ == '\\' && (*s == '"' || *s == '\'')) + s++; + } + *end = s; + if (!*s) + return UNMATCHED_QUOTE; + in_a_word = 1; + break; + } + default: + in_a_word = 1; + break; + } + + s++; + + } while (1); +} + +/* This function handles redirection and passes the rest to system1 + or to the shell. */ +int +system (const char *cmdline) +{ + /* Set the feature bits for this run: either from the + environment or from global variable. */ + const char *envflags = getenv ("DJSYSFLAGS"); + const char *comspec = getenv ("COMSPEC"); + const char *shell = 0; + int call_shell; + + sys_flags = __system_flags; + if (envflags && *envflags) + { + char *stop; + long flags = strtol (envflags, &stop, 0); + + if (*stop == '\0') + sys_flags = flags; + } + + if (sys_flags & __system_use_shell) + shell = getenv ("SHELL"); + if (!shell) + shell = comspec; + if (!shell) + shell = command_com; + + call_shell = + (sys_flags & __system_call_cmdproc) + || (!(sys_flags & __system_emulate_command) && _is_unixy_shell (shell)); + + /* Special case: NULL means return non-zero if the command + interpreter is available. This is ANSI C requirement. + + If we will call the shell to do everything, we need to see + whether it exists. But if most of the work will be done by us + anyway (like it usually is with stock DOS shell), return non-zero + without checking, since our emulation is always ``available''. */ + if (cmdline == 0) + { + if (!call_shell) + return 1; + else + { + char full_path[FILENAME_MAX]; + + return __dosexec_find_on_path (shell, (char **)0, full_path) ? 1 : 0; + } + } + + /* Strip initial spaces (so that if the command is empty, we + know it right here). */ + while (isspace(*cmdline)) + cmdline++; + + /* Call the shell if: + + the command line is empty + or + they want to always do it via command processor + or + $SHELL or $COMSPEC point to a unixy shell */ + if (!*cmdline || call_shell) + return _shell_command ("", cmdline); + else + { + char *f_in = 0, *f_out = 0; + int rm_in = 0, rm_out = 0; + /* Assigned to silence -Wall */ + int h_in = 0, h_inbak = 0, h_out = 0, h_outbak = 0; + char *s, *t, *u, *v, *tmp, *cmdstart; + int result = 0, done = 0; + int append_out = 0; + cmd_sym_t token; + char *prog; + + tmp = alloca(L_tmpnam); + prog = alloca (L_tmpnam); + + s = strcpy (alloca (strlen (cmdline) + 1), cmdline); + while (!done && result >= 0) + { + char **fp = &f_in; + /* Assignments pacify -Wall */ + int hin_err = 0, hbak_err = 0, hout_err = 0; + int needcmd = 1; + int again; + + if (rm_in) + remove (f_in); + f_in = f_out; /* Piping. */ + rm_in = rm_out; + f_out = 0; + rm_out = 0; + append_out = 0; + + cmdstart = s; + + do { + again = 0; + token = get_sym (s, &t, &u); /* get next symbol */ + + /* Weed out extra whitespace, leaving only a single + whitespace character between any two tokens. + This way, if we eventually pass the command to a + shell, it won't fail due to length > 126 chars + unless it really *is* that long. */ + + if (s == cmdstart) + v = s; /* don't need blank at beginning of cmdline */ + else + v = s + 1; + if (t > v) + { + strcpy (v, t); + u -= t - v; + t = v; + } + + switch (token) + { + case WORD: + /* First word we see is the program to run. */ + if (needcmd) + { + __unquote (prog, t, u); /* unquote and copy to prog */ + /* We can't grok commands in parentheses, so assume they + use a shell that knows about these, like 4DOS or `sh'. + + FIXME: if the parenthesized group is NOT the first command + in a pipe, the commands that preceed it will be run twice. */ + if (prog[0] == '(') + return _shell_command ("", cmdline); + strcpy (s, u); /* remove program name from cmdline */ + needcmd = 0; + } + else + s = u; + again = 1; + break; + case REDIR_INPUT: + case REDIR_OUTPUT: + case REDIR_APPEND: + if (!(sys_flags & __system_redirect)) + return _shell_command ("", cmdline); + if (token == REDIR_INPUT) + { + if (f_in) + { + result = emiterror ("Ambiguous input redirect.", 0); + errno = EINVAL; + goto leave; + } + fp = &f_in; + } + else if (token == REDIR_OUTPUT || token == REDIR_APPEND) + { + if (f_out) + { + result = emiterror ("Ambiguous output redirect.", 0); + errno = EINVAL; + goto leave; + } + fp = &f_out; + if (token == REDIR_APPEND) + append_out = 1; + } + if (get_sym (u, &u, &v) != WORD) + { + result = emiterror ("Target of redirect is not a filename.", 0); + errno = EINVAL; + goto leave; + } + *fp = memcpy ((char *)alloca (v - u + 1), u, v - u); + (*fp)[v - u] = 0; + strcpy (t, v); + again = 1; + break; + case PIPE: + if (!(sys_flags & __system_redirect)) + return _shell_command ("", cmdline); + if (f_out) + { + result = emiterror ("Ambiguous output redirect.", 0); + errno = EINVAL; + goto leave; + } + + /* tmpnam guarantees unique names */ + tmpnam(tmp); + f_out = strcpy (alloca (L_tmpnam), tmp); + rm_out = 1; + /* Fall through. */ + case SEMICOLON: + case EOL: + if (needcmd) + { + result = emiterror ("No command name seen.", 0); + errno = EINVAL; + goto leave; + } + + /* Remove extra whitespace at end of command. */ + while (s > cmdstart && isspace (s[-1])) s--; + while (t > s && isspace (t[-1])) t--; + *t = 0; + +#ifdef TEST + fprintf (stderr, "Input from: %s\nOutput%s to: %s\n", + f_in ? f_in : "<stdin>", + append_out ? " appended" : "", + f_out ? f_out : "<stdout>"); + fflush (stderr); +#endif + if (f_in) + { + int e = errno; + + errno = 0; + h_in = open (f_in, O_RDONLY | O_BINARY); + hin_err = errno; + errno = 0; + h_inbak = dup (0); + hbak_err = errno; + dup2 (h_in, 0); + errno = e; + } + if (f_out) + { + int e = errno; + + errno = 0; + h_out = open (f_out, + O_WRONLY | O_BINARY | O_CREAT + | (append_out ? O_APPEND: O_TRUNC), + S_IREAD | S_IWRITE); + hout_err = errno; + errno = 0; + h_outbak = dup (1); + hbak_err = errno; + fflush(stdout); /* so any buffered chars will be written out */ + dup2 (h_out, 1); + errno = e; + } + if (f_in && h_in < 0) + result = emiterror ("Cannot redirect input", hin_err); + else if ((f_in && h_inbak < 0) || (f_out && h_outbak < 0)) + result = emiterror ("Out of file handles in redirect", hbak_err); + else if (f_out && h_out < 0) + result = emiterror ("Cannot redirect output", hout_err); + + if (!result) + { +#ifdef TEST + fprintf (stderr, "system1 (\"%s\", \"%s\")\n", prog, cmdstart); + fflush (stderr); +#endif + /* Tell `__spawnve' it was invoked by `system', so it would + know how to deal with command-line arguments' quoting. */ + __dosexec_in_system = 1; + result = system1 (prog, cmdstart); + __dosexec_in_system = 0; + } + if (f_in) + { + dup2 (h_inbak, 0); + close (h_in); + close (h_inbak); + } + if (f_out) + { + dup2 (h_outbak, 1); + close (h_out); + close (h_outbak); + } + + if (token == EOL) + done = 1; + else + { + if (token == SEMICOLON) + f_in = f_out = 0; + s = u; + } + break; + case UNMATCHED_QUOTE: + result = emiterror ("Unmatched quote character.", 0); + errno = EINVAL; + goto leave; + default: + result = emiterror ("I cannot grok this.", 0); + errno = EINVAL; + goto leave; + } + } while (again); + } + leave: + if (rm_in) + remove (f_in); + if (rm_out) + remove (f_out); + + return result; + } +} +#endif + +#if NEW_KPSE + + + + + + + +#endif +#endif + diff --git a/Build/source/libs/libgnuw32/home.c b/Build/source/libs/libgnuw32/home.c new file mode 100644 index 00000000000..f6f7ac52324 --- /dev/null +++ b/Build/source/libs/libgnuw32/home.c @@ -0,0 +1,115 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +#include <win32lib.h> +#include <shlobj.h> + +char initial_directory[MAXPATHLEN]; + +static char *cached_home_directory; + +void +uncache_home_directory (void) +{ + cached_home_directory = NULL; /* in some cases, this may cause the leaking + of a few bytes */ +} + +int output_home_warning = 0; + +void +set_home_warning() { + output_home_warning = 1; +} + +/* Returns the home directory, in external format */ +char * +get_home_directory (void) +{ + + if (cached_home_directory != NULL) + goto done; + + if ((cached_home_directory = getenv("HOME")) != NULL) { + char q[MAXPATHLEN]; + /* In case it is %HOMEDRIVE%%HOMEPATH% */ + if (ExpandEnvironmentStrings(cached_home_directory, q, sizeof(q)) == 0) { + /* Error */ + cached_home_directory = NULL; + } + else { + cached_home_directory = xstrdup(q); + goto done; + } + } + + { + char *homedrive, *homepath; + if ((homedrive = getenv("HOMEDRIVE")) != NULL && + (homepath = getenv("HOMEPATH")) != NULL) { + cached_home_directory = concat(homedrive, homepath); + goto done; + } + } + + /* This method is the prefered one because even if it requires a more recent shell32.dll, + it does not need to call SHMalloc()->Free() */ + { + /* This will probably give the wrong value */ + char q [MAXPATHLEN]; + HINSTANCE h; + HRESULT (WINAPI * p1)(HWND, LPSTR, int, BOOL); + HWND (WINAPI * p2)(void); + HWND hwnd = NULL; + + if (h = LoadLibrary("user32.dll")) { + if (p2 = GetProcAddress(h, "GetDesktopWindow")) + hwnd = (*p2)(); + FreeLibrary(h); + } + + if (hwnd && (h = LoadLibrary("shell32.dll")) != NULL) { + if (p1 = GetProcAddress(h, "SHGetSpecialFolderPathA")) + if ((*p1)(hwnd, q, CSIDL_PERSONAL, TRUE)) { + cached_home_directory = xstrdup(q); + } + FreeLibrary(h); + } + if (cached_home_directory) goto done; + } + + if (output_home_warning) { + fprintf(stderr, "fpTeX has been unable to determine a good value for the user's $HOME\n" + " directory, and will be using the value:\n" + " %s\n" + " This is probably incorrect.\n", + cached_home_directory + ); + } + done: + return cached_home_directory; +} diff --git a/Build/source/libs/libgnuw32/libgnuw32.rc b/Build/source/libs/libgnuw32/libgnuw32.rc new file mode 100644 index 00000000000..1146d9d5c15 --- /dev/null +++ b/Build/source/libs/libgnuw32/libgnuw32.rc @@ -0,0 +1,36 @@ +/* libgnuw32.rc: libgnuw32 resources -*- C++ -*- + + Copyright (C) 1996-2003 Fabrice Popineau <fabrice.popineau@supelec.fr> + + This file 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 2, or (at your + option) any later version. + + This file 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 this file; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#include <texlive-version.h> + +#define VER_FILEVERSION TEXLIVE_MAJOR_VERSION,TEXLIVE_MINOR_VERSION,TEXLIVE_BETA_NUMBER,TEXLIVE_ALPHA_NUMBER +#define VER_FILEVERSION_STR TEXLIVE_PRODUCTVERSION_STR " libgnuw32 0.1" + +#define VER_INTERNALNAME_STR "libgnuw32" +#define VER_ORIGINALFILENAME_STR "libgnuw32.dll" + +#define VER_FILEDESCRIPTION_STR "Gnu Win32 compatibility DLL" + +#define VER_LEGALCOPYRIGHT_STR "Copyright (c) 1999-2003 Fabrice Popineau, Supelec" + +#define VER_FILETYPE VFT_DLL + +#include <texlive.version> + +/* libgnuw32.rc ends here */ diff --git a/Build/source/libs/libgnuw32/lookcmd.c b/Build/source/libs/libgnuw32/lookcmd.c new file mode 100644 index 00000000000..bd4f2d8a4b1 --- /dev/null +++ b/Build/source/libs/libgnuw32/lookcmd.c @@ -0,0 +1,778 @@ +/* libc replacement functions for win32. + +Copyright (C) 1998, 99 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + This does make sense only under WIN32. + Functions: + - look_for_cmd() : locates an executable file + - parse_cmd_line() : splits a command with pipes and redirections + - build_cmd_line() : builds a command with pipes and redirections (useful ?) + */ + +/* + This part looks for the real location of the program invoked + by cmd. If it can find the program, that's good. Else + command processor is invoked. +*/ + +#include <win32lib.h> +#include <errno.h> + +#undef _DEBUG + +#ifdef _DEBUG +#define TRACE(x) x +#else +#define TRACE(x) +#endif + +#define DIR_SEP '/' +#define DIR_SEP_STRING "/" +#define IS_DEVICE_SEP(ch) ((ch) == ':') +#define NAME_BEGINS_WITH_DEVICE(name) (*(name) && IS_DEVICE_SEP((name)[1])) +/* On DOS, it's good to allow both \ and / between directories. */ +#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\') +/* On win32, UNC names are authorized */ +#define IS_UNC_NAME(name) (strlen(name)>=3 && IS_DIR_SEP(*name) \ + && IS_DIR_SEP(*(name+1)) && isalnum(*(name+2))) + +#if (defined(_DEBUG) || defined(TEST)) +void display_cmd(char ***cmd, char *input, char *output, char *errput); +#endif + +void +free_cmd_pipe(char ***cmd_pipe, int n) +{ + int i,j; + if (cmd_pipe) { + for (i = 0; i < n; i++) { + for (j = 0; cmd_pipe[i][j]; j++) { + TRACE(fprintf(stderr, "freeing %x\n", cmd_pipe[i][j])); + free(cmd_pipe[i][j]); + } + TRACE(fprintf(stderr, "freeing %x\n", cmd_pipe[i])); + free(cmd_pipe[i]); + } + TRACE(fprintf(stderr, "freeing %x\n", cmd_pipe)); + free(cmd_pipe); + } +} + +/* + Return a quoted string if space is found + New string is allocated +*/ +static char * +quote_elt(char *elt) +{ + int len = 2*strlen(elt)*sizeof(char) + 2; + char *to = xmalloc(len); + char *p = to; + BOOL need_quote = FALSE; + + if (strchr(elt, ' ')) { + *to++ = '"'; + need_quote = TRUE; + } + + while (*elt) { + switch (*elt) { + case '"': + case '\'': + /* case '\\': */ + *to++ = '\\'; + default: + *to++ = *elt++; + } + } + if (need_quote) { + *to++ = '"'; + } + + *to = *elt; + to = xstrdup(p); + free(p); + + return to; +} + +/* + Process an array of strings, quote them + an return their catenation +*/ +char * +quote_args(char **argv) +{ + int i; + char *line = NULL, *new_line; + char *new_argv_i; + + if (!argv) + return line; + + line = quote_elt(argv[0]); + for (i = 1; argv[i]; i++) { + new_argv_i = quote_elt(argv[i]); + new_line = concat3(line, " ", new_argv_i); + TRACE(fprintf(stderr, "quote_args: new_line = %s\n", new_line)); + free(line); + free(new_argv_i); + line = new_line; + } + + return line; +} + +static BOOL +is_absolute(const char *filename) +{ + BOOL absolute = IS_DIR_SEP (*filename) + /* Novell allows non-alphanumeric drive letters. */ + || (*filename && IS_DEVICE_SEP (filename[1])) + /* UNC names */ + || IS_UNC_NAME(filename) + ; + BOOL explicit_relative = (*filename == '.' && (IS_DIR_SEP (filename[1]) + || (filename[1] == '.' && IS_DIR_SEP (filename[2])))); + /* FIXME: On UNIX an IS_DIR_SEP of any but the last character in the name + implies relative. */ + return absolute || explicit_relative; +} + +BOOL +look_for_cmd(const char *cmd, char **app) +{ + char *env_path = NULL; + char *p, *q; + char pname[MAXPATHLEN]; + char *suffixes[] = {".com", ".exe", ".bat", ".cmd", NULL }; + char **s; + char *app_name = NULL, *bare_name = NULL; + int i; + BOOL bIsWindowsNT = (GetVersion() < 0x80000000); + BOOL found, has_suffix = FALSE; + + *app = app_name = bare_name = NULL; + + /* We should look for the application name along the PATH, + and decide to prepend "%COMSPEC% /c " or not to the command line. + Do nothing for the moment. */ + + /* Another way to do that would be to try CreateProcess first without + invoking cmd, and look at the error code. If it fails because of + command not found, try to prepend "cmd /c" to the cmd line. + */ + + /* Look for the application name */ + for (p = (char *)cmd; *p && isspace(*p); p++); /* Trim spaces on the left */ + if (*p == '"') { /* If quoted string */ + q = ++p; + while(*p && *p != '"') p++; /* stop at next quote */ + if (*p == '\0') { + fprintf(stderr, "Look_for_cmd: malformed command (\" not terminated)\n"); + return FALSE; + } + } + else { + for (q = p; *p && !isspace(*p); p++); /* stop at next space */ + } + + /* q points to the beginning of appname, p to the last + 1 char */ + if ((app_name = xmalloc(p - q + 1)) == NULL) { + fprintf(stderr, "Look_for_cmd: malloc(app_name) failed.\n"); + return FALSE; + } + /* the app name has been found */ + for (i = 0; i < p - q; i++) + app_name[i] = (q[i] == '/' ? '\\' : q[i]); + // strncpy(app_name, q, p - q ); + app_name[p - q] = '\0'; + + /* First of all : if it is an absolute path ... */ + if (is_absolute(app_name)) { + if (_access(app_name, 0) == 0) { /* and it exists */ + *app = app_name; + found = TRUE; + } + else { /* not found */ + found = FALSE; + } + goto exit_1; + } + + /* pname[] will serve as full path name */ + pname[0] = '\0'; + /* app_name without potential extension */ + bare_name = xstrdup(app_name); + has_suffix = ((p = strrchr(bare_name, '.')) != NULL); + + TRACE(fprintf(stderr, "look for command: app_name = %s\n", app_name)); + + /* Add the current directory */ + { + char *tmp = getenv("PATH"); + env_path = xmalloc(strlen(tmp) + 3); + strcpy(env_path, ".;"); + strcat(env_path, tmp); + } + + /* Looping over directories in env_path */ + p = strtok(env_path, ";"); + found = FALSE; + while (p != NULL && ! found) { + /* If the file has an extension ... */ + if (has_suffix) { + strcpy(pname, p); + strcat(pname, "\\"); + strcat(pname, app_name); + TRACE(fprintf(stderr, "look for command: trying %s\n", pname)); + if (_access(pname, 0) == 0) { + free(app_name); + app_name = xstrdup(pname); + found = TRUE; + break; + } + } + else { + /* For each suffix in the list */ + for (s = suffixes; *s != NULL; *s++) { + strcpy(pname, p); + strcat(pname, "\\"); + strcat(pname, bare_name); + strcat(pname, *s); + TRACE(fprintf(stderr, "look for command: trying %s\n", pname)); + if (_access(pname, 0) == 0) { + free(app_name); + app_name = xstrdup(pname); + found = TRUE; + break; + } + } + } + p = strtok(NULL, ";"); + } + + exit_1: + + if (found == TRUE) { + TRACE(fprintf(stderr, "look for command: app_name = %s\n", app_name)); + if (! bIsWindowsNT) { + // Fix against short pathnames vs long pathnames + char lpShortPathName[_MAX_PATH]; + if (GetShortPathName((LPCTSTR)app_name, lpShortPathName, sizeof(lpShortPathName)) != 0) { + free(app_name); + app_name = xstrdup(lpShortPathName); + } + } + for (p = app_name; p && *p; p++) { + *p = (*p == '/' ? '\\' : *p); + } + TRACE(fprintf(stderr, "\n!!! Absolute path = %s\n", app_name)); + *app = app_name; + } + else { + /* the app_name was not found */ + TRACE(fprintf(stderr, "look for command: %s not found\n", app_name)); + if (app_name) free(app_name); + *app = app_name = NULL; + } + + if (env_path) free(env_path); + if (bare_name) free(bare_name); + + return found; +} + +/* + Command parser. Borrowed from DJGPP. + */ + +static BOOL __system_allow_multiple_cmds = FALSE; + +typedef enum { + EMPTY, + WORDARG, + REDIR_INPUT, + REDIR_APPEND, + REDIR_OUTPUT, + PIPE, + SEMICOLON, + UNMATCHED_QUOTE, + EOL +} cmd_sym_t; + +/* Return a copy of a word between BEG and (excluding) END with all + quoting characters removed from it. */ + +static char * +__unquote (char *to, const char *beg, const char *end) +{ + const char *s = beg; + char *d = to; + int quote = 0; + + while (s < end) + { + switch (*s) + { + case '"': + case '\'': + if (!quote) + quote = *s; + else if (quote == *s) + quote = 0; + s++; + break; + case '\\': + if (s[1] == '"' || s[1] == '\'' + || (s[1] == '&' + && (__system_allow_multiple_cmds))) + s++; + /* Fall-through. */ + default: + *d++ = *s++; + break; + } + } + + *d = 0; + TRACE(fprintf(stderr, "unquote returns `%s' (%x)\n", to, to)); + return to; +} + +/* A poor-man's lexical analyzer for simplified command processing. + + It only knows about these: + + redirection and pipe symbols + semi-colon `;' (that possibly ends a command) + argument quoting rules with quotes and `\' + whitespace delimiters of words (except in quoted args) + + Returns the type of next symbol and pointers to its first and (one + after) the last characters. + + Only `get_sym' and `unquote' should know about quoting rules. */ + +static cmd_sym_t +get_sym (char *s, char **beg, char **end) +{ + int in_a_word = 0; + + while (isspace (*s)) + s++; + + *beg = s; + + do { + *end = s + 1; + + if (in_a_word + && (!*s || strchr ("<>| \t\n", *s) + || ((__system_allow_multiple_cmds) && *s == '&'))) + { + --*end; + return WORDARG; + } + + switch (*s) + { + case '<': + return REDIR_INPUT; + case '>': + if (**end == '>') + { + ++*end; + return REDIR_APPEND; + } + return REDIR_OUTPUT; + case '|': + return PIPE; + case '&': + if (__system_allow_multiple_cmds) + return SEMICOLON; + else + in_a_word = 1; + break; + case '\0': + --*end; + return EOL; + case '\\': + if (s[1] == '"' || s[1] == '\'' + || (s[1] == '&' && (__system_allow_multiple_cmds))) + s++; + in_a_word = 1; + break; + case '\'': + case '"': + { + char quote = *s++; + + while (*s && *s != quote) + { + if (*s++ == '\\' && (*s == '"' || *s == '\'')) + s++; + } + *end = s; + if (!*s) + return UNMATCHED_QUOTE; + in_a_word = 1; + break; + } + default: + in_a_word = 1; + break; + } + + s++; + + } while (1); +} + +/* + What we allow : + [cmd] [arg1] ... [argn] < [redinput] | [cmd2] | ... | [cmdn] > [redoutput] +*/ +void *parse_cmdline(char *line, char **input, char **output, int *nb_cmds) +{ + BOOL again, needcmd = TRUE, bSuccess = TRUE, append_out = FALSE; + char *beg = line, *end, *new_end; + cmd_sym_t token = EMPTY, prev_token = EMPTY; + int ncmd = 0, narg = 0; + char **fp; + char ***cmd; + char *dummy_input; /* So that we could pass NULL */ + char *dummy_output; /* instead of a real ??put */ + +#if 0 + /* if _DEBUG is not defined, these macros will result in nothing. */ + SETUP_CRTDBG; + /* Set the debug-heap flag so that freed blocks are kept on the + linked list, to catch any inadvertent use of freed memory */ + SET_CRT_DEBUG_FIELD( _CRTDBG_CHECK_ALWAYS_DF ); + SET_CRT_DEBUG_FIELD( _CRTDBG_ALLOC_MEM_DF ); +#endif + if (input == NULL) input = &dummy_input; + if (output == NULL) output = &dummy_output; + + *input = NULL; + *output = NULL; + cmd = xmalloc(MAX_PIPES*sizeof(char **)); + TRACE(fprintf(stderr, "cmd = %x, size = %d\n", cmd, MAX_PIPES*sizeof(char **))); + cmd[ncmd] = NULL; + + TRACE(fprintf(stderr, "line = %s\n", line)); + + do { + again = FALSE; + prev_token = token; + token = get_sym (beg, &beg, &end); /* get next symbol */ + + TRACE(fprintf(stderr, "token = %s\n", beg)); + + switch (token) { + case WORDARG: + TRACE(fprintf(stderr, "WORDARG: ")); + if (prev_token == REDIR_INPUT + || prev_token == REDIR_OUTPUT) { + fprintf(stderr, "Ambigous input/output redirect."); + bSuccess = FALSE; + goto leave; + } + /* Incrementing number of arguments */ + narg++; + /* First word we see is the program to run. */ + if (needcmd) { + cmd[ncmd] = xmalloc(narg * sizeof(char *)); + TRACE(fprintf(stderr, "cmd[%d] = %x, size = %d\n", ncmd, cmd[ncmd], narg*sizeof(char *))); + if (cmd[ncmd] == NULL) { + fprintf(stderr, "parse_cmdline: xmalloc(%d) failed.\n", narg * sizeof(char *)); + } + needcmd = FALSE; + } + else { + TRACE(fprintf(stderr, "cmd[%d] = %x -> ", ncmd, cmd[ncmd])); + cmd[ncmd] = xrealloc(cmd[ncmd], narg * sizeof(char *)); + TRACE(fprintf(stderr, "%x, size = %d\n", cmd[ncmd], narg*sizeof(char *))); + if (cmd[ncmd] == NULL) { + fprintf(stderr, "parse_cmdline: xrealloc(%d) failed.\n", narg * sizeof(char *)); + } + } + cmd[ncmd][narg - 1] = xmalloc(end - beg + 10); + TRACE(fprintf(stderr, "cmd[%d][%d] = %x, size = %d\n", ncmd, narg-1, cmd[ncmd][narg-1], end-beg+1)); + if (cmd[ncmd] == NULL) { + fprintf(stderr, "parse_cmdline: xmalloc(%d) failed.\n", end - beg + 1); + } + __unquote (cmd[ncmd][narg - 1], beg, end); /* unquote and copy to prog */ + TRACE(fprintf(stderr, "parse_cmd_line: cmd[%d][%d] = %s\n", ncmd, narg - 1, cmd[ncmd][narg - 1])); + if (cmd[ncmd][narg - 1][0] == '(') { + fprintf(stderr, "parse_cmdline(%s): Parenthesized groups not allowed.\n", line); + bSuccess = FALSE; + goto leave; + } + beg = end; /* go forward */ + again = TRUE; + break; + + case REDIR_INPUT: + case REDIR_OUTPUT: + case REDIR_APPEND: + TRACE(fprintf(stderr, "REDIR: ")); + if (token == REDIR_INPUT) { + if (*input) { + fprintf(stderr, "Ambiguous input redirect."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + } + fp = input; + } + else if (token == REDIR_OUTPUT || token == REDIR_APPEND) { + if (*output) { + fprintf(stderr, "Ambiguous output redirect."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + } + fp = output; + if (token == REDIR_APPEND) + append_out = TRUE; + } + if (get_sym (end, &end, &new_end) != WORDARG) { + fprintf(stderr, "Target of redirect is not a filename."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + } + *fp = (char *)xmalloc (new_end - end + 1); + if (*fp == NULL) { + fprintf(stderr, "parse_cmdline: xmalloc(%d) failed.\n", new_end - end + 1); + } + __unquote (*fp, end, new_end); + /* (*fp)[new_end - end] = '\0'; */ + beg = new_end; + again = TRUE; + break; + case PIPE: + TRACE(fprintf(stderr, "PIPE: ")); + if (*output) { + fprintf(stderr, "Ambiguous output redirect."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + } + narg++; + TRACE(fprintf(stderr, "cmd[%d] = %x -> ", ncmd, cmd[ncmd])); + cmd[ncmd] = xrealloc(cmd[ncmd], narg * sizeof(char *)); + TRACE(fprintf(stderr, "%x, size = %d\n", cmd[ncmd], narg*sizeof(char *))); + cmd[ncmd][narg - 1] = NULL; + ncmd++; + needcmd = TRUE; + cmd[ncmd] = NULL; + beg = end; + again = TRUE; + break; + case SEMICOLON: + case EOL: + TRACE(fprintf(stderr, "SEMICOLON|EOL: ")); + if (needcmd) { + fprintf(stderr, "No command name seen."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + } + narg++; + TRACE(fprintf(stderr, "cmd[%d] = %x -> ", ncmd, cmd[ncmd])); + cmd[ncmd] = xrealloc(cmd[ncmd], narg * sizeof(char *)); + TRACE(fprintf(stderr, "%x, size = %d\n", cmd[ncmd], narg*sizeof(char *))); + cmd[ncmd][narg - 1] = NULL; + ncmd++; + cmd[ncmd] = NULL; + again = FALSE; + break; + + case UNMATCHED_QUOTE: + fprintf(stderr, "Unmatched quote character."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + default: + fprintf(stderr, "I cannot grok this."); + errno = EINVAL; + bSuccess = FALSE; + goto leave; + + } + + } while (again); + + leave: + if (!bSuccess) { + int i; + char **p; + /* Need to free everything that was allocated */ + for (i = 0; i < ncmd; i++) { + for (p = cmd[i]; *p; p++) + free(*p); + free(cmd[i]); + } + if (cmd[ncmd]) { + for (i = 0; i < narg; i++) + free(cmd[ncmd][i]); + free(cmd[ncmd]); + } + free(cmd); + *cmd = NULL; + ncmd = 0; + } + + if (nb_cmds != NULL) *nb_cmds = ncmd; + +#if (defined(_DEBUG) || defined(TEST)) + display_cmd(cmd, *input, *output, NULL); +#endif + return cmd; +} + +char * +build_cmdline(char ***cmd, char *input, char *output) +{ + int ncmd; + char *line = NULL, *new_line; + + if (!cmd) + return line; + + line = quote_args(cmd[0]); + if (input) { + new_line = concat3(line, " < ", quote_elt(input)); + free(line); + line = new_line; + } + for(ncmd = 1; cmd[ncmd]; ncmd++) { + new_line = concat3(line, " | ", quote_args(cmd[ncmd])); + free(line); + line = new_line; + } + + if (output) { + new_line = concat3(line, " > ", quote_elt(output)); + free(line); + line = new_line; + } + + return line; +} + +#if (defined(_DEBUG) || defined(TEST)) +void +display_cmd(char ***cmd, char *input, char *output, char *errput) +{ + int ncmd = 0, narg; + + if (cmd) { + for (ncmd = 0; cmd[ncmd]; ncmd++) { + printf("cmd[%d] = %s ", ncmd, cmd[ncmd][0]); + for(narg = 1; cmd[ncmd][narg] != NULL; narg++) + printf("%s ", cmd[ncmd][narg]); + printf("\n"); + } + } + printf("input = %s\n", (input ? input : "<stdin>")); + printf("output = %s\n", (output ? output : "<stdout>")); + printf("errput = %s\n", (errput ? errput : "<stderr>")); +} +#endif + +#ifdef TEST +main(int argc, char *argv[]) +{ + char *input; + char *output; + char ***cmd; + char *line; + + /* SETUP_CRTDBG; */ + + printf("%s\n", line = "foo a b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo < a > b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "filter 1 | filter 2"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo > a < b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo | a b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo a | b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo | a > b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo < a | b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo < a | b"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "foo < a | b b1 b2 | c > d"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + + printf("%s\n", line = "foo > a | b < c"); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + printf("%s\n", line = "\"C:\\Program Files\\WinEdt\\WinEdt.exe\" -F \"[Open('%f');SelLine(%l,8)]\""); + if (cmd = parse_cmdline(line, &input, &output, 0)) { + display_cmd(cmd, input, output, NULL); + } + + { + char buf[256]; + char *app, *cmd; + while (gets(buf)) { + look_for_cmd(buf, &app, &cmd); + if (app) { + printf("app: %s, cmd: %s\n", app, cmd); + } + else { + printf("app not found, cmd: %s\n", cmd); + } + if (app) free(app); + if (cmd) free(cmd); + } + } +} +#endif diff --git a/Build/source/libs/libgnuw32/lookcmd.exe b/Build/source/libs/libgnuw32/lookcmd.exe Binary files differnew file mode 100755 index 00000000000..add27d9bf17 --- /dev/null +++ b/Build/source/libs/libgnuw32/lookcmd.exe diff --git a/Build/source/libs/libgnuw32/oldnames.h b/Build/source/libs/libgnuw32/oldnames.h new file mode 100644 index 00000000000..6ffcd62613d --- /dev/null +++ b/Build/source/libs/libgnuw32/oldnames.h @@ -0,0 +1,469 @@ + +#ifndef _OLDNAMES_H_ +#define _OLDNAMES_H_ + +/* These have to be defined because our compilers treat __STDC__ as being + defined (most of them anyway). */ +/* Non-ANSI names for compatibility. Those symbols are defined + in oldnames.lib . + However, even if it is less safe, it might be better to just + #define the oldnames to the new names. Use the next macro + to change the behaviour. +*/ + +#if __STDC__ + +/* from fcntl.h */ + +#ifndef O_RDONLY +#define O_RDONLY _O_RDONLY +#endif +#ifndef O_WRONLY +#define O_WRONLY _O_WRONLY +#endif +#ifndef O_RDWR +#define O_RDWR _O_RDWR +#endif +#ifndef O_APPEND +#define O_APPEND _O_APPEND +#endif +#ifndef O_CREAT +#define O_CREAT _O_CREAT +#endif +#ifndef O_TRUNC +#define O_TRUNC _O_TRUNC +#endif +#ifndef O_EXCL +#define O_EXCL _O_EXCL +#endif +#ifndef O_TEXT +#define O_TEXT _O_TEXT +#endif +#ifndef O_BINARY +#define O_BINARY _O_BINARY +#endif +#ifndef O_RAW +#define O_RAW _O_BINARY +#endif +#ifndef O_TEMPORARY +#define O_TEMPORARY _O_TEMPORARY +#endif +#ifndef O_NOINHERIT +#define O_NOINHERIT _O_NOINHERIT +#endif +#ifndef O_SEQUENTIAL +#define O_SEQUENTIAL _O_SEQUENTIAL +#endif +#ifndef O_RANDOM +#define O_RANDOM _O_RANDOM +#endif + + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct stat { + _dev_t st_dev; + _ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + _dev_t st_rdev; + _off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; + }; + +/* from io.h */ +#if OLDNAMES_WITH_MACROS +#define access _access +#define chmod _chmod +#define chsize _chsize +#define close _close +#define creat _creat +#define dup _dup +#define dup2 _dup2 +#if 0 +/* This one conflicts with texk/web2/lib/eofeoln.c */ +#define eof _eof +#endif +#define filelength _filelength +#define isatty _isatty +#define locking _locking +#define lseek _lseek +#define mktemp _mktemp +#define open _open +#define read _read +#define setmode _setmode +#define sopen _sopen +#define tell _tell +#define umask _umask +#define unlink _unlink +#define write _write +#else +_CRTIMP int __cdecl access(const char *, int); +_CRTIMP int __cdecl chmod(const char *, int); +_CRTIMP int __cdecl chsize(int, long); +_CRTIMP int __cdecl close(int); +_CRTIMP int __cdecl creat(const char *, int); +_CRTIMP int __cdecl dup(int); +_CRTIMP int __cdecl dup2(int, int); +#if 0 +_CRTIMP int __cdecl eof(int); +#endif +_CRTIMP long __cdecl filelength(int); +_CRTIMP int __cdecl isatty(int); +_CRTIMP int __cdecl locking(int, int, long); +_CRTIMP long __cdecl lseek(int, long, int); +_CRTIMP char * __cdecl mktemp(char *); +_CRTIMP int __cdecl open(const char *, int, ...); +_CRTIMP int __cdecl read(int, void *, unsigned int); +_CRTIMP int __cdecl setmode(int, int); +_CRTIMP int __cdecl sopen(const char *, int, int, ...); +_CRTIMP long __cdecl tell(int); +_CRTIMP int __cdecl umask(int); +_CRTIMP int __cdecl unlink(const char *); +_CRTIMP int __cdecl write(int, const void *, unsigned int); +#endif + +/* from conio.h */ +#if OLDNAMES_WITH_MACROS +#define cgets _cgets +#define cprintf _cprintf +#define cputs _cputs +#define cscanf _cscanf +#define inp _inp +#define inpw _inpw +#define getch _getch +#define getche _getche +#define kbhit _kbhit +#define outp _outp +#define outpw _outpw +#define putch _putch +#define ungetch _ungetch +#else +_CRTIMP char * __cdecl cgets(char *); +_CRTIMP int __cdecl cprintf(const char *, ...); +_CRTIMP int __cdecl cputs(const char *); +_CRTIMP int __cdecl cscanf(const char *, ...); +int __cdecl inp(unsigned short); +unsigned short __cdecl inpw(unsigned short); +_CRTIMP int __cdecl getch(void); +_CRTIMP int __cdecl getche(void); +_CRTIMP int __cdecl kbhit(void); +int __cdecl outp(unsigned short, int); +unsigned short __cdecl outpw(unsigned short, unsigned short); +_CRTIMP int __cdecl putch(int); +_CRTIMP int __cdecl ungetch(int); +#endif + +/* from malloc.h */ +#define alloca _alloca + +/* from direct.h */ +#if OLDNAMES_WITH_MACROS +#define chdir _chdir +#define getcwd _getcwd +#define mkdir _mkdir +#define rmdir _rmdir +#else +_CRTIMP int __cdecl chdir(const char *); +_CRTIMP char * __cdecl getcwd(char *, int); +_CRTIMP int __cdecl mkdir(const char *); +_CRTIMP int __cdecl rmdir(const char *); +#endif + +/* from time.h */ +#define CLK_TCK CLOCKS_PER_SEC + +#if OLDNAMES_WITH_MACROS +#define daylight _daylight +#define timezone _timezone +#define tzname _tzname + +#define tzset _tzset +#else +_CRTIMP extern int daylight; +_CRTIMP extern long timezone; +_CRTIMP extern char * tzname[2]; + +#define tzset _tzset +#endif + +/* from process.h */ +#define P_WAIT _P_WAIT +#define P_NOWAIT _P_NOWAIT +#define P_OVERLAY _P_OVERLAY +#define OLD_P_OVERLAY _OLD_P_OVERLAY +#define P_NOWAITO _P_NOWAITO +#define P_DETACH _P_DETACH +#define WAIT_CHILD _WAIT_CHILD +#define WAIT_GRANDCHILD _WAIT_GRANDCHILD + +#if OLD_P_OVERLAY +#define cwait _cwait +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execlpe _execlpe +#define execv _execv +#define execve _execve +#define execvp _execvp +#define execvpe _execvpe +#define spawnl _spawnl +#define spawnle _spawnle +#define spawnlp _spawnlp +#define spawnlpe _spawnlpe +#define spawnv _spawnv +#define spawnve _spawnve +#define spawnvp _spawnvp +#define spawnvpe _spawnvpe + +#define getpid _getpid +#else +_CRTIMP int __cdecl cwait(int *, int, int); +_CRTIMP int __cdecl execl(const char *, const char *, ...); +_CRTIMP int __cdecl execle(const char *, const char *, ...); +_CRTIMP int __cdecl execlp(const char *, const char *, ...); +_CRTIMP int __cdecl execlpe(const char *, const char *, ...); +_CRTIMP int __cdecl execv(const char *, const char * const *); +_CRTIMP int __cdecl execve(const char *, const char * const *, const char * const *); +_CRTIMP int __cdecl execvp(const char *, const char * const *); +_CRTIMP int __cdecl execvpe(const char *, const char * const *, const char * const *); +_CRTIMP int __cdecl spawnl(int, const char *, const char *, ...); +_CRTIMP int __cdecl spawnle(int, const char *, const char *, ...); +_CRTIMP int __cdecl spawnlp(int, const char *, const char *, ...); +_CRTIMP int __cdecl spawnlpe(int, const char *, const char *, ...); +_CRTIMP int __cdecl spawnv(int, const char *, const char * const *); +_CRTIMP int __cdecl spawnve(int, const char *, const char * const *, + const char * const *); +_CRTIMP int __cdecl spawnvp(int, const char *, const char * const *); +_CRTIMP int __cdecl spawnvpe(int, const char *, const char * const *, + const char * const *); + +_CRTIMP int __cdecl getpid(void); +#endif + +/* from stdio.h */ +#define P_tmpdir _P_tmpdir +#define SYS_OPEN _SYS_OPEN + +#if OLDNAMES_WITH_MACROS +#define fcloseall _fcloseall +#define fdopen _fdopen +#define fgetchar _fgetchar +#define fileno _fileno +#define flushall _flushall +#define fputchar _fputchar +#define getw _getw +#define putw _putw +#define rmtmp _rmtmp +#define tempnam _tempnam +#define unlink _unlink +#else +_CRTIMP int __cdecl fcloseall(void); +_CRTIMP FILE * __cdecl fdopen(int, const char *); +_CRTIMP int __cdecl fgetchar(void); +_CRTIMP int __cdecl fileno(FILE *); +_CRTIMP int __cdecl flushall(void); +_CRTIMP int __cdecl fputchar(int); +_CRTIMP int __cdecl getw(FILE *); +_CRTIMP int __cdecl putw(int, FILE *); +_CRTIMP int __cdecl rmtmp(void); +_CRTIMP char * __cdecl tempnam(const char *, const char *); +_CRTIMP int __cdecl unlink(const char *); +#endif + +/* from stdlib.h */ + +#define sys_errlist _sys_errlist +#define sys_nerr _sys_nerr +#define environ _environ + +#define onexit_t _onexit_t + +#if OLDNAMES_WITH_MACROS +#define ecvt _ecvt +#define fcvt _fcvt +#define gcvt _gcvt +#define itoa _itoa +#define ltoa _ltoa +#define onexit _onexit +#define putenv _putenv +#define swab _swab +#define ultoa _ultoa +#else +_CRTIMP char * __cdecl ecvt(double, int, int *, int *); +_CRTIMP char * __cdecl fcvt(double, int, int *, int *); +_CRTIMP char * __cdecl gcvt(double, int, char *); +_CRTIMP char * __cdecl itoa(int, char *, int); +_CRTIMP char * __cdecl ltoa(long, char *, int); + onexit_t __cdecl onexit(onexit_t); +_CRTIMP int __cdecl putenv(const char *); +_CRTIMP void __cdecl swab(char *, char *, int); +_CRTIMP char * __cdecl ultoa(unsigned long, char *, int); +#endif + +/* from sys/stat.h */ +#ifndef S_IFMT +#define S_IFMT _S_IFMT +#endif +#ifndef S_IFDIR +#define S_IFDIR _S_IFDIR +#endif +#ifndef S_IFCHR +#define S_IFCHR _S_IFCHR +#endif +#ifndef S_IFIFO +#define S_IFIFO _S_IFIFO +#endif +#ifndef S_IFREG +#define S_IFREG _S_IFREG +#endif +#ifndef S_IREAD +#define S_IREAD _S_IREAD +#endif +#ifndef S_IWRITE +#define S_IWRITE _S_IWRITE +#endif +#ifndef S_IEXEC +#define S_IEXEC _S_IEXEC +#endif +#ifndef S_IXUSR +#define S_IXUSR _S_IEXEC +#endif +#ifndef S_IXGRP +#define S_IXGRP _S_IEXEC +#endif +#ifndef S_IXOTH +#define S_IXOTH _S_IEXEC +#endif +#ifndef S_IRUSR +#define S_IRUSR _S_IREAD +#endif +#ifndef S_IRGRP +#define S_IRGRP _S_IREAD +#endif +#ifndef S_IROTH +#define S_IROTH _S_IREAD +#endif +#ifndef S_IWUSR +#define S_IWUSR _S_IWRITE +#endif +#ifndef S_IWGRP +#define S_IWGRP _S_IWRITE +#endif +#ifndef S_IWOTH +#define S_IWOTH _S_IWRITE +#endif + +#if OLDNAMES_WITH_MACROS +#define fstat _fstat +#else +_CRTIMP int __cdecl fstat(int, struct stat *); +#endif + +/* Alternatively, we could always use the MS one. + Which one is the most buggy ? :-> */ +#if REPLACE_LIBC_FUNCTIONS +# define stat(p, s) win32_stat(p, s) +# define system(p) win32_system(p, 0) +# define popen(cmd, mode) win32_popen(cmd, mode) +# define pclose(file) win32_pclose(file) +#else +# define popen(cmd, mode) _popen(cmd, mode) +# define pclose(file) _pclose(file) +_CRTIMP int __cdecl system(const char *); +_CRTIMP FILE * __cdecl _popen(const char *, const char *); +_CRTIMP int __cdecl _pclose(FILE *); +# if OLDNAMES_WITH_MACROS +# define stat _stat +# else +_CRTIMP int __cdecl stat(const char *, struct stat *); +# endif +#endif + +/* from sys/types.h */ +typedef long off_t; + +/* from string.h */ +#if OLDNAMES_WITH_MACROS +#define memccpy _memccpy +#define memicmp _memicmp +#define strcmpi _strcmpi +#define stricmp _stricmp +#define strdup _strdup +#define strlwr _strlwr +#define strnicmp _strnicmp +#define strnset _strnset +#define strrev _strrev +#define strset _strset +#define strupr _strupr +#else +_CRTIMP void * __cdecl memccpy(void *, const void *, int, unsigned int); +_CRTIMP int __cdecl memicmp(const void *, const void *, unsigned int); +_CRTIMP int __cdecl strcmpi(const char *, const char *); +_CRTIMP int __cdecl stricmp(const char *, const char *); +_CRTIMP char * __cdecl strdup(const char *); +_CRTIMP char * __cdecl strlwr(char *); +_CRTIMP int __cdecl strnicmp(const char *, const char *, size_t); +_CRTIMP char * __cdecl strnset(char *, int, size_t); +_CRTIMP char * __cdecl strrev(char *); + char * __cdecl strset(char *, int); +_CRTIMP char * __cdecl strupr(char *); +#endif + +/* from ctype.h */ +#if !defined(_CTYPE_DEFINED) && !defined(OLDNAMES_WITH_MACROS) +_CRTIMP int __cdecl isascii(int); +_CRTIMP int __cdecl toascii(int); +_CRTIMP int __cdecl iscsymf(int); +_CRTIMP int __cdecl iscsym(int); +#else +#define isascii __isascii +#define toascii __toascii +#define iscsymf __iscsymf +#define iscsym __iscsym +#endif + +/* from sys/time.h */ +/* Non-ANSI name for compatibility */ + +struct timeb { + time_t time; + unsigned short millitm; + short timezone; + short dstflag; + }; + +#if OLDNAMES_WITH_MACROS +#define ftime _ftime +#else +_CRTIMP void __cdecl ftime(struct timeb *); +#endif + +/* from sys/utime.h */ + +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ + }; + +#if OLDNAMES_WITH_MACROS +#define utime _utime +#else +_CRTIMP int __cdecl utime(const char *, struct utimbuf *); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __STDC__ */ + +#endif /* _OLDNAMES_H_ */ diff --git a/Build/source/libs/libgnuw32/popen.c b/Build/source/libs/libgnuw32/popen.c new file mode 100644 index 00000000000..796a54eeecf --- /dev/null +++ b/Build/source/libs/libgnuw32/popen.c @@ -0,0 +1,296 @@ +/* libc replacement functions for win32. + +Copyright (C) 1998, 99 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + This does make sense only under WIN32. + Functions: + - popen() rewritten + - pclose() rewritten + + FIXME : + - exit code ? + - check leaks. +*/ + +#include <win32lib.h> +#include <errno.h> + +extern void free_cmd_pipe(char ***cmd_pipe, int nCmds); +extern char *quote_args(char **argv); + +#undef _DEBUG + +#ifdef _DEBUG +#define TRACE(x) x +#else +#define TRACE(x) +#endif + +#define IS_DIRECTORY_SEP(c) IS_DIR_SEP(c) + +struct _popen_elt { + FILE *f; /* File stream returned */ + HANDLE hp; /* Handle of associated process */ + struct _popen_elt *next; /* Next list element */ +}; + +static struct _popen_elt _z = { NULL, 0, &_z }; +static struct _popen_elt *_popen_list = &_z; + +static BOOL bCriticalSectionInitialized = FALSE; +CRITICAL_SECTION thePopenCriticalSection; + +void __cdecl +popen_cleanup(void) +{ + if (bCriticalSectionInitialized) { + DeleteCriticalSection(&thePopenCriticalSection); + } +} + +FILE * __cdecl win32_popen (const char *cmd, const char *mode) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + FILE *f = NULL; + int fno, i; + HANDLE child_in, child_out; + HANDLE father_in, father_out; + HANDLE father_in_dup, father_out_dup; + HANDLE current_pid; + int binary_mode; + char *new_cmd = NULL, *app_name = NULL; + struct _popen_elt *new_process; + BOOL read_mode, write_mode; + char ***cmd_pipe; + int nCmds; + + /* Admittedly, the command interpreter will allways be found. */ + if (cmd == NULL) { + TRACE(fprintf(stderr, "popen: (null) command.\n")); + return NULL; + } + + + cmd_pipe = parse_cmdline(cmd, NULL, NULL, &nCmds); + + /* Allow only one command in the pipe */ + if (nCmds != 1) { + /* Failed to find the command or malformed cmd */ + TRACE(fprintf(stderr, "system: failed to find command.\n")); + return NULL; + } + + /* First time, allow to call the command interpretor */ + if (look_for_cmd(cmd_pipe[0][0], &app_name) == FALSE) { + /* releasing previous split */ + free_cmd_pipe(cmd_pipe, nCmds); + TRACE(fprintf(stderr, "look for command: %s not found, concatenating comspec\n", app_name)); + new_cmd = concatn(getenv("COMSPEC"), " /c ", cmd, NULL); + TRACE(fprintf(stderr, "new command is: %s\n", new_cmd)); + cmd_pipe = parse_cmdline(new_cmd, NULL, NULL, &nCmds); + /* We don't need it anymore */ + free(new_cmd); + if (look_for_cmd(cmd_pipe[0][0], &app_name) == FALSE) { + /* Failed to find the command or malformed cmd */ + TRACE(fprintf(stderr, "system: failed to find command.\n")); + return NULL; + } + } + + new_cmd = quote_args(cmd_pipe[0]); + + TRACE(fprintf(stderr, "popen: app_name = %s\n", app_name)); + TRACE(fprintf(stderr, "popen: cmd_line = %s\n", new_cmd)); + + current_pid = GetCurrentProcess(); + + ZeroMemory( &si, sizeof(STARTUPINFO) ); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ; + si.wShowWindow = /* 0 */ SW_HIDE ; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + binary_mode = (strchr(mode, 'b') ? _O_BINARY : _O_TEXT); + + read_mode = (strchr(mode, 'r') != 0); + write_mode = (strchr(mode, 'w') != 0); + + /* Opening the pipe for writing */ + if (write_mode) { + binary_mode |= _O_WRONLY; + if (CreatePipe(&child_in, &father_out, NULL, 0) == FALSE) { + fprintf(stderr, "popen: error CreatePipe\n"); + return NULL; + } + + if (DuplicateHandle(current_pid, child_in, + current_pid, &father_in_dup, + 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { + fprintf(stderr, "popen: error DuplicateHandle father_out\n"); + return NULL; + } + si.hStdInput = father_in_dup; + + CloseHandle(child_in); + fno = _open_osfhandle((long)father_out, binary_mode); + f = _fdopen(fno, mode); + i = setvbuf( f, NULL, _IONBF, 0 ); + } + /* Opening the pipe for reading */ + else if (read_mode) { + binary_mode |= _O_RDONLY; + if (CreatePipe(&father_in, &child_out, NULL, 0) == FALSE) { + fprintf(stderr, "popen: error CreatePipe\n"); + return NULL; + } + if (DuplicateHandle(current_pid, child_out, + current_pid, &father_out_dup, + 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { + fprintf(stderr, "popen: error DuplicateHandle father_in\n"); + return NULL; + } + CloseHandle(child_out); + si.hStdOutput = father_out_dup; + fno = _open_osfhandle((long)father_in, binary_mode); + f = _fdopen(fno, mode); + i = setvbuf( f, NULL, _IONBF, 0 ); + } + else { + fprintf(stderr, "popen: invalid mode %s\n", mode); + return NULL; + } + + /* creating child process */ + if (CreateProcess(app_name, /* pointer to name of executable module */ + new_cmd, /* pointer to command line string */ + NULL, /* pointer to process security attributes */ + NULL, /* pointer to thread security attributes */ + TRUE, /* handle inheritance flag */ + 0, /* creation flags */ + NULL, /* pointer to environment */ + NULL, /* pointer to current directory */ + &si, /* pointer to STARTUPINFO */ + &pi /* pointer to PROCESS_INFORMATION */ + ) == FALSE) { + fprintf(stderr, "popen: CreateProcess %x\n", GetLastError()); + return NULL; + } + + /* Only the process handle is needed, ignore errors */ + CloseHandle(pi.hThread); + + /* Closing the unnecessary part of the pipe */ + if (read_mode) { + CloseHandle(father_out_dup); + } + else if (write_mode) { + CloseHandle(father_in_dup); + } + + /* Add the pair (f, pi.hProcess) to the list */ + if ((new_process = malloc(sizeof(struct _popen_elt))) == NULL) { + fprintf (stderr, "popen: malloc(new_process) error\n"); + return NULL; + } + + if (! bCriticalSectionInitialized) { + InitializeCriticalSection(&thePopenCriticalSection); + atexit(popen_cleanup); + bCriticalSectionInitialized = TRUE; + } + + EnterCriticalSection(&thePopenCriticalSection); + + /* Saving the FILE * pointer, access key for retrieving the process + handle later on */ + new_process->f = f; + /* Saving the process handle */ + new_process->hp = pi.hProcess; + /* Linking it to the list of popen() processes */ + new_process->next = _popen_list; + _popen_list = new_process; + + LeaveCriticalSection(&thePopenCriticalSection); + + free_cmd_pipe(cmd_pipe, nCmds); + + if (new_cmd) free(new_cmd); + if (app_name) free(app_name); + + return f; +} + +int __cdecl win32_pclose (FILE *f) +{ + HANDLE h; + struct _popen_elt *p, *q; + int exit_code; + + EnterCriticalSection(&thePopenCriticalSection); + + /* Look for f as the access key in the linked list */ + for (q = NULL, p = _popen_list; + p != &_z && p->f != f; + q = p, p = p->next); + + /* remove the elt from the list if found */ + if (p != &_z) { + if (q != NULL) + q->next = p->next; + else + _popen_list = p->next; + /* remember the handle */ + h = p->hp; + /* free up the block */ + free(p); + } + + LeaveCriticalSection(&thePopenCriticalSection); + + if (p == &_z) { + fprintf(stderr, "pclose: error, file not found."); + return -1; + } + + /* Closing the FILE pointer */ + fclose(f); + + /* Waiting for the process to terminate */ + if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) { + fprintf(stderr, "pclose: error, process still active\n"); + return -1; + } + + /* retrieving the exit code */ + if (GetExitCodeProcess(h, &exit_code) == 0) { + fprintf(stderr, "pclose: can't get process exit code\n"); + return -1; + } + + /* Closing the process handle, this will cause the system to + remove the process from memory */ + if (CloseHandle(h) == FALSE) { + fprintf(stderr, "pclose: error closing process handle\n"); + return -1; + } + + return exit_code; +} diff --git a/Build/source/libs/libgnuw32/stat.c b/Build/source/libs/libgnuw32/stat.c new file mode 100644 index 00000000000..f0353bd68c3 --- /dev/null +++ b/Build/source/libs/libgnuw32/stat.c @@ -0,0 +1,248 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +/* + MSVC stat function can't cope with UNC names and has other bugs, so + replace it with our own. This also allows us to calculate consistent + inode values without hacks in the main Emacs code. +*/ + +#include <win32lib.h> +#include <errno.h> +#if 0 +#include <sys/dir.h> +#include <sys/stat.h> +#include <pwd.h> +#endif + +extern struct passwd the_passwd; + +extern struct direct dir_static; /* simulated directory contents */ +extern HANDLE dir_find_handle; +extern char dir_pathname[MAXPATHLEN+1]; +extern WIN32_FIND_DATA dir_find_data; + +extern FILETIME utc_base_ft; +extern volume_info_data volume_info; + +int __cdecl +win32_stat (const char * path, struct stat * buf) +{ + char * name; + WIN32_FIND_DATA wfd; + HANDLE fh; + DWORD fake_inode; + int permission; + int len; + int rootdir = FALSE; + + if (path == NULL || buf == NULL) + { + errno = EFAULT; + return -1; + } + + name = (char *) map_win32_filename (path, &path); + /* must be valid filename, no wild cards */ + if (strchr (name, '*') || strchr (name, '?')) + { + errno = ENOENT; + return -1; + } + + /* Remove trailing directory separator, unless name is the root + directory of a drive or UNC volume in which case ensure there + is a trailing separator. */ + len = strlen (name); + rootdir = (path >= name + len - 1 + && (IS_DIR_SEP (*path) || *path == 0)); + name = strcpy (alloca (len + 2), name); + + if (rootdir) + { + if (!IS_DIR_SEP (name[len-1])) + strcat (name, "\\"); + if (GetDriveType (name) < 2) + { + errno = ENOENT; + return -1; + } + memset (&wfd, 0, sizeof (wfd)); + wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + wfd.ftCreationTime = utc_base_ft; + wfd.ftLastAccessTime = utc_base_ft; + wfd.ftLastWriteTime = utc_base_ft; + strcpy (wfd.cFileName, name); + } + else + { + if (IS_DIR_SEP (name[len-1])) + name[len - 1] = 0; + +#if 0 + /* (This is hacky, but helps when doing file completions on + network drives.) Optimize by using information available from + active readdir if possible. */ + if (dir_find_handle != INVALID_HANDLE_VALUE && + (len = strlen (dir_pathname)), + strnicmp (name, dir_pathname, len) == 0 && + IS_DIR_SEP (name[len]) && + stricmp (name + len + 1, dir_static.d_name) == 0) + { + /* This was the last entry returned by readdir. */ + wfd = dir_find_data; + } + else +#endif + { + fh = FindFirstFile (name, &wfd); + if (fh == INVALID_HANDLE_VALUE) + { + errno = ENOENT; + return -1; + } + FindClose (fh); + } + } + + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { +#ifdef TRACE_STAT + fprintf(stderr, "stat found %s is a directory\n", name ); +#endif + buf->st_mode = _S_IFDIR; + buf->st_nlink = 2; /* doesn't really matter */ + fake_inode = 0; /* this doesn't either I think */ + } + else +#if 0 + if (!NILP (Vmswindows_get_true_file_attributes)) + { + /* This is more accurate in terms of getting the correct number + of links, but is quite slow (it is noticeable when Emacs is + making a list of file name completions). */ + BY_HANDLE_FILE_INFORMATION info; + + /* No access rights required to get info. */ + fh = CreateFile (name, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, 0, NULL); + + if (GetFileInformationByHandle (fh, &info)) + { + switch (GetFileType (fh)) + { + case FILE_TYPE_DISK: + buf->st_mode = _S_IFREG; + break; + case FILE_TYPE_PIPE: + buf->st_mode = _S_IFIFO; + break; + case FILE_TYPE_CHAR: + case FILE_TYPE_UNKNOWN: + default: + buf->st_mode = _S_IFCHR; + } + buf->st_nlink = (short) info.nNumberOfLinks; + /* Might as well use file index to fake inode values, but this + is not guaranteed to be unique unless we keep a handle open + all the time (even then there are situations where it is + not unique). Reputedly, there are at most 48 bits of info + (on NTFS, presumably less on FAT). */ + fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh; + CloseHandle (fh); + } + else + { + errno = EACCES; + return -1; + } + } + else +#endif /* 0 */ + { + /* Don't bother to make this information more accurate. */ + buf->st_mode = _S_IFREG; + buf->st_nlink = 1; + fake_inode = 0; + } + +#if 0 + /* Not sure if there is any point in this. */ + if (!NILP (Vwin32_generate_fake_inodes)) + fake_inode = generate_inode_val (name); + else if (fake_inode == 0) + { + /* For want of something better, try to make everything unique. */ + static DWORD gen_num = 0; + fake_inode = ++gen_num; + } +#endif + + /* #### MSVC defines _ino_t to be short; other libc's might not. */ + buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); + + /* consider files to belong to current user */ + buf->st_uid = the_passwd.pw_uid; + buf->st_gid = the_passwd.pw_gid; + + /* volume_info is set indirectly by map_win32_filename */ + buf->st_dev = volume_info.serialnum; + buf->st_rdev = volume_info.serialnum; + + + buf->st_size = wfd.nFileSizeLow; + + /* Convert timestamps to Unix format. */ + buf->st_mtime = convert_time (wfd.ftLastWriteTime); + buf->st_atime = convert_time (wfd.ftLastAccessTime); + if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; + buf->st_ctime = convert_time (wfd.ftCreationTime); + if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; + + /* determine rwx permissions */ + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + permission = _S_IREAD; + else + permission = _S_IREAD | _S_IWRITE; + + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + permission |= _S_IEXEC; + else + { + char * p = strrchr (name, '.'); + if (p != NULL && + (stricmp (p, ".exe") == 0 || + stricmp (p, ".com") == 0 || + stricmp (p, ".bat") == 0 || + stricmp (p, ".cmd") == 0)) + permission |= _S_IEXEC; + } + + buf->st_mode |= permission | (permission >> 3) | (permission >> 6); + + return 0; +} diff --git a/Build/source/libs/libgnuw32/string.c b/Build/source/libs/libgnuw32/string.c new file mode 100644 index 00000000000..774a02c3354 --- /dev/null +++ b/Build/source/libs/libgnuw32/string.c @@ -0,0 +1,100 @@ +/* libc replacement functions for win32. + +Copyright (C) 1998, 99 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <win32lib.h> + +char *xstrdup(const char *s) +{ + char *p = _strdup(s); + if (!p) { + fprintf(stderr, "strdup(%x) failed in gnuw32.c at line %d\n", s, __LINE__); + exit(1); + } + return p; +} + +void *xmalloc(unsigned size) +{ + void *p = malloc(size); + if (!p) { + fprintf(stderr, "malloc(%d) failed in gnuw32.c at line %d\n", size, __LINE__); + exit(1); + } + return p; +} + +void *xrealloc(void *p, unsigned size) +{ + p = realloc(p, size); + if (!p) { + fprintf(stderr, "realloc(%d) failed in gnuw32.c at line %d\n", size, __LINE__); + exit(1); + } + return p; +} + +char *concat(const char *s1, const char *s2) +{ + char *answer = (char *) xmalloc (strlen (s1) + strlen (s2) + 1); + strcpy (answer, s1); + strcat (answer, s2); + + return answer; +} + +char *concat3(const char *s1, const char *s2, const char *s3) +{ + char *answer + = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1); + strcpy (answer, s1); + strcat (answer, s2); + strcat (answer, s3); + + return answer; +} + +char *concatn(const char *str1, ...) +{ + char *arg, *ret; + int size = 1; + va_list marker; + + if (!str1) + return NULL; + + size = strlen(str1); + + va_start(marker, str1); + while ((arg = va_arg (marker, char*)) != NULL) { + size += strlen(arg); + } + va_end (marker); + + + ret = xmalloc(size + 1); + strcpy(ret, str1); + + va_start(marker, str1); + while ((arg = va_arg (marker, char*)) != NULL) { + strcat(ret, arg); + } + va_end (marker); + + return ret; +} diff --git a/Build/source/libs/libgnuw32/system.c b/Build/source/libs/libgnuw32/system.c new file mode 100644 index 00000000000..fbc20a8f513 --- /dev/null +++ b/Build/source/libs/libgnuw32/system.c @@ -0,0 +1,307 @@ +/* libc replacement functions for win32. + +Copyright (C) 1998, 99 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* + This does make sense only under WIN32. + Functions: + - win32_system() rewritten + */ + +#include <win32lib.h> +#include <errno.h> + +#undef _DEBUG + +#ifdef _DEBUG +#define TRACE(x) x +#else +#define TRACE(x) +#endif + +extern char *quote_args(char **argv); +extern void free_cmd_pipe(char ***cmd_pipe, int nCmds); + +/* + It has been proven that system() fails to retrieve exit codes + under Win9x. This is a workaround for this bug. +*/ + +int __cdecl win32_system(const char *cmd, int async) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD ret = 0, dwCode; + HANDLE *hIn, *hOut, *hProcess, hDummyIn, hDummyOut, hDummyErr, hCurrentProcess; + int i, j, nCmds; + + char *app_name = NULL, *new_cmd = NULL; + char *red_input, *red_output, ***cmd_pipe; + + /* Reset errno ??? */ + errno = 0; + + /* Admittedly, the command interpreter will allways be found. */ + if (! cmd) { + TRACE(fprintf(stderr, "system: (null) command.\n")); + errno = 0; + return 1; + } + + cmd_pipe = parse_cmdline(cmd, &red_input, &red_output, &nCmds); + + if (nCmds == 0) { + /* Failed to find the command or malformed cmd */ + TRACE(fprintf(stderr, "system: failed to find command.\n")); + errno = ENOEXEC; + return -1; + } + + /* First time, allow to call the command interpretor */ + if (look_for_cmd(cmd_pipe[0][0], &app_name) == FALSE) { + /* releasing previous split */ + TRACE(fprintf(stderr, "look for command: `%s' not found, concatenating comspec\n", cmd_pipe[0][0])); + free_cmd_pipe(cmd_pipe, nCmds); + new_cmd = concatn(getenv("COMSPEC"), " /c ", cmd, NULL); + TRACE(fprintf(stderr, "new command is: %s\n", new_cmd)); + cmd_pipe = parse_cmdline(new_cmd, &red_input, &red_output, &nCmds); + if (nCmds == 0 || look_for_cmd(cmd_pipe[0][0], &app_name) == FALSE) { + /* Failed to find the command or malformed cmd */ + TRACE(fprintf(stderr, "system: failed to find command.\n")); + errno = ENOEXEC; + return -1; + } + } + + /* Arrays for pipes handles and process handles */ + hIn = malloc(nCmds * sizeof(HANDLE)); + hOut = malloc(nCmds * sizeof(HANDLE)); + hProcess = malloc(nCmds * sizeof(HANDLE)); + + for (i = 0; i < nCmds; i++) { + hIn[i] = hOut[i] = hProcess[i] = INVALID_HANDLE_VALUE; + } + + /* We need this handle to duplicate other handles */ + hCurrentProcess = GetCurrentProcess(); + + TRACE(fprintf(stderr, "%d cmds found\n", nCmds)); + + /* First time, use red_input if available */ + + if (red_input) { + hIn[0] = CreateFile(red_input, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, /* non inheritable */ + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hIn[0] == INVALID_HANDLE_VALUE) { + TRACE(fprintf(stderr, "system: failed to open hIn (%s) with error %d.\n", red_input, GetLastError())); + errno = EIO; + return -1; + } + + TRACE(fprintf(stderr, "First pipe input redirected to %s\n", red_input)); + + } + else { + hDummyIn = GetStdHandle(STD_INPUT_HANDLE); + DuplicateHandle(hCurrentProcess, hDummyIn, + hCurrentProcess, &hIn[0], 0, + FALSE, + DUPLICATE_SAME_ACCESS); + TRACE(fprintf(stderr, "STD_INPUT_HANDLE %x -> %x\n", hDummyIn, hIn[0])); + } + + /* Last time, use red_output if available */ + if (red_output) { + hOut[nCmds - 1] = CreateFile(red_output, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, /* non inheritable */ + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hOut[nCmds - 1] == INVALID_HANDLE_VALUE) { + + TRACE(fprintf(stderr, "system: failed to open hOut (%s) with error %d.\n", + red_output, GetLastError())); + + errno = EIO; + return -1; + } + + TRACE(fprintf(stderr, "Last pipe output redirected to %s\n", red_output)); + + } + else { + hDummyOut = GetStdHandle(STD_OUTPUT_HANDLE); + DuplicateHandle(hCurrentProcess, hDummyOut, + hCurrentProcess, &hOut[nCmds - 1], 0, + FALSE, + DUPLICATE_SAME_ACCESS); + TRACE(fprintf(stderr, "STD_OUTPUT_HANDLE %x -> %x\n", hDummyOut, hOut[nCmds - 1])); + } + + hDummyErr = GetStdHandle(STD_ERROR_HANDLE); + + + /* Loop on every command */ + for (i = 0; i < nCmds; i++) { + + /* free the cmd and build the current one */ + if (new_cmd) { + free(new_cmd); + new_cmd = NULL; + } + if (app_name) { + free(app_name); + app_name = NULL; + } + + /* Get the real app_name */ + if (look_for_cmd(cmd_pipe[i][0], &app_name) == FALSE) { + errno = ENOEXEC; + ret = -1; + goto cleanup; + } + + new_cmd = quote_args(cmd_pipe[i]); + + TRACE(fprintf(stderr, "Cmd[%d] = %s\n", i, new_cmd)); + + if (i < nCmds - 1) { + /* Handles are created non-inheritable */ + if (CreatePipe(&hIn[i+1], &hOut[i], NULL, 4096) == FALSE) { + fprintf(stderr, "win32_system(%s) call failed to create pipe (Error %d).\n", cmd, GetLastError()); + } + + TRACE(fprintf(stderr, "Creating pipe between hOut[%d] = %x and hIn[%d] = %x\n", + i, hOut[i], i+1, hIn[i+1])); + + } + + /* Enable handle inheritance for hIn[i] */ + DuplicateHandle(hCurrentProcess, hIn[i], + hCurrentProcess, &hDummyIn, 0, + TRUE, + DUPLICATE_SAME_ACCESS); + + TRACE(fprintf(stderr, "Duplicating hIn %x -> %x\n", hIn[i], hDummyIn)); + + /* Enable handle inheritance for hOut[i] */ + DuplicateHandle(hCurrentProcess, hOut[i], + hCurrentProcess, &hDummyOut, 0, + TRUE, + DUPLICATE_SAME_ACCESS); + + TRACE(fprintf(stderr, "Duplicating hOut %x -> %x\n", hOut[i], hDummyOut)); + + /* We don't need them anymore */ + CloseHandle(hIn[i]); + CloseHandle(hOut[i]); + TRACE(fprintf(stderr, "Close handles hIn = %x and hOut = %x\n", hIn[i], hOut[i])); + + ZeroMemory( &si, sizeof(STARTUPINFO) ); + si.cb = sizeof(STARTUPINFO); + si.dwFlags = STARTF_USESTDHANDLES /* | STARTF_USESHOWWINDOW */ ; + si.wShowWindow = 0 /* SW_SHOWDEFAULT */ ; + si.hStdInput = hDummyIn; + si.hStdOutput = hDummyOut; + si.hStdError = hDummyErr; + + TRACE(fprintf(stderr, "Executing: %s (app_name = %s)\n", new_cmd, app_name)); + + dwCode = CreateProcess(app_name, + new_cmd, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &si, + &pi); + + TRACE(fprintf(stderr, "New cmd(%s), process handle %x, Id %d, ret (%d), error (%d).\n", + new_cmd, pi.hProcess, pi.dwProcessId, dwCode, + (dwCode ? 0 : GetLastError() ))); + + CloseHandle(hDummyIn); + CloseHandle(hDummyOut); + + if (dwCode != 0) { + TRACE(fprintf(stderr, "StdIn = %x(%x), StdOut = %x(%x)\n", + hIn[i], hDummyIn, hOut[i], hDummyOut)); + + /* Only the process handle is needed */ + CloseHandle(pi.hThread); + hProcess[i] = pi.hProcess; + } + else { + fprintf(stderr, "win32_system(%s) call failed to create process (Error %d, hProcess %d).\n", new_cmd, GetLastError(), pi.hProcess); + ret = -1; + goto cleanup; + } + } + + cleanup: + + for (i = 0; i < nCmds; i++) { + if (hProcess[i] != INVALID_HANDLE_VALUE) { + if (ret == -1) { + TerminateProcess(hProcess[i], -1); + } + else if (async == 0) { + DWORD dwRet = WaitForSingleObject(hProcess[i], INFINITE); + if (dwRet == WAIT_OBJECT_0) { + + TRACE(fprintf(stderr, "Process %d exited\n", i)); + + } + else { + fprintf(stderr, "Failed to wait for process termination: %s (Ret %d, Error %d)\n", + cmd, dwRet, GetLastError()); + ret = -1; + } + } + } + } + + if (async == 0 && hProcess[nCmds - 1] != INVALID_HANDLE_VALUE) { + if (GetExitCodeProcess(hProcess[nCmds - 1], &ret) == 0) { + fprintf(stderr, "Failed to retrieve exit code: %s (Error %d)\n", cmd, GetLastError()); + ret = -1; + } + + TRACE(fprintf(stderr, "All processes terminated, exit code = %d\n", ret)); + + } + + for(i = 0; i < nCmds; i++) { + if (hProcess[i] != INVALID_HANDLE_VALUE) + CloseHandle(hProcess[i]); + } + free_cmd_pipe(cmd_pipe, nCmds); + + if (new_cmd) free(new_cmd); + if (app_name) free(app_name); + + return ret; +} diff --git a/Build/source/libs/libgnuw32/system_popen_check.c b/Build/source/libs/libgnuw32/system_popen_check.c new file mode 100644 index 00000000000..f8fbe62dc5f --- /dev/null +++ b/Build/source/libs/libgnuw32/system_popen_check.c @@ -0,0 +1,27 @@ +#include "win32lib.h" + +main(int argc, char *argv[]) +{ + int ret; + FILE *f; + int c; + + if (argc != 3) { + exit(1); + } + if (strncmp(argv[1], "syst", 4) == 0) { + printf("Running cmd `%s'\n", argv[2]); + ret = system(argv[2]); + printf("return code = %d\n"); + } + else if (strncmp(argv[1], "popr", 4) == 0) { + f = popen(argv[2], "r"); + while ((c = fgetc(f)) != EOF) fputc(c, stdout); + pclose(f); + } + else if (strncmp(argv[1], "popw", 4) == 0) { + f = popen(argv[2], "w"); + while ((c = fgetc(stdin)) != EOF) fputc(c, f); + pclose(f); + } +} diff --git a/Build/source/libs/libgnuw32/time.c b/Build/source/libs/libgnuw32/time.c new file mode 100644 index 00000000000..747cd59d997 --- /dev/null +++ b/Build/source/libs/libgnuw32/time.c @@ -0,0 +1,64 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +#include <win32lib.h> + +FILETIME utc_base_ft; +static long double utc_base; +static int init = 0; + +time_t +convert_time (FILETIME ft) +{ + long double ret; + + if (!init) + { + /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ + SYSTEMTIME st; + + st.wYear = 1970; + st.wMonth = 1; + st.wDay = 1; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + SystemTimeToFileTime (&st, &utc_base_ft); + utc_base = (long double) utc_base_ft.dwHighDateTime + * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; + init = 1; + } + + if (CompareFileTime (&ft, &utc_base_ft) < 0) + return 0; + + ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime; + ret -= utc_base; + return (time_t) (ret * 1e-7); +} diff --git a/Build/source/libs/libgnuw32/user.c b/Build/source/libs/libgnuw32/user.c new file mode 100644 index 00000000000..ec870c278b4 --- /dev/null +++ b/Build/source/libs/libgnuw32/user.c @@ -0,0 +1,224 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +/* Emulate getpwuid, getpwnam and others. */ + +#include <win32lib.h> + +#define PASSWD_FIELD_SIZE 256 + +static char the_passwd_name[PASSWD_FIELD_SIZE]; +static char the_passwd_passwd[PASSWD_FIELD_SIZE]; +static char the_passwd_gecos[PASSWD_FIELD_SIZE]; +static char the_passwd_dir[PASSWD_FIELD_SIZE]; +static char the_passwd_shell[PASSWD_FIELD_SIZE]; + +struct passwd the_passwd = +{ + the_passwd_name, + the_passwd_passwd, + 0, + 0, + 0, + the_passwd_gecos, + the_passwd_dir, + the_passwd_shell, +}; + +int +getuid () +{ + return the_passwd.pw_uid; +} + +int +geteuid () +{ + /* I could imagine arguing for checking to see whether the user is + in the Administrators group and returning a UID of 0 for that + case, but I don't know how wise that would be in the long run. */ + return getuid (); +} + +int +getgid () +{ + return the_passwd.pw_gid; +} + +int +getegid () +{ + return getgid (); +} + +struct passwd * +getpwuid (int uid) +{ + if (uid == the_passwd.pw_uid) + return &the_passwd; + return NULL; +} + +struct passwd * +getpwnam (const char *name) +{ + struct passwd *pw; + + pw = getpwuid (getuid ()); + if (!pw) + return pw; + + if (stricmp (name, pw->pw_name)) + return NULL; + + return pw; +} + +void +init_user_info () +{ + /* Find the user's real name by opening the process token and + looking up the name associated with the user-sid in that token. + + Use the relative portion of the identifier authority value from + the user-sid as the user id value (same for group id using the + primary group sid from the process token). */ +#if 0 + char user_sid[256], name[256], domain[256]; + DWORD length = sizeof (name), dlength = sizeof (domain), trash; + HANDLE token = NULL; + SID_NAME_USE user_type; + + if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token) + && GetTokenInformation (token, TokenUser, + (PVOID) user_sid, sizeof (user_sid), &trash) + && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length, + domain, &dlength, &user_type)) + { + strcpy (the_passwd.pw_name, name); + /* Determine a reasonable uid value. */ + if (stricmp ("administrator", name) == 0) + { + the_passwd.pw_uid = 0; + the_passwd.pw_gid = 0; + } + else + { + SID_IDENTIFIER_AUTHORITY * pSIA; + + pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid)); + /* I believe the relative portion is the last 4 bytes (of 6) + with msb first. */ + the_passwd.pw_uid = ((pSIA->Value[2] << 24) + + (pSIA->Value[3] << 16) + + (pSIA->Value[4] << 8) + + (pSIA->Value[5] << 0)); + /* restrict to conventional uid range for normal users */ + the_passwd.pw_uid = the_passwd.pw_uid % 60001; + + /* Get group id */ + if (GetTokenInformation (token, TokenPrimaryGroup, + (PVOID) user_sid, sizeof (user_sid), &trash)) + { + SID_IDENTIFIER_AUTHORITY * pSIA; + + pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid)); + the_passwd.pw_gid = ((pSIA->Value[2] << 24) + + (pSIA->Value[3] << 16) + + (pSIA->Value[4] << 8) + + (pSIA->Value[5] << 0)); + /* I don't know if this is necessary, but for safety... */ + the_passwd.pw_gid = the_passwd.pw_gid % 60001; + } + else + the_passwd.pw_gid = the_passwd.pw_uid; + } + } + /* If security calls are not supported (presumably because we + are running under Windows 95), fallback to this. */ + else + if (GetUserName (name, &length)) + { + strcpy (the_passwd.pw_name, name); + if (stricmp ("administrator", name) == 0) + the_passwd.pw_uid = 0; + else + the_passwd.pw_uid = 123; + the_passwd.pw_gid = the_passwd.pw_uid; + } + else +#else + { + strcpy (the_passwd.pw_name, "unknown"); + the_passwd.pw_uid = 123; + the_passwd.pw_gid = 123; + } +#endif + + /* Ensure HOME and SHELL are defined. */ +#if 1 + /* + * With XEmacs, setting $HOME is deprecated. + * But with fpTeX, it is safer to assume $HOME defined. + */ + { + char *home = get_home_directory(); + if (home) { + putenv(concat("HOME=", home)); + } + else { + putenv ("HOME=c:/"); + } + } +#endif + if (getenv ("SHELL") == NULL) + putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); + + { + /* Win2K problem : we need a specific TEMP directory with + full access rights so that any user building a format file + or a font file will build it with full access rights. The installer + takes care of defining TEXMFTEMP=$SELFAUTOPARENT/tmp in the environment. + If it is defined, then use it as the TEMP and TMP variables. + */ + char *p; + if ((p = getenv("TEXMFTEMP")) != NULL) { + putenv(concat("TEMP=", p)); + putenv(concat("TMP=", p)); + } + } + + /* Set dir and shell from environment variables. */ + strcpy (the_passwd.pw_dir, get_home_directory()); + strcpy (the_passwd.pw_shell, getenv ("SHELL")); + +#if 0 + if (token) + CloseHandle (token); +#endif +} diff --git a/Build/source/libs/libgnuw32/volume.c b/Build/source/libs/libgnuw32/volume.c new file mode 100644 index 00000000000..ad5e35dbc44 --- /dev/null +++ b/Build/source/libs/libgnuw32/volume.c @@ -0,0 +1,244 @@ +/* Utility and Unix shadow routines for XEmacs on Windows NT. + Copyright (C) 1994, 1995 Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs 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 2, or (at your option) any +later version. + +XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + + + Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */ + +/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ +/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ +/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */ + +#include <win32lib.h> + +/* #### This is an evil dirty hack. We must get rid of it. + Word "munging" is not in XEmacs lexicon. - kkm */ + +/* Internal MSVC data and functions for low-level descriptor munging */ +#if (_MSC_VER == 900) +extern char _osfile[]; +#endif +extern int __cdecl _set_osfhnd (int fd, long h); +extern int __cdecl _free_osfhnd (int fd); + +#if 0 +/* parallel array of private info on file handles */ +typedef struct +{ + unsigned flags; + HANDLE hnd; + child_process * cp; +} filedesc; + +/* parallel array of private info on file handles */ +filedesc fd_info [ MAXDESC ]; +#endif + +/* Global referenced by various functions. */ +volume_info_data volume_info; + +/* Vector to indicate which drives are local and fixed (for which cached + data never expires). */ +static BOOL fixed_drives[26]; + +/* Consider cached volume information to be stale if older than 10s, + at least for non-local drives. Info for fixed drives is never stale. */ +#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' ) +#define VOLINFO_STILL_VALID( root_dir, info ) \ + ( ( isalpha (root_dir[0]) && \ + fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \ + || GetTickCount () - info->timestamp < 10000 ) + +/* Cache support functions. */ + +/* Simple linked list with linear search is sufficient. */ +static volume_info_data *volume_cache = NULL; + +static volume_info_data * +lookup_volume_info (char * root_dir) +{ + volume_info_data * info; + + for (info = volume_cache; info; info = info->next) + if (stricmp (info->root_dir, root_dir) == 0) + break; + return info; +} + +static void +add_volume_info (char * root_dir, volume_info_data * info) +{ + info->root_dir = xstrdup (root_dir); + info->next = volume_cache; + volume_cache = info; +} + + +/* Wrapper for GetVolumeInformation, which uses caching to avoid + performance penalty (~2ms on 486 for local drives, 7.5ms for local + cdrom drive, ~5-10ms or more for remote drives on LAN). */ +volume_info_data * +GetCachedVolumeInformation (char * root_dir) +{ + volume_info_data * info; + char default_root[ MAX_PATH ]; + + /* NULL for root_dir means use root from current directory. */ + if (root_dir == NULL) + { + if (GetCurrentDirectory (MAX_PATH, default_root) == 0) + return NULL; + _parse_root (default_root, &root_dir); + *root_dir = 0; + root_dir = default_root; + } + + /* Local fixed drives can be cached permanently. Removable drives + cannot be cached permanently, since the volume name and serial + number (if nothing else) can change. Remote drives should be + treated as if they are removable, since there is no sure way to + tell whether they are or not. Also, the UNC association of drive + letters mapped to remote volumes can be changed at any time (even + by other processes) without notice. + + As a compromise, so we can benefit from caching info for remote + volumes, we use a simple expiry mechanism to invalidate cache + entries that are more than ten seconds old. */ + +#if 0 + /* No point doing this, because WNetGetConnection is even slower than + GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW, + GetDriveType is about the only call of this type which does not + involve network access, and so is extremely quick). */ + + /* Map drive letter to UNC if remote. */ + if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] ) + { + char remote_name[ 256 ]; + char drive[3] = { root_dir[0], ':' }; + + if (WNetGetConnection (drive, remote_name, sizeof (remote_name)) + == NO_ERROR) + /* do something */ ; + } +#endif + + info = lookup_volume_info (root_dir); + + if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info)) + { + char name[ 256 ]; + DWORD serialnum; + DWORD maxcomp; + DWORD flags; + char type[ 256 ]; + + /* Info is not cached, or is stale. */ + if (!GetVolumeInformation (root_dir, + name, sizeof (name), + &serialnum, + &maxcomp, + &flags, + type, sizeof (type))) + return NULL; + + /* Cache the volume information for future use, overwriting existing + entry if present. */ + if (info == NULL) + { + info = (volume_info_data *) xmalloc (sizeof (volume_info_data)); + add_volume_info (root_dir, info); + } + else + { + free (info->name); + free (info->type); + } + + info->name = xstrdup (name); + info->serialnum = serialnum; + info->maxcomp = maxcomp; + info->flags = flags; + info->type = xstrdup (type); + info->timestamp = GetTickCount (); + } + + return info; +} + +/* Get information on the volume where name is held; set path pointer to + start of pathname in name (past UNC header\volume header if present). */ +int +get_volume_info (const char * name, const char ** pPath) +{ + char temp[MAX_PATH]; + char *rootname = NULL; /* default to current volume */ + volume_info_data * info; + + if (name == NULL) + return FALSE; + + /* find the root name of the volume if given */ + if (isalpha (name[0]) && name[1] == ':') + { + rootname = temp; + temp[0] = *name++; + temp[1] = *name++; + temp[2] = '\\'; + temp[3] = 0; + } + else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1])) + { + char *str = temp; + int slashes = 4; + rootname = temp; + do + { + if (IS_DIR_SEP (*name) && --slashes == 0) + break; + *str++ = *name++; + } + while ( *name ); + + *str++ = '\\'; + *str = 0; + } + + if (pPath) + *pPath = name; + + info = GetCachedVolumeInformation (rootname); + if (info != NULL) + { + /* Set global referenced by other functions. */ + volume_info = *info; + return TRUE; + } + return FALSE; +} + +/* Determine if volume is FAT format (ie. only supports short 8.3 + names); also set path pointer to start of pathname in name. */ +int +is_fat_volume (const char * name, const char ** pPath) +{ + if (get_volume_info (name, pPath)) + return (volume_info.maxcomp == 12); + return FALSE; +} diff --git a/Build/source/libs/libgnuw32/win32.mak b/Build/source/libs/libgnuw32/win32.mak new file mode 100644 index 00000000000..e654ab2de84 --- /dev/null +++ b/Build/source/libs/libgnuw32/win32.mak @@ -0,0 +1,82 @@ +################################################################################ +# +# Makefile : Gnu Win32 +# Author : Fabrice Popineau <Fabrice.Popineau@supelec.fr> +# Platform : Win32, Microsoft VC++ 6.0, depends upon fpTeX 0.5 sources +# Time-stamp: <02/10/25 23:50:48 popineau> +# +################################################################################ +root_srcdir=..\.. +!ifdef DEVELOPMENT +INCLUDE=$(INCLUDE);$(root_srcdir)\texk.development +!else +INCLUDE=$(INCLUDE);$(root_srcdir)\texk +!endif + +USE_GNUW32 = 1 +MAKE_GNUW32 = 1 + +!include <msvc/common.mak> + +{$(root_srcdir)/texk/kpathsea}.c{$(objdir)}.obj: + $(compile) $< + +DEFS = $(DEFS) -I$(kpathseadir)\.. + +objects = \ +# $(objdir)\dirent.obj \ + $(objdir)\error.obj \ + $(objdir)\filename.obj \ + $(objdir)\getopt.obj \ + $(objdir)\getopt1.obj \ + $(objdir)\home.obj \ + $(objdir)\lookcmd.obj \ + $(objdir)\popen.obj \ + $(objdir)\stat.obj \ + $(objdir)\string.obj \ + $(objdir)\system.obj \ + $(objdir)\time.obj \ + $(objdir)\user.obj \ + $(objdir)\volume.obj + +programs = $(gnuw32dll) +libfiles = $(gnuw32lib) +includefiles = win32lib.h + +default: all + +all: $(objdir) $(gnuw32) + +lib: $(objdir) $(gnuw32lib) + +!ifdef GNUW32_DLL +DEFS= $(DEFS) -DMAKE_GNUW32_DLL + +$(gnuw32lib): $(objdir) $(objects) + $(archive) /DEF $(objects) + +$(gnuw32dll): $(objects) $(objdir)\libgnuw32.lib $(objdir)\libgnuw32.res + $(link_dll) $(**) $(gnuw32lib:.lib=.exp) $(conlibs) +!else +$(gnuw32lib): $(objdir) $(objects) + $(archive) $(objects) +!endif + +check: $(objdir)\system_popen_check.exe + +$(objdir)\system_popen_check.exe: $(objdir)\system_popen_check.obj $(gnuw32lib) + $(link) $(**) $(conlibs) + +!include <msvc/config.mak> +!include <msvc/install.mak> + +install:: install-exec install-lib install-include + +!include <msvc/clean.mak> +!include <msvc/rdepend.mak> +!include "./depend.mak" + +# +# Local Variables: +# mode: makefile +# End:
\ No newline at end of file diff --git a/Build/source/libs/libgnuw32/win32lib.h b/Build/source/libs/libgnuw32/win32lib.h new file mode 100644 index 00000000000..c3040d141c9 --- /dev/null +++ b/Build/source/libs/libgnuw32/win32lib.h @@ -0,0 +1,306 @@ +/* System description file for Windows NT. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + +This file is part of Web2C. + +Web2C 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 2, or (at your option) +any later version. + +Web2C 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 Web2C; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GNU_W32_H_ +#define _GNU_W32_H_ + +#pragma warning( disable : 4007 4096 4018 4244 ) + +#if defined(WIN32) +# if defined(KPSEDLL) +# define GNUW32DLL KPSEDLL +# else +# if defined(GNUW32_DLL) || defined(KPSE_DLL) +# if defined(MAKE_GNUW32_DLL) || defined(MAKE_KPSE_DLL) +# define GNUW32DLL __declspec( dllexport) +# else +# define GNUW32DLL __declspec( dllimport) +# endif +# else +# define GNUW32DLL +# endif +# endif +#else /* ! WIN32 */ +# define GNUW32DLL +#endif + +/* + * Define symbols to identify the version of Unix this is. + * Define all the symbols that apply correctly. + */ + +#ifndef DOSISH +#define DOSISH +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN _MAX_PATH +#endif + +#define HAVE_DUP2 1 +#define HAVE_RENAME 1 +#define HAVE_RMDIR 1 +#define HAVE_MKDIR 1 +#define HAVE_GETHOSTNAME 1 +#define HAVE_RANDOM 1 +#define USE_UTIME 1 +#define HAVE_MOUSE 1 +#define HAVE_TZNAME 1 + +typedef unsigned char boolean; +#define HAVE_BOOLEAN 1 +#define false FALSE +#define true TRUE + +#include <windows.h> + +#undef CDECL +#define CDECL __cdecl + +/* Defines size_t and alloca (). */ +#include <malloc.h> + +/* For proper declaration of environ. */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <io.h> +#include <process.h> +#include <direct.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * pwd.h doesn't exist on NT, so we put together our own. + */ + +struct passwd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + int pw_quota; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; + +#ifdef FPTEX +#define REPLACE_LIBC_FUNCTIONS 1 +#endif + +#if defined(__STDC__) +/* We want to compile with __STDC__ defined, but in this + case, MSVC headers do not define the standard names for + the C library functions (_open() instead of open()) */ +#include <oldnames.h> +#else +# if REPLACE_LIBC_FUNCTIONS +# define stat(p, s) win32_stat(p, s) +# define system(p) win32_system(p, 0) +# define popen(cmd, mode) win32_popen(cmd, mode) +# define pclose(file) win32_pclose(file) +# endif +#endif + +#define getwd(dir) GetCurrentDirectory(MAXPATHLEN, dir) +#ifndef index +#define index(s, c) strchr(s, c) +#endif +#ifndef rindex +#define rindex(s, c) strrchr(s, c) +#endif +#define pipe(fd, size, mode) _pipe(fd, size, mode) +#define strcasecmp(s1, s2) _stricmp(s1, s2) +#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n) +#define sleep(n) Sleep((DWORD)n); +#define vsnprintf _vsnprintf +#define snprintf _snprintf + +#ifdef _MSC_VER + +/* Test for each symbol individually and define the ones necessary (some + systems claiming Posix compatibility define some but not all). */ + +#if defined (S_IFBLK) && !defined (S_ISBLK) +#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */ +#endif + +#if defined (S_IFCHR) && !defined (S_ISCHR) +#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */ +#endif + +#if defined (S_IFDIR) && !defined (S_ISDIR) +#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */ +#endif + +#if defined (S_IFREG) && !defined (S_ISREG) +#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */ +#endif + +#if defined (S_IFIFO) && !defined (S_ISFIFO) +#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */ +#endif + +#if defined (S_IFLNK) && !defined (S_ISLNK) +#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */ +#endif + +#if defined (S_IFSOCK) && !defined (S_ISSOCK) +#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */ +#endif + +#endif /* _MSC_VER */ + +/* For access. */ +#ifndef F_OK +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 +#endif /* not F_OK */ + +/* + Path separators. + Redundant with <kpathsea/c-pathch.h>, but useful + outside of kpathsea. +*/ + +/* On DOS, it's good to allow both \ and / between directories. */ +#ifndef IS_DIR_SEP +#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\') +#endif +#ifndef IS_DEVICE_SEP +#define IS_DEVICE_SEP(ch) ((ch) == ':') +#endif +#ifndef NAME_BEGINS_WITH_DEVICE +#define NAME_BEGINS_WITH_DEVICE(name) (*(name) && IS_DEVICE_SEP((name)[1])) +#endif +/* On win32, UNC names are authorized */ +#ifndef IS_UNC_NAME +#define IS_UNC_NAME(name) (strlen(name)>=3 && IS_DIR_SEP(*name) \ + && IS_DIR_SEP(*(name+1)) && isalnum(*(name+2))) +#endif + +#ifndef min +#define min(a,b) ((b) > (a) ? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions from popen.c */ + +#define MAX_PIPES 128 + +extern GNUW32DLL FILE * __cdecl win32_popen(const char *, const char *); +extern GNUW32DLL int __cdecl win32_pclose(FILE *); + +/* Functions from stat.c */ + +extern GNUW32DLL int __cdecl win32_stat(const char * path, struct stat * buf); + +/* Functions from system.c */ + +extern GNUW32DLL int __cdecl win32_system(const char * cmd, int async); + +/* Functions from string.c */ +/* + Unfortunately, these functions are defined in kpathsea + but useful elsewhere too. As they have a small footprint, + they are duplicated for the moment and not exported. +*/ +extern GNUW32DLL void *xmalloc(unsigned size); +extern GNUW32DLL void *xrealloc(void *, unsigned size); +extern GNUW32DLL char *xstrdup(const char *); +extern GNUW32DLL char *concat(const char *s1, const char *s2); +extern GNUW32DLL char *concat3(const char *s1, const char *s2, const char *s3); +extern GNUW32DLL char * __cdecl concatn(const char *s1, ...); + +/* Functions from volume.c */ + +typedef struct volume_info_data { + struct volume_info_data * next; + + /* time when info was obtained */ + DWORD timestamp; + + /* actual volume info */ + char * root_dir; + DWORD serialnum; + DWORD maxcomp; + DWORD flags; + char * name; + char * type; +} volume_info_data; + +extern GNUW32DLL int is_fat_volume (const char * name, const char ** pPath); +extern GNUW32DLL int get_volume_info (const char * name, const char ** pPath); + +/* Functions from filename.c */ + +extern GNUW32DLL void dostounix_filename (char *p); +extern GNUW32DLL void unixtodos_filename (char *p); +extern GNUW32DLL char *quote_filename (char *p); +extern GNUW32DLL char *unquote_filename (char *p); +extern GNUW32DLL int crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count); +extern GNUW32DLL BOOL win32_get_long_filename (char * name, char * buf, int size); +extern GNUW32DLL const char *map_win32_filename (const char * name, const char ** pPath); +extern int _parse_root (char * name, char ** pPath); + +/* Functions from user.c */ +extern GNUW32DLL int getuid(); +extern GNUW32DLL int geteuid(); +extern GNUW32DLL int getgid(); +extern GNUW32DLL int getegid(); +extern GNUW32DLL struct passwd *getpwuid(int); +extern GNUW32DLL struct passwd *getpwnam(const char *); +extern GNUW32DLL void init_user_info(); +extern GNUW32DLL void init_user_info(); + +/* Functions from home.c */ +extern GNUW32DLL void set_home_warning(void); +extern GNUW32DLL char *get_home_directory (void); + +/* Functions from time.h */ +extern time_t convert_time (FILETIME ft); + +/* Functions from lookcmd.c */ + +extern GNUW32DLL BOOL look_for_cmd(const char *command, char **app_name); + +extern GNUW32DLL void *parse_cmdline(char *line, char **input, char **output, int *nb_cmds); +extern GNUW32DLL char *build_cmdline(char ***cmd, char *input, char *output); + +/* Functions from error.c */ + +extern GNUW32DLL void Win32Error(char *caller); +extern GNUW32DLL void Win32Msg(char *msg); + +/* ============================================================ */ + +#ifdef __cplusplus +} +#endif + +#endif /* not _GNU_W32_H_ */ |